]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bpf: fix crash in bpf_[set|remove]_dentry_xattr for negative dentries
authorMatt Bobrowski <mattbobrowski@google.com>
Thu, 30 Apr 2026 07:38:36 +0000 (07:38 +0000)
committerChristian Brauner <brauner@kernel.org>
Mon, 11 May 2026 09:23:00 +0000 (11:23 +0200)
bpf_set_dentry_xattr and bpf_remove_dentry_xattr BPF kfuncs attempt to
lock the inode of the supplied dentry without checking if it is
NULL. If a negative dentry is passed (e.g. from
security_inode_create), d_inode(dentry) returns NULL, and
inode_lock(inode) will cause a NULL pointer dereference.

Trivially fix this by adding a NULL check for inode before attempting
to lock it, returning -EINVAL if it is NULL.

Additionally, drop WARN_ON(!inode) in bpf_xattr_read_permission() and
bpf_xattr_write_permission(). These warnings could be triggered by
passing a negative dentry to bpf_get_dentry_xattr() or the _locked
variants of the xattr kfuncs, potentially causing a Denial of Service
on systems with panic_on_warn enabled. Instead, simply return -EINVAL.

Reported-by: Quan Sun <2022090917019@std.uestc.edu.cn>
Closes: https://lore.kernel.org/bpf/1587cbf4-1293-4e25-ad24-c970836a1686@std.uestc.edu.cn/
Fixes: 56467292794b ("bpf: fs/xattr: Add BPF kfuncs to set and remove xattrs")
Signed-off-by: Matt Bobrowski <mattbobrowski@google.com>
Link: https://patch.msgid.link/20260430073836.2894001-1-mattbobrowski@google.com
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/bpf_fs_kfuncs.c

index e4e51a1d0de2817e03d72e2c9497e47cc8108a5a..606319dd69e803fb1d346fa10ebc5cf081a8a6fa 100644 (file)
@@ -100,7 +100,7 @@ static bool match_security_bpf_prefix(const char *name__str)
 
 static int bpf_xattr_read_permission(const char *name, struct inode *inode)
 {
-       if (WARN_ON(!inode))
+       if (!inode)
                return -EINVAL;
 
        /* Allow reading xattr with user. and security.bpf. prefix */
@@ -170,7 +170,7 @@ __bpf_kfunc_end_defs();
 
 static int bpf_xattr_write_permission(const char *name, struct inode *inode)
 {
-       if (WARN_ON(!inode))
+       if (!inode)
                return -EINVAL;
 
        /* Only allow setting and removing security.bpf. xattrs */
@@ -289,6 +289,9 @@ __bpf_kfunc int bpf_set_dentry_xattr(struct dentry *dentry, const char *name__st
        struct inode *inode = d_inode(dentry);
        int ret;
 
+       if (!inode)
+               return -EINVAL;
+
        inode_lock(inode);
        ret = bpf_set_dentry_xattr_locked(dentry, name__str, value_p, flags);
        inode_unlock(inode);
@@ -314,6 +317,9 @@ __bpf_kfunc int bpf_remove_dentry_xattr(struct dentry *dentry, const char *name_
        struct inode *inode = d_inode(dentry);
        int ret;
 
+       if (!inode)
+               return -EINVAL;
+
        inode_lock(inode);
        ret = bpf_remove_dentry_xattr_locked(dentry, name__str);
        inode_unlock(inode);