summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaulo Alcantara <pc@manguebit.org>2026-09-13 21:09:15 -0300
committerPaulo Alcantara <pc@manguebit.org>2026-09-14 21:52:55 -0300
commite1aeaf79dea51e6065da56924bc07e22d59012ac (patch)
tree3982701c7e78ada7769e4850daf4bf5c68875927
parente75c96157d45e498970158c8f7373d90102e33b9 (diff)
downloadlinux-next-e1aeaf79dea51e6065da56924bc07e22d59012ac.tar.gz
linux-next-e1aeaf79dea51e6065da56924bc07e22d59012ac.zip
smb: client: fix unaligned access in WSL reparse point parser
When wsl_to_fattr() parses WSL extended attributes, it computes a payload pointer from ea->ea_data + ea_name_length + 1. Since the smb2_file_full_ea_info struct is __packed and all WSL xattr names are 6 bytes long, the value pointer always lands at an odd byte offset, never satisfying __le32 or __le64 alignment requirements. The code then casts this pointer to __le32 * or __le64 * and dereferences it directly, which may cause alignment faults on some architectures. Replace all such casts with get_unaligned_le32() and get_unaligned_le64() in reparse_mkdev(), wsl_make_kuid(), wsl_make_kgid() and wsl_to_fattr(). Closes: https://sashiko.dev/#/patchset/20260906200517.725015-1-pc%40manguebit.org Fixes: 78e26bec4d6d ("smb: client: parse uid, gid, mode and dev from WSL reparse points") Reviewed-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org> Cc: David Howells <dhowells@redhat.com> Cc: Tom Talpey <tom@talpey.com> Cc: Shyam Prasad N <sprasad@microsoft.com> Cc: Ronnie Sahlberg <ronniesahlberg@gmail.com> Cc: Bharath SM <bharathsm@microsoft.com> Cc: Namjae Jeon <linkinjeon@kernel.org> Cc: stable@vger.kernel.org
-rw-r--r--fs/smb/client/reparse.c4
-rw-r--r--fs/smb/client/reparse.h7
2 files changed, 6 insertions, 5 deletions
diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
index 9e31fce7e0a5..6ac69f4d391a 100644
--- a/fs/smb/client/reparse.c
+++ b/fs/smb/client/reparse.c
@@ -1201,9 +1201,9 @@ static bool wsl_to_fattr(struct cifs_open_info_data *data,
fattr->cf_gid = wsl_make_kgid(cifs_sb, v);
} else if (!strncmp(name, SMB2_WSL_XATTR_MODE, nlen)) {
/* File type in reparse point tag and in xattr mode must match. */
- if (S_DT(fattr->cf_mode) != S_DT(le32_to_cpu(*(__le32 *)v)))
+ if (S_DT(fattr->cf_mode) != S_DT(get_unaligned_le32(v)))
return false;
- fattr->cf_mode = (umode_t)le32_to_cpu(*(__le32 *)v);
+ fattr->cf_mode = (umode_t)get_unaligned_le32(v);
} else if (!strncmp(name, SMB2_WSL_XATTR_DEV, nlen)) {
fattr->cf_rdev = reparse_mkdev(v);
have_xattr_dev = true;
diff --git a/fs/smb/client/reparse.h b/fs/smb/client/reparse.h
index 49efd85b1e94..05b2cecb4495 100644
--- a/fs/smb/client/reparse.h
+++ b/fs/smb/client/reparse.h
@@ -9,6 +9,7 @@
#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/uidgid.h>
+#include <linux/unaligned.h>
#include "fs_context.h"
#include "cifsglob.h"
#include "../common/smbfsctl.h"
@@ -23,7 +24,7 @@
static inline dev_t reparse_mkdev(void *ptr)
{
- u64 v = le64_to_cpu(*(__le64 *)ptr);
+ u64 v = get_unaligned_le64(ptr);
return MKDEV(v & 0xffffffff, v >> 32);
}
@@ -31,7 +32,7 @@ static inline dev_t reparse_mkdev(void *ptr)
static inline kuid_t wsl_make_kuid(struct cifs_sb_info *cifs_sb,
void *ptr)
{
- u32 uid = le32_to_cpu(*(__le32 *)ptr);
+ u32 uid = get_unaligned_le32(ptr);
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_OVERR_UID)
return cifs_sb->ctx->linux_uid;
@@ -41,7 +42,7 @@ static inline kuid_t wsl_make_kuid(struct cifs_sb_info *cifs_sb,
static inline kgid_t wsl_make_kgid(struct cifs_sb_info *cifs_sb,
void *ptr)
{
- u32 gid = le32_to_cpu(*(__le32 *)ptr);
+ u32 gid = get_unaligned_le32(ptr);
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_OVERR_GID)
return cifs_sb->ctx->linux_gid;