Author: markj
Date: Mon Apr 13 19:20:39 2020
New Revision: 359892
URL: https://svnweb.freebsd.org/changeset/base/359892

Log:
  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

Modified:
  head/sys/kern/uipc_shm.c

Modified: head/sys/kern/uipc_shm.c
==============================================================================
--- head/sys/kern/uipc_shm.c    Mon Apr 13 17:55:31 2020        (r359891)
+++ head/sys/kern/uipc_shm.c    Mon Apr 13 19:20:39 2020        (r359892)
@@ -1136,23 +1136,28 @@ shm_mmap(struct file *fp, vm_map_t map, vm_offset_t *a
 
        /*
         * 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;
 
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to