lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Fri, 24 Nov 2023 14:43:24 +0100
From: Jakub Sitnicki <jakub@...udflare.com>
To: Cong Wang <xiyou.wangcong@...il.com>
Cc: John Fastabend <john.fastabend@...il.com>, martin.lau@...nel.org,
 bpf@...r.kernel.org, netdev@...r.kernel.org
Subject: Re: [PATCH bpf v2 1/2] bpf: sockmap, af_unix stream sockets need to
 hold ref for pair sock


On Thu, Nov 23, 2023 at 12:24 PM -08, Cong Wang wrote:
> On Wed, Nov 22, 2023 at 11:24:51AM -0800, John Fastabend wrote:
>> AF_UNIX stream sockets are a paired socket. So sending on one of the pairs
>> will lookup the paired socket as part of the send operation. It is possible
>> however to put just one of the pairs in a BPF map. This currently
>> increments the refcnt on the sock in the sockmap to ensure it is not
>> free'd by the stack before sockmap cleans up its state and stops any
>> skbs being sent/recv'd to that socket.
>> 
>> But we missed a case. If the peer socket is closed it will be
>> free'd by the stack. However, the paired socket can still be
>> referenced from BPF sockmap side because we hold a reference
>> there. Then if we are sending traffic through BPF sockmap to
>> that socket it will try to dereference the free'd pair in its
>> send logic creating a use after free.  And following splat,
>
> Hmm, how could it pass the SOCK_DEAD test in unix_stream_sendmsg()?
>
> 2285                 unix_state_lock(other);
> 2286
> 2287                 if (sock_flag(other, SOCK_DEAD) ||
> 2288                     (other->sk_shutdown & RCV_SHUTDOWN))
> 2289                         goto pipe_err_free;

The quoted UAF happens after unix_state_unlock(other):

  2285                  unix_state_lock(other);
  2286
  2287                  if (sock_flag(other, SOCK_DEAD) ||
  2288                      (other->sk_shutdown & RCV_SHUTDOWN))
  2289                          goto pipe_err_free;
  2290
  2291                  maybe_add_creds(skb, sock, other);
  2292                  scm_stat_add(other, skb);
  2293                  skb_queue_tail(&other->sk_receive_queue, skb);
  2294                  unix_state_unlock(other);
  2295                  other->sk_data_ready(other); <-- UAF

Although, I think I saw it happen at unix_state_lock(other) as well.

We don't hold a ref on other, so we're racing with __sock_release /
unix_release_sock.

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ