History

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next

Pablo Neira Ayuso says: ==================== Netfilter updates for net-next The following patchset contains Netfilter updates for net-next: 1) Add nfgenmsg field to nfnetlink's struct nfnl_info and use it. 2) Remove nft_ctx_init_from_elemattr() and nft_ctx_init_from_setattr() helper functions. 3) Add the nf_ct_pernet() helper function to fetch the conntrack pernetns data area. 4) Expose TCP and UDP flowtable offload timeouts through sysctl, from Oz Shlomo. 5) Add nfnetlink_hook subsystem to fetch the netfilter hook pipeline configuration, from Florian Westphal. This also includes a new field to annotate the hook type as metadata. 6) Fix unsafe memory access to non-linear skbuff in the new SCTP chunk support for nft_exthdr, from Phil Sutter. ====================

David S. Miller committed 5 years ago

Commit 7f3579e2 parents 4e744cb c5c6acc27 files · +697 −205Browse files

Unified · Split

27 files
  1. include/linux/netfilter.h +7 −1
  2. include/linux/netfilter/nfnetlink.h +1 −0
  3. include/net/netfilter/nf_conntrack.h +7 −0
  4. include/net/netfilter/nf_flow_table.h +2 −0
  5. include/net/netns/conntrack.h +8 −0
  6. include/uapi/linux/netfilter/nfnetlink.h +2 −1
  7. include/uapi/linux/netfilter/nfnetlink_hook.h +55 −0
  8. net/netfilter/Kconfig +10 −0
  9. net/netfilter/Makefile +1 −0
  10. net/netfilter/nf_conntrack_core.c +9 −13
  11. net/netfilter/nf_conntrack_ecache.c +3 −5
  12. net/netfilter/nf_conntrack_expect.c +5 −7
  13. net/netfilter/nf_conntrack_helper.c +2 −4
  14. net/netfilter/nf_conntrack_netlink.c +9 −14
  15. net/netfilter/nf_conntrack_proto.c +2 −4
  16. net/netfilter/nf_conntrack_proto_tcp.c +5 −0
  17. net/netfilter/nf_conntrack_proto_udp.c +5 −0
  18. net/netfilter/nf_conntrack_standalone.c +49 −5
  19. net/netfilter/nf_flow_table_core.c +37 −10
  20. net/netfilter/nf_flow_table_offload.c +2 −2
  21. net/netfilter/nf_tables_api.c +84 −118
  22. net/netfilter/nfnetlink.c +3 −0
  23. net/netfilter/nfnetlink_hook.c +375 −0
  24. net/netfilter/nfnetlink_log.c +2 −3
  25. net/netfilter/nfnetlink_queue.c +3 −6
  26. net/netfilter/nft_compat.c +6 −11
  27. net/netfilter/nft_exthdr.c +3 −1
include/linux/netfilter.h+7−1
@@ -77,12 +77,18 @@ struct nf_hook_state { · 76 unmodified lines
7777 typedef unsigned int nf_hookfn(void *priv,
7878 struct sk_buff *skb,
7979 const struct nf_hook_state *state);
80+enum nf_hook_ops_type {
81+ NF_HOOK_OP_UNDEFINED,
82+ NF_HOOK_OP_NF_TABLES,
83+};
84+
8085 struct nf_hook_ops {
8186 /* User fills in from here down. */
8287 nf_hookfn *hook;
8388 struct net_device *dev;
8489 void *priv;
85− u_int8_t pf;
90+ u8 pf;
91+ enum nf_hook_ops_type hook_ops_type:8;
8692 unsigned int hooknum;
8793 /* Hooks are ordered in ascending priority. */
8894 int priority;
include/linux/netfilter/nfnetlink.h+1−0
@@ -11,6 +11,7 @@ struct nfnl_info { · 10 unmodified lines
1111 struct net *net;
1212 struct sock *sk;
1313 const struct nlmsghdr *nlh;
14+ const struct nfgenmsg *nfmsg;
1415 struct netlink_ext_ack *extack;
1516 };
1617
include/net/netfilter/nf_conntrack.h+7−0
@@ -346,6 +346,13 @@ nf_ct_set(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info info) · 345 unmodified lines
346346 skb_set_nfct(skb, (unsigned long)ct | info);
347347 }
348348
349+extern unsigned int nf_conntrack_net_id;
350+
351+static inline struct nf_conntrack_net *nf_ct_pernet(const struct net *net)
352+{
353+ return net_generic(net, nf_conntrack_net_id);
354+}
355+
349356 #define NF_CT_STAT_INC(net, count) __this_cpu_inc((net)->ct.stat->count)
350357 #define NF_CT_STAT_INC_ATOMIC(net, count) this_cpu_inc((net)->ct.stat->count)
351358 #define NF_CT_STAT_ADD_ATOMIC(net, count, v) this_cpu_add((net)->ct.stat->count, (v))
include/net/netfilter/nf_flow_table.h+2−0
@@ -177,6 +177,8 @@ struct flow_offload { · 176 unmodified lines
177177 #define NF_FLOW_TIMEOUT (30 * HZ)
178178 #define nf_flowtable_time_stamp (u32)jiffies
179179
180+unsigned long flow_offload_get_timeout(struct flow_offload *flow);
181+
180182 static inline __s32 nf_flow_timeout_delta(unsigned int timeout)
181183 {
182184 return (__s32)(timeout - nf_flowtable_time_stamp);
include/net/netns/conntrack.h+8−0
@@ -27,6 +27,10 @@ struct nf_tcp_net { · 26 unmodified lines
2727 u8 tcp_loose;
2828 u8 tcp_be_liberal;
2929 u8 tcp_max_retrans;
30+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
31+ unsigned int offload_timeout;
32+ unsigned int offload_pickup;
33+#endif
3034 };
3135
3236 enum udp_conntrack {
@@ -37,6 +41,10 @@ enum udp_conntrack { · 4 unmodified lines
3741
3842 struct nf_udp_net {
3943 unsigned int timeouts[UDP_CT_MAX];
44+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
45+ unsigned int offload_timeout;
46+ unsigned int offload_pickup;
47+#endif
4048 };
4149
4250 struct nf_icmp_net {
include/uapi/linux/netfilter/nfnetlink.h+2−1
@@ -60,7 +60,8 @@ struct nfgenmsg { · 59 unmodified lines
6060 #define NFNL_SUBSYS_CTHELPER 9
6161 #define NFNL_SUBSYS_NFTABLES 10
6262 #define NFNL_SUBSYS_NFT_COMPAT 11
63−#define NFNL_SUBSYS_COUNT 12
63+#define NFNL_SUBSYS_HOOK 12
64+#define NFNL_SUBSYS_COUNT 13
6465
6566 /* Reserved control nfnetlink messages */
6667 #define NFNL_MSG_BATCH_BEGIN NLMSG_MIN_TYPE
include/uapi/linux/netfilter/nfnetlink_hook.h+55−0
@@ -0,0 +1,55 @@
1+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2+#ifndef _NFNL_HOOK_H_
3+#define _NFNL_HOOK_H_
4+
5+enum nfnl_hook_msg_types {
6+ NFNL_MSG_HOOK_GET,
7+ NFNL_MSG_HOOK_MAX,
8+};
9+
10+/**
11+ * enum nfnl_hook_attributes - netfilter hook netlink attributes
12+ *
13+ * @NFNLA_HOOK_HOOKNUM: netfilter hook number (NLA_U32)
14+ * @NFNLA_HOOK_PRIORITY: netfilter hook priority (NLA_U32)
15+ * @NFNLA_HOOK_DEV: netdevice name (NLA_STRING)
16+ * @NFNLA_HOOK_FUNCTION_NAME: hook function name (NLA_STRING)
17+ * @NFNLA_HOOK_MODULE_NAME: kernel module that registered this hook (NLA_STRING)
18+ * @NFNLA_HOOK_CHAIN_INFO: basechain hook metadata (NLA_NESTED)
19+ */
20+enum nfnl_hook_attributes {
21+ NFNLA_HOOK_UNSPEC,
22+ NFNLA_HOOK_HOOKNUM,
23+ NFNLA_HOOK_PRIORITY,
24+ NFNLA_HOOK_DEV,
25+ NFNLA_HOOK_FUNCTION_NAME,
26+ NFNLA_HOOK_MODULE_NAME,
27+ NFNLA_HOOK_CHAIN_INFO,
28+ __NFNLA_HOOK_MAX
29+};
30+#define NFNLA_HOOK_MAX (__NFNLA_HOOK_MAX - 1)
31+
32+/**
33+ * enum nfnl_hook_chain_info_attributes - chain description
34+ *
35+ * NFNLA_HOOK_INFO_DESC: nft chain and table name (enum nft_table_attributes) (NLA_NESTED)
36+ * NFNLA_HOOK_INFO_TYPE: chain type (enum nfnl_hook_chaintype) (NLA_U32)
37+ */
38+enum nfnl_hook_chain_info_attributes {
39+ NFNLA_HOOK_INFO_UNSPEC,
40+ NFNLA_HOOK_INFO_DESC,
41+ NFNLA_HOOK_INFO_TYPE,
42+ __NFNLA_HOOK_INFO_MAX,
43+};
44+#define NFNLA_HOOK_INFO_MAX (__NFNLA_HOOK_INFO_MAX - 1)
45+
46+/**
47+ * enum nfnl_hook_chaintype - chain type
48+ *
49+ * @NFNL_HOOK_TYPE_NFTABLES nf_tables base chain
50+ */
51+enum nfnl_hook_chaintype {
52+ NFNL_HOOK_TYPE_NFTABLES = 0x1,
53+};
54+
55+#endif /* _NFNL_HOOK_H */
net/netfilter/Kconfig+10−0
@@ -19,6 +19,16 @@ config NETFILTER_FAMILY_BRIDGE · 18 unmodified lines
1919 config NETFILTER_FAMILY_ARP
2020 bool
2121
22+config NETFILTER_NETLINK_HOOK
23+ tristate "Netfilter base hook dump support"
24+ depends on NETFILTER_ADVANCED
25+ depends on NF_TABLES
26+ select NETFILTER_NETLINK
27+ help
28+ If this option is enabled, the kernel will include support
29+ to list the base netfilter hooks via NFNETLINK.
30+ This is helpful for debugging.
31+
2232 config NETFILTER_NETLINK_ACCT
2333 tristate "Netfilter NFACCT over NFNETLINK interface"
2434 depends on NETFILTER_ADVANCED
net/netfilter/Makefile+1−0
@@ -22,6 +22,7 @@ obj-$(CONFIG_NETFILTER_NETLINK_ACCT) += nfnetlink_acct.o · 21 unmodified lines
2222 obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o
2323 obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o
2424 obj-$(CONFIG_NETFILTER_NETLINK_OSF) += nfnetlink_osf.o
25+obj-$(CONFIG_NETFILTER_NETLINK_HOOK) += nfnetlink_hook.o
2526
2627 # connection tracking
2728 obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o
net/netfilter/nf_conntrack_core.c+9−13
@@ -55,8 +55,6 @@ · 54 unmodified lines
5555
5656 #include "nf_internals.h"
5757
58−extern unsigned int nf_conntrack_net_id;
59−
6058 __cacheline_aligned_in_smp spinlock_t nf_conntrack_locks[CONNTRACK_LOCKS];
6159 EXPORT_SYMBOL_GPL(nf_conntrack_locks);
6260
@@ -87,8 +85,6 @@ static __read_mostly bool nf_conntrack_locks_all; · 24 unmodified lines
8785
8886 static struct conntrack_gc_work conntrack_gc_work;
8987
90−extern unsigned int nf_conntrack_net_id;
91−
9288 void nf_conntrack_lock(spinlock_t *lock) __acquires(lock)
9389 {
9490 /* 1) Acquire the lock */
@@ -1404,7 +1400,7 @@ static void gc_worker(struct work_struct *work) · 1309 unmodified lines
14041400 continue;
14051401
14061402 net = nf_ct_net(tmp);
1407− cnet = net_generic(net, nf_conntrack_net_id);
1403+ cnet = nf_ct_pernet(net);
14081404 if (atomic_read(&cnet->count) < nf_conntrack_max95)
14091405 continue;
14101406
@@ -1484,7 +1480,7 @@ __nf_conntrack_alloc(struct net *net, · 73 unmodified lines
14841480 const struct nf_conntrack_tuple *repl,
14851481 gfp_t gfp, u32 hash)
14861482 {
1487− struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
1483+ struct nf_conntrack_net *cnet = nf_ct_pernet(net);
14881484 unsigned int ct_count;
14891485 struct nf_conn *ct;
14901486
@@ -1556,7 +1552,7 @@ void nf_conntrack_free(struct nf_conn *ct) · 65 unmodified lines
15561552
15571553 nf_ct_ext_destroy(ct);
15581554 kmem_cache_free(nf_conntrack_cachep, ct);
1559− cnet = net_generic(net, nf_conntrack_net_id);
1555+ cnet = nf_ct_pernet(net);
15601556
15611557 smp_mb__before_atomic();
15621558 atomic_dec(&cnet->count);
@@ -1614,7 +1610,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, · 51 unmodified lines
16141610 GFP_ATOMIC);
16151611
16161612 local_bh_disable();
1617− cnet = net_generic(net, nf_conntrack_net_id);
1613+ cnet = nf_ct_pernet(net);
16181614 if (cnet->expect_count) {
16191615 spin_lock(&nf_conntrack_expect_lock);
16201616 exp = nf_ct_find_expectation(net, zone, tuple);
@@ -2317,7 +2313,7 @@ __nf_ct_unconfirmed_destroy(struct net *net) · 696 unmodified lines
23172313
23182314 void nf_ct_unconfirmed_destroy(struct net *net)
23192315 {
2320− struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
2316+ struct nf_conntrack_net *cnet = nf_ct_pernet(net);
23212317
23222318 might_sleep();
23232319
@@ -2333,7 +2329,7 @@ void nf_ct_iterate_cleanup_net(struct net *net, · 9 unmodified lines
23332329 int (*iter)(struct nf_conn *i, void *data),
23342330 void *data, u32 portid, int report)
23352331 {
2336− struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
2332+ struct nf_conntrack_net *cnet = nf_ct_pernet(net);
23372333 struct iter_data d;
23382334
23392335 might_sleep();
@@ -2367,7 +2363,7 @@ nf_ct_iterate_destroy(int (*iter)(struct nf_conn *i, void *data), void *data) · 27 unmodified lines
23672363
23682364 down_read(&net_rwsem);
23692365 for_each_net(net) {
2370− struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
2366+ struct nf_conntrack_net *cnet = nf_ct_pernet(net);
23712367
23722368 if (atomic_read(&cnet->count) == 0)
23732369 continue;
@@ -2449,7 +2445,7 @@ void nf_conntrack_cleanup_net_list(struct list_head *net_exit_list) · 75 unmodified lines
24492445 i_see_dead_people:
24502446 busy = 0;
24512447 list_for_each_entry(net, net_exit_list, exit_list) {
2452− struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
2448+ struct nf_conntrack_net *cnet = nf_ct_pernet(net);
24532449
24542450 nf_ct_iterate_cleanup(kill_all, net, 0, 0);
24552451 if (atomic_read(&cnet->count) != 0)
@@ -2733,7 +2729,7 @@ void nf_conntrack_init_end(void) · 277 unmodified lines
27332729
27342730 int nf_conntrack_init_net(struct net *net)
27352731 {
2736− struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
2732+ struct nf_conntrack_net *cnet = nf_ct_pernet(net);
27372733 int ret = -ENOMEM;
27382734 int cpu;
27392735
net/netfilter/nf_conntrack_ecache.c+3−5
@@ -27,8 +27,6 @@ · 26 unmodified lines
2727 #include <net/netfilter/nf_conntrack_ecache.h>
2828 #include <net/netfilter/nf_conntrack_extend.h>
2929
30−extern unsigned int nf_conntrack_net_id;
31−
3230 static DEFINE_MUTEX(nf_ct_ecache_mutex);
3331
3432 #define ECACHE_RETRY_WAIT (HZ/10)
@@ -348,7 +346,7 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier); · 313 unmodified lines
348346
349347 void nf_conntrack_ecache_work(struct net *net, enum nf_ct_ecache_state state)
350348 {
351− struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
349+ struct nf_conntrack_net *cnet = nf_ct_pernet(net);
352350
353351 if (state == NFCT_ECACHE_DESTROY_FAIL &&
354352 !delayed_work_pending(&cnet->ecache_dwork)) {
@@ -371,7 +369,7 @@ static const struct nf_ct_ext_type event_extend = { · 16 unmodified lines
371369
372370 void nf_conntrack_ecache_pernet_init(struct net *net)
373371 {
374− struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
372+ struct nf_conntrack_net *cnet = nf_ct_pernet(net);
375373
376374 net->ct.sysctl_events = nf_ct_events;
377375 cnet->ct_net = &net->ct;
@@ -380,7 +378,7 @@ void nf_conntrack_ecache_pernet_init(struct net *net) · 2 unmodified lines
380378
381379 void nf_conntrack_ecache_pernet_fini(struct net *net)
382380 {
383− struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
381+ struct nf_conntrack_net *cnet = nf_ct_pernet(net);
384382
385383 cancel_delayed_work_sync(&cnet->ecache_dwork);
386384 }
net/netfilter/nf_conntrack_expect.c+5−7
@@ -43,8 +43,6 @@ unsigned int nf_ct_expect_max __read_mostly; · 42 unmodified lines
4343 static struct kmem_cache *nf_ct_expect_cachep __read_mostly;
4444 static unsigned int nf_ct_expect_hashrnd __read_mostly;
4545
46−extern unsigned int nf_conntrack_net_id;
47−
4846 /* nf_conntrack_expect helper functions */
4947 void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
5048 u32 portid, int report)
@@ -58,7 +56,7 @@ void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp, · 7 unmodified lines
5856
5957 hlist_del_rcu(&exp->hnode);
6058
61− cnet = net_generic(net, nf_conntrack_net_id);
59+ cnet = nf_ct_pernet(net);
6260 cnet->expect_count--;
6361
6462 hlist_del_rcu(&exp->lnode);
@@ -123,7 +121,7 @@ __nf_ct_expect_find(struct net *net, · 58 unmodified lines
123121 const struct nf_conntrack_zone *zone,
124122 const struct nf_conntrack_tuple *tuple)
125123 {
126− struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
124+ struct nf_conntrack_net *cnet = nf_ct_pernet(net);
127125 struct nf_conntrack_expect *i;
128126 unsigned int h;
129127
@@ -164,7 +162,7 @@ nf_ct_find_expectation(struct net *net, · 34 unmodified lines
164162 const struct nf_conntrack_zone *zone,
165163 const struct nf_conntrack_tuple *tuple)
166164 {
167− struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
165+ struct nf_conntrack_net *cnet = nf_ct_pernet(net);
168166 struct nf_conntrack_expect *i, *exp = NULL;
169167 unsigned int h;
170168
@@ -397,7 +395,7 @@ static void nf_ct_expect_insert(struct nf_conntrack_expect *exp) · 226 unmodified lines
397395 master_help->expecting[exp->class]++;
398396
399397 hlist_add_head_rcu(&exp->hnode, &nf_ct_expect_hash[h]);
400− cnet = net_generic(net, nf_conntrack_net_id);
398+ cnet = nf_ct_pernet(net);
401399 cnet->expect_count++;
402400
403401 NF_CT_STAT_INC(net, expect_create);
@@ -468,7 +466,7 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect, · 64 unmodified lines
468466 }
469467 }
470468
471− cnet = net_generic(net, nf_conntrack_net_id);
469+ cnet = nf_ct_pernet(net);
472470 if (cnet->expect_count >= nf_ct_expect_max) {
473471 net_warn_ratelimited("nf_conntrack: expectation table full\n");
474472 ret = -EMFILE;
net/netfilter/nf_conntrack_helper.c+2−4
@@ -43,8 +43,6 @@ MODULE_PARM_DESC(nf_conntrack_helper, · 42 unmodified lines
4343 static DEFINE_MUTEX(nf_ct_nat_helpers_mutex);
4444 static struct list_head nf_ct_nat_helpers __read_mostly;
4545
46−extern unsigned int nf_conntrack_net_id;
47−
4846 /* Stupid hash, but collision free for the default registrations of the
4947 * helpers currently in the kernel. */
5048 static unsigned int helper_hash(const struct nf_conntrack_tuple *tuple)
@@ -214,7 +212,7 @@ EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add); · 163 unmodified lines
214212 static struct nf_conntrack_helper *
215213 nf_ct_lookup_helper(struct nf_conn *ct, struct net *net)
216214 {
217− struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
215+ struct nf_conntrack_net *cnet = nf_ct_pernet(net);
218216
219217 if (!cnet->sysctl_auto_assign_helper) {
220218 if (cnet->auto_assign_helper_warned)
@@ -560,7 +558,7 @@ static const struct nf_ct_ext_type helper_extend = { · 339 unmodified lines
560558
561559 void nf_conntrack_helper_pernet_init(struct net *net)
562560 {
563− struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
561+ struct nf_conntrack_net *cnet = nf_ct_pernet(net);
564562
565563 cnet->sysctl_auto_assign_helper = nf_ct_auto_assign_helper;
566564 }
net/netfilter/nf_conntrack_netlink.c+9−14
@@ -1528,7 +1528,7 @@ static int ctnetlink_del_conntrack(struct sk_buff *skb, · 1527 unmodified lines
15281528 const struct nfnl_info *info,
15291529 const struct nlattr * const cda[])
15301530 {
1531− struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
1531+ u8 family = info->nfmsg->nfgen_family;
15321532 struct nf_conntrack_tuple_hash *h;
15331533 struct nf_conntrack_tuple tuple;
15341534 struct nf_conntrack_zone zone;
@@ -1541,12 +1541,12 @@ static int ctnetlink_del_conntrack(struct sk_buff *skb, · 6 unmodified lines
15411541
15421542 if (cda[CTA_TUPLE_ORIG])
15431543 err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG,
1544− nfmsg->nfgen_family, &zone);
1544+ family, &zone);
15451545 else if (cda[CTA_TUPLE_REPLY])
15461546 err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY,
1547− nfmsg->nfgen_family, &zone);
1547+ family, &zone);
15481548 else {
1549− u_int8_t u3 = nfmsg->version ? nfmsg->nfgen_family : AF_UNSPEC;
1549+ u_int8_t u3 = info->nfmsg->version ? family : AF_UNSPEC;
15501550
15511551 return ctnetlink_flush_conntrack(info->net, cda,
15521552 NETLINK_CB(skb).portid,
@@ -1586,8 +1586,7 @@ static int ctnetlink_get_conntrack(struct sk_buff *skb, · 33 unmodified lines
15861586 const struct nfnl_info *info,
15871587 const struct nlattr * const cda[])
15881588 {
1589− struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
1590− u_int8_t u3 = nfmsg->nfgen_family;
1589+ u_int8_t u3 = info->nfmsg->nfgen_family;
15911590 struct nf_conntrack_tuple_hash *h;
15921591 struct nf_conntrack_tuple tuple;
15931592 struct nf_conntrack_zone zone;
@@ -2363,10 +2362,9 @@ static int ctnetlink_new_conntrack(struct sk_buff *skb, · 769 unmodified lines
23632362 const struct nfnl_info *info,
23642363 const struct nlattr * const cda[])
23652364 {
2366− struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
23672365 struct nf_conntrack_tuple otuple, rtuple;
23682366 struct nf_conntrack_tuple_hash *h = NULL;
2369− u_int8_t u3 = nfmsg->nfgen_family;
2367+ u_int8_t u3 = info->nfmsg->nfgen_family;
23702368 struct nf_conntrack_zone zone;
23712369 struct nf_conn *ct;
23722370 int err;
@@ -3259,8 +3257,7 @@ static int ctnetlink_get_expect(struct sk_buff *skb, · 886 unmodified lines
32593257 const struct nfnl_info *info,
32603258 const struct nlattr * const cda[])
32613259 {
3262− struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
3263− u_int8_t u3 = nfmsg->nfgen_family;
3260+ u_int8_t u3 = info->nfmsg->nfgen_family;
32643261 struct nf_conntrack_tuple tuple;
32653262 struct nf_conntrack_expect *exp;
32663263 struct nf_conntrack_zone zone;
@@ -3349,8 +3346,7 @@ static int ctnetlink_del_expect(struct sk_buff *skb, · 82 unmodified lines
33493346 const struct nfnl_info *info,
33503347 const struct nlattr * const cda[])
33513348 {
3352− struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
3353− u_int8_t u3 = nfmsg->nfgen_family;
3349+ u_int8_t u3 = info->nfmsg->nfgen_family;
33543350 struct nf_conntrack_expect *exp;
33553351 struct nf_conntrack_tuple tuple;
33563352 struct nf_conntrack_zone zone;
@@ -3601,8 +3597,7 @@ static int ctnetlink_new_expect(struct sk_buff *skb, · 244 unmodified lines
36013597 const struct nfnl_info *info,
36023598 const struct nlattr * const cda[])
36033599 {
3604− struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
3605− u_int8_t u3 = nfmsg->nfgen_family;
3600+ u_int8_t u3 = info->nfmsg->nfgen_family;
36063601 struct nf_conntrack_tuple tuple;
36073602 struct nf_conntrack_expect *exp;
36083603 struct nf_conntrack_zone zone;
net/netfilter/nf_conntrack_proto.c+2−4
@@ -42,8 +42,6 @@ · 41 unmodified lines
4242 #include <net/ipv6.h>
4343 #include <net/inet_frag.h>
4444
45−extern unsigned int nf_conntrack_net_id;
46−
4745 static DEFINE_MUTEX(nf_ct_proto_mutex);
4846
4947 #ifdef CONFIG_SYSCTL
@@ -446,7 +444,7 @@ static struct nf_ct_bridge_info *nf_ct_bridge_info; · 396 unmodified lines
446444
447445 static int nf_ct_netns_do_get(struct net *net, u8 nfproto)
448446 {
449− struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
447+ struct nf_conntrack_net *cnet = nf_ct_pernet(net);
450448 bool fixup_needed = false, retry = true;
451449 int err = 0;
452450 retry:
@@ -531,7 +529,7 @@ retry: · 78 unmodified lines
531529
532530 static void nf_ct_netns_do_put(struct net *net, u8 nfproto)
533531 {
534− struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
532+ struct nf_conntrack_net *cnet = nf_ct_pernet(net);
535533
536534 mutex_lock(&nf_ct_proto_mutex);
537535 switch (nfproto) {
net/netfilter/nf_conntrack_proto_tcp.c+5−0
@@ -1441,6 +1441,11 @@ void nf_conntrack_tcp_init_net(struct net *net) · 1440 unmodified lines
14411441 * will be started.
14421442 */
14431443 tn->tcp_max_retrans = 3;
1444+
1445+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
1446+ tn->offload_timeout = 30 * HZ;
1447+ tn->offload_pickup = 120 * HZ;
1448+#endif
14441449 }
14451450
14461451 const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp =
net/netfilter/nf_conntrack_proto_udp.c+5−0
@@ -270,6 +270,11 @@ void nf_conntrack_udp_init_net(struct net *net) · 269 unmodified lines
270270
271271 for (i = 0; i < UDP_CT_MAX; i++)
272272 un->timeouts[i] = udp_timeouts[i];
273+
274+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
275+ un->offload_timeout = 30 * HZ;
276+ un->offload_pickup = 30 * HZ;
277+#endif
273278 }
274279
275280 const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp =
net/netfilter/nf_conntrack_standalone.c+49−5
@@ -512,9 +512,7 @@ static void nf_conntrack_standalone_fini_proc(struct net *net) · 511 unmodified lines
512512
513513 u32 nf_conntrack_count(const struct net *net)
514514 {
515− const struct nf_conntrack_net *cnet;
516−
517− cnet = net_generic(net, nf_conntrack_net_id);
515+ const struct nf_conntrack_net *cnet = nf_ct_pernet(net);
518516
519517 return atomic_read(&cnet->count);
520518 }
@@ -575,11 +573,19 @@ enum nf_ct_sysctl_index { · 54 unmodified lines
575573 NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_CLOSE,
576574 NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_RETRANS,
577575 NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_UNACK,
576+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
577+ NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD,
578+ NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD_PICKUP,
579+#endif
578580 NF_SYSCTL_CT_PROTO_TCP_LOOSE,
579581 NF_SYSCTL_CT_PROTO_TCP_LIBERAL,
580582 NF_SYSCTL_CT_PROTO_TCP_MAX_RETRANS,
581583 NF_SYSCTL_CT_PROTO_TIMEOUT_UDP,
582584 NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_STREAM,
585+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
586+ NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD,
587+ NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD_PICKUP,
588+#endif
583589 NF_SYSCTL_CT_PROTO_TIMEOUT_ICMP,
584590 NF_SYSCTL_CT_PROTO_TIMEOUT_ICMPV6,
585591 #ifdef CONFIG_NF_CT_PROTO_SCTP
@@ -762,6 +768,20 @@ static struct ctl_table nf_ct_sysctl_table[] = { · 176 unmodified lines
762768 .mode = 0644,
763769 .proc_handler = proc_dointvec_jiffies,
764770 },
771+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
772+ [NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD] = {
773+ .procname = "nf_flowtable_tcp_timeout",
774+ .maxlen = sizeof(unsigned int),
775+ .mode = 0644,
776+ .proc_handler = proc_dointvec_jiffies,
777+ },
778+ [NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD_PICKUP] = {
779+ .procname = "nf_flowtable_tcp_pickup",
780+ .maxlen = sizeof(unsigned int),
781+ .mode = 0644,
782+ .proc_handler = proc_dointvec_jiffies,
783+ },
784+#endif
765785 [NF_SYSCTL_CT_PROTO_TCP_LOOSE] = {
766786 .procname = "nf_conntrack_tcp_loose",
767787 .maxlen = sizeof(u8),
@@ -796,6 +816,20 @@ static struct ctl_table nf_ct_sysctl_table[] = { · 28 unmodified lines
796816 .mode = 0644,
797817 .proc_handler = proc_dointvec_jiffies,
798818 },
819+#if IS_ENABLED(CONFIG_NFT_FLOW_OFFLOAD)
820+ [NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD] = {
821+ .procname = "nf_flowtable_udp_timeout",
822+ .maxlen = sizeof(unsigned int),
823+ .mode = 0644,
824+ .proc_handler = proc_dointvec_jiffies,
825+ },
826+ [NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD_PICKUP] = {
827+ .procname = "nf_flowtable_udp_pickup",
828+ .maxlen = sizeof(unsigned int),
829+ .mode = 0644,
830+ .proc_handler = proc_dointvec_jiffies,
831+ },
832+#endif
799833 [NF_SYSCTL_CT_PROTO_TIMEOUT_ICMP] = {
800834 .procname = "nf_conntrack_icmp_timeout",
801835 .maxlen = sizeof(unsigned int),
@@ -971,6 +1005,12 @@ static void nf_conntrack_standalone_init_tcp_sysctl(struct net *net, · 169 unmodified lines
9711005 XASSIGN(LIBERAL, &tn->tcp_be_liberal);
9721006 XASSIGN(MAX_RETRANS, &tn->tcp_max_retrans);
9731007 #undef XASSIGN
1008+
1009+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
1010+ table[NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD].data = &tn->offload_timeout;
1011+ table[NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD_PICKUP].data = &tn->offload_pickup;
1012+#endif
1013+
9741014 }
9751015
9761016 static void nf_conntrack_standalone_init_sctp_sysctl(struct net *net,
@@ -1032,7 +1072,7 @@ static void nf_conntrack_standalone_init_gre_sysctl(struct net *net, · 55 unmodified lines
10321072
10331073 static int nf_conntrack_standalone_init_sysctl(struct net *net)
10341074 {
1035− struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
1075+ struct nf_conntrack_net *cnet = nf_ct_pernet(net);
10361076 struct nf_udp_net *un = nf_udp_pernet(net);
10371077 struct ctl_table *table;
10381078
@@ -1059,6 +1099,10 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net) · 20 unmodified lines
10591099 table[NF_SYSCTL_CT_PROTO_TIMEOUT_ICMPV6].data = &nf_icmpv6_pernet(net)->timeout;
10601100 table[NF_SYSCTL_CT_PROTO_TIMEOUT_UDP].data = &un->timeouts[UDP_CT_UNREPLIED];
10611101 table[NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_STREAM].data = &un->timeouts[UDP_CT_REPLIED];
1102+#if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
1103+ table[NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD].data = &un->offload_timeout;
1104+ table[NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD_PICKUP].data = &un->offload_pickup;
1105+#endif
10621106
10631107 nf_conntrack_standalone_init_tcp_sysctl(net, table);
10641108 nf_conntrack_standalone_init_sctp_sysctl(net, table);
@@ -1085,7 +1129,7 @@ out_unregister_netfilter: · 20 unmodified lines
10851129
10861130 static void nf_conntrack_standalone_fini_sysctl(struct net *net)
10871131 {
1088− struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
1132+ struct nf_conntrack_net *cnet = nf_ct_pernet(net);
10891133 struct ctl_table *table;
10901134
10911135 table = cnet->sysctl_header->ctl_table_arg;
net/netfilter/nf_flow_table_core.c+37−10
@@ -178,12 +178,10 @@ static void flow_offload_fixup_tcp(struct ip_ct_tcp *tcp) · 177 unmodified lines
178178 tcp->seen[1].td_maxwin = 0;
179179 }
180180
181−#define NF_FLOWTABLE_TCP_PICKUP_TIMEOUT (120 * HZ)
182−#define NF_FLOWTABLE_UDP_PICKUP_TIMEOUT (30 * HZ)
183−
184181 static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
185182 {
186183 const struct nf_conntrack_l4proto *l4proto;
184+ struct net *net = nf_ct_net(ct);
187185 int l4num = nf_ct_protonum(ct);
188186 unsigned int timeout;
189187
@@ -191,12 +189,17 @@ static void flow_offload_fixup_ct_timeout(struct nf_conn *ct) · 1 unmodified line
191189 if (!l4proto)
192190 return;
193191
194− if (l4num == IPPROTO_TCP)
195− timeout = NF_FLOWTABLE_TCP_PICKUP_TIMEOUT;
196− else if (l4num == IPPROTO_UDP)
197− timeout = NF_FLOWTABLE_UDP_PICKUP_TIMEOUT;
198− else
192+ if (l4num == IPPROTO_TCP) {
193+ struct nf_tcp_net *tn = nf_tcp_pernet(net);
194+
195+ timeout = tn->offload_pickup;
196+ } else if (l4num == IPPROTO_UDP) {
197+ struct nf_udp_net *tn = nf_udp_pernet(net);
198+
199+ timeout = tn->offload_pickup;
200+ } else {
199201 return;
202+ }
200203
201204 if (nf_flow_timeout_delta(ct->timeout) > (__s32)timeout)
202205 ct->timeout = nfct_time_stamp + timeout;
@@ -268,11 +271,35 @@ static const struct rhashtable_params nf_flow_offload_rhash_params = { · 65 unmodified lines
268271 .automatic_shrinking = true,
269272 };
270273
274+unsigned long flow_offload_get_timeout(struct flow_offload *flow)
275+{
276+ const struct nf_conntrack_l4proto *l4proto;
277+ unsigned long timeout = NF_FLOW_TIMEOUT;
278+ struct net *net = nf_ct_net(flow->ct);
279+ int l4num = nf_ct_protonum(flow->ct);
280+
281+ l4proto = nf_ct_l4proto_find(l4num);
282+ if (!l4proto)
283+ return timeout;
284+
285+ if (l4num == IPPROTO_TCP) {
286+ struct nf_tcp_net *tn = nf_tcp_pernet(net);
287+
288+ timeout = tn->offload_timeout;
289+ } else if (l4num == IPPROTO_UDP) {
290+ struct nf_udp_net *tn = nf_udp_pernet(net);
291+
292+ timeout = tn->offload_timeout;
293+ }
294+
295+ return timeout;
296+}
297+
271298 int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
272299 {
273300 int err;
274301
275− flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT;
302+ flow->timeout = nf_flowtable_time_stamp + flow_offload_get_timeout(flow);
276303
277304 err = rhashtable_insert_fast(&flow_table->rhashtable,
278305 &flow->tuplehash[0].node,
@@ -304,7 +331,7 @@ EXPORT_SYMBOL_GPL(flow_offload_add); · 25 unmodified lines
304331 void flow_offload_refresh(struct nf_flowtable *flow_table,
305332 struct flow_offload *flow)
306333 {
307− flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT;
334+ flow->timeout = nf_flowtable_time_stamp + flow_offload_get_timeout(flow);
308335
309336 if (likely(!nf_flowtable_hw_offload(flow_table)))
310337 return;
net/netfilter/nf_flow_table_offload.c+2−2
@@ -937,7 +937,7 @@ static void flow_offload_work_stats(struct flow_offload_work *offload) · 936 unmodified lines
937937
938938 lastused = max_t(u64, stats[0].lastused, stats[1].lastused);
939939 offload->flow->timeout = max_t(u64, offload->flow->timeout,
940− lastused + NF_FLOW_TIMEOUT);
940+ lastused + flow_offload_get_timeout(offload->flow));
941941
942942 if (offload->flowtable->flags & NF_FLOWTABLE_COUNTER) {
943943 if (stats[0].pkts)
@@ -1041,7 +1041,7 @@ void nf_flow_offload_stats(struct nf_flowtable *flowtable, · 97 unmodified lines
10411041 __s32 delta;
10421042
10431043 delta = nf_flow_timeout_delta(flow->timeout);
1044− if ((delta >= (9 * NF_FLOW_TIMEOUT) / 10))
1044+ if ((delta >= (9 * flow_offload_get_timeout(flow)) / 10))
10451045 return;
10461046
10471047 offload = nf_flow_offload_work_alloc(flowtable, flow, FLOW_CLS_STATS);
net/netfilter/nf_tables_api.c+84−118
@@ -862,10 +862,9 @@ static int nft_netlink_dump_start_rcu(struct sock *nlsk, struct sk_buff *skb, · 861 unmodified lines
862862 static int nf_tables_gettable(struct sk_buff *skb, const struct nfnl_info *info,
863863 const struct nlattr * const nla[])
864864 {
865− const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
866865 struct netlink_ext_ack *extack = info->extack;
867866 u8 genmask = nft_genmask_cur(info->net);
868− int family = nfmsg->nfgen_family;
867+ u8 family = info->nfmsg->nfgen_family;
869868 const struct nft_table *table;
870869 struct net *net = info->net;
871870 struct sk_buff *skb2;
@@ -1068,10 +1067,9 @@ static int nf_tables_newtable(struct sk_buff *skb, const struct nfnl_info *info, · 196 unmodified lines
10681067 const struct nlattr * const nla[])
10691068 {
10701069 struct nftables_pernet *nft_net = nft_pernet(info->net);
1071− const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
10721070 struct netlink_ext_ack *extack = info->extack;
10731071 u8 genmask = nft_genmask_next(info->net);
1074− int family = nfmsg->nfgen_family;
1072+ u8 family = info->nfmsg->nfgen_family;
10751073 struct net *net = info->net;
10761074 const struct nlattr *attr;
10771075 struct nft_table *table;
@@ -1263,10 +1261,9 @@ out: · 185 unmodified lines
12631261 static int nf_tables_deltable(struct sk_buff *skb, const struct nfnl_info *info,
12641262 const struct nlattr * const nla[])
12651263 {
1266− const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
12671264 struct netlink_ext_ack *extack = info->extack;
12681265 u8 genmask = nft_genmask_next(info->net);
1269− int family = nfmsg->nfgen_family;
1266+ u8 family = info->nfmsg->nfgen_family;
12701267 struct net *net = info->net;
12711268 const struct nlattr *attr;
12721269 struct nft_table *table;
@@ -1636,10 +1633,9 @@ done: · 363 unmodified lines
16361633 static int nf_tables_getchain(struct sk_buff *skb, const struct nfnl_info *info,
16371634 const struct nlattr * const nla[])
16381635 {
1639− const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
16401636 struct netlink_ext_ack *extack = info->extack;
16411637 u8 genmask = nft_genmask_cur(info->net);
1642− int family = nfmsg->nfgen_family;
1638+ u8 family = info->nfmsg->nfgen_family;
16431639 const struct nft_chain *chain;
16441640 struct net *net = info->net;
16451641 struct nft_table *table;
@@ -2015,11 +2011,12 @@ static void nft_basechain_hook_init(struct nf_hook_ops *ops, u8 family, · 369 unmodified lines
20152011 const struct nft_chain_hook *hook,
20162012 struct nft_chain *chain)
20172013 {
2018− ops->pf = family;
2019− ops->hooknum = hook->num;
2020− ops->priority = hook->priority;
2021− ops->priv = chain;
2022− ops->hook = hook->type->hooks[ops->hooknum];
2014+ ops->pf = family;
2015+ ops->hooknum = hook->num;
2016+ ops->priority = hook->priority;
2017+ ops->priv = chain;
2018+ ops->hook = hook->type->hooks[ops->hooknum];
2019+ ops->hook_ops_type = NF_HOOK_OP_NF_TABLES;
20232020 }
20242021
20252022 static int nft_basechain_init(struct nft_base_chain *basechain, u8 family,
@@ -2371,10 +2368,9 @@ static int nf_tables_newchain(struct sk_buff *skb, const struct nfnl_info *info, · 345 unmodified lines
23712368 const struct nlattr * const nla[])
23722369 {
23732370 struct nftables_pernet *nft_net = nft_pernet(info->net);
2374− const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
23752371 struct netlink_ext_ack *extack = info->extack;
23762372 u8 genmask = nft_genmask_next(info->net);
2377− int family = nfmsg->nfgen_family;
2373+ u8 family = info->nfmsg->nfgen_family;
23782374 struct nft_chain *chain = NULL;
23792375 struct net *net = info->net;
23802376 const struct nlattr *attr;
@@ -2469,10 +2465,9 @@ static int nf_tables_newchain(struct sk_buff *skb, const struct nfnl_info *info, · 88 unmodified lines
24692465 static int nf_tables_delchain(struct sk_buff *skb, const struct nfnl_info *info,
24702466 const struct nlattr * const nla[])
24712467 {
2472− const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
24732468 struct netlink_ext_ack *extack = info->extack;
24742469 u8 genmask = nft_genmask_next(info->net);
2475− int family = nfmsg->nfgen_family;
2470+ u8 family = info->nfmsg->nfgen_family;
24762471 struct net *net = info->net;
24772472 const struct nlattr *attr;
24782473 struct nft_table *table;
@@ -3096,10 +3091,9 @@ static int nf_tables_dump_rules_done(struct netlink_callback *cb) · 617 unmodified lines
30963091 static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
30973092 const struct nlattr * const nla[])
30983093 {
3099− const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
31003094 struct netlink_ext_ack *extack = info->extack;
31013095 u8 genmask = nft_genmask_cur(info->net);
3102− int family = nfmsg->nfgen_family;
3096+ u8 family = info->nfmsg->nfgen_family;
31033097 const struct nft_chain *chain;
31043098 const struct nft_rule *rule;
31053099 struct net *net = info->net;
@@ -3237,13 +3231,12 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info, · 131 unmodified lines
32373231 const struct nlattr * const nla[])
32383232 {
32393233 struct nftables_pernet *nft_net = nft_pernet(info->net);
3240− const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
32413234 struct netlink_ext_ack *extack = info->extack;
32423235 unsigned int size, i, n, ulen = 0, usize = 0;
32433236 u8 genmask = nft_genmask_next(info->net);
32443237 struct nft_rule *rule, *old_rule = NULL;
32453238 struct nft_expr_info *expr_info = NULL;
3246− int family = nfmsg->nfgen_family;
3239+ u8 family = info->nfmsg->nfgen_family;
32473240 struct net *net = info->net;
32483241 struct nft_flow_rule *flow;
32493242 struct nft_userdata *udata;
@@ -3477,15 +3470,15 @@ static struct nft_rule *nft_rule_lookup_byid(const struct net *net, · 227 unmodified lines
34773470 static int nf_tables_delrule(struct sk_buff *skb, const struct nfnl_info *info,
34783471 const struct nlattr * const nla[])
34793472 {
3480− const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
34813473 struct netlink_ext_ack *extack = info->extack;
3482− int family = nfmsg->nfgen_family, err = 0;
34833474 u8 genmask = nft_genmask_next(info->net);
3475+ u8 family = info->nfmsg->nfgen_family;
34843476 struct nft_chain *chain = NULL;
34853477 struct net *net = info->net;
34863478 struct nft_table *table;
34873479 struct nft_rule *rule;
34883480 struct nft_ctx ctx;
3481+ int err = 0;
34893482
34903483 table = nft_table_lookup(net, nla[NFTA_RULE_TABLE], family, genmask,
34913484 NETLINK_CB(skb).portid);
@@ -3665,30 +3658,6 @@ static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = { · 173 unmodified lines
36653658 [NFTA_SET_DESC_CONCAT] = { .type = NLA_NESTED },
36663659 };
36673660
3668−static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, struct net *net,
3669− const struct sk_buff *skb,
3670− const struct nlmsghdr *nlh,
3671− const struct nlattr * const nla[],
3672− struct netlink_ext_ack *extack,
3673− u8 genmask, u32 nlpid)
3674−{
3675− const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
3676− int family = nfmsg->nfgen_family;
3677− struct nft_table *table = NULL;
3678−
3679− if (nla[NFTA_SET_TABLE] != NULL) {
3680− table = nft_table_lookup(net, nla[NFTA_SET_TABLE], family,
3681− genmask, nlpid);
3682− if (IS_ERR(table)) {
3683− NL_SET_BAD_ATTR(extack, nla[NFTA_SET_TABLE]);
3684− return PTR_ERR(table);
3685− }
3686− }
3687−
3688− nft_ctx_init(ctx, net, skb, nlh, family, table, NULL, nla);
3689− return 0;
3690−}
3691−
36923661 static struct nft_set *nft_set_lookup(const struct nft_table *table,
36933662 const struct nlattr *nla, u8 genmask)
36943663 {
@@ -4068,20 +4037,26 @@ static int nf_tables_dump_sets_done(struct netlink_callback *cb) · 373 unmodified lines
40684037 static int nf_tables_getset(struct sk_buff *skb, const struct nfnl_info *info,
40694038 const struct nlattr * const nla[])
40704039 {
4071− const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
40724040 struct netlink_ext_ack *extack = info->extack;
40734041 u8 genmask = nft_genmask_cur(info->net);
4042+ u8 family = info->nfmsg->nfgen_family;
4043+ struct nft_table *table = NULL;
40744044 struct net *net = info->net;
40754045 const struct nft_set *set;
40764046 struct sk_buff *skb2;
40774047 struct nft_ctx ctx;
40784048 int err;
40794049
4080− /* Verify existence before starting dump */
4081− err = nft_ctx_init_from_setattr(&ctx, net, skb, info->nlh, nla, extack,
4082− genmask, 0);
4083− if (err < 0)
4084− return err;
4050+ if (nla[NFTA_SET_TABLE]) {
4051+ table = nft_table_lookup(net, nla[NFTA_SET_TABLE], family,
4052+ genmask, 0);
4053+ if (IS_ERR(table)) {
4054+ NL_SET_BAD_ATTR(extack, nla[NFTA_SET_TABLE]);
4055+ return PTR_ERR(table);
4056+ }
4057+ }
4058+
4059+ nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
40854060
40864061 if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
40874062 struct netlink_dump_control c = {
@@ -4096,12 +4071,12 @@ static int nf_tables_getset(struct sk_buff *skb, const struct nfnl_info *info, · 8 unmodified lines
40964071 }
40974072
40984073 /* Only accept unspec with dump */
4099− if (nfmsg->nfgen_family == NFPROTO_UNSPEC)
4074+ if (info->nfmsg->nfgen_family == NFPROTO_UNSPEC)
41004075 return -EAFNOSUPPORT;
41014076 if (!nla[NFTA_SET_TABLE])
41024077 return -EINVAL;
41034078
4104− set = nft_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask);
4079+ set = nft_set_lookup(table, nla[NFTA_SET_NAME], genmask);
41054080 if (IS_ERR(set))
41064081 return PTR_ERR(set);
41074082
@@ -4189,11 +4164,10 @@ static int nf_tables_set_desc_parse(struct nft_set_desc *desc, · 81 unmodified lines
41894164 static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
41904165 const struct nlattr * const nla[])
41914166 {
4192− const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
41934167 u32 ktype, dtype, flags, policy, gc_int, objtype;
41944168 struct netlink_ext_ack *extack = info->extack;
41954169 u8 genmask = nft_genmask_next(info->net);
4196− int family = nfmsg->nfgen_family;
4170+ u8 family = info->nfmsg->nfgen_family;
41974171 const struct nft_set_ops *ops;
41984172 struct nft_expr *expr = NULL;
41994173 struct net *net = info->net;
@@ -4493,31 +4467,31 @@ static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set) · 293 unmodified lines
44934467 static int nf_tables_delset(struct sk_buff *skb, const struct nfnl_info *info,
44944468 const struct nlattr * const nla[])
44954469 {
4496− const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
44974470 struct netlink_ext_ack *extack = info->extack;
44984471 u8 genmask = nft_genmask_next(info->net);
4472+ u8 family = info->nfmsg->nfgen_family;
44994473 struct net *net = info->net;
45004474 const struct nlattr *attr;
4475+ struct nft_table *table;
45014476 struct nft_set *set;
45024477 struct nft_ctx ctx;
4503− int err;
45044478
4505− if (nfmsg->nfgen_family == NFPROTO_UNSPEC)
4479+ if (info->nfmsg->nfgen_family == NFPROTO_UNSPEC)
45064480 return -EAFNOSUPPORT;
4507− if (nla[NFTA_SET_TABLE] == NULL)
4508− return -EINVAL;
45094481
4510− err = nft_ctx_init_from_setattr(&ctx, net, skb, info->nlh, nla, extack,
4511− genmask, NETLINK_CB(skb).portid);
4512− if (err < 0)
4513− return err;
4482+ table = nft_table_lookup(net, nla[NFTA_SET_TABLE], family,
4483+ genmask, NETLINK_CB(skb).portid);
4484+ if (IS_ERR(table)) {
4485+ NL_SET_BAD_ATTR(extack, nla[NFTA_SET_TABLE]);
4486+ return PTR_ERR(table);
4487+ }
45144488
45154489 if (nla[NFTA_SET_HANDLE]) {
45164490 attr = nla[NFTA_SET_HANDLE];
4517− set = nft_set_lookup_byhandle(ctx.table, attr, genmask);
4491+ set = nft_set_lookup_byhandle(table, attr, genmask);
45184492 } else {
45194493 attr = nla[NFTA_SET_NAME];
4520− set = nft_set_lookup(ctx.table, attr, genmask);
4494+ set = nft_set_lookup(table, attr, genmask);
45214495 }
45224496
45234497 if (IS_ERR(set)) {
@@ -4531,6 +4505,8 @@ static int nf_tables_delset(struct sk_buff *skb, const struct nfnl_info *info, · 7 unmodified lines
45314505 return -EBUSY;
45324506 }
45334507
4508+ nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
4509+
45344510 return nft_delset(&ctx, set);
45354511 }
45364512
@@ -4732,28 +4708,6 @@ static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX + · 195 unmodified lines
47324708 [NFTA_SET_ELEM_LIST_SET_ID] = { .type = NLA_U32 },
47334709 };
47344710
4735−static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, struct net *net,
4736− const struct sk_buff *skb,
4737− const struct nlmsghdr *nlh,
4738− const struct nlattr * const nla[],
4739− struct netlink_ext_ack *extack,
4740− u8 genmask, u32 nlpid)
4741−{
4742− const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
4743− int family = nfmsg->nfgen_family;
4744− struct nft_table *table;
4745−
4746− table = nft_table_lookup(net, nla[NFTA_SET_ELEM_LIST_TABLE], family,
4747− genmask, nlpid);
4748− if (IS_ERR(table)) {
4749− NL_SET_BAD_ATTR(extack, nla[NFTA_SET_ELEM_LIST_TABLE]);
4750− return PTR_ERR(table);
4751− }
4752−
4753− nft_ctx_init(ctx, net, skb, nlh, family, table, NULL, nla);
4754− return 0;
4755−}
4756−
47574711 static int nft_set_elem_expr_dump(struct sk_buff *skb,
47584712 const struct nft_set *set,
47594713 const struct nft_set_ext *ext)
@@ -5211,21 +5165,27 @@ static int nf_tables_getsetelem(struct sk_buff *skb, · 451 unmodified lines
52115165 {
52125166 struct netlink_ext_ack *extack = info->extack;
52135167 u8 genmask = nft_genmask_cur(info->net);
5168+ u8 family = info->nfmsg->nfgen_family;
52145169 struct net *net = info->net;
5170+ struct nft_table *table;
52155171 struct nft_set *set;
52165172 struct nlattr *attr;
52175173 struct nft_ctx ctx;
52185174 int rem, err = 0;
52195175
5220− err = nft_ctx_init_from_elemattr(&ctx, net, skb, info->nlh, nla, extack,
5221− genmask, NETLINK_CB(skb).portid);
5222− if (err < 0)
5223− return err;
5176+ table = nft_table_lookup(net, nla[NFTA_SET_ELEM_LIST_TABLE], family,
5177+ genmask, NETLINK_CB(skb).portid);
5178+ if (IS_ERR(table)) {
5179+ NL_SET_BAD_ATTR(extack, nla[NFTA_SET_ELEM_LIST_TABLE]);
5180+ return PTR_ERR(table);
5181+ }
52245182
5225− set = nft_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET], genmask);
5183+ set = nft_set_lookup(table, nla[NFTA_SET_ELEM_LIST_SET], genmask);
52265184 if (IS_ERR(set))
52275185 return PTR_ERR(set);
52285186
5187+ nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
5188+
52295189 if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
52305190 struct netlink_dump_control c = {
52315191 .start = nf_tables_dump_set_start,
@@ -5994,8 +5954,10 @@ static int nf_tables_newsetelem(struct sk_buff *skb, · 762 unmodified lines
59945954 struct nftables_pernet *nft_net = nft_pernet(info->net);
59955955 struct netlink_ext_ack *extack = info->extack;
59965956 u8 genmask = nft_genmask_next(info->net);
5957+ u8 family = info->nfmsg->nfgen_family;
59975958 struct net *net = info->net;
59985959 const struct nlattr *attr;
5960+ struct nft_table *table;
59995961 struct nft_set *set;
60005962 struct nft_ctx ctx;
60015963 int rem, err;
@@ -6003,12 +5965,14 @@ static int nf_tables_newsetelem(struct sk_buff *skb, · 1 unmodified line
60035965 if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL)
60045966 return -EINVAL;
60055967
6006− err = nft_ctx_init_from_elemattr(&ctx, net, skb, info->nlh, nla, extack,
6007− genmask, NETLINK_CB(skb).portid);
6008− if (err < 0)
6009− return err;
5968+ table = nft_table_lookup(net, nla[NFTA_SET_ELEM_LIST_TABLE], family,
5969+ genmask, NETLINK_CB(skb).portid);
5970+ if (IS_ERR(table)) {
5971+ NL_SET_BAD_ATTR(extack, nla[NFTA_SET_ELEM_LIST_TABLE]);
5972+ return PTR_ERR(table);
5973+ }
60105974
6011− set = nft_set_lookup_global(net, ctx.table, nla[NFTA_SET_ELEM_LIST_SET],
5975+ set = nft_set_lookup_global(net, table, nla[NFTA_SET_ELEM_LIST_SET],
60125976 nla[NFTA_SET_ELEM_LIST_SET_ID], genmask);
60135977 if (IS_ERR(set))
60145978 return PTR_ERR(set);
@@ -6016,6 +5980,8 @@ static int nf_tables_newsetelem(struct sk_buff *skb, · 1 unmodified line
60165980 if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT)
60175981 return -EBUSY;
60185982
5983+ nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
5984+
60195985 nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
60205986 err = nft_add_set_elem(&ctx, set, attr, info->nlh->nlmsg_flags);
60215987 if (err < 0)
@@ -6023,7 +5989,7 @@ static int nf_tables_newsetelem(struct sk_buff *skb, · 1 unmodified line
60235989 }
60245990
60255991 if (nft_net->validate_state == NFT_VALIDATE_DO)
6026− return nft_table_validate(net, ctx.table);
5992+ return nft_table_validate(net, table);
60275993
60285994 return 0;
60295995 }
@@ -6261,23 +6227,29 @@ static int nf_tables_delsetelem(struct sk_buff *skb, · 231 unmodified lines
62616227 {
62626228 struct netlink_ext_ack *extack = info->extack;
62636229 u8 genmask = nft_genmask_next(info->net);
6230+ u8 family = info->nfmsg->nfgen_family;
62646231 struct net *net = info->net;
62656232 const struct nlattr *attr;
6233+ struct nft_table *table;
62666234 struct nft_set *set;
62676235 struct nft_ctx ctx;
62686236 int rem, err = 0;
62696237
6270− err = nft_ctx_init_from_elemattr(&ctx, net, skb, info->nlh, nla, extack,
6271− genmask, NETLINK_CB(skb).portid);
6272− if (err < 0)
6273− return err;
6238+ table = nft_table_lookup(net, nla[NFTA_SET_ELEM_LIST_TABLE], family,
6239+ genmask, NETLINK_CB(skb).portid);
6240+ if (IS_ERR(table)) {
6241+ NL_SET_BAD_ATTR(extack, nla[NFTA_SET_ELEM_LIST_TABLE]);
6242+ return PTR_ERR(table);
6243+ }
62746244
6275− set = nft_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET], genmask);
6245+ set = nft_set_lookup(table, nla[NFTA_SET_ELEM_LIST_SET], genmask);
62766246 if (IS_ERR(set))
62776247 return PTR_ERR(set);
62786248 if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT)
62796249 return -EBUSY;
62806250
6251+ nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
6252+
62816253 if (!nla[NFTA_SET_ELEM_LIST_ELEMENTS])
62826254 return nft_set_flush(&ctx, set, genmask);
62836255
@@ -6545,11 +6517,10 @@ err_free_trans: · 261 unmodified lines
65456517 static int nf_tables_newobj(struct sk_buff *skb, const struct nfnl_info *info,
65466518 const struct nlattr * const nla[])
65476519 {
6548− const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
65496520 struct netlink_ext_ack *extack = info->extack;
65506521 u8 genmask = nft_genmask_next(info->net);
6522+ u8 family = info->nfmsg->nfgen_family;
65516523 const struct nft_object_type *type;
6552− int family = nfmsg->nfgen_family;
65536524 struct net *net = info->net;
65546525 struct nft_table *table;
65556526 struct nft_object *obj;
@@ -6801,10 +6772,9 @@ static int nf_tables_dump_obj_done(struct netlink_callback *cb) · 245 unmodified lines
68016772 static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info,
68026773 const struct nlattr * const nla[])
68036774 {
6804− const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
68056775 struct netlink_ext_ack *extack = info->extack;
68066776 u8 genmask = nft_genmask_cur(info->net);
6807− int family = nfmsg->nfgen_family;
6777+ u8 family = info->nfmsg->nfgen_family;
68086778 const struct nft_table *table;
68096779 struct net *net = info->net;
68106780 struct nft_object *obj;
@@ -6891,10 +6861,9 @@ static void nft_obj_destroy(const struct nft_ctx *ctx, struct nft_object *obj) · 80 unmodified lines
68916861 static int nf_tables_delobj(struct sk_buff *skb, const struct nfnl_info *info,
68926862 const struct nlattr * const nla[])
68936863 {
6894− const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
68956864 struct netlink_ext_ack *extack = info->extack;
68966865 u8 genmask = nft_genmask_next(info->net);
6897− int family = nfmsg->nfgen_family;
6866+ u8 family = info->nfmsg->nfgen_family;
68986867 struct net *net = info->net;
68996868 const struct nlattr *attr;
69006869 struct nft_table *table;
@@ -7322,12 +7291,11 @@ static int nf_tables_newflowtable(struct sk_buff *skb, · 421 unmodified lines
73227291 const struct nfnl_info *info,
73237292 const struct nlattr * const nla[])
73247293 {
7325− const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
73267294 struct netlink_ext_ack *extack = info->extack;
73277295 struct nft_flowtable_hook flowtable_hook;
73287296 u8 genmask = nft_genmask_next(info->net);
7297+ u8 family = info->nfmsg->nfgen_family;
73297298 const struct nf_flowtable_type *type;
7330− int family = nfmsg->nfgen_family;
73317299 struct nft_flowtable *flowtable;
73327300 struct nft_hook *hook, *next;
73337301 struct net *net = info->net;
@@ -7511,10 +7479,9 @@ static int nf_tables_delflowtable(struct sk_buff *skb, · 177 unmodified lines
75117479 const struct nfnl_info *info,
75127480 const struct nlattr * const nla[])
75137481 {
7514− const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
75157482 struct netlink_ext_ack *extack = info->extack;
75167483 u8 genmask = nft_genmask_next(info->net);
7517− int family = nfmsg->nfgen_family;
7484+ u8 family = info->nfmsg->nfgen_family;
75187485 struct nft_flowtable *flowtable;
75197486 struct net *net = info->net;
75207487 const struct nlattr *attr;
@@ -7706,9 +7673,8 @@ static int nf_tables_getflowtable(struct sk_buff *skb, · 185 unmodified lines
77067673 const struct nfnl_info *info,
77077674 const struct nlattr * const nla[])
77087675 {
7709− const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
77107676 u8 genmask = nft_genmask_cur(info->net);
7711− int family = nfmsg->nfgen_family;
7677+ u8 family = info->nfmsg->nfgen_family;
77127678 struct nft_flowtable *flowtable;
77137679 const struct nft_table *table;
77147680 struct net *net = info->net;
net/netfilter/nfnetlink.c+3−0
@@ -68,6 +68,7 @@ static const char *const nfnl_lockdep_names[NFNL_SUBSYS_COUNT] = { · 67 unmodified lines
6868 [NFNL_SUBSYS_CTHELPER] = "nfnl_subsys_cthelper",
6969 [NFNL_SUBSYS_NFTABLES] = "nfnl_subsys_nftables",
7070 [NFNL_SUBSYS_NFT_COMPAT] = "nfnl_subsys_nftcompat",
71+ [NFNL_SUBSYS_HOOK] = "nfnl_subsys_hook",
7172 };
7273
7374 static const int nfnl_group2type[NFNLGRP_MAX+1] = {
@@ -256,6 +257,7 @@ replay: · 182 unmodified lines
256257 .net = net,
257258 .sk = nfnlnet->nfnl,
258259 .nlh = nlh,
260+ .nfmsg = nlmsg_data(nlh),
259261 .extack = extack,
260262 };
261263
@@ -491,6 +493,7 @@ replay_abort: · 229 unmodified lines
491493 .net = net,
492494 .sk = nfnlnet->nfnl,
493495 .nlh = nlh,
496+ .nfmsg = nlmsg_data(nlh),
494497 .extack = &extack,
495498 };
496499
net/netfilter/nfnetlink_hook.c+375−0
@@ -0,0 +1,375 @@
1+// SPDX-License-Identifier: GPL-2.0-or-later
2+/*
3+ * Copyright (c) 2021 Red Hat GmbH
4+ *
5+ * Author: Florian Westphal <fw@strlen.de>
6+ */
7+
8+#include <linux/module.h>
9+#include <linux/kernel.h>
10+#include <linux/types.h>
11+#include <linux/skbuff.h>
12+#include <linux/errno.h>
13+#include <linux/netlink.h>
14+#include <linux/slab.h>
15+
16+#include <linux/netfilter.h>
17+
18+#include <linux/netfilter/nfnetlink.h>
19+#include <linux/netfilter/nfnetlink_hook.h>
20+
21+#include <net/netfilter/nf_tables.h>
22+#include <net/sock.h>
23+
24+static const struct nla_policy nfnl_hook_nla_policy[NFNLA_HOOK_MAX + 1] = {
25+ [NFNLA_HOOK_HOOKNUM] = { .type = NLA_U32 },
26+ [NFNLA_HOOK_PRIORITY] = { .type = NLA_U32 },
27+ [NFNLA_HOOK_DEV] = { .type = NLA_STRING,
28+ .len = IFNAMSIZ - 1 },
29+ [NFNLA_HOOK_FUNCTION_NAME] = { .type = NLA_NUL_STRING,
30+ .len = KSYM_NAME_LEN, },
31+ [NFNLA_HOOK_MODULE_NAME] = { .type = NLA_NUL_STRING,
32+ .len = MODULE_NAME_LEN, },
33+ [NFNLA_HOOK_CHAIN_INFO] = { .type = NLA_NESTED, },
34+};
35+
36+static int nf_netlink_dump_start_rcu(struct sock *nlsk, struct sk_buff *skb,
37+ const struct nlmsghdr *nlh,
38+ struct netlink_dump_control *c)
39+{
40+ int err;
41+
42+ if (!try_module_get(THIS_MODULE))
43+ return -EINVAL;
44+
45+ rcu_read_unlock();
46+ err = netlink_dump_start(nlsk, skb, nlh, c);
47+ rcu_read_lock();
48+ module_put(THIS_MODULE);
49+
50+ return err;
51+}
52+
53+struct nfnl_dump_hook_data {
54+ char devname[IFNAMSIZ];
55+ unsigned long headv;
56+ u8 hook;
57+};
58+
59+static int nfnl_hook_put_nft_chain_info(struct sk_buff *nlskb,
60+ const struct nfnl_dump_hook_data *ctx,
61+ unsigned int seq,
62+ const struct nf_hook_ops *ops)
63+{
64+ struct net *net = sock_net(nlskb->sk);
65+ struct nlattr *nest, *nest2;
66+ struct nft_chain *chain;
67+ int ret = 0;
68+
69+ if (ops->hook_ops_type != NF_HOOK_OP_NF_TABLES)
70+ return 0;
71+
72+ chain = ops->priv;
73+ if (WARN_ON_ONCE(!chain))
74+ return 0;
75+
76+ if (!nft_is_active(net, chain))
77+ return 0;
78+
79+ nest = nla_nest_start(nlskb, NFNLA_HOOK_CHAIN_INFO);
80+ if (!nest)
81+ return -EMSGSIZE;
82+
83+ ret = nla_put_be32(nlskb, NFNLA_HOOK_INFO_TYPE,
84+ htonl(NFNL_HOOK_TYPE_NFTABLES));
85+ if (ret)
86+ goto cancel_nest;
87+
88+ nest2 = nla_nest_start(nlskb, NFNLA_HOOK_INFO_DESC);
89+ if (!nest2)
90+ goto cancel_nest;
91+
92+ ret = nla_put_string(nlskb, NFTA_CHAIN_TABLE, chain->table->name);
93+ if (ret)
94+ goto cancel_nest;
95+
96+ ret = nla_put_string(nlskb, NFTA_CHAIN_NAME, chain->name);
97+ if (ret)
98+ goto cancel_nest;
99+
100+ nla_nest_end(nlskb, nest2);
101+ nla_nest_end(nlskb, nest);
102+ return ret;
103+
104+cancel_nest:
105+ nla_nest_cancel(nlskb, nest);
106+ return -EMSGSIZE;
107+}
108+
109+static int nfnl_hook_dump_one(struct sk_buff *nlskb,
110+ const struct nfnl_dump_hook_data *ctx,
111+ const struct nf_hook_ops *ops,
112+ unsigned int seq)
113+{
114+ u16 event = nfnl_msg_type(NFNL_SUBSYS_HOOK, NFNL_MSG_HOOK_GET);
115+ unsigned int portid = NETLINK_CB(nlskb).portid;
116+ struct nlmsghdr *nlh;
117+ int ret = -EMSGSIZE;
118+#ifdef CONFIG_KALLSYMS
119+ char sym[KSYM_SYMBOL_LEN];
120+ char *module_name;
121+#endif
122+ nlh = nfnl_msg_put(nlskb, portid, seq, event,
123+ NLM_F_MULTI, ops->pf, NFNETLINK_V0, 0);
124+ if (!nlh)
125+ goto nla_put_failure;
126+
127+#ifdef CONFIG_KALLSYMS
128+ ret = snprintf(sym, sizeof(sym), "%ps", ops->hook);
129+ if (ret < 0 || ret > (int)sizeof(sym))
130+ goto nla_put_failure;
131+
132+ module_name = strstr(sym, " [");
133+ if (module_name) {
134+ char *end;
135+
136+ module_name += 2;
137+ end = strchr(module_name, ']');
138+ if (end) {
139+ *end = 0;
140+
141+ ret = nla_put_string(nlskb, NFNLA_HOOK_MODULE_NAME, module_name);
142+ if (ret)
143+ goto nla_put_failure;
144+ }
145+ }
146+
147+ ret = nla_put_string(nlskb, NFNLA_HOOK_FUNCTION_NAME, sym);
148+ if (ret)
149+ goto nla_put_failure;
150+#endif
151+
152+ ret = nla_put_be32(nlskb, NFNLA_HOOK_HOOKNUM, htonl(ops->hooknum));
153+ if (ret)
154+ goto nla_put_failure;
155+
156+ ret = nla_put_be32(nlskb, NFNLA_HOOK_PRIORITY, htonl(ops->priority));
157+ if (ret)
158+ goto nla_put_failure;
159+
160+ ret = nfnl_hook_put_nft_chain_info(nlskb, ctx, seq, ops);
161+ if (ret)
162+ goto nla_put_failure;
163+
164+ nlmsg_end(nlskb, nlh);
165+ return 0;
166+nla_put_failure:
167+ nlmsg_trim(nlskb, nlh);
168+ return ret;
169+}
170+
171+static const struct nf_hook_entries *
172+nfnl_hook_entries_head(u8 pf, unsigned int hook, struct net *net, const char *dev)
173+{
174+ const struct nf_hook_entries *hook_head = NULL;
175+ struct net_device *netdev;
176+
177+ switch (pf) {
178+ case NFPROTO_IPV4:
179+ if (hook >= ARRAY_SIZE(net->nf.hooks_ipv4))
180+ return ERR_PTR(-EINVAL);
181+ hook_head = rcu_dereference(net->nf.hooks_ipv4[hook]);
182+ break;
183+ case NFPROTO_IPV6:
184+ if (hook >= ARRAY_SIZE(net->nf.hooks_ipv6))
185+ return ERR_PTR(-EINVAL);
186+ hook_head = rcu_dereference(net->nf.hooks_ipv6[hook]);
187+ break;
188+ case NFPROTO_ARP:
189+#ifdef CONFIG_NETFILTER_FAMILY_ARP
190+ if (hook >= ARRAY_SIZE(net->nf.hooks_arp))
191+ return ERR_PTR(-EINVAL);
192+ hook_head = rcu_dereference(net->nf.hooks_arp[hook]);
193+#endif
194+ break;
195+ case NFPROTO_BRIDGE:
196+#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE
197+ if (hook >= ARRAY_SIZE(net->nf.hooks_bridge))
198+ return ERR_PTR(-EINVAL);
199+ hook_head = rcu_dereference(net->nf.hooks_bridge[hook]);
200+#endif
201+ break;
202+#if IS_ENABLED(CONFIG_DECNET)
203+ case NFPROTO_DECNET:
204+ if (hook >= ARRAY_SIZE(net->nf.hooks_decnet))
205+ return ERR_PTR(-EINVAL);
206+ hook_head = rcu_dereference(net->nf.hooks_decnet[hook]);
207+ break;
208+#endif
209+#ifdef CONFIG_NETFILTER_INGRESS
210+ case NFPROTO_NETDEV:
211+ if (hook != NF_NETDEV_INGRESS)
212+ return ERR_PTR(-EOPNOTSUPP);
213+
214+ if (!dev)
215+ return ERR_PTR(-ENODEV);
216+
217+ netdev = dev_get_by_name_rcu(net, dev);
218+ if (!netdev)
219+ return ERR_PTR(-ENODEV);
220+
221+ return rcu_dereference(netdev->nf_hooks_ingress);
222+#endif
223+ default:
224+ return ERR_PTR(-EPROTONOSUPPORT);
225+ }
226+
227+ return hook_head;
228+}
229+
230+static int nfnl_hook_dump(struct sk_buff *nlskb,
231+ struct netlink_callback *cb)
232+{
233+ struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
234+ struct nfnl_dump_hook_data *ctx = cb->data;
235+ int err, family = nfmsg->nfgen_family;
236+ struct net *net = sock_net(nlskb->sk);
237+ struct nf_hook_ops * const *ops;
238+ const struct nf_hook_entries *e;
239+ unsigned int i = cb->args[0];
240+
241+ rcu_read_lock();
242+
243+ e = nfnl_hook_entries_head(family, ctx->hook, net, ctx->devname);
244+ if (!e)
245+ goto done;
246+
247+ if (IS_ERR(e)) {
248+ cb->seq++;
249+ goto done;
250+ }
251+
252+ if ((unsigned long)e != ctx->headv || i >= e->num_hook_entries)
253+ cb->seq++;
254+
255+ ops = nf_hook_entries_get_hook_ops(e);
256+
257+ for (; i < e->num_hook_entries; i++) {
258+ err = nfnl_hook_dump_one(nlskb, ctx, ops[i], cb->seq);
259+ if (err)
260+ break;
261+ }
262+
263+done:
264+ nl_dump_check_consistent(cb, nlmsg_hdr(nlskb));
265+ rcu_read_unlock();
266+ cb->args[0] = i;
267+ return nlskb->len;
268+}
269+
270+static int nfnl_hook_dump_start(struct netlink_callback *cb)
271+{
272+ const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
273+ const struct nlattr * const *nla = cb->data;
274+ struct nfnl_dump_hook_data *ctx = NULL;
275+ struct net *net = sock_net(cb->skb->sk);
276+ u8 family = nfmsg->nfgen_family;
277+ char name[IFNAMSIZ] = "";
278+ const void *head;
279+ u32 hooknum;
280+
281+ hooknum = ntohl(nla_get_be32(nla[NFNLA_HOOK_HOOKNUM]));
282+ if (hooknum > 255)
283+ return -EINVAL;
284+
285+ if (family == NFPROTO_NETDEV) {
286+ if (!nla[NFNLA_HOOK_DEV])
287+ return -EINVAL;
288+
289+ nla_strscpy(name, nla[NFNLA_HOOK_DEV], sizeof(name));
290+ }
291+
292+ rcu_read_lock();
293+ /* Not dereferenced; for consistency check only */
294+ head = nfnl_hook_entries_head(family, hooknum, net, name);
295+ rcu_read_unlock();
296+
297+ if (head && IS_ERR(head))
298+ return PTR_ERR(head);
299+
300+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
301+ if (!ctx)
302+ return -ENOMEM;
303+
304+ strscpy(ctx->devname, name, sizeof(ctx->devname));
305+ ctx->headv = (unsigned long)head;
306+ ctx->hook = hooknum;
307+
308+ cb->seq = 1;
309+ cb->data = ctx;
310+
311+ return 0;
312+}
313+
314+static int nfnl_hook_dump_stop(struct netlink_callback *cb)
315+{
316+ kfree(cb->data);
317+ return 0;
318+}
319+
320+static int nfnl_hook_get(struct sk_buff *skb,
321+ const struct nfnl_info *info,
322+ const struct nlattr * const nla[])
323+{
324+ if (!nla[NFNLA_HOOK_HOOKNUM])
325+ return -EINVAL;
326+
327+ if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
328+ struct netlink_dump_control c = {
329+ .start = nfnl_hook_dump_start,
330+ .done = nfnl_hook_dump_stop,
331+ .dump = nfnl_hook_dump,
332+ .module = THIS_MODULE,
333+ .data = (void *)nla,
334+ };
335+
336+ return nf_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
337+ }
338+
339+ return -EOPNOTSUPP;
340+}
341+
342+static const struct nfnl_callback nfnl_hook_cb[NFNL_MSG_HOOK_MAX] = {
343+ [NFNL_MSG_HOOK_GET] = {
344+ .call = nfnl_hook_get,
345+ .type = NFNL_CB_RCU,
346+ .attr_count = NFNLA_HOOK_MAX,
347+ .policy = nfnl_hook_nla_policy
348+ },
349+};
350+
351+static const struct nfnetlink_subsystem nfhook_subsys = {
352+ .name = "nfhook",
353+ .subsys_id = NFNL_SUBSYS_HOOK,
354+ .cb_count = NFNL_MSG_HOOK_MAX,
355+ .cb = nfnl_hook_cb,
356+};
357+
358+MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_HOOK);
359+
360+static int __init nfnetlink_hook_init(void)
361+{
362+ return nfnetlink_subsys_register(&nfhook_subsys);
363+}
364+
365+static void __exit nfnetlink_hook_exit(void)
366+{
367+ nfnetlink_subsys_unregister(&nfhook_subsys);
368+}
369+
370+module_init(nfnetlink_hook_init);
371+module_exit(nfnetlink_hook_exit);
372+
373+MODULE_LICENSE("GPL");
374+MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");
375+MODULE_DESCRIPTION("nfnetlink_hook: list registered netfilter hooks");
net/netfilter/nfnetlink_log.c+2−3
@@ -871,15 +871,14 @@ static int nfulnl_recv_config(struct sk_buff *skb, const struct nfnl_info *info, · 870 unmodified lines
871871 const struct nlattr * const nfula[])
872872 {
873873 struct nfnl_log_net *log = nfnl_log_pernet(info->net);
874− struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
875− u_int16_t group_num = ntohs(nfmsg->res_id);
874+ u_int16_t group_num = ntohs(info->nfmsg->res_id);
876875 struct nfulnl_msg_config_cmd *cmd = NULL;
877876 struct nfulnl_instance *inst;
878877 u16 flags = 0;
879878 int ret = 0;
880879
881880 if (nfula[NFULA_CFG_CMD]) {
882− u_int8_t pf = nfmsg->nfgen_family;
881+ u_int8_t pf = info->nfmsg->nfgen_family;
883882 cmd = nla_data(nfula[NFULA_CFG_CMD]);
884883
885884 /* Commands without queue context */
net/netfilter/nfnetlink_queue.c+3−6
@@ -1051,8 +1051,7 @@ static int nfqnl_recv_verdict_batch(struct sk_buff *skb, · 1050 unmodified lines
10511051 const struct nlattr * const nfqa[])
10521052 {
10531053 struct nfnl_queue_net *q = nfnl_queue_pernet(info->net);
1054− struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
1055− u16 queue_num = ntohs(nfmsg->res_id);
1054+ u16 queue_num = ntohs(info->nfmsg->res_id);
10561055 struct nf_queue_entry *entry, *tmp;
10571056 struct nfqnl_msg_verdict_hdr *vhdr;
10581057 struct nfqnl_instance *queue;
@@ -1160,8 +1159,7 @@ static int nfqnl_recv_verdict(struct sk_buff *skb, const struct nfnl_info *info, · 101 unmodified lines
11601159 const struct nlattr * const nfqa[])
11611160 {
11621161 struct nfnl_queue_net *q = nfnl_queue_pernet(info->net);
1163− struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
1164− u_int16_t queue_num = ntohs(nfmsg->res_id);
1162+ u_int16_t queue_num = ntohs(info->nfmsg->res_id);
11651163 struct nfqnl_msg_verdict_hdr *vhdr;
11661164 enum ip_conntrack_info ctinfo;
11671165 struct nfqnl_instance *queue;
@@ -1243,8 +1241,7 @@ static int nfqnl_recv_config(struct sk_buff *skb, const struct nfnl_info *info, · 75 unmodified lines
12431241 const struct nlattr * const nfqa[])
12441242 {
12451243 struct nfnl_queue_net *q = nfnl_queue_pernet(info->net);
1246− struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
1247− u_int16_t queue_num = ntohs(nfmsg->res_id);
1244+ u_int16_t queue_num = ntohs(info->nfmsg->res_id);
12481245 struct nfqnl_msg_config_cmd *cmd = NULL;
12491246 struct nfqnl_instance *queue;
12501247 __u32 flags = 0, mask = 0;
net/netfilter/nft_compat.c+6−11
@@ -625,7 +625,7 @@ static int nfnl_compat_get_rcu(struct sk_buff *skb, · 624 unmodified lines
625625 const struct nfnl_info *info,
626626 const struct nlattr * const tb[])
627627 {
628− struct nfgenmsg *nfmsg;
628+ u8 family = info->nfmsg->nfgen_family;
629629 const char *name, *fmt;
630630 struct sk_buff *skb2;
631631 int ret = 0, target;
@@ -640,9 +640,7 @@ static int nfnl_compat_get_rcu(struct sk_buff *skb, · 8 unmodified lines
640640 rev = ntohl(nla_get_be32(tb[NFTA_COMPAT_REV]));
641641 target = ntohl(nla_get_be32(tb[NFTA_COMPAT_TYPE]));
642642
643− nfmsg = nlmsg_data(info->nlh);
644−
645− switch(nfmsg->nfgen_family) {
643+ switch(family) {
646644 case AF_INET:
647645 fmt = "ipt_%s";
648646 break;
@@ -656,8 +654,7 @@ static int nfnl_compat_get_rcu(struct sk_buff *skb, · 7 unmodified lines
656654 fmt = "arpt_%s";
657655 break;
658656 default:
659− pr_err("nft_compat: unsupported protocol %d\n",
660− nfmsg->nfgen_family);
657+ pr_err("nft_compat: unsupported protocol %d\n", family);
661658 return -EINVAL;
662659 }
663660
@@ -665,9 +662,8 @@ static int nfnl_compat_get_rcu(struct sk_buff *skb, · 1 unmodified line
665662 return -EINVAL;
666663
667664 rcu_read_unlock();
668− try_then_request_module(xt_find_revision(nfmsg->nfgen_family, name,
669− rev, target, &ret),
670− fmt, name);
665+ try_then_request_module(xt_find_revision(family, name, rev, target, &ret),
666+ fmt, name);
671667 if (ret < 0)
672668 goto out_put;
673669
@@ -682,8 +678,7 @@ static int nfnl_compat_get_rcu(struct sk_buff *skb, · 8 unmodified lines
682678 info->nlh->nlmsg_seq,
683679 NFNL_MSG_TYPE(info->nlh->nlmsg_type),
684680 NFNL_MSG_COMPAT_GET,
685− nfmsg->nfgen_family,
686− name, ret, target) <= 0) {
681+ family, name, ret, target) <= 0) {
687682 kfree_skb(skb2);
688683 goto out_put;
689684 }
net/netfilter/nft_exthdr.c+3−1
@@ -327,7 +327,9 @@ static void nft_exthdr_sctp_eval(const struct nft_expr *expr, · 326 unmodified lines
327327 break;
328328
329329 dest[priv->len / NFT_REG32_SIZE] = 0;
330− memcpy(dest, (char *)sch + priv->offset, priv->len);
330+ if (skb_copy_bits(pkt->skb, offset + priv->offset,
331+ dest, priv->len) < 0)
332+ break;
331333 return;
332334 }
333335 offset += SCTP_PAD4(ntohs(sch->length));

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t