[PATCH] fs/ntfs3: fix NULL deref in ni_std5() on stream inodes

From: Henry Martin

Date: Tue Oct 27 2026 - 11:23:55 EST


ni_std5() looks up the standard information attribute in the inode's
own MFT record:

attr = mi_find_attr(ni, &ni->mi, NULL, ATTR_STD, NULL, 0, NULL);

without redirecting to the base inode. For an ADS stream inode,
ni->mi.mrec is never initialized (ntfs_init_ads_node() in
fs/ntfs3/inode.c leaves mi.mrec NULL), so mi_find_attr() ->
mi_enum_attr() dereferences rec == NULL:

BUG: unable to handle kernel NULL pointer dereference
RIP: mi_enum_attr+0x18/0x180

The SYSTEM_NTFS_SECURITY xattr path calls ni_std5() without a guard
for stream inodes (fs/ntfs3/xattr.c): ntfs_set_acl()/ntfs_xattr_set()
reach it via ntfs_insert_security -> ni_lock(ni) -> ni_std5(ni) on the
stream inode, and the stream inode inherits the base's i_mode/uid/gid,
so the may_write_xattr() ownership check passes for the file owner.
The default stream-name parsing (colons) is enabled, so an
unprivileged local user can open("file:stream"), set the security
descriptor xattr on it and panic the kernel.

Redirect stream inodes to their base record in ni_std5().

This issue was discovered by Tencent CodeBuddy Security.

Fixes: be71b5cba2e6 ("fs/ntfs3: Add attrib operations")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Henry Martin <bsdhenrymartin@xxxxxxxxx>
---
fs/ntfs3/frecord.c | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c
index bead01a953f3f..dce6400195aee 100644
--- a/fs/ntfs3/frecord.c
+++ b/fs/ntfs3/frecord.c
@@ -89,6 +89,13 @@ struct ATTR_STD_INFO5 *ni_std5(struct ntfs_inode *ni)
{
const struct ATTRIB *attr;

+ /* Stream inodes have no MFT record of their own (mi.mrec is
+ * NULL); the standard information attribute lives in the base
+ * record.
+ */
+ if (ni->base && ni->base != ni)
+ ni = ni->base;
+
attr = mi_find_attr(ni, &ni->mi, NULL, ATTR_STD, NULL, 0, NULL);

return attr ? resident_data_ex(attr, sizeof(struct ATTR_STD_INFO5)) :
--
2.43.7