aboutsummaryrefslogtreecommitdiff
path: root/sys/vm/vm_object.h
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2017-02-12 21:05:44 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2017-02-12 21:05:44 +0000
commit987ff181841049684ccaf3edc864a8b3853cde93 (patch)
treee6261f7e0308269c9ef9a9ee257d447c5b6d30c5 /sys/vm/vm_object.h
parentf2277b64ec547dae1aa5220dd396cc4c498cdc2c (diff)
downloadsrc-987ff181841049684ccaf3edc864a8b3853cde93.tar.gz
src-987ff181841049684ccaf3edc864a8b3853cde93.zip
Consistently handle negative or wrapping offsets in the mmap(2) syscalls.
For regular files and posix shared memory, POSIX requires that [offset, offset + size) range is legitimate. At the maping time, check that offset is not negative. Allowing negative offsets might expose the data that filesystem put into vm_object for internal use, esp. due to OFF_TO_IDX() signess treatment. Fault handler verifies that the mapped range is valid, assuming that mmap(2) checked that arithmetic gives no undefined results. For device mappings, leave the semantic of negative offsets to the driver. Correct object page index calculation to not erronously propagate sign. In either case, disallow overflow of offset + size. Update mmap(2) man page to explain the requirement of the range validity, and behaviour when the range becomes invalid after mapping. Reported and tested by: royger (previous version) Reviewed by: alc Sponsored by: The FreeBSD Foundation MFC after: 2 weeks
Notes
Notes: svn path=/head/; revision=313690
Diffstat (limited to 'sys/vm/vm_object.h')
-rw-r--r--sys/vm/vm_object.h15
1 files changed, 15 insertions, 0 deletions
diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h
index e957c4cce396..9b2192efef58 100644
--- a/sys/vm/vm_object.h
+++ b/sys/vm/vm_object.h
@@ -183,8 +183,23 @@ struct vm_object {
#define OBJ_DISCONNECTWNT 0x4000 /* disconnect from vnode wanted */
#define OBJ_TMPFS 0x8000 /* has tmpfs vnode allocated */
+/*
+ * Helpers to perform conversion between vm_object page indexes and offsets.
+ * IDX_TO_OFF() converts an index into an offset.
+ * OFF_TO_IDX() converts an offset into an index. Since offsets are signed
+ * by default, the sign propagation in OFF_TO_IDX(), when applied to
+ * negative offsets, is intentional and returns a vm_object page index
+ * that cannot be created by a userspace mapping.
+ * UOFF_TO_IDX() treats the offset as an unsigned value and converts it
+ * into an index accordingly. Use it only when the full range of offset
+ * values are allowed. Currently, this only applies to device mappings.
+ * OBJ_MAX_SIZE specifies the maximum page index corresponding to the
+ * maximum unsigned offset.
+ */
#define IDX_TO_OFF(idx) (((vm_ooffset_t)(idx)) << PAGE_SHIFT)
#define OFF_TO_IDX(off) ((vm_pindex_t)(((vm_ooffset_t)(off)) >> PAGE_SHIFT))
+#define UOFF_TO_IDX(off) (((vm_pindex_t)(off)) >> PAGE_SHIFT)
+#define OBJ_MAX_SIZE (UOFF_TO_IDX(UINT64_MAX) + 1)
#ifdef _KERNEL