From a08846c6d30599db5756f9a8a3537e3c7497d7ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Wed, 7 Feb 2024 01:30:01 +0000 Subject: [PATCH] netd.c: handle overflowuid in bpf_owner_match() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Linux kernel implementation is: sock* sk_to_full_sk(sk): return (sk && sk->sk_state == TCP_NEW_SYN_RECV) ? inet_reqsk(sk)->rsk_listener : sk; bool sk_fullsock(sk): return (1 << sk->sk_state) & ~(TCPF_TIME_WAIT | TCPF_NEW_SYN_RECV) u32 bpf_get_socket_uid(skb): sk = sk_to_full_sk(skb->sk); if (!sk || !sk_fullsock(sk)) return overflowuid; kuid = sock_net_uid(sock_net(sk), sk); return from_kuid_munged(sock_net(sk)->user_ns, kuid); u64 bpf_get_socket_cookie(skb): return skb->sk ? __sock_gen_cookie(skb->sk) : 0 Test: TreeHugger Signed-off-by: Maciej Żenczykowski Change-Id: I0f9c2ffc24821068ebd2e5712789ff68aa196c48 --- bpf_progs/netd.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/bpf_progs/netd.c b/bpf_progs/netd.c index f223dd15e5..1c84d63479 100644 --- a/bpf_progs/netd.c +++ b/bpf_progs/netd.c @@ -446,8 +446,18 @@ static __always_inline inline int bpf_traffic_account(struct __sk_buff* skb, const struct egress_bool egress, const bool enable_tracing, const struct kver_uint kver) { + // sock_uid will be 'overflowuid' if !sk_fullsock(sk_to_full_sk(skb->sk)) uint32_t sock_uid = bpf_get_socket_uid(skb); - uint64_t cookie = bpf_get_socket_cookie(skb); + + // kernel's DEFAULT_OVERFLOWUID is 65534, this is the overflow 'nobody' uid, + // usually this being returned means that skb->sk is NULL during RX + // (early decap socket lookup failure), which commonly happens for incoming + // packets to an unconnected udp socket. + // But it can also happen for egress from a timewait socket. + // Let's treat such cases as 'root' which is_system_uid() + if (sock_uid == 65534) sock_uid = 0; + + uint64_t cookie = bpf_get_socket_cookie(skb); // 0 iff !skb->sk UidTagValue* utag = bpf_cookie_tag_map_lookup_elem(&cookie); uint32_t uid, tag; if (utag) {