Commit 0f74d0cd authored by Paolo Abeni's avatar Paolo Abeni

Merge tag 'nf-24-06-19' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf

Pablo Neira Ayuso says:

====================
Netfilter fixes for net

The following patchset contains Netfilter fixes for net:

Patch #1 fixes the suspicious RCU usage warning that resulted from the
	 recent fix for the race between namespace cleanup and gc in
	 ipset left out checking the pernet exit phase when calling
	 rcu_dereference_protected(), from Jozsef Kadlecsik.

Patch #2 fixes incorrect input and output netdevice in SRv6 prerouting
	 hooks, from Jianguo Wu.

Patch #3 moves nf_hooks_lwtunnel sysctl toggle to the netfilter core.
	 The connection tracking system is loaded on-demand, this
	 ensures availability of this knob regardless.

Patch #4-#5 adds selftests for SRv6 netfilter hooks also from Jianguo Wu.

netfilter pull request 24-06-19

* tag 'nf-24-06-19' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf:
  selftests: add selftest for the SRv6 End.DX6 behavior with netfilter
  selftests: add selftest for the SRv6 End.DX4 behavior with netfilter
  netfilter: move the sysctl nf_hooks_lwtunnel into the netfilter core
  seg6: fix parameter passing when calling NF_HOOK() in End.DX4 and End.DX6 behaviors
  netfilter: ipset: Fix suspicious rcu_dereference_protected()
====================

Link: https://lore.kernel.org/r/20240619170537.2846-1-pablo@netfilter.orgSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 6cd4a78d 221200ff
...@@ -15,6 +15,9 @@ struct netns_nf { ...@@ -15,6 +15,9 @@ struct netns_nf {
const struct nf_logger __rcu *nf_loggers[NFPROTO_NUMPROTO]; const struct nf_logger __rcu *nf_loggers[NFPROTO_NUMPROTO];
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
struct ctl_table_header *nf_log_dir_header; struct ctl_table_header *nf_log_dir_header;
#ifdef CONFIG_LWTUNNEL
struct ctl_table_header *nf_lwtnl_dir_header;
#endif
#endif #endif
struct nf_hook_entries __rcu *hooks_ipv4[NF_INET_NUMHOOKS]; struct nf_hook_entries __rcu *hooks_ipv4[NF_INET_NUMHOOKS];
struct nf_hook_entries __rcu *hooks_ipv6[NF_INET_NUMHOOKS]; struct nf_hook_entries __rcu *hooks_ipv6[NF_INET_NUMHOOKS];
......
...@@ -941,8 +941,8 @@ static int input_action_end_dx6(struct sk_buff *skb, ...@@ -941,8 +941,8 @@ static int input_action_end_dx6(struct sk_buff *skb,
if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled)) if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled))
return NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, return NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING,
dev_net(skb->dev), NULL, skb, NULL, dev_net(skb->dev), NULL, skb, skb->dev,
skb_dst(skb)->dev, input_action_end_dx6_finish); NULL, input_action_end_dx6_finish);
return input_action_end_dx6_finish(dev_net(skb->dev), NULL, skb); return input_action_end_dx6_finish(dev_net(skb->dev), NULL, skb);
drop: drop:
...@@ -991,8 +991,8 @@ static int input_action_end_dx4(struct sk_buff *skb, ...@@ -991,8 +991,8 @@ static int input_action_end_dx4(struct sk_buff *skb,
if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled)) if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled))
return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING,
dev_net(skb->dev), NULL, skb, NULL, dev_net(skb->dev), NULL, skb, skb->dev,
skb_dst(skb)->dev, input_action_end_dx4_finish); NULL, input_action_end_dx4_finish);
return input_action_end_dx4_finish(dev_net(skb->dev), NULL, skb); return input_action_end_dx4_finish(dev_net(skb->dev), NULL, skb);
drop: drop:
......
...@@ -815,12 +815,21 @@ int __init netfilter_init(void) ...@@ -815,12 +815,21 @@ int __init netfilter_init(void)
if (ret < 0) if (ret < 0)
goto err; goto err;
#ifdef CONFIG_LWTUNNEL
ret = netfilter_lwtunnel_init();
if (ret < 0)
goto err_lwtunnel_pernet;
#endif
ret = netfilter_log_init(); ret = netfilter_log_init();
if (ret < 0) if (ret < 0)
goto err_pernet; goto err_log_pernet;
return 0; return 0;
err_pernet: err_log_pernet:
#ifdef CONFIG_LWTUNNEL
netfilter_lwtunnel_fini();
err_lwtunnel_pernet:
#endif
unregister_pernet_subsys(&netfilter_net_ops); unregister_pernet_subsys(&netfilter_net_ops);
err: err:
return ret; return ret;
......
...@@ -53,12 +53,13 @@ MODULE_DESCRIPTION("core IP set support"); ...@@ -53,12 +53,13 @@ MODULE_DESCRIPTION("core IP set support");
MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET); MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET);
/* When the nfnl mutex or ip_set_ref_lock is held: */ /* When the nfnl mutex or ip_set_ref_lock is held: */
#define ip_set_dereference(p) \ #define ip_set_dereference(inst) \
rcu_dereference_protected(p, \ rcu_dereference_protected((inst)->ip_set_list, \
lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET) || \ lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET) || \
lockdep_is_held(&ip_set_ref_lock)) lockdep_is_held(&ip_set_ref_lock) || \
(inst)->is_deleted)
#define ip_set(inst, id) \ #define ip_set(inst, id) \
ip_set_dereference((inst)->ip_set_list)[id] ip_set_dereference(inst)[id]
#define ip_set_ref_netlink(inst,id) \ #define ip_set_ref_netlink(inst,id) \
rcu_dereference_raw((inst)->ip_set_list)[id] rcu_dereference_raw((inst)->ip_set_list)[id]
#define ip_set_dereference_nfnl(p) \ #define ip_set_dereference_nfnl(p) \
...@@ -1133,7 +1134,7 @@ static int ip_set_create(struct sk_buff *skb, const struct nfnl_info *info, ...@@ -1133,7 +1134,7 @@ static int ip_set_create(struct sk_buff *skb, const struct nfnl_info *info,
if (!list) if (!list)
goto cleanup; goto cleanup;
/* nfnl mutex is held, both lists are valid */ /* nfnl mutex is held, both lists are valid */
tmp = ip_set_dereference(inst->ip_set_list); tmp = ip_set_dereference(inst);
memcpy(list, tmp, sizeof(struct ip_set *) * inst->ip_set_max); memcpy(list, tmp, sizeof(struct ip_set *) * inst->ip_set_max);
rcu_assign_pointer(inst->ip_set_list, list); rcu_assign_pointer(inst->ip_set_list, list);
/* Make sure all current packets have passed through */ /* Make sure all current packets have passed through */
......
...@@ -22,9 +22,6 @@ ...@@ -22,9 +22,6 @@
#include <net/netfilter/nf_conntrack_acct.h> #include <net/netfilter/nf_conntrack_acct.h>
#include <net/netfilter/nf_conntrack_zones.h> #include <net/netfilter/nf_conntrack_zones.h>
#include <net/netfilter/nf_conntrack_timestamp.h> #include <net/netfilter/nf_conntrack_timestamp.h>
#ifdef CONFIG_LWTUNNEL
#include <net/netfilter/nf_hooks_lwtunnel.h>
#endif
#include <linux/rculist_nulls.h> #include <linux/rculist_nulls.h>
static bool enable_hooks __read_mostly; static bool enable_hooks __read_mostly;
...@@ -612,9 +609,6 @@ enum nf_ct_sysctl_index { ...@@ -612,9 +609,6 @@ enum nf_ct_sysctl_index {
NF_SYSCTL_CT_PROTO_TIMEOUT_GRE, NF_SYSCTL_CT_PROTO_TIMEOUT_GRE,
NF_SYSCTL_CT_PROTO_TIMEOUT_GRE_STREAM, NF_SYSCTL_CT_PROTO_TIMEOUT_GRE_STREAM,
#endif #endif
#ifdef CONFIG_LWTUNNEL
NF_SYSCTL_CT_LWTUNNEL,
#endif
NF_SYSCTL_CT_LAST_SYSCTL, NF_SYSCTL_CT_LAST_SYSCTL,
}; };
...@@ -946,15 +940,6 @@ static struct ctl_table nf_ct_sysctl_table[] = { ...@@ -946,15 +940,6 @@ static struct ctl_table nf_ct_sysctl_table[] = {
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
}, },
#endif #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[] = { static struct ctl_table nf_ct_netfilter_table[] = {
......
...@@ -3,6 +3,9 @@ ...@@ -3,6 +3,9 @@
#include <linux/sysctl.h> #include <linux/sysctl.h>
#include <net/lwtunnel.h> #include <net/lwtunnel.h>
#include <net/netfilter/nf_hooks_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) static inline int nf_hooks_lwtunnel_get(void)
{ {
...@@ -50,4 +53,68 @@ int nf_hooks_lwtunnel_sysctl_handler(struct ctl_table *table, int write, ...@@ -50,4 +53,68 @@ int nf_hooks_lwtunnel_sysctl_handler(struct ctl_table *table, int write,
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(nf_hooks_lwtunnel_sysctl_handler); 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 */ #endif /* CONFIG_SYSCTL */
...@@ -29,6 +29,12 @@ void nf_queue_nf_hook_drop(struct net *net); ...@@ -29,6 +29,12 @@ void nf_queue_nf_hook_drop(struct net *net);
/* nf_log.c */ /* nf_log.c */
int __init netfilter_log_init(void); 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 */ /* core.c */
void nf_hook_entries_delete_raw(struct nf_hook_entries __rcu **pp, void nf_hook_entries_delete_raw(struct nf_hook_entries __rcu **pp,
const struct nf_hook_ops *reg); const struct nf_hook_ops *reg);
......
...@@ -43,6 +43,8 @@ TEST_PROGS += srv6_hl2encap_red_l2vpn_test.sh ...@@ -43,6 +43,8 @@ TEST_PROGS += srv6_hl2encap_red_l2vpn_test.sh
TEST_PROGS += srv6_end_next_csid_l3vpn_test.sh TEST_PROGS += srv6_end_next_csid_l3vpn_test.sh
TEST_PROGS += srv6_end_x_next_csid_l3vpn_test.sh TEST_PROGS += srv6_end_x_next_csid_l3vpn_test.sh
TEST_PROGS += srv6_end_flavors_test.sh TEST_PROGS += srv6_end_flavors_test.sh
TEST_PROGS += srv6_end_dx4_netfilter_test.sh
TEST_PROGS += srv6_end_dx6_netfilter_test.sh
TEST_PROGS += vrf_strict_mode_test.sh TEST_PROGS += vrf_strict_mode_test.sh
TEST_PROGS += arp_ndisc_evict_nocarrier.sh TEST_PROGS += arp_ndisc_evict_nocarrier.sh
TEST_PROGS += ndisc_unsolicited_na_test.sh TEST_PROGS += ndisc_unsolicited_na_test.sh
......
...@@ -101,3 +101,5 @@ CONFIG_NETFILTER_XT_MATCH_POLICY=m ...@@ -101,3 +101,5 @@ CONFIG_NETFILTER_XT_MATCH_POLICY=m
CONFIG_CRYPTO_ARIA=y CONFIG_CRYPTO_ARIA=y
CONFIG_XFRM_INTERFACE=m CONFIG_XFRM_INTERFACE=m
CONFIG_XFRM_USER=m CONFIG_XFRM_USER=m
CONFIG_IP_NF_MATCH_RPFILTER=m
CONFIG_IP6_NF_MATCH_RPFILTER=m
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment