From 668be05fcab6ebd5077d38114621d84cca6da56a Mon Sep 17 00:00:00 2001
From: Luis Gerhorst <privat@luisgerhorst.de>
Date: Wed, 7 Jul 2021 14:43:50 +0200
Subject: [PATCH] bpf_task_iterdents64: Pass name_user to BPF callback

---
 include/uapi/linux/bpf.h       |  2 +-
 kernel/bpf/task.c              | 19 +++++++++++++++++--
 tools/include/uapi/linux/bpf.h |  2 +-
 3 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 340cbbd160232..cbb0defbd8418 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -3845,7 +3845,7 @@ union bpf_attr {
  *	Return
  *		TODO.
  *
- * int bpf_task_iterdents64(int dir_fd, int prog_fd)
+ * int bpf_task_iterdents64(u32 dir_fd, u32 prog_fd, void *name_user, u32 name_user_size)
  *	Description
  *		TODO.
  *	Return
diff --git a/kernel/bpf/task.c b/kernel/bpf/task.c
index 222f4efb11d5c..06313581b32cd 100644
--- a/kernel/bpf/task.c
+++ b/kernel/bpf/task.c
@@ -123,6 +123,8 @@ struct iterdents_callback64 {
 	struct bpf_prog *prog;
 	int dfd;
 	int error;
+	void __user *name_user;
+	size_t name_user_size;
 };
 
 static int iterdents64_actor(struct dir_context *ctx, const char *name, int namelen,
@@ -130,6 +132,8 @@ static int iterdents64_actor(struct dir_context *ctx, const char *name, int name
 {
 	struct iterdents_callback64 *buf =
 		container_of(ctx, struct iterdents_callback64, ctx);
+	void __user *name_user = buf->name_user;
+	size_t name_user_size = buf->name_user_size;
 
 	/* TODO: Is the following required? */
 	/* buf->error = verify_dirent_name(name, namlen); */
@@ -137,9 +141,16 @@ static int iterdents64_actor(struct dir_context *ctx, const char *name, int name
 	/* 	goto ret; */
 	/* } */
 
+	if (name_user && namelen + 1 <= name_user_size) {
+		if (copy_to_user(name_user, name, namelen + 1)) {
+			buf->error = -EFAULT;
+			goto ret;
+		}
+	}
+
 	struct bpf_dirent64 d = {
 		.name = name,
-		.name_end = name + namelen + 1, /* null byte */
+		.name_end = (void *) name + namelen + 1, /* null byte */
 		.namelen = namelen,
 		.offset = offset,
 		.ino = ino,
@@ -155,7 +166,7 @@ static int iterdents64_actor(struct dir_context *ctx, const char *name, int name
 	return buf->error;
 }
 
-BPF_CALL_2(bpf_task_iterdents64, unsigned int, dfd, unsigned int, prog_fd)
+BPF_CALL_4(bpf_task_iterdents64, u32, dfd, u32, prog_fd, void *, name_user, u32, name_user_size)
 {
 	int ret = 0;
 	int error;
@@ -163,6 +174,8 @@ BPF_CALL_2(bpf_task_iterdents64, unsigned int, dfd, unsigned int, prog_fd)
 	struct iterdents_callback64 buf = {
 		.ctx.actor = iterdents64_actor,
 		.dfd = dfd,
+		.name_user = name_user,
+		.name_user_size = name_user_size,
 	};
 
 	/* TODO: Check priviledge level / capability of current process before
@@ -201,6 +214,8 @@ const struct bpf_func_proto bpf_task_iterdents64_proto = {
 	.ret_type	= RET_INTEGER,
 	.arg1_type	= ARG_ANYTHING,
 	.arg2_type	= ARG_ANYTHING,
+	.arg3_type	= ARG_ANYTHING,
+	.arg4_type	= ARG_ANYTHING,
 };
 
 long do_open_kernel(int dfd, const char *filename, int flags, umode_t mode);
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 079cd34b3858d..09242c14dbc51 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -3845,7 +3845,7 @@ union bpf_attr {
  *	Return
  *		TODO.
  *
- * int bpf_task_iterdents64(int dir_fd, int prog_fd)
+ * int bpf_task_iterdents64(u32 dir_fd, u32 prog_fd, void *name_user, u32 name_user_size)
  *	Description
  *		TODO.
  *	Return
-- 
GitLab