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
This commit is contained in:
John Baldwin 2015-08-06 16:50:37 +00:00
parent 7f43ee0fb7
commit fada4adf95

View File

@ -1774,13 +1774,24 @@ devfs_mmap_f(struct file *fp, vm_map_t map, vm_offset_t *addr, vm_size_t size,
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;