netd.c: handle overflowuid in bpf_owner_match()

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 <maze@google.com>
Change-Id: I0f9c2ffc24821068ebd2e5712789ff68aa196c48
diff --git a/bpf_progs/netd.c b/bpf_progs/netd.c
index f223dd1..1c84d63 100644
--- a/bpf_progs/netd.c
+++ b/bpf_progs/netd.c
@@ -446,8 +446,18 @@
                                                       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) {