[PATCH 08/10] net: use new capable_any functionality
From: Christian Göttsche <hidden>
Date: 2024-03-15 11:39:09
Also in:
bpf, linux-security-module, lkml
Subsystem:
ieee 802.15.4 subsystem, networking [general], networking [ipv4/ipv6], networking [sockets], networking [unix sockets], the rest · Maintainers:
Alexander Aring, Stefan Schmidt, Miquel Raynal, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, David Ahern, Ido Schimmel, Kuniyuki Iwashima, Willem de Bruijn, Linus Torvalds
Use the new added capable_any function in appropriate cases, where a task is required to have any of two capabilities. Add sock_ns_capable_any() wrapper similar to existing sock_ns_capable() one. Reorder CAP_SYS_ADMIN last. Signed-off-by: Christian Göttsche <redacted> Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com> (ieee802154 portion) --- v4: - introduce sockopt_ns_capable_any() v3: - rename to capable_any() - make use of ns_capable_any --- include/net/sock.h | 1 + net/caif/caif_socket.c | 2 +- net/core/sock.c | 15 +++++++++------ net/ieee802154/socket.c | 6 ++---- net/ipv4/ip_sockglue.c | 5 +++-- net/ipv6/ipv6_sockglue.c | 3 +-- net/unix/af_unix.c | 2 +- 7 files changed, 18 insertions(+), 16 deletions(-)
diff --git a/include/net/sock.h b/include/net/sock.h
index b5e00702acc1..2e64a80c8fca 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h@@ -1736,6 +1736,7 @@ static inline void unlock_sock_fast(struct sock *sk, bool slow) void sockopt_lock_sock(struct sock *sk); void sockopt_release_sock(struct sock *sk); bool sockopt_ns_capable(struct user_namespace *ns, int cap); +bool sockopt_ns_capable_any(struct user_namespace *ns, int cap1, int cap2); bool sockopt_capable(int cap); /* Used by processes to "lock" a socket state, so that
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
index 039dfbd367c9..2d811037e378 100644
--- a/net/caif/caif_socket.c
+++ b/net/caif/caif_socket.c@@ -1026,7 +1026,7 @@ static int caif_create(struct net *net, struct socket *sock, int protocol, .usersize = sizeof_field(struct caifsock, conn_req.param) }; - if (!capable(CAP_SYS_ADMIN) && !capable(CAP_NET_ADMIN)) + if (!capable_any(CAP_NET_ADMIN, CAP_SYS_ADMIN)) return -EPERM; /* * The sock->type specifies the socket type to use.
diff --git a/net/core/sock.c b/net/core/sock.c
index 43bf3818c19e..fa9edcc3e23d 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c@@ -1077,6 +1077,12 @@ bool sockopt_ns_capable(struct user_namespace *ns, int cap) } EXPORT_SYMBOL(sockopt_ns_capable); +bool sockopt_ns_capable_any(struct user_namespace *ns, int cap1, int cap2) +{ + return has_current_bpf_ctx() || ns_capable_any(ns, cap1, cap2); +} +EXPORT_SYMBOL(sockopt_ns_capable_any); + bool sockopt_capable(int cap) { return has_current_bpf_ctx() || capable(cap);
@@ -1118,8 +1124,7 @@ int sk_setsockopt(struct sock *sk, int level, int optname, switch (optname) { case SO_PRIORITY: if ((val >= 0 && val <= 6) || - sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) || - sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) { + sockopt_ns_capable_any(sock_net(sk)->user_ns, CAP_NET_RAW, CAP_NET_ADMIN)) { sock_set_priority(sk, val); return 0; }
@@ -1422,8 +1427,7 @@ int sk_setsockopt(struct sock *sk, int level, int optname, break; case SO_MARK: - if (!sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) && - !sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) { + if (!sockopt_ns_capable_any(sock_net(sk)->user_ns, CAP_NET_RAW, CAP_NET_ADMIN)) { ret = -EPERM; break; }
@@ -2813,8 +2817,7 @@ int __sock_cmsg_send(struct sock *sk, struct cmsghdr *cmsg, switch (cmsg->cmsg_type) { case SO_MARK: - if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) && - !ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) + if (!ns_capable_any(sock_net(sk)->user_ns, CAP_NET_RAW, CAP_NET_ADMIN)) return -EPERM; if (cmsg->cmsg_len != CMSG_LEN(sizeof(u32))) return -EINVAL;
diff --git a/net/ieee802154/socket.c b/net/ieee802154/socket.c
index 990a83455dcf..42b3b12eb493 100644
--- a/net/ieee802154/socket.c
+++ b/net/ieee802154/socket.c@@ -902,8 +902,7 @@ static int dgram_setsockopt(struct sock *sk, int level, int optname, ro->want_lqi = !!val; break; case WPAN_SECURITY: - if (!ns_capable(net->user_ns, CAP_NET_ADMIN) && - !ns_capable(net->user_ns, CAP_NET_RAW)) { + if (!ns_capable_any(net->user_ns, CAP_NET_ADMIN, CAP_NET_RAW)) { err = -EPERM; break; }
@@ -926,8 +925,7 @@ static int dgram_setsockopt(struct sock *sk, int level, int optname, } break; case WPAN_SECURITY_LEVEL: - if (!ns_capable(net->user_ns, CAP_NET_ADMIN) && - !ns_capable(net->user_ns, CAP_NET_RAW)) { + if (!ns_capable_any(net->user_ns, CAP_NET_ADMIN, CAP_NET_RAW)) { err = -EPERM; break; }
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index cf377377b52d..5a1e5ee20ddd 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c@@ -1008,8 +1008,9 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname, inet_assign_bit(MC_ALL, sk, val); return 0; case IP_TRANSPARENT: - if (!!val && !sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) && - !sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) + if (!!val && + !sockopt_ns_capable_any(sock_net(sk)->user_ns, + CAP_NET_RAW, CAP_NET_ADMIN)) return -EPERM; if (optlen < 1) return -EINVAL;
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index d4c28ec1bc51..e46b11b5d3dd 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c@@ -773,8 +773,7 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname, break; case IPV6_TRANSPARENT: - if (valbool && !sockopt_ns_capable(net->user_ns, CAP_NET_RAW) && - !sockopt_ns_capable(net->user_ns, CAP_NET_ADMIN)) { + if (valbool && !sockopt_ns_capable_any(net->user_ns, CAP_NET_RAW, CAP_NET_ADMIN)) { retv = -EPERM; break; }
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 5b41e2321209..acc36b2d25d7 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c@@ -1783,7 +1783,7 @@ static inline bool too_many_unix_fds(struct task_struct *p) struct user_struct *user = current_user(); if (unlikely(READ_ONCE(user->unix_inflight) > task_rlimit(p, RLIMIT_NOFILE))) - return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN); + return !capable_any(CAP_SYS_RESOURCE, CAP_SYS_ADMIN); return false; }
--
2.43.0