In the Linux kernel, the following vulnerability has been resolved:
net: implement lockless setsockopt(SOPEEKOFF)
syzbot reported a lockdep violation [1] involving afunix support of SOPEEK_OFF.
Since SOPEEKOFF is inherently not thread safe (it uses a per-socket skpeekoff field), there is really no point to enforce a pointless thread safety in the kernel.
After this patch :
setsockopt(SOPEEKOFF) no longer acquires the socket lock.
skbconsumeudp() no longer has to acquire the socket lock.
afunix no longer needs a special version of sksetpeekoff(), because it does not lock u->iolock anymore.
As a followup, we could replace prot->setpeekoff to be a boolean and avoid an indirect call, since we always use sksetpeek_off().
[1]
WARNING: possible circular locking dependency detected 6.8.0-rc4-syzkaller-00267-g0f1dd5e91e2b #0 Not tainted
syz-executor.2/30025 is trying to acquire lock: ffff8880765e7d80 (&u->iolock){+.+.}-{3:3}, at: unixsetpeekoff+0x26/0xa0 net/unix/afunix.c:789
but task is already holding lock: ffff8880765e7930 (sklock-AFUNIX){+.+.}-{0:0}, at: locksock include/net/sock.h:1691 [inline] ffff8880765e7930 (sklock-AFUNIX){+.+.}-{0:0}, at: sockoptlocksock net/core/sock.c:1060 [inline] ffff8880765e7930 (sklock-AFUNIX){+.+.}-{0:0}, at: sksetsockopt+0xe52/0x3360 net/core/sock.c:1193
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #1 (sklock-AFUNIX){+.+.}-{0:0}: lockacquire+0x1e3/0x530 kernel/locking/lockdep.c:5754 locksocknested+0x48/0x100 net/core/sock.c:3524 locksock include/net/sock.h:1691 [inline] unixdgramrecvmsg+0x1275/0x12c0 net/unix/afunix.c:2415 sockrecvmsgnosec+0x18e/0x1d0 net/socket.c:1046 _sysrecvmsg+0x3c0/0x470 net/socket.c:2801 _sysrecvmsg net/socket.c:2845 [inline] dorecvmmsg+0x474/0xae0 net/socket.c:2939 _sysrecvmmsg net/socket.c:3018 [inline] _dosysrecvmmsg net/socket.c:3041 [inline] _sesysrecvmmsg net/socket.c:3034 [inline] _x64sysrecvmmsg+0x199/0x250 net/socket.c:3034 dosyscall64+0xf9/0x240 entrySYSCALL64afterhwframe+0x6f/0x77
-> #0 (&u->iolock){+.+.}-{3:3}: checkprevadd kernel/locking/lockdep.c:3134 [inline] checkprevsadd kernel/locking/lockdep.c:3253 [inline] validatechain+0x18ca/0x58e0 kernel/locking/lockdep.c:3869 _lockacquire+0x1345/0x1fd0 kernel/locking/lockdep.c:5137 lockacquire+0x1e3/0x530 kernel/locking/lockdep.c:5754 _mutexlockcommon kernel/locking/mutex.c:608 [inline] _mutexlock+0x136/0xd70 kernel/locking/mutex.c:752 unixsetpeekoff+0x26/0xa0 net/unix/afunix.c:789 sksetsockopt+0x207e/0x3360 dosocksetsockopt+0x2fb/0x720 net/socket.c:2307 _syssetsockopt+0x1ad/0x250 net/socket.c:2334 _dosyssetsockopt net/socket.c:2343 [inline] _sesyssetsockopt net/socket.c:2340 [inline] _x64syssetsockopt+0xb5/0xd0 net/socket.c:2340 dosyscall64+0xf9/0x240 entrySYSCALL64after_hwframe+0x6f/0x77
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(sklock-AFUNIX); lock(&u->iolock); lock(sklock-AFUNIX); lock(&u->iolock);
* DEADLOCK *
1 lock held by syz-executor.2/30025: #0: ffff8880765e7930 (sklock-AFUNIX){+.+.}-{0:0}, at: locksock include/net/sock.h:1691 [inline] #0: ffff8880765e7930 (sklock-AFUNIX){+.+.}-{0:0}, at: sockoptlocksock net/core/sock.c:1060 [inline] #0: ffff8880765e7930 (sklock-AFUNIX){+.+.}-{0:0}, at: sksetsockopt+0xe52/0x3360 net/core/sock.c:1193
stack backtrace: CPU: 0 PID: 30025 Comm: syz-executor.2 Not tainted 6.8.0-rc4-syzkaller-00267-g0f1dd5e91e2b #0 Hardware name: Google Google C ---truncated---