diff options
author | Mark Johnston <markj@FreeBSD.org> | 2020-04-13 19:20:39 +0000 |
---|---|---|
committer | Mark Johnston <markj@FreeBSD.org> | 2020-04-13 19:20:39 +0000 |
commit | c7841c6b8e41ea0567d5320a13f33856d6feaca7 (patch) | |
tree | d671fbdaa8f228d2e9d26d2ea7e70a5ff9596aa4 /sys/kern/uipc_shm.c | |
parent | 605c4cda2f5c274f0b9fc874d254d62944a93a37 (diff) | |
download | src-c7841c6b8e41ea0567d5320a13f33856d6feaca7.tar.gz src-c7841c6b8e41ea0567d5320a13f33856d6feaca7.zip |
Relax restrictions on private mappings of POSIX shm objects.
When creating a private mapping of a POSIX shared memory object,
VM_PROT_WRITE should always be included in maxprot regardless of
permissions on the underlying FD. Otherwise it is possible to open a
shm object read-only, map it with MAP_PRIVATE and PROT_WRITE, and
violate the invariant in vm_map_insert() that (prot & maxprot) == prot.
Reported by: syzkaller
Reviewed by: kevans, kib
MFC after: 1 week
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D24398
Notes
Notes:
svn path=/head/; revision=359892
Diffstat (limited to 'sys/kern/uipc_shm.c')
-rw-r--r-- | sys/kern/uipc_shm.c | 33 |
1 files changed, 19 insertions, 14 deletions
diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c index 886a0bad8746..a5f550f35e62 100644 --- a/sys/kern/uipc_shm.c +++ b/sys/kern/uipc_shm.c @@ -1136,23 +1136,28 @@ shm_mmap(struct file *fp, vm_map_t map, vm_offset_t *addr, vm_size_t objsize, /* * If FWRITE's set, we can allow VM_PROT_WRITE unless it's a shared - * mapping with a write seal applied. + * mapping with a write seal applied. Private mappings are always + * writeable. */ - if ((fp->f_flag & FWRITE) != 0 && ((flags & MAP_SHARED) == 0 || - (shmfd->shm_seals & F_SEAL_WRITE) == 0)) + if ((flags & MAP_SHARED) == 0) { + cap_maxprot |= VM_PROT_WRITE; maxprot |= VM_PROT_WRITE; + writecnt = false; + } else { + if ((fp->f_flag & FWRITE) != 0 && + (shmfd->shm_seals & F_SEAL_WRITE) == 0) + maxprot |= VM_PROT_WRITE; + writecnt = (prot & VM_PROT_WRITE) != 0; + if (writecnt && (shmfd->shm_seals & F_SEAL_WRITE) != 0) { + error = EPERM; + goto out; + } - writecnt = (flags & MAP_SHARED) != 0 && (prot & VM_PROT_WRITE) != 0; - - if (writecnt && (shmfd->shm_seals & F_SEAL_WRITE) != 0) { - error = EPERM; - goto out; - } - - /* Don't permit shared writable mappings on read-only descriptors. */ - if (writecnt && (maxprot & VM_PROT_WRITE) == 0) { - error = EACCES; - goto out; + /* Don't permit shared writable mappings on read-only descriptors. */ + if (writecnt && (maxprot & VM_PROT_WRITE) == 0) { + error = EACCES; + goto out; + } } maxprot &= cap_maxprot; |