[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20240725234706.655613-2-song@kernel.org>
Date: Thu, 25 Jul 2024 16:47:05 -0700
From: Song Liu <song@...nel.org>
To: bpf@...r.kernel.org,
linux-fsdevel@...r.kernel.org,
linux-kernel@...r.kernel.org
Cc: kernel-team@...a.com,
andrii@...nel.org,
eddyz87@...il.com,
ast@...nel.org,
daniel@...earbox.net,
martin.lau@...ux.dev,
viro@...iv.linux.org.uk,
brauner@...nel.org,
jack@...e.cz,
kpsingh@...nel.org,
mattbobrowski@...gle.com,
Song Liu <song@...nel.org>
Subject: [PATCH bpf-next 1/2] bpf: Add kfunc bpf_get_dentry_xattr() to read xattr from dentry
The primary use case here is to read xattr for directories from BPF
programs. This feature enables tagging all the files in a directory
with a xattr on the directory. More specifically, starting from LSM hook
security_file_open(), we can read xattr of the file's parent directories.
To have referenced access to dentry, a few more kfuncs are added:
- bpf_file_dentry
- bpf_dget_parent
- bpf_dput
Both bpf_file_dentry and bpf_dget_parent take a reference to the dentry
(KF_ACQUIRE), which has to be released by bpf_dput (KF_RELEASE). This
makes sure only trusted pointers (KF_TRUSTED_ARGS) can be used for the
dentry.
Note that, file_dentry() doesn't take reference to the dentry, but
bpf_file_dentry() does.
Signed-off-by: Song Liu <song@...nel.org>
---
kernel/trace/bpf_trace.c | 60 ++++++++++++++++++++++++++++++++++------
1 file changed, 51 insertions(+), 9 deletions(-)
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index cd098846e251..b8e6eeabb773 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -1443,22 +1443,21 @@ late_initcall(bpf_key_sig_kfuncs_init);
__bpf_kfunc_start_defs();
/**
- * bpf_get_file_xattr - get xattr of a file
- * @file: file to get xattr from
+ * bpf_get_dentry_xattr - get xattr of a dentry
+ * @dentry: dentry to get xattr from
* @name__str: name of the xattr
* @value_p: output buffer of the xattr value
*
- * Get xattr *name__str* of *file* and store the output in *value_ptr*.
+ * Get xattr *name__str* of *dentry* and store the output in *value_ptr*.
*
* For security reasons, only *name__str* with prefix "user." is allowed.
*
* Return: 0 on success, a negative value on error.
*/
-__bpf_kfunc int bpf_get_file_xattr(struct file *file, const char *name__str,
- struct bpf_dynptr *value_p)
+__bpf_kfunc int bpf_get_dentry_xattr(struct dentry *dentry, const char *name__str,
+ struct bpf_dynptr *value_p)
{
struct bpf_dynptr_kern *value_ptr = (struct bpf_dynptr_kern *)value_p;
- struct dentry *dentry;
u32 value_len;
void *value;
int ret;
@@ -1471,20 +1470,63 @@ __bpf_kfunc int bpf_get_file_xattr(struct file *file, const char *name__str,
if (!value)
return -EINVAL;
- dentry = file_dentry(file);
ret = inode_permission(&nop_mnt_idmap, dentry->d_inode, MAY_READ);
if (ret)
return ret;
return __vfs_getxattr(dentry, dentry->d_inode, name__str, value, value_len);
}
+/**
+ * bpf_get_file_xattr - get xattr of a file
+ * @file: file to get xattr from
+ * @name__str: name of the xattr
+ * @value_p: output buffer of the xattr value
+ *
+ * Get xattr *name__str* of *file* and store the output in *value_ptr*.
+ *
+ * For security reasons, only *name__str* with prefix "user." is allowed.
+ *
+ * Return: 0 on success, a negative value on error.
+ */
+__bpf_kfunc int bpf_get_file_xattr(struct file *file, const char *name__str,
+ struct bpf_dynptr *value_p)
+{
+ struct dentry *dentry;
+
+ dentry = file_dentry(file);
+ return bpf_get_dentry_xattr(dentry, name__str, value_p);
+}
+
+__bpf_kfunc struct dentry *bpf_file_dentry(const struct file *file)
+{
+ /* file_dentry() does not hold reference to the dentry. We add a
+ * dget() here so that we can add KF_ACQUIRE flag to
+ * bpf_file_dentry().
+ */
+ return dget(file_dentry(file));
+}
+
+__bpf_kfunc struct dentry *bpf_dget_parent(struct dentry *dentry)
+{
+ return dget_parent(dentry);
+}
+
+__bpf_kfunc void bpf_dput(struct dentry *dentry)
+{
+ return dput(dentry);
+}
+
__bpf_kfunc_end_defs();
BTF_KFUNCS_START(fs_kfunc_set_ids)
+BTF_ID_FLAGS(func, bpf_get_dentry_xattr, KF_SLEEPABLE | KF_TRUSTED_ARGS)
BTF_ID_FLAGS(func, bpf_get_file_xattr, KF_SLEEPABLE | KF_TRUSTED_ARGS)
+BTF_ID_FLAGS(func, bpf_file_dentry, KF_TRUSTED_ARGS | KF_ACQUIRE)
+BTF_ID_FLAGS(func, bpf_dget_parent, KF_TRUSTED_ARGS | KF_ACQUIRE)
+BTF_ID_FLAGS(func, bpf_dput, KF_RELEASE)
BTF_KFUNCS_END(fs_kfunc_set_ids)
-static int bpf_get_file_xattr_filter(const struct bpf_prog *prog, u32 kfunc_id)
+static int fs_kfunc_filter(const struct bpf_prog *prog, u32 kfunc_id)
{
if (!btf_id_set8_contains(&fs_kfunc_set_ids, kfunc_id))
return 0;
@@ -1496,7 +1538,7 @@ static int bpf_get_file_xattr_filter(const struct bpf_prog *prog, u32 kfunc_id)
static const struct btf_kfunc_id_set bpf_fs_kfunc_set = {
.owner = THIS_MODULE,
.set = &fs_kfunc_set_ids,
- .filter = bpf_get_file_xattr_filter,
+ .filter = fs_kfunc_filter,
};
static int __init bpf_fs_kfuncs_init(void)
--
2.43.0
Powered by blists - more mailing lists