diff options
| author | Namjae Jeon <linkinjeon@kernel.org> | 2026-07-05 15:55:14 +0900 |
|---|---|---|
| committer | Namjae Jeon <linkinjeon@kernel.org> | 2026-08-17 15:00:29 +0900 |
| commit | 4ea46ea602fc7055eee4b5b0e84f90f22da7f7e7 (patch) | |
| tree | 2b3a47dae1756cc693d0fd292e76913e77deb424 | |
| parent | 497dbc5999a52efd55e079589b166e5c18a20fe3 (diff) | |
| download | linux-4ea46ea602fc7055eee4b5b0e84f90f22da7f7e7.tar.gz linux-4ea46ea602fc7055eee4b5b0e84f90f22da7f7e7.zip | |
ksmbd: protect private extended attributes
SMB clients can currently create an EA named NTACL because SMB EAs are
mapped into the user namespace while the ksmbd security descriptor is
stored as security.NTACL. Allowing the reserved logical name makes the
server-private ACL metadata appear writable through the SMB EA API.
Reject NTACL, DOSATTRIB, and DosStream-prefixed EA names without regard
to case. Filter the same private names from EA query results so stale or
externally-created user namespace attributes cannot be exposed.
This fixes smb2.ea.acl_xattr when acl_xattr_name is configured as
NTACL.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
| -rw-r--r-- | fs/smb/server/smb2pdu.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c index f16f3da4ee3d..31ca0872b0fb 100644 --- a/fs/smb/server/smb2pdu.c +++ b/fs/smb/server/smb2pdu.c @@ -2658,6 +2658,22 @@ out: return err; } +static bool smb2_is_private_ea(const char *name, size_t name_len) +{ + if (name_len == SD_PREFIX_LEN && + !strncasecmp(name, SD_PREFIX, SD_PREFIX_LEN)) + return true; + if (name_len == DOS_ATTRIBUTE_PREFIX_LEN && + !strncasecmp(name, DOS_ATTRIBUTE_PREFIX, + DOS_ATTRIBUTE_PREFIX_LEN)) + return true; + if (name_len >= STREAM_PREFIX_LEN && + !strncasecmp(name, STREAM_PREFIX, STREAM_PREFIX_LEN)) + return true; + + return false; +} + /** * smb2_set_ea() - handler for setting extended attributes using set * info command @@ -2699,6 +2715,10 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len, rc = -EINVAL; break; } + if (smb2_is_private_ea(eabuf->name, eabuf->EaNameLength)) { + rc = -EACCES; + break; + } memcpy(attr_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN); memcpy(&attr_name[XATTR_USER_PREFIX_LEN], eabuf->name, @@ -5274,17 +5294,13 @@ static int smb2_get_ea(struct ksmbd_work *work, struct ksmbd_file *fp, if (strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) continue; - if (!strncmp(&name[XATTR_USER_PREFIX_LEN], STREAM_PREFIX, - STREAM_PREFIX_LEN)) - continue; - if (req->InputBufferLength && strncmp(&name[XATTR_USER_PREFIX_LEN], ea_req->name, ea_req->EaNameLength)) continue; - if (!strncmp(&name[XATTR_USER_PREFIX_LEN], - DOS_ATTRIBUTE_PREFIX, DOS_ATTRIBUTE_PREFIX_LEN)) + if (smb2_is_private_ea(&name[XATTR_USER_PREFIX_LEN], + name_len - XATTR_USER_PREFIX_LEN)) continue; if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) |
