[PATCH RFC v3 78/90] netfilter: use net_may() for configuration
From: Josef Bacik
Date: Thu Nov 05 2026 - 10:56:06 EST
Userspace configures netfilter in two ways. One is nfnetlink, which has a
single CAP_NET_ADMIN check in nfnetlink_rcv() for all of its subsystems.
The other is the set of socket options of ip_tables, ip6_tables,
arp_tables, ebtables and ipset. Convert all of these checks to
NET_RIGHT_FILTER.
Two nfnetlink subsystems keep state that is global rather than per network
namespace: the fingerprints of nfnetlink_osf and the helpers of
nfnetlink_cthelper. Both also call capable(CAP_NET_ADMIN), which requires
the capability in the initial user namespace. Those calls are not changed.
IPVS is not converted.
No functional change.
Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
---
net/bridge/netfilter/ebtables.c | 4 ++--
net/ipv4/netfilter/arp_tables.c | 4 ++--
net/ipv4/netfilter/ip_tables.c | 4 ++--
net/ipv6/netfilter/ip6_tables.c | 4 ++--
net/netfilter/ipset/ip_set_core.c | 2 +-
net/netfilter/nfnetlink.c | 2 +-
6 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 0bf541936f60..10a9d206a613 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -2491,7 +2491,7 @@ static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
struct ebt_table *t;
int ret;
- if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
+ if (!net_may(net, NET_RIGHT_FILTER))
return -EPERM;
if (!xt_compat_check())
return -EPERM;
@@ -2558,7 +2558,7 @@ static int do_ebt_set_ctl(struct sock *sk, int cmd, sockptr_t arg,
struct net *net = sock_net(sk);
int ret;
- if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
+ if (!net_may(net, NET_RIGHT_FILTER))
return -EPERM;
if (!xt_compat_check())
return -EPERM;
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index cf747e1e17a3..22fe0706b003 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -974,7 +974,7 @@ static int do_arpt_set_ctl(struct sock *sk, int cmd, sockptr_t arg,
{
int ret;
- if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
+ if (!net_may(sock_net(sk), NET_RIGHT_FILTER))
return -EPERM;
if (!xt_compat_check())
return -EPERM;
@@ -999,7 +999,7 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
{
int ret;
- if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
+ if (!net_may(sock_net(sk), NET_RIGHT_FILTER))
return -EPERM;
if (!xt_compat_check())
return -EPERM;
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 809441cedced..40a5e3cb7abd 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -1619,7 +1619,7 @@ do_ipt_set_ctl(struct sock *sk, int cmd, sockptr_t arg, unsigned int len)
{
int ret;
- if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
+ if (!net_may(sock_net(sk), NET_RIGHT_FILTER))
return -EPERM;
if (!xt_compat_check())
return -EPERM;
@@ -1650,7 +1650,7 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
{
int ret;
- if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
+ if (!net_may(sock_net(sk), NET_RIGHT_FILTER))
return -EPERM;
if (!xt_compat_check())
return -EPERM;
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 313c4aac377a..5339e35eb1a5 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1633,7 +1633,7 @@ do_ip6t_set_ctl(struct sock *sk, int cmd, sockptr_t arg, unsigned int len)
{
int ret;
- if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
+ if (!net_may(sock_net(sk), NET_RIGHT_FILTER))
return -EPERM;
if (!xt_compat_check())
return -EPERM;
@@ -1664,7 +1664,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
{
int ret;
- if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
+ if (!net_may(sock_net(sk), NET_RIGHT_FILTER))
return -EPERM;
if (!xt_compat_check())
return -EPERM;
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index 4aeb767088cf..dfe2c8ef1054 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -2267,7 +2267,7 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
struct net *net = sock_net(sk);
struct ip_set_net *inst = ip_set_pernet(net);
- if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
+ if (!net_may(net, NET_RIGHT_FILTER))
return -EPERM;
if (optval != SO_IP_SET)
return -EBADF;
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index 47f3ed441f64..524941691e29 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -656,7 +656,7 @@ static void nfnetlink_rcv(struct sk_buff *skb)
skb->len < nlh->nlmsg_len)
return;
- if (!netlink_net_capable(skb, CAP_NET_ADMIN)) {
+ if (!netlink_net_may(skb, sock_net(skb->sk), NET_RIGHT_FILTER)) {
netlink_ack(skb, nlh, -EPERM, NULL);
return;
}
--
2.55.0