@@ -10,6 +10,7 @@
#include <linux/bpf_perf_event.h>
#include <linux/btf.h>
#include <linux/filter.h>
+#include <linux/fs_struct.h>
#include <linux/uaccess.h>
#include <linux/ctype.h>
#include <linux/kprobes.h>
@@ -1557,6 +1558,83 @@ __bpf_kfunc void bpf_put_file(struct file *f)
fput(f);
}
+/**
+ * bpf_get_task_fs_root - get a reference on the fs_struct's root for the
+ * supplied task_struct
+ * @task: task_struct of which the fs_struct's root path to get a reference on
+ *
+ * Get a reference on the root path associated with the supplied *task*. The
+ * referenced path retruned from this kfunc must be released using
+ * bpf_put_path().
+ *
+ * Return: A referenced path pointer to the fs_struct's root of the supplied
+ * *task*, or NULL.
+ */
+__bpf_kfunc struct path *bpf_get_task_fs_root(struct task_struct *task)
+{
+ struct path *root;
+ struct fs_struct *fs;
+
+ task_lock(task);
+ fs = task->fs;
+ if (unlikely(fs)) {
+ task_unlock(task);
+ return NULL;
+ }
+
+ spin_lock(&fs->lock);
+ root = &fs->root;
+ path_get(root);
+ spin_unlock(&fs->lock);
+ task_unlock(task);
+
+ return root;
+}
+
+/**
+ * bpf_get_task_fs_pwd - get a reference on the fs_struct's pwd for the supplied
+ * task_struct
+ * @task: task_struct of which the fs_struct's pwd path to get a reference on
+ *
+ * Get a reference on the pwd path associated with the supplied *task*. A
+ * referenced path returned from this kfunc must be released using
+ * bpf_put_path().
+ *
+ * Return: A referenced path pointer to the fs_struct's pwd of the supplied
+ * *task*, or NULL.
+ */
+__bpf_kfunc struct path *bpf_get_task_fs_pwd(struct task_struct *task)
+{
+ struct path *pwd;
+ struct fs_struct *fs;
+
+ task_lock(task);
+ fs = task->fs;
+ if (unlikely(fs)) {
+ task_unlock(task);
+ return NULL;
+ }
+
+ spin_lock(&fs->lock);
+ pwd = &fs->pwd;
+ path_get(pwd);
+ spin_unlock(&fs->lock);
+ task_unlock(task);
+
+ return pwd;
+}
+
+/**
+ * bpf_put_path - put the reference on the supplied path
+ * @path: path of which to put a reference on
+ *
+ * Put a reference on the supplied *path*.
+ */
+__bpf_kfunc void bpf_put_path(struct path *path)
+{
+ path_put(path);
+}
+
__bpf_kfunc_end_defs();
BTF_KFUNCS_START(lsm_kfunc_set_ids)
@@ -1568,6 +1646,11 @@ BTF_ID_FLAGS(func, bpf_get_task_exe_file,
BTF_ID_FLAGS(func, bpf_get_mm_exe_file,
KF_ACQUIRE | KF_TRUSTED_ARGS | KF_RET_NULL)
BTF_ID_FLAGS(func, bpf_put_file, KF_RELEASE | KF_SLEEPABLE)
+BTF_ID_FLAGS(func, bpf_get_task_fs_root,
+ KF_ACQUIRE | KF_TRUSTED_ARGS | KF_RET_NULL)
+BTF_ID_FLAGS(func, bpf_get_task_fs_pwd,
+ KF_ACQUIRE | KF_TRUSTED_ARGS | KF_RET_NULL)
+BTF_ID_FLAGS(func, bpf_put_path, KF_RELEASE | KF_SLEEPABLE)
BTF_KFUNCS_END(lsm_kfunc_set_ids)
static int bpf_lsm_kfunc_filter(const struct bpf_prog *prog, u32 kfunc_id)
Add the ability to obtain a reference on a common set of path's that are associated with a task_struct's fs_struct. Both fs_struct's root and pwd paths are commonly operated on in BPF LSM programs and at times handed off to BPF helpers and such. There needs to be a mechanism that supports BPF LSM programs to obtain stable handle to such in-kernel structures. We provide that mechanism through the introduction of the following new BPF kfuncs: struct path *bpf_get_task_fs_root(struct task_struct *task); struct path *bpf_get_task_fs_pwd(struct task_struct *task); void bpf_put_path(struct path *path); Signed-off-by: Matt Bobrowski <mattbobrowski@google.com> --- kernel/trace/bpf_trace.c | 83 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+)