diff options
author | 2017-01-23 23:22:00 +0000 | |
---|---|---|
committer | 2017-01-23 23:22:00 +0000 | |
commit | 99f4395a92357dec2f9cfce05f5356f40aefd487 (patch) | |
tree | f11b8a4ce0e0dd88bc4b2c859349b4f819a14dbb | |
parent | For testing http redirect unset http_proxy, not ftp_proxy. (diff) | |
download | wireguard-openbsd-99f4395a92357dec2f9cfce05f5356f40aefd487.tar.xz wireguard-openbsd-99f4395a92357dec2f9cfce05f5356f40aefd487.zip |
Allocate all memory chunks, and potentially sleeping, before freeing
the old array of open files.
Fix a race for multi-threaded processes reported by cheeky.m@gmx.com
on bugs@ and analyzed with bluhm@.
ok deraadt@, bluhm@
-rw-r--r-- | sys/kern/kern_descrip.c | 17 |
1 files changed, 11 insertions, 6 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index e4b44839b37..904f7b43439 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_descrip.c,v 1.137 2017/01/23 22:34:10 deraadt Exp $ */ +/* $OpenBSD: kern_descrip.c,v 1.138 2017/01/23 23:22:00 mpi Exp $ */ /* $NetBSD: kern_descrip.c,v 1.42 1996/03/30 22:24:38 christos Exp $ */ /* @@ -835,6 +835,16 @@ fdexpand(struct proc *p) nfiles = 2 * fdp->fd_nfiles; newofile = mallocarray(nfiles, OFILESIZE, M_FILEDESC, M_WAITOK); + /* + * Allocate all required chunks before calling free(9) to make + * sure that ``fd_ofiles'' stays valid if we go to sleep. + */ + if (NDHISLOTS(nfiles) > NDHISLOTS(fdp->fd_nfiles)) { + newhimap = mallocarray(NDHISLOTS(nfiles), sizeof(u_int), + M_FILEDESC, M_WAITOK); + newlomap = mallocarray(NDLOSLOTS(nfiles), sizeof(u_int), + M_FILEDESC, M_WAITOK); + } newofileflags = (char *) &newofile[nfiles]; /* @@ -853,11 +863,6 @@ fdexpand(struct proc *p) free(fdp->fd_ofiles, M_FILEDESC, fdp->fd_nfiles * OFILESIZE); if (NDHISLOTS(nfiles) > NDHISLOTS(fdp->fd_nfiles)) { - newhimap = mallocarray(NDHISLOTS(nfiles), sizeof(u_int), - M_FILEDESC, M_WAITOK); - newlomap = mallocarray(NDLOSLOTS(nfiles), sizeof(u_int), - M_FILEDESC, M_WAITOK); - copylen = NDHISLOTS(fdp->fd_nfiles) * sizeof(u_int); memcpy(newhimap, fdp->fd_himap, copylen); memset((char *)newhimap + copylen, 0, |