smb: client: avoid using uninitialized SIDs in cifs_posix_to_fattr()

cifs_posix_to_fattr() ignores the return value of posix_info_parse().
When a malformed POSIX directory entry is encountered (e.g. invalid
SID lengths from an untrusted server), posix_info_parse() returns -1
without populating the 'parsed' struct.  The uninitialized stack
memory in parsed.owner and parsed.group is then passed to
sid_to_id(), which processes the garbage bytes and passes them to
request_key() to construct a SID string, potentially leaking kernel
stack contents to the userspace idmap daemon.

Fix this by checking the return value and skipping the SID-to-id
mapping when parsing fails.  The remaining fattr fields (timestamps,
mode, etc.) are populated directly from the 'info' pointer so they
are unaffected.

Closes: https://sashiko.dev/#/patchset/20260906172005.627163-1-pc%40manguebit.org
Closes: https://sashiko.dev/#/patchset/20260906181540.647469-1-pc%40manguebit.org
Reviewed-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Paulo Alcantara <pc@manguebit.org>
Cc: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Cc: Shyam Prasad N <sprasad@microsoft.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Bharath SM <bharathsm@microsoft.com>
Cc: stable@vger.kernel.org
This commit is contained in:
Paulo Alcantara 2026-09-06 14:40:39 -03:00
parent cd2b2b5792
commit da6e258424

View File

@ -244,8 +244,9 @@ cifs_posix_to_fattr(struct cifs_fattr *fattr, struct smb2_posix_info *info,
{
unsigned int sbflags = cifs_sb_flags(cifs_sb);
struct smb2_posix_info_parsed parsed;
int rc;
posix_info_parse(info, NULL, &parsed);
rc = posix_info_parse(info, NULL, &parsed);
memset(fattr, 0, sizeof(*fattr));
fattr->cf_uniqueid = le64_to_cpu(info->Inode);
@ -284,10 +285,15 @@ cifs_posix_to_fattr(struct cifs_fattr *fattr, struct smb2_posix_info *info,
fattr->cf_uid = cifs_sb->ctx->linux_uid;
fattr->cf_gid = cifs_sb->ctx->linux_gid;
if (!(sbflags & CIFS_MOUNT_OVERR_UID))
sid_to_id(cifs_sb, &parsed.owner, fattr, SIDOWNER);
if (!(sbflags & CIFS_MOUNT_OVERR_GID))
sid_to_id(cifs_sb, &parsed.group, fattr, SIDGROUP);
if (rc < 0) {
cifs_dbg(VFS, "%s: failed to parse SIDs: %d\n",
__func__, rc);
} else {
if (!(sbflags & CIFS_MOUNT_OVERR_UID))
sid_to_id(cifs_sb, &parsed.owner, fattr, SIDOWNER);
if (!(sbflags & CIFS_MOUNT_OVERR_GID))
sid_to_id(cifs_sb, &parsed.group, fattr, SIDGROUP);
}
}
static void __dir_info_to_fattr(struct cifs_fattr *fattr, const void *info)