path: root/sys/sys/mount.h
diff options
authorRyan Moeller <freqlabs@FreeBSD.org>2020-06-03 09:38:51 +0000
committerRyan Moeller <freqlabs@FreeBSD.org>2020-06-03 09:38:51 +0000
commit693d10a29176e9128d5d09bbd74c9205addc091b (patch)
treec797567cc738d2676c6bb6f18385092a207daef4 /sys/sys/mount.h
parent06f6997eb5fd0d91560b9eec0f842214c21856e8 (diff)
tmpfs: Preserve alignment of struct fid fields
On 64-bit platforms, the two short fields in `struct tmpfs_fid` are padded to the 64-bit alignment of the long field. This pushes the offsets of the subsequent fields by 4 bytes and makes `struct tmpfs_fid` bigger than `struct fid`. `tmpfs_vptofh()` casts a `struct fid *` to `struct tmpfs_fid *`, causing 4 bytes of adjacent memory to be overwritten when the struct fields are set. Through several layers of indirection and embedded structs, the adjacent memory for one particular call to `tmpfs_vptofh()` happens to be the stack canary for `nfsrvd_compound()`. Half of the canary ends up being clobbered, going unnoticed until eventually the stack check fails when `nfsrvd_compound()` returns and a panic is triggered. Instead of duplicating fields of `struct fid` in `struct tmpfs_fid`, narrow the struct to cover only the unique fields for tmpfs and assert at compile time that the struct fits in the allotted space. This way we don't have to replicate the offsets of `struct fid` fields, we just use them directly. Reviewed by: kib, mav, rmacklem Approved by: mav (mentor) MFC after: 1 week Sponsored by: iXsystems, Inc. Differential Revision: https://reviews.freebsd.org/D25077
Notes: svn path=/head/; revision=361748
Diffstat (limited to 'sys/sys/mount.h')
1 files changed, 3 insertions, 0 deletions
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index 00040932e7a3..1477ffad9fe3 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -57,6 +57,9 @@ typedef struct fsid { int32_t val[2]; } fsid_t; /* filesystem id type */
* File identifier.
* These are unique per filesystem on a single machine.
+ *
+ * Note that the offset of fid_data is 4 bytes, so care must be taken to avoid
+ * undefined behavior accessing unaligned fields within an embedded struct.
#define MAXFIDSZ 16