--- a/sys/kern/sysv_shm.c +++ b/sys/kern/sysv_shm.c @@ -359,6 +359,17 @@ else align = PAGE_SIZE; + /* + * Increment the attach count BEFORE any operation that can block. + * While blocked (e.g. inside vm_object_hold() below) lwkt drops + * shm_token, and a concurrent shmctl(IPC_RMID) would otherwise see + * shm_nattch == 0 and deallocate the segment (terminating the VM + * object) out from under this attach, leaving a reference on an + * OBJ_DEAD object (vm_object_terminate2 panic) or corrupting a + * recycled shmseg's accounting. + */ + shmseg->shm_nattch++; + shm_handle = shmseg->shm_internal; vm_object_hold(shm_handle->shm_object); vm_object_reference_locked(shm_handle->shm_object); @@ -373,6 +384,12 @@ if (rv != KERN_SUCCESS) { vm_object_deallocate(shm_handle->shm_object); shmmap_s->reserved = 0; + if ((--shmseg->shm_nattch <= 0) && + (shmseg->shm_perm.mode & SHMSEG_REMOVED)) { + /* deferred deallocate from IPC_RMID */ + shm_deallocate_segment(shmseg); + shm_last_free = IPCID_TO_IX(uap->shmid); + } error = ENOMEM; goto done; } @@ -385,7 +402,6 @@ shmmap_s->reserved = 0; shmseg->shm_lpid = p->p_pid; shmseg->shm_atime = time_second; - shmseg->shm_nattch++; sysmsg->sysmsg_resultp = (void *)attach_va; error = 0; done: