Committed, thanks!

On Sat, Jul 02, 2022 at 08:50:33AM +0200, Anton Lindqvist wrote:
> On Fri, Jul 01, 2022 at 03:56:18AM -0600, Vitaliy Makkoveev wrote:
> > CVSROOT:    /cvs
> > Module name:        src
> > Changes by: m...@cvs.openbsd.org    2022/07/01 03:56:18
> > 
> > Modified files:
> >     sys/kern       : uipc_socket.c uipc_socket2.c uipc_syscalls.c 
> >                      uipc_usrreq.c 
> >     sys/miscfs/fifofs: fifo_vnops.c 
> >     sys/sys        : socketvar.h unpcb.h 
> > 
> > Log message:
> > Make fine grained unix(4) domain sockets locking. Use the per-socket
> > `so_lock' rwlock(9) instead of global `unp_lock' which locks the whole
> > layer.
> > 
> > The PCB of unix(4) sockets are linked to each other and we need to lock
> > them both. This introduces the lock ordering problem, because when the
> > thread (1) keeps lock on `so1' and trying to lock `so2', the thread (2)
> > could hold lock on `so2' and trying to lock `so1'. To solve this we
> > always lock sockets in the strict order.
> > 
> > For the sockets which are already accessible from userland, we always
> > lock socket with the smallest memory address first. Sometimes we need to
> > unlock socket before lock it's peer and lock it again.
> > 
> > We use reference counters for prevent the connected peer destruction
> > during to relock. We also handle the case where the peer socket was
> > replaced by another socket.
> > 
> > For the newly connected sockets, which are not yet exported to the
> > userland by accept(2), we always lock the listening socket `head' first.
> > This allows us to avoid unwanted relock within accept(2) syscall.
> > 
> > ok claudio@
> 
> syzkaller found a panic, I'm spotting one missed unlock. Feel free to
> commit.
> 
> diff --git sys/kern/uipc_usrreq.c sys/kern/uipc_usrreq.c
> index 0710393d376..7231b16b735 100644
> --- sys/kern/uipc_usrreq.c
> +++ sys/kern/uipc_usrreq.c
> @@ -363,6 +363,7 @@ uipc_usrreq(struct socket *so, int req, struct mbuf *m, 
> struct mbuf *nam,
>                                       control = NULL;
>                               } else {
>                                       error = ENOBUFS;
> +                                     sounlock(so2);
>                                       break;
>                               }
>                       } else if (so->so_type == SOCK_SEQPACKET)
> 
> syzbot has found a reproducer for the following issue on:
> 
> HEAD commit:    a4a82b864d54 Remove PIPEXCSESSION ioctl(2) call only from ..
> git tree:       openbsd
> console output: https://syzkaller.appspot.com/x/log.txt?x=10cffe24080000
> kernel config:  https://syzkaller.appspot.com/x/.config?x=7058272de1526588
> dashboard link: https://syzkaller.appspot.com/bug?extid=a648408d6a58fd40b59a
> syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=15cc61f4080000
> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=178e44ec080000
> 
> IMPORTANT: if you fix the issue, please add the following tag to the commit:
> Reported-by: syzbot+a648408d6a58fd40b...@syzkaller.appspotmail.com
> 
> witness: userret: returning with the following locks held:
> exclusive rwlock solock r = 0 (0xfffffd8073dde420)
> #0  witness_lock+0x44d
> #1  unp_solock_peer+0x64 sys/kern/uipc_usrreq.c:168
> #2  uipc_usrreq+0x7c6 sys/kern/uipc_usrreq.c:350
> #3  sosend+0x61b sys/kern/uipc_socket.c:657
> #4  sendit+0x65d sys/kern/uipc_syscalls.c:682
> #5  sys_sendmsg+0x198 sys/kern/uipc_syscalls.c:589
> #6  syscall+0x4c3 mi_syscall sys/sys/syscall_mi.h:101 [inline]
> #6  syscall+0x4c3 sys/arch/amd64/amd64/trap.c:585
> #7  Xsyscall+0x128

Reply via email to