summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2015-08-06 16:50:37 +0000
committerjhb <jhb@FreeBSD.org>2015-08-06 16:50:37 +0000
commit3fab33edd0332263171c2527b0e575cb6e6850c5 (patch)
tree185621b468b045e60686d757731ff14a8ae6d40c /sys/fs
parent6dd6018a93450318ff7958db08c1bce4c365bcc4 (diff)
downloadFreeBSD-src-3fab33edd0332263171c2527b0e575cb6e6850c5.zip
FreeBSD-src-3fab33edd0332263171c2527b0e575cb6e6850c5.tar.gz
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
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/devfs/devfs_vnops.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
index fe8e9ef..8068437 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -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;
OpenPOWER on IntegriCloud