If a process exit(3)s while one of its threads is blocking in accept(2) and the half-opened descriptor has already been dup'ed, we get the following panic:
panic: closef: count (1) < 2 Stopped at db_enter+0x5: popq %rbp TID PID UID PRFLAGS PFLAGS CPU COMMAND *204115 80020 0 0x1003 0x80000 0K dup2_accept db_enter() at db_enter+0x5 panic() at panic+0x120 closef(ffffff000583d948,ffff8000ffffa020) at closef+0x145 doaccept(1e0,ffff8000ffffa020,1e,ffff8000039a03c0,7f7ffffc9d58,bc7efe80dd509fa1) at doaccept+0x2a3 syscall(1) at syscall+0x31d Xsyscall_untramp(6,0,0,0,0,1e) at Xsyscall_untramp+0xc0 end of kernel A test for this problem can be found there: https://marc.info/?l=openbsd-tech&m=152637351632752&w=2 Diff below prevents the problem by returning EBUSY in dup2(2) & friends like Linux does when trying to dup an half-opened file. I'd like to reuse this logic to keep the future locking simple, ok? Index: sys/kern/kern_descrip.c =================================================================== RCS file: /cvs/src/sys/kern/kern_descrip.c,v retrieving revision 1.158 diff -u -p -r1.158 kern_descrip.c --- sys/kern/kern_descrip.c 8 May 2018 09:03:58 -0000 1.158 +++ sys/kern/kern_descrip.c 21 May 2018 12:12:50 -0000 @@ -634,13 +634,14 @@ finishdup(struct proc *p, struct file *f return (EDEADLK); } - /* - * Don't fd_getfile here. We want to closef LARVAL files and - * closef can deal with that. - */ oldfp = fdp->fd_ofiles[new]; - if (oldfp != NULL) + if (oldfp != NULL) { + if (!FILE_IS_USABLE(oldfp)) { + FRELE(fp, p); + return (EBUSY); + } FREF(oldfp); + } fdp->fd_ofiles[new] = fp; fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] & ~UF_EXCLOSE; Index: lib/libc/sys//dup.2 =================================================================== RCS file: /cvs/src/lib/libc/sys/dup.2,v retrieving revision 1.18 diff -u -p -r1.18 dup.2 --- lib/libc/sys//dup.2 10 Dec 2014 19:46:48 -0000 1.18 +++ lib/libc/sys//dup.2 21 May 2018 12:12:38 -0000 @@ -157,6 +157,10 @@ is not a valid active descriptor or is negative or greater than or equal to the process's .Dv RLIMIT_NOFILE limit. +.It Bq Er EBUSY +A race condition with +.Xr accept 2 +has been detected. .It Bq Er EINTR An interrupt was received. .It Bq Er EIO
