summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Komarov <almaz.alexandrovich@paragon-software.com>2026-06-10 12:31:01 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-07-04 13:45:02 +0200
commit293a84fa40b3a1b3471c0545722724bc10973f76 (patch)
tree5734818d5bcc6e3283f5928fca0a2f64ba14be11
parentc04d9ece23deb9e26c19f9ca215e98b3295aa1bb (diff)
downloadlinux-293a84fa40b3a1b3471c0545722724bc10973f76.tar.gz
linux-293a84fa40b3a1b3471c0545722724bc10973f76.zip
ntfs3: reject direct userspace writes to reserved $LX* xattrs
commit 5b08dccecf825cbf905f348bc6ccb497507e28e2 upstream. NTFS3 uses $LXUID, $LXGID, $LXMOD and $LXDEV as internal WSL permission metadata and reloads them into i_uid, i_gid and i_mode from ntfs_get_wsl_perm(). Because the empty-prefix xattr handler also lets file owners call setxattr() on these names directly, an unprivileged writer on a writable ntfs3 mount can plant root ownership and S_ISUID on their own file and gain euid 0 after inode reload. Reject direct userspace writes to the reserved $LX* names. Internal ntfs3 metadata updates are unchanged because ntfs_save_wsl_perm() writes them via ntfs_set_ea() directly. Signed-off-by: Zhen Yan <sdjasjbuaa@gmail.com> [almaz.alexandrovich@paragon-software.com: added an additional check for non privileged users] Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/ntfs3/xattr.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c
index 9eeac0ab2b71..372cf2f2e89b 100644
--- a/fs/ntfs3/xattr.c
+++ b/fs/ntfs3/xattr.c
@@ -851,6 +851,12 @@ out:
return err;
}
+static bool ntfs_is_reserved_lxattr(const char *name)
+{
+ return !strcmp(name, "$LXUID") || !strcmp(name, "$LXGID") ||
+ !strcmp(name, "$LXMOD") || !strcmp(name, "$LXDEV");
+}
+
/*
* ntfs_setxattr - inode_operations::setxattr
*/
@@ -955,6 +961,12 @@ set_new_fa:
goto out;
}
+ /* Do not allow non privileged users to change $LXUID/$LXGID... */
+ if (ntfs_is_reserved_lxattr(name) && !capable(CAP_SYS_ADMIN)) {
+ err = -EPERM;
+ goto out;
+ }
+
/* Deal with NTFS extended attribute. */
err = ntfs_set_ea(inode, name, strlen(name), value, size, flags, 0,
NULL);