summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvisa <visa@openbsd.org>2020-06-11 13:23:18 +0000
committervisa <visa@openbsd.org>2020-06-11 13:23:18 +0000
commit484822295e51fa79b81d4d5db59c84d5a3bd1682 (patch)
tree60d28afb36415883748ed778b44f9599abee801d
parentFix length parameter to strlcpy, inputFS is a pointer. (diff)
downloadwireguard-openbsd-484822295e51fa79b81d4d5db59c84d5a3bd1682.tar.xz
wireguard-openbsd-484822295e51fa79b81d4d5db59c84d5a3bd1682.zip
Move FRELE() outside fdplock in dup*(2) code. This avoids a potential
lock order issue with the file close path. The FRELE() can trigger the close path during dup*(2) if another thread manages to close the file descriptor simultaneously. This race is possible because the file reference is taken before the file descriptor table is locked for write access. Vitaliy Makkoveev agrees OK anton@ mpi@
-rw-r--r--sys/kern/kern_descrip.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 1b79eefaf7d..744b2247801 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_descrip.c,v 1.201 2020/03/13 10:07:01 anton Exp $ */
+/* $OpenBSD: kern_descrip.c,v 1.202 2020/06/11 13:23:18 visa Exp $ */
/* $NetBSD: kern_descrip.c,v 1.42 1996/03/30 22:24:38 christos Exp $ */
/*
@@ -301,13 +301,14 @@ restart:
return (EBADF);
fdplock(fdp);
if ((error = fdalloc(p, 0, &new)) != 0) {
- FRELE(fp, p);
if (error == ENOSPC) {
fdexpand(p);
fdpunlock(fdp);
+ FRELE(fp, p);
goto restart;
}
fdpunlock(fdp);
+ FRELE(fp, p);
return (error);
}
/* No need for FRELE(), finishdup() uses current ref. */
@@ -373,13 +374,14 @@ restart:
fdplock(fdp);
if (new >= fdp->fd_nfiles) {
if ((error = fdalloc(p, new, &i)) != 0) {
- FRELE(fp, p);
if (error == ENOSPC) {
fdexpand(p);
fdpunlock(fdp);
+ FRELE(fp, p);
goto restart;
}
fdpunlock(fdp);
+ FRELE(fp, p);
return (error);
}
if (new != i)
@@ -433,13 +435,14 @@ restart:
}
fdplock(fdp);
if ((error = fdalloc(p, newmin, &i)) != 0) {
- FRELE(fp, p);
if (error == ENOSPC) {
fdexpand(p);
fdpunlock(fdp);
+ FRELE(fp, p);
goto restart;
}
fdpunlock(fdp);
+ FRELE(fp, p);
} else {
int dupflags = 0;