-

CVE-2023-53585

In the Linux kernel, the following vulnerability has been resolved:

bpf: reject unhashed sockets in bpf_sk_assign

The semantics for bpf_sk_assign are as follows:

    sk = some_lookup_func()
    bpf_sk_assign(skb, sk)
    bpf_sk_release(sk)

That is, the sk is not consumed by bpf_sk_assign. The function
therefore needs to make sure that sk lives long enough to be
consumed from __inet_lookup_skb. The path through the stack for a
TCPv4 packet is roughly:

  netif_receive_skb_core: takes RCU read lock
    __netif_receive_skb_core:
      sch_handle_ingress:
        tcf_classify:
          bpf_sk_assign()
      deliver_ptype_list_skb:
        deliver_skb:
          ip_packet_type->func == ip_rcv:
            ip_rcv_core:
            ip_rcv_finish_core:
              dst_input:
                ip_local_deliver:
                  ip_local_deliver_finish:
                    ip_protocol_deliver_rcu:
                      tcp_v4_rcv:
                        __inet_lookup_skb:
                          skb_steal_sock

The existing helper takes advantage of the fact that everything
happens in the same RCU critical section: for sockets with
SOCK_RCU_FREE set bpf_sk_assign never takes a reference.
skb_steal_sock then checks SOCK_RCU_FREE again and does sock_put
if necessary.

This approach assumes that SOCK_RCU_FREE is never set on a sk
between bpf_sk_assign and skb_steal_sock, but this invariant is
violated by unhashed UDP sockets. A new UDP socket is created
in TCP_CLOSE state but without SOCK_RCU_FREE set. That flag is only
added in udp_lib_get_port() which happens when a socket is bound.

When bpf_sk_assign was added it wasn't possible to access unhashed
UDP sockets from BPF, so this wasn't a problem. This changed
in commit 0c48eefae712 ("sock_map: Lift socket state restriction
for datagram sockets"), but the helper wasn't adjusted accordingly.
The following sequence of events will therefore lead to a refcount
leak:

1. Add socket(AF_INET, SOCK_DGRAM) to a sockmap.
2. Pull socket out of sockmap and bpf_sk_assign it. Since
   SOCK_RCU_FREE is not set we increment the refcount.
3. bind() or connect() the socket, setting SOCK_RCU_FREE.
4. skb_steal_sock will now set refcounted = false due to
   SOCK_RCU_FREE.
5. tcp_v4_rcv() skips sock_put().

Fix the problem by rejecting unhashed sockets in bpf_sk_assign().
This matches the behaviour of __inet_lookup_skb which is ultimately
the goal of bpf_sk_assign().

Verknüpft mit AI von unstrukturierten Daten zu bestehenden CPE der NVD
This information is available to logged-in users.
Daten sind bereitgestellt durch das CVE Programm von einer CVE Numbering Authority (CNA) (Unstrukturiert).
VendorLinux
Product Linux
Default Statusunaffected
Version < 791a12102e5191dcb6ce0b3a99d71b5a2802d12a
Version cf7fbe660f2dbd738ab58aea8e9b0ca6ad232449
Status affected
Version < 7dcbc0bb0e5cc1823923744befce59ac353135e6
Version cf7fbe660f2dbd738ab58aea8e9b0ca6ad232449
Status affected
Version < c0ce0fb76610d5fad31f56f2ca8241a2a6717a1b
Version cf7fbe660f2dbd738ab58aea8e9b0ca6ad232449
Status affected
Version < 8aa43cfbb68b25119d2ced14ec717173e2901fa2
Version cf7fbe660f2dbd738ab58aea8e9b0ca6ad232449
Status affected
Version < 3d4522f59fb748a54446846522941a4f09da63e9
Version cf7fbe660f2dbd738ab58aea8e9b0ca6ad232449
Status affected
Version < 67312adc96b5a585970d03b62412847afe2c6b01
Version cf7fbe660f2dbd738ab58aea8e9b0ca6ad232449
Status affected
VendorLinux
Product Linux
Default Statusaffected
Version 5.7
Status affected
Version < 5.7
Version 0
Status unaffected
Version <= 5.10.*
Version 5.10.195
Status unaffected
Version <= 5.15.*
Version 5.15.132
Status unaffected
Version <= 6.1.*
Version 6.1.53
Status unaffected
Version <= 6.4.*
Version 6.4.16
Status unaffected
Version <= 6.5.*
Version 6.5.3
Status unaffected
Version <= *
Version 6.6
Status unaffected
Zu dieser CVE wurde keine CISA KEV oder CERT.AT-Warnung gefunden.
EPSS Metriken
Type Source Score Percentile
EPSS FIRST.org 0.02% 0.053
CVSS Metriken
Source Base Score Exploit Score Impact Score Vector string