CVSROOT:        /cvs
Module name:    src
Changes by:     [email protected]  2026/10/03 22:45:55

Modified files:
        sys/kern       : sysv_shm.c 

Log message:
sysv_shm: claim the vm_shm slot after uvm_map(), not before

sys_shmat() chose a free slot in the per-vmspace vm_shm array, then slept
in uvm_map(), then published into the slot it had chosen.  Nothing marked
the slot taken across the sleep, so a sibling thread entering sys_shmat()
scanned the same array, found the same slot still reading -1, and took it
too.  Both uvm_map() calls succeed at different addresses and the thread
that stores last wins; the other mapping is left with no vm_shm entry, so
shmdt() returns EINVAL for it and shmexit() cannot drop its shm_nattch.
The permanently raised count keeps IPC_RMID from deallocating the segment,
which then sits in shmsegs[] reachable by nobody; 128 of those and
shmget() returns ENOSPC system-wide.

uvm_map() is the only sleep between choosing the slot and filling it in,
so moving the scan below the map closes the window without a reserved
state that shmdt(), shmexit() and shmfork() would each have to learn
about.  EMFILE is now discovered after the mapping exists, so that path
undoes it.

While here, balance the uao reference on the uvm_map() failure path: a
failed uvm_map() does not consume the caller reference, so two were
outstanding and the deallocate arm dropped only one.  r1.88 already
unpublishes the segment before shm_deallocate_segment(), so the detach can
be done unconditionally and first.

OK mvs@

Reported-by: Acts1631 <[email protected]>

Reply via email to