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>
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 */
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 */
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);
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);