Index: sys/fs/tmpfs/tmpfs.h =================================================================== --- sys/fs/tmpfs/tmpfs.h +++ sys/fs/tmpfs/tmpfs.h @@ -37,6 +37,7 @@ #ifndef _FS_TMPFS_TMPFS_H_ #define _FS_TMPFS_TMPFS_H_ +#include #include #include @@ -393,12 +394,12 @@ * This structure maps a file identifier to a tmpfs node. Used by the * NFS code. */ -struct tmpfs_fid { - uint16_t tf_len; - uint16_t tf_pad; - ino_t tf_id; - unsigned long tf_gen; +struct tmpfs_fid_data { + ino_t tfd_id; + unsigned long tfd_gen; }; +_Static_assert(sizeof(struct tmpfs_fid_data) <= MAXFIDSZ, + "(struct tmpfs_fid_data) is larger than (struct fid).fid_data"); struct tmpfs_dir_cursor { struct tmpfs_dirent *tdc_current; Index: sys/fs/tmpfs/tmpfs_vfsops.c =================================================================== --- sys/fs/tmpfs/tmpfs_vfsops.c +++ sys/fs/tmpfs/tmpfs_vfsops.c @@ -566,24 +566,29 @@ tmpfs_fhtovp(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp) { - struct tmpfs_fid *tfhp; + struct tmpfs_fid_data tfd; struct tmpfs_mount *tmp; struct tmpfs_node *node; int error; + if (fhp->fid_len != sizeof(struct tmpfs_fid_data)) + return (EINVAL); + + /* + * Copy from fid_data onto the stack to avoid unaligned pointer use. + * See the comment in sys/mount.h on struct fid for details. + */ + memcpy(&tfd, fhp->fid_data, fhp->fid_len); + tmp = VFS_TO_TMPFS(mp); - tfhp = (struct tmpfs_fid *)fhp; - if (tfhp->tf_len != sizeof(struct tmpfs_fid)) + if (tfd.tfd_id >= tmp->tm_nodes_max) return (EINVAL); - if (tfhp->tf_id >= tmp->tm_nodes_max) - return (EINVAL); - TMPFS_LOCK(tmp); LIST_FOREACH(node, &tmp->tm_nodes_used, tn_entries) { - if (node->tn_id == tfhp->tf_id && - node->tn_gen == tfhp->tf_gen) { + if (node->tn_id == tfd.tfd_id && + node->tn_gen == tfd.tfd_gen) { tmpfs_ref_node(node); break; } Index: sys/fs/tmpfs/tmpfs_vnops.c =================================================================== --- sys/fs/tmpfs/tmpfs_vnops.c +++ sys/fs/tmpfs/tmpfs_vnops.c @@ -1435,16 +1435,28 @@ static int tmpfs_vptofh(struct vop_vptofh_args *ap) +/* +vop_vptofh { + IN struct vnode *a_vp; + IN struct fid *a_fhp; +}; +*/ { - struct tmpfs_fid *tfhp; + struct tmpfs_fid_data tfd; struct tmpfs_node *node; + struct fid *fhp; - tfhp = (struct tmpfs_fid *)ap->a_fhp; node = VP_TO_TMPFS_NODE(ap->a_vp); + fhp = ap->a_fhp; + fhp->fid_len = sizeof(tfd); - tfhp->tf_len = sizeof(struct tmpfs_fid); - tfhp->tf_id = node->tn_id; - tfhp->tf_gen = node->tn_gen; + /* + * Copy into fid_data from the stack to avoid unaligned pointer use. + * See the comment in sys/mount.h on struct fid for details. + */ + tfd.tfd_id = node->tn_id; + tfd.tfd_gen = node->tn_gen; + memcpy(fhp->fid_data, &tfd, fhp->fid_len); return (0); } Index: sys/sys/mount.h =================================================================== --- sys/sys/mount.h +++ sys/sys/mount.h @@ -57,6 +57,13 @@ /* * File identifier. * These are unique per filesystem on a single machine. + * + * Note that fid_data is at a 32-bit offset, so care must be taken to avoid + * unaligned access to fields within an embedded struct, which is undefined + * behavior. For example, if fid_data is used for a struct with 64-bit + * fields, it is undefined behavior to access the fields through a pointer + * to fid_data on 64-bit platforms. Use memcpy to load/store the struct + * instead. */ #define MAXFIDSZ 16