netfilter: move the sysctl nf_hooks_lwtunnel into the netfilter core
authorJianguo Wu <wujianguo@chinatelecom.cn>
Thu, 13 Jun 2024 09:42:47 +0000 (17:42 +0800)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 19 Jun 2024 16:41:59 +0000 (18:41 +0200)
Currently, the sysctl net.netfilter.nf_hooks_lwtunnel depends on the
nf_conntrack module, but the nf_conntrack module is not always loaded.
Therefore, accessing net.netfilter.nf_hooks_lwtunnel may have an error.

Move sysctl nf_hooks_lwtunnel into the netfilter core.

Fixes: 7a3f5b0de364 ("netfilter: add netfilter hooks to SRv6 data plane")
Suggested-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Jianguo Wu <wujianguo@chinatelecom.cn>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/net/netns/netfilter.h
net/netfilter/core.c
net/netfilter/nf_conntrack_standalone.c
net/netfilter/nf_hooks_lwtunnel.c
net/netfilter/nf_internals.h

index 02bbdc577f8e2881c50e7eaccf9f1c4223d9da50..a6a0bf4a247e51e95189d98f5438a12cfe3cfb74 100644 (file)
@@ -15,6 +15,9 @@ struct netns_nf {
        const struct nf_logger __rcu *nf_loggers[NFPROTO_NUMPROTO];
 #ifdef CONFIG_SYSCTL
        struct ctl_table_header *nf_log_dir_header;
+#ifdef CONFIG_LWTUNNEL
+       struct ctl_table_header *nf_lwtnl_dir_header;
+#endif
 #endif
        struct nf_hook_entries __rcu *hooks_ipv4[NF_INET_NUMHOOKS];
        struct nf_hook_entries __rcu *hooks_ipv6[NF_INET_NUMHOOKS];
index 3126911f5042592a33594053c1225c265a2fd2c1..b00fc285b3349914eb3b2ea9bc921397568aafb6 100644 (file)
@@ -815,12 +815,21 @@ int __init netfilter_init(void)
        if (ret < 0)
                goto err;
 
+#ifdef CONFIG_LWTUNNEL
+       ret = netfilter_lwtunnel_init();
+       if (ret < 0)
+               goto err_lwtunnel_pernet;
+#endif
        ret = netfilter_log_init();
        if (ret < 0)
-               goto err_pernet;
+               goto err_log_pernet;
 
        return 0;
-err_pernet:
+err_log_pernet:
+#ifdef CONFIG_LWTUNNEL
+       netfilter_lwtunnel_fini();
+err_lwtunnel_pernet:
+#endif
        unregister_pernet_subsys(&netfilter_net_ops);
 err:
        return ret;
index 74112e9c5dabc3f045392edd789b9f4decef5d61..6c40bdf8b05ab5bfbcf0e56cb6ba5bedb3f95ad9 100644 (file)
@@ -22,9 +22,6 @@
 #include <net/netfilter/nf_conntrack_acct.h>
 #include <net/netfilter/nf_conntrack_zones.h>
 #include <net/netfilter/nf_conntrack_timestamp.h>
-#ifdef CONFIG_LWTUNNEL
-#include <net/netfilter/nf_hooks_lwtunnel.h>
-#endif
 #include <linux/rculist_nulls.h>
 
 static bool enable_hooks __read_mostly;
@@ -612,9 +609,6 @@ enum nf_ct_sysctl_index {
        NF_SYSCTL_CT_PROTO_TIMEOUT_GRE,
        NF_SYSCTL_CT_PROTO_TIMEOUT_GRE_STREAM,
 #endif
-#ifdef CONFIG_LWTUNNEL
-       NF_SYSCTL_CT_LWTUNNEL,
-#endif
 
        NF_SYSCTL_CT_LAST_SYSCTL,
 };
@@ -946,15 +940,6 @@ static struct ctl_table nf_ct_sysctl_table[] = {
                .proc_handler   = proc_dointvec_jiffies,
        },
 #endif
-#ifdef CONFIG_LWTUNNEL
-       [NF_SYSCTL_CT_LWTUNNEL] = {
-               .procname       = "nf_hooks_lwtunnel",
-               .data           = NULL,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = nf_hooks_lwtunnel_sysctl_handler,
-       },
-#endif
 };
 
 static struct ctl_table nf_ct_netfilter_table[] = {
index 00e89ffd78f69216388d40c937928d187b776db6..7cdb59bb4459f377ca1f1443657baeb16648ecc0 100644 (file)
@@ -3,6 +3,9 @@
 #include <linux/sysctl.h>
 #include <net/lwtunnel.h>
 #include <net/netfilter/nf_hooks_lwtunnel.h>
+#include <linux/netfilter.h>
+
+#include "nf_internals.h"
 
 static inline int nf_hooks_lwtunnel_get(void)
 {
@@ -50,4 +53,68 @@ int nf_hooks_lwtunnel_sysctl_handler(struct ctl_table *table, int write,
        return ret;
 }
 EXPORT_SYMBOL_GPL(nf_hooks_lwtunnel_sysctl_handler);
+
+static struct ctl_table nf_lwtunnel_sysctl_table[] = {
+       {
+               .procname       = "nf_hooks_lwtunnel",
+               .data           = NULL,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = nf_hooks_lwtunnel_sysctl_handler,
+       },
+};
+
+static int __net_init nf_lwtunnel_net_init(struct net *net)
+{
+       struct ctl_table_header *hdr;
+       struct ctl_table *table;
+
+       table = nf_lwtunnel_sysctl_table;
+       if (!net_eq(net, &init_net)) {
+               table = kmemdup(nf_lwtunnel_sysctl_table,
+                               sizeof(nf_lwtunnel_sysctl_table),
+                               GFP_KERNEL);
+               if (!table)
+                       goto err_alloc;
+       }
+
+       hdr = register_net_sysctl_sz(net, "net/netfilter", table,
+                                    ARRAY_SIZE(nf_lwtunnel_sysctl_table));
+       if (!hdr)
+               goto err_reg;
+
+       net->nf.nf_lwtnl_dir_header = hdr;
+
+       return 0;
+err_reg:
+       if (!net_eq(net, &init_net))
+               kfree(table);
+err_alloc:
+       return -ENOMEM;
+}
+
+static void __net_exit nf_lwtunnel_net_exit(struct net *net)
+{
+       const struct ctl_table *table;
+
+       table = net->nf.nf_lwtnl_dir_header->ctl_table_arg;
+       unregister_net_sysctl_table(net->nf.nf_lwtnl_dir_header);
+       if (!net_eq(net, &init_net))
+               kfree(table);
+}
+
+static struct pernet_operations nf_lwtunnel_net_ops = {
+       .init = nf_lwtunnel_net_init,
+       .exit = nf_lwtunnel_net_exit,
+};
+
+int __init netfilter_lwtunnel_init(void)
+{
+       return register_pernet_subsys(&nf_lwtunnel_net_ops);
+}
+
+void netfilter_lwtunnel_fini(void)
+{
+       unregister_pernet_subsys(&nf_lwtunnel_net_ops);
+}
 #endif /* CONFIG_SYSCTL */
index 832ae64179f0f2e2e5c51812551dfc4029f8cc0b..25403023060b6d6763c16f860aff60884b78a863 100644 (file)
@@ -29,6 +29,12 @@ void nf_queue_nf_hook_drop(struct net *net);
 /* nf_log.c */
 int __init netfilter_log_init(void);
 
+#ifdef CONFIG_LWTUNNEL
+/* nf_hooks_lwtunnel.c */
+int __init netfilter_lwtunnel_init(void);
+void netfilter_lwtunnel_fini(void);
+#endif
+
 /* core.c */
 void nf_hook_entries_delete_raw(struct nf_hook_entries __rcu **pp,
                                const struct nf_hook_ops *reg);