diff options
-rw-r--r-- | sys/kern/uipc_shm.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c index 38065dee7cb0..de8451f951dd 100644 --- a/sys/kern/uipc_shm.c +++ b/sys/kern/uipc_shm.c @@ -895,6 +895,7 @@ shm_mmap(struct file *fp, vm_map_t map, vm_offset_t *addr, vm_size_t objsize, struct shmfd *shmfd; vm_prot_t maxprot; int error; + bool writecnt; shmfd = fp->f_data; maxprot = VM_PROT_NONE; @@ -905,10 +906,10 @@ shm_mmap(struct file *fp, vm_map_t map, vm_offset_t *addr, vm_size_t objsize, if ((fp->f_flag & FWRITE) != 0) maxprot |= VM_PROT_WRITE; + writecnt = (flags & MAP_SHARED) != 0 && (prot & VM_PROT_WRITE) != 0; + /* Don't permit shared writable mappings on read-only descriptors. */ - if ((flags & MAP_SHARED) != 0 && - (maxprot & VM_PROT_WRITE) == 0 && - (prot & VM_PROT_WRITE) != 0) + if (writecnt && (maxprot & VM_PROT_WRITE) == 0) return (EACCES); maxprot &= cap_maxprot; @@ -931,10 +932,16 @@ shm_mmap(struct file *fp, vm_map_t map, vm_offset_t *addr, vm_size_t objsize, mtx_unlock(&shm_timestamp_lock); vm_object_reference(shmfd->shm_object); + if (writecnt) + vm_pager_update_writecount(shmfd->shm_object, 0, objsize); error = vm_mmap_object(map, addr, objsize, prot, maxprot, flags, - shmfd->shm_object, foff, FALSE, td); - if (error != 0) + shmfd->shm_object, foff, writecnt, td); + if (error != 0) { + if (writecnt) + vm_pager_release_writecount(shmfd->shm_object, 0, + objsize); vm_object_deallocate(shmfd->shm_object); + } return (error); } |