Author: jhb
Date: Thu Aug  6 16:50:37 2015
New Revision: 286371
URL: https://svnweb.freebsd.org/changeset/base/286371

Log:
  The changes that introduced fo_mmap() treated all character device
  mappings as if MAP_SHARED was always present since in general MAP_PRIVATE
  is not permitted for character devices.  However, there is one exception
  in that MAP_PRIVATE mappings are permitted for /dev/zero.
  
  Only require a writable file descriptor (FWRITE) for shared, writable
  mappings of character devices.  vm_mmap_cdev() will reject any private
  mappings for other devices.
  
  Reviewed by:  kib
  Reported by:  sbruno (broke qemu cross-builds), peter
  Differential Revision:        https://reviews.freebsd.org/D3316

Modified:
  head/sys/fs/devfs/devfs_vnops.c

Modified: head/sys/fs/devfs/devfs_vnops.c
==============================================================================
--- head/sys/fs/devfs/devfs_vnops.c     Thu Aug  6 16:14:29 2015        
(r286370)
+++ head/sys/fs/devfs/devfs_vnops.c     Thu Aug  6 16:50:37 2015        
(r286371)
@@ -1774,13 +1774,24 @@ devfs_mmap_f(struct file *fp, vm_map_t m
                return (EACCES);
 
        /*
-        * Character devices always share mappings, so
-        * require a writable fd for writable mappings.
+        * If we are sharing potential changes via MAP_SHARED and we
+        * are trying to get write permission although we opened it
+        * without asking for it, bail out.
+        *
+        * Note that most character devices always share mappings.
+        * The one exception is that D_MMAP_ANON devices
+        * (i.e. /dev/zero) permit private writable mappings.
+        *
+        * Rely on vm_mmap_cdev() to fail invalid MAP_PRIVATE requests
+        * as well as updating maxprot to permit writing for
+        * D_MMAP_ANON devices rather than doing that here.
         */
-       if ((fp->f_flag & FWRITE) != 0)
-               maxprot |= VM_PROT_WRITE;
-       else if ((prot & VM_PROT_WRITE) != 0)
-               return (EACCES);
+       if ((flags & MAP_SHARED) != 0) {
+               if ((fp->f_flag & FWRITE) != 0)
+                       maxprot |= VM_PROT_WRITE;
+               else if ((prot & VM_PROT_WRITE) != 0)
+                       return (EACCES);
+       }
        maxprot &= cap_maxprot;
 
        fpop = td->td_fpop;
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to