aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter_bridge.h29
-rw-r--r--net/bridge/br_netfilter.c48
-rw-r--r--net/ipv4/ip_output.c5
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c4
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c3
-rw-r--r--net/netfilter/nf_conntrack_acct.c8
-rw-r--r--net/netfilter/nf_conntrack_expect.c4
-rw-r--r--net/netfilter/nf_tables_api.c23
-rw-r--r--net/netfilter/nfnetlink_log.c12
-rw-r--r--net/netfilter/nft_rbtree.c6
-rw-r--r--net/netfilter/xt_physdev.c3
11 files changed, 77 insertions, 68 deletions
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h
index bb39113ea596..2734977199ca 100644
--- a/include/linux/netfilter_bridge.h
+++ b/include/linux/netfilter_bridge.h
@@ -19,23 +19,10 @@ enum nf_br_hook_priorities {
19 19
20#define BRNF_PKT_TYPE 0x01 20#define BRNF_PKT_TYPE 0x01
21#define BRNF_BRIDGED_DNAT 0x02 21#define BRNF_BRIDGED_DNAT 0x02
22#define BRNF_BRIDGED 0x04
23#define BRNF_NF_BRIDGE_PREROUTING 0x08 22#define BRNF_NF_BRIDGE_PREROUTING 0x08
24#define BRNF_8021Q 0x10 23#define BRNF_8021Q 0x10
25#define BRNF_PPPoE 0x20 24#define BRNF_PPPoE 0x20
26 25
27static inline unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb)
28{
29 switch (skb->protocol) {
30 case __cpu_to_be16(ETH_P_8021Q):
31 return VLAN_HLEN;
32 case __cpu_to_be16(ETH_P_PPP_SES):
33 return PPPOE_SES_HLEN;
34 default:
35 return 0;
36 }
37}
38
39static inline unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb) 26static inline unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb)
40{ 27{
41 if (unlikely(skb->nf_bridge->mask & BRNF_PPPoE)) 28 if (unlikely(skb->nf_bridge->mask & BRNF_PPPoE))
@@ -45,21 +32,6 @@ static inline unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb)
45 32
46int br_handle_frame_finish(struct sk_buff *skb); 33int br_handle_frame_finish(struct sk_buff *skb);
47 34
48/* This is called by the IP fragmenting code and it ensures there is
49 * enough room for the encapsulating header (if there is one). */
50static inline unsigned int nf_bridge_pad(const struct sk_buff *skb)
51{
52 if (skb->nf_bridge)
53 return nf_bridge_encap_header_len(skb);
54 return 0;
55}
56
57struct bridge_skb_cb {
58 union {
59 __be32 ipv4;
60 } daddr;
61};
62
63static inline void br_drop_fake_rtable(struct sk_buff *skb) 35static inline void br_drop_fake_rtable(struct sk_buff *skb)
64{ 36{
65 struct dst_entry *dst = skb_dst(skb); 37 struct dst_entry *dst = skb_dst(skb);
@@ -69,7 +41,6 @@ static inline void br_drop_fake_rtable(struct sk_buff *skb)
69} 41}
70 42
71#else 43#else
72#define nf_bridge_pad(skb) (0)
73#define br_drop_fake_rtable(skb) do { } while (0) 44#define br_drop_fake_rtable(skb) do { } while (0)
74#endif /* CONFIG_BRIDGE_NETFILTER */ 45#endif /* CONFIG_BRIDGE_NETFILTER */
75 46
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index b260a97275db..f3884a1b942f 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -37,17 +37,16 @@
37#include <net/route.h> 37#include <net/route.h>
38#include <net/netfilter/br_netfilter.h> 38#include <net/netfilter/br_netfilter.h>
39 39
40#if IS_ENABLED(CONFIG_NF_CONNTRACK)
41#include <net/netfilter/nf_conntrack.h>
42#endif
43
40#include <asm/uaccess.h> 44#include <asm/uaccess.h>
41#include "br_private.h" 45#include "br_private.h"
42#ifdef CONFIG_SYSCTL 46#ifdef CONFIG_SYSCTL
43#include <linux/sysctl.h> 47#include <linux/sysctl.h>
44#endif 48#endif
45 49
46#define skb_origaddr(skb) (((struct bridge_skb_cb *) \
47 (skb->nf_bridge->data))->daddr.ipv4)
48#define store_orig_dstaddr(skb) (skb_origaddr(skb) = ip_hdr(skb)->daddr)
49#define dnat_took_place(skb) (skb_origaddr(skb) != ip_hdr(skb)->daddr)
50
51#ifdef CONFIG_SYSCTL 50#ifdef CONFIG_SYSCTL
52static struct ctl_table_header *brnf_sysctl_header; 51static struct ctl_table_header *brnf_sysctl_header;
53static int brnf_call_iptables __read_mostly = 1; 52static int brnf_call_iptables __read_mostly = 1;
@@ -154,6 +153,18 @@ static inline struct nf_bridge_info *nf_bridge_unshare(struct sk_buff *skb)
154 return nf_bridge; 153 return nf_bridge;
155} 154}
156 155
156static unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb)
157{
158 switch (skb->protocol) {
159 case __cpu_to_be16(ETH_P_8021Q):
160 return VLAN_HLEN;
161 case __cpu_to_be16(ETH_P_PPP_SES):
162 return PPPOE_SES_HLEN;
163 default:
164 return 0;
165 }
166}
167
157static inline void nf_bridge_push_encap_header(struct sk_buff *skb) 168static inline void nf_bridge_push_encap_header(struct sk_buff *skb)
158{ 169{
159 unsigned int len = nf_bridge_encap_header_len(skb); 170 unsigned int len = nf_bridge_encap_header_len(skb);
@@ -322,6 +333,22 @@ free_skb:
322 return 0; 333 return 0;
323} 334}
324 335
336static bool dnat_took_place(const struct sk_buff *skb)
337{
338#if IS_ENABLED(CONFIG_NF_CONNTRACK)
339 enum ip_conntrack_info ctinfo;
340 struct nf_conn *ct;
341
342 ct = nf_ct_get(skb, &ctinfo);
343 if (!ct || nf_ct_is_untracked(ct))
344 return false;
345
346 return test_bit(IPS_DST_NAT_BIT, &ct->status);
347#else
348 return false;
349#endif
350}
351
325/* This requires some explaining. If DNAT has taken place, 352/* This requires some explaining. If DNAT has taken place,
326 * we will need to fix up the destination Ethernet address. 353 * we will need to fix up the destination Ethernet address.
327 * 354 *
@@ -625,7 +652,7 @@ static unsigned int br_nf_pre_routing(const struct nf_hook_ops *ops,
625 return NF_DROP; 652 return NF_DROP;
626 if (!setup_pre_routing(skb)) 653 if (!setup_pre_routing(skb))
627 return NF_DROP; 654 return NF_DROP;
628 store_orig_dstaddr(skb); 655
629 skb->protocol = htons(ETH_P_IP); 656 skb->protocol = htons(ETH_P_IP);
630 657
631 NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, skb->dev, NULL, 658 NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, skb->dev, NULL,
@@ -721,8 +748,6 @@ static unsigned int br_nf_forward_ip(const struct nf_hook_ops *ops,
721 if (pf == NFPROTO_IPV4 && br_parse_ip_options(skb)) 748 if (pf == NFPROTO_IPV4 && br_parse_ip_options(skb))
722 return NF_DROP; 749 return NF_DROP;
723 750
724 /* The physdev module checks on this */
725 nf_bridge->mask |= BRNF_BRIDGED;
726 nf_bridge->physoutdev = skb->dev; 751 nf_bridge->physoutdev = skb->dev;
727 if (pf == NFPROTO_IPV4) 752 if (pf == NFPROTO_IPV4)
728 skb->protocol = htons(ETH_P_IP); 753 skb->protocol = htons(ETH_P_IP);
@@ -842,7 +867,12 @@ static unsigned int br_nf_post_routing(const struct nf_hook_ops *ops,
842 struct net_device *realoutdev = bridge_parent(skb->dev); 867 struct net_device *realoutdev = bridge_parent(skb->dev);
843 u_int8_t pf; 868 u_int8_t pf;
844 869
845 if (!nf_bridge || !(nf_bridge->mask & BRNF_BRIDGED)) 870 /* if nf_bridge is set, but ->physoutdev is NULL, this packet came in
871 * on a bridge, but was delivered locally and is now being routed:
872 *
873 * POST_ROUTING was already invoked from the ip stack.
874 */
875 if (!nf_bridge || !nf_bridge->physoutdev)
846 return NF_ACCEPT; 876 return NF_ACCEPT;
847 877
848 if (!realoutdev) 878 if (!realoutdev)
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index a7aea2048a0d..90b49e88e84a 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -636,10 +636,7 @@ slow_path:
636 left = skb->len - hlen; /* Space per frame */ 636 left = skb->len - hlen; /* Space per frame */
637 ptr = hlen; /* Where to start from */ 637 ptr = hlen; /* Where to start from */
638 638
639 /* for bridged IP traffic encapsulated inside f.e. a vlan header, 639 ll_rs = LL_RESERVED_SPACE(rt->dst.dev);
640 * we need to make room for the encapsulating header
641 */
642 ll_rs = LL_RESERVED_SPACE_EXTRA(rt->dst.dev, nf_bridge_pad(skb));
643 640
644 /* 641 /*
645 * Fragment the datagram. 642 * Fragment the datagram.
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
index a460a87e14f8..f0dfe92a00d6 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
@@ -300,7 +300,9 @@ static int exp_seq_show(struct seq_file *s, void *v)
300 __nf_ct_l3proto_find(exp->tuple.src.l3num), 300 __nf_ct_l3proto_find(exp->tuple.src.l3num),
301 __nf_ct_l4proto_find(exp->tuple.src.l3num, 301 __nf_ct_l4proto_find(exp->tuple.src.l3num,
302 exp->tuple.dst.protonum)); 302 exp->tuple.dst.protonum));
303 return seq_putc(s, '\n'); 303 seq_putc(s, '\n');
304
305 return 0;
304} 306}
305 307
306static const struct seq_operations exp_seq_ops = { 308static const struct seq_operations exp_seq_ops = {
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index 544b0a9da1b5..12331efd49cf 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -83,7 +83,8 @@ static int reject_tg6_check(const struct xt_tgchk_param *par)
83 return -EINVAL; 83 return -EINVAL;
84 } else if (rejinfo->with == IP6T_TCP_RESET) { 84 } else if (rejinfo->with == IP6T_TCP_RESET) {
85 /* Must specify that it's a TCP packet */ 85 /* Must specify that it's a TCP packet */
86 if (e->ipv6.proto != IPPROTO_TCP || 86 if (!(e->ipv6.flags & IP6T_F_PROTO) ||
87 e->ipv6.proto != IPPROTO_TCP ||
87 (e->ipv6.invflags & XT_INV_PROTO)) { 88 (e->ipv6.invflags & XT_INV_PROTO)) {
88 pr_info("TCP_RESET illegal for non-tcp\n"); 89 pr_info("TCP_RESET illegal for non-tcp\n");
89 return -EINVAL; 90 return -EINVAL;
diff --git a/net/netfilter/nf_conntrack_acct.c b/net/netfilter/nf_conntrack_acct.c
index a4b5e2a435ac..45da11afa785 100644
--- a/net/netfilter/nf_conntrack_acct.c
+++ b/net/netfilter/nf_conntrack_acct.c
@@ -47,9 +47,11 @@ seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir)
47 return 0; 47 return 0;
48 48
49 counter = acct->counter; 49 counter = acct->counter;
50 return seq_printf(s, "packets=%llu bytes=%llu ", 50 seq_printf(s, "packets=%llu bytes=%llu ",
51 (unsigned long long)atomic64_read(&counter[dir].packets), 51 (unsigned long long)atomic64_read(&counter[dir].packets),
52 (unsigned long long)atomic64_read(&counter[dir].bytes)); 52 (unsigned long long)atomic64_read(&counter[dir].bytes));
53
54 return 0;
53}; 55};
54EXPORT_SYMBOL_GPL(seq_print_acct); 56EXPORT_SYMBOL_GPL(seq_print_acct);
55 57
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 91a1837acd0e..7a17070c5dab 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -561,7 +561,9 @@ static int exp_seq_show(struct seq_file *s, void *v)
561 helper->expect_policy[expect->class].name); 561 helper->expect_policy[expect->class].name);
562 } 562 }
563 563
564 return seq_putc(s, '\n'); 564 seq_putc(s, '\n');
565
566 return 0;
565} 567}
566 568
567static const struct seq_operations exp_seq_ops = { 569static const struct seq_operations exp_seq_ops = {
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index ea51833c8f5a..f7e3371ce856 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -687,11 +687,10 @@ static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb,
687 if (!try_module_get(afi->owner)) 687 if (!try_module_get(afi->owner))
688 return -EAFNOSUPPORT; 688 return -EAFNOSUPPORT;
689 689
690 err = -ENOMEM;
690 table = kzalloc(sizeof(*table), GFP_KERNEL); 691 table = kzalloc(sizeof(*table), GFP_KERNEL);
691 if (table == NULL) { 692 if (table == NULL)
692 module_put(afi->owner); 693 goto err1;
693 return -ENOMEM;
694 }
695 694
696 nla_strlcpy(table->name, name, NFT_TABLE_MAXNAMELEN); 695 nla_strlcpy(table->name, name, NFT_TABLE_MAXNAMELEN);
697 INIT_LIST_HEAD(&table->chains); 696 INIT_LIST_HEAD(&table->chains);
@@ -700,13 +699,16 @@ static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb,
700 699
701 nft_ctx_init(&ctx, skb, nlh, afi, table, NULL, nla); 700 nft_ctx_init(&ctx, skb, nlh, afi, table, NULL, nla);
702 err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE); 701 err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE);
703 if (err < 0) { 702 if (err < 0)
704 kfree(table); 703 goto err2;
705 module_put(afi->owner); 704
706 return err;
707 }
708 list_add_tail_rcu(&table->list, &afi->tables); 705 list_add_tail_rcu(&table->list, &afi->tables);
709 return 0; 706 return 0;
707err2:
708 kfree(table);
709err1:
710 module_put(afi->owner);
711 return err;
710} 712}
711 713
712static int nft_flush_table(struct nft_ctx *ctx) 714static int nft_flush_table(struct nft_ctx *ctx)
@@ -3136,6 +3138,9 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
3136 elem.flags = ntohl(nla_get_be32(nla[NFTA_SET_ELEM_FLAGS])); 3138 elem.flags = ntohl(nla_get_be32(nla[NFTA_SET_ELEM_FLAGS]));
3137 if (elem.flags & ~NFT_SET_ELEM_INTERVAL_END) 3139 if (elem.flags & ~NFT_SET_ELEM_INTERVAL_END)
3138 return -EINVAL; 3140 return -EINVAL;
3141 if (!(set->flags & NFT_SET_INTERVAL) &&
3142 elem.flags & NFT_SET_ELEM_INTERVAL_END)
3143 return -EINVAL;
3139 } 3144 }
3140 3145
3141 if (set->flags & NFT_SET_MAP) { 3146 if (set->flags & NFT_SET_MAP) {
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 61d04bf9be2b..957b83a0223b 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -998,11 +998,13 @@ static int seq_show(struct seq_file *s, void *v)
998{ 998{
999 const struct nfulnl_instance *inst = v; 999 const struct nfulnl_instance *inst = v;
1000 1000
1001 return seq_printf(s, "%5d %6d %5d %1d %5d %6d %2d\n", 1001 seq_printf(s, "%5d %6d %5d %1d %5d %6d %2d\n",
1002 inst->group_num, 1002 inst->group_num,
1003 inst->peer_portid, inst->qlen, 1003 inst->peer_portid, inst->qlen,
1004 inst->copy_mode, inst->copy_range, 1004 inst->copy_mode, inst->copy_range,
1005 inst->flushtimeout, atomic_read(&inst->use)); 1005 inst->flushtimeout, atomic_read(&inst->use));
1006
1007 return 0;
1006} 1008}
1007 1009
1008static const struct seq_operations nful_seq_ops = { 1010static const struct seq_operations nful_seq_ops = {
diff --git a/net/netfilter/nft_rbtree.c b/net/netfilter/nft_rbtree.c
index 46214f245665..2c75361077f7 100644
--- a/net/netfilter/nft_rbtree.c
+++ b/net/netfilter/nft_rbtree.c
@@ -37,10 +37,11 @@ static bool nft_rbtree_lookup(const struct nft_set *set,
37{ 37{
38 const struct nft_rbtree *priv = nft_set_priv(set); 38 const struct nft_rbtree *priv = nft_set_priv(set);
39 const struct nft_rbtree_elem *rbe, *interval = NULL; 39 const struct nft_rbtree_elem *rbe, *interval = NULL;
40 const struct rb_node *parent = priv->root.rb_node; 40 const struct rb_node *parent;
41 int d; 41 int d;
42 42
43 spin_lock_bh(&nft_rbtree_lock); 43 spin_lock_bh(&nft_rbtree_lock);
44 parent = priv->root.rb_node;
44 while (parent != NULL) { 45 while (parent != NULL) {
45 rbe = rb_entry(parent, struct nft_rbtree_elem, node); 46 rbe = rb_entry(parent, struct nft_rbtree_elem, node);
46 47
@@ -158,7 +159,6 @@ static int nft_rbtree_get(const struct nft_set *set, struct nft_set_elem *elem)
158 struct nft_rbtree_elem *rbe; 159 struct nft_rbtree_elem *rbe;
159 int d; 160 int d;
160 161
161 spin_lock_bh(&nft_rbtree_lock);
162 while (parent != NULL) { 162 while (parent != NULL) {
163 rbe = rb_entry(parent, struct nft_rbtree_elem, node); 163 rbe = rb_entry(parent, struct nft_rbtree_elem, node);
164 164
@@ -173,11 +173,9 @@ static int nft_rbtree_get(const struct nft_set *set, struct nft_set_elem *elem)
173 !(rbe->flags & NFT_SET_ELEM_INTERVAL_END)) 173 !(rbe->flags & NFT_SET_ELEM_INTERVAL_END))
174 nft_data_copy(&elem->data, rbe->data); 174 nft_data_copy(&elem->data, rbe->data);
175 elem->flags = rbe->flags; 175 elem->flags = rbe->flags;
176 spin_unlock_bh(&nft_rbtree_lock);
177 return 0; 176 return 0;
178 } 177 }
179 } 178 }
180 spin_unlock_bh(&nft_rbtree_lock);
181 return -ENOENT; 179 return -ENOENT;
182} 180}
183 181
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index f440f57a452f..50a52043650f 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -56,8 +56,7 @@ physdev_mt(const struct sk_buff *skb, struct xt_action_param *par)
56 56
57 /* This only makes sense in the FORWARD and POSTROUTING chains */ 57 /* This only makes sense in the FORWARD and POSTROUTING chains */
58 if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) && 58 if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) &&
59 (!!(nf_bridge->mask & BRNF_BRIDGED) ^ 59 (!!nf_bridge->physoutdev ^ !(info->invert & XT_PHYSDEV_OP_BRIDGED)))
60 !(info->invert & XT_PHYSDEV_OP_BRIDGED)))
61 return false; 60 return false;
62 61
63 if ((info->bitmask & XT_PHYSDEV_OP_ISIN && 62 if ((info->bitmask & XT_PHYSDEV_OP_ISIN &&