Index: sys/kern/kern_descrip.c =================================================================== --- sys/kern/kern_descrip.c (revision 255814) +++ sys/kern/kern_descrip.c (working copy) @@ -1511,11 +1511,18 @@ fdgrowtable(struct filedesc *fdp, int nfd) memcpy(ntable, otable, onfiles * sizeof(*otable)); memcpy(nmap, omap, NDSLOTS(onfiles) * sizeof(*omap)); - /* update the pointers and counters */ - fdp->fd_nfiles = nnfiles; + /* + * Update the pointers and counters. + * In order to have a valid pattern for fget_unlocked() + * fdp->fd_nfiles might be the last member to be updated, otherwise + * fget_unlocked() consumers may reference a new, higher value for + * fdp->fd_nfiles before to access the fdp->fd_ofiles array, + * resulting in OOB accesses. + */ memcpy(ntable, otable, onfiles * sizeof(ntable[0])); fdp->fd_ofiles = ntable; fdp->fd_map = nmap; + atomic_store_rel_int(&fdp->fd_nfiles, nnfiles); /* * Do not free the old file table, as some threads may still @@ -2308,7 +2315,8 @@ fget_unlocked(struct filedesc *fdp, int fd, cap_ri int error; #endif - if (fd < 0 || fd >= fdp->fd_nfiles) + /* See the comment in fdgrowtable() about memory barriers. */ + if (fd < 0 || fd >= atomic_load_acq_int(&fdp->fd_nfiles)) return (EBADF); /* * Fetch the descriptor locklessly. We avoid fdrop() races by