Hi Eric, On Fri, Feb 22, 2019 at 09:45:35AM -0800, Eric Dumazet wrote: > > > On 02/21/2019 02:13 PM, Eric Biggers wrote: > > From: Eric Biggers <ebigg...@google.com> > > > > Commit 9060cb719e61 ("net: crypto set sk to NULL when af_alg_release.") > > fixed a use-after-free in sockfs_setattr() when an AF_ALG socket is > > closed concurrently with fchownat(). However, it ignored that many > > other proto_ops::release() methods don't set sock->sk to NULL and > > therefore allow the same use-after-free: > > > > I fail to see how setting a pointer to NULL can avoid races. > > > We lack some kind of protection, rcu or something, if another thread can > change sock->sk at anytime > while sockfs_setattr() is used. > > sockfs_setattr() > ... > if (sock->sk) > > // even if sock->sk was not NULL for the if (...). > > // it can be NULL right now, compiler could read sock->sk a second time and > catch a NULL. > > sock->sk->sk_uid = iattr->ia_uid; > >
->setattr() is called under inode_lock(), which __sock_release() also takes. So the uses of sock->sk are serialized. See commit 6d8c50dcb029 ("socket: close race condition between sock_close() and sockfs_setattr()"). The issue now is that if ->setattr() happens *after* __sock_release() (which is possible if fchownat() gets the reference to the file's 'struct path', then the file is close()d by another thread, then fchownat() continues), it will see stale sock->sk because for many socket types it wasn't set to NULL earlier. - Eric