Skip to content

Commit

Permalink
Relax restrictions on private mappings of POSIX shm objects.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
markjdb committed Apr 13, 2020
1 parent 605c4cd commit c7841c6
Showing 1 changed file with 19 additions and 14 deletions.
33 changes: 19 additions & 14 deletions sys/kern/uipc_shm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down

0 comments on commit c7841c6

Please sign in to comment.