From: Kui-Feng Lee <thinker.li@gmail.com>
To: bpf@vger.kernel.org, ast@kernel.org, martin.lau@linux.dev,
andrii@kernel.org
Cc: sinquersw@gmail.com, kuifeng@meta.com,
Kui-Feng Lee <thinker.li@gmail.com>
Subject: [RFC bpf-next v4 6/6] selftests/bpf: test __uptr on the value of a task storage map.
Date: Fri, 16 Aug 2024 12:12:13 -0700 [thread overview]
Message-ID: <20240816191213.35573-7-thinker.li@gmail.com> (raw)
In-Reply-To: <20240816191213.35573-1-thinker.li@gmail.com>
Make sure the memory of uptrs have been mapped to the kernel properly. Also
ensure the values of uptrs in the kernel haven't been copied to userspace.
Signed-off-by: Kui-Feng Lee <thinker.li@gmail.com>
---
.../bpf/prog_tests/task_local_storage.c | 106 ++++++++++++++++++
.../selftests/bpf/progs/task_ls_uptr.c | 65 +++++++++++
2 files changed, 171 insertions(+)
create mode 100644 tools/testing/selftests/bpf/progs/task_ls_uptr.c
diff --git a/tools/testing/selftests/bpf/prog_tests/task_local_storage.c b/tools/testing/selftests/bpf/prog_tests/task_local_storage.c
index c33c05161a9e..5709b083021c 100644
--- a/tools/testing/selftests/bpf/prog_tests/task_local_storage.c
+++ b/tools/testing/selftests/bpf/prog_tests/task_local_storage.c
@@ -5,6 +5,7 @@
#include <unistd.h>
#include <sched.h>
#include <pthread.h>
+#include <sys/eventfd.h>
#include <sys/syscall.h> /* For SYS_xxx definitions */
#include <sys/types.h>
#include <test_progs.h>
@@ -14,6 +15,20 @@
#include "task_ls_recursion.skel.h"
#include "task_storage_nodeadlock.skel.h"
+struct user_data {
+ int a;
+ int b;
+ int result;
+};
+
+struct value_type {
+ struct user_data *udata;
+};
+
+#define MAGIC_VALUE 0xabcd1234
+
+#include "task_ls_uptr.skel.h"
+
static void test_sys_enter_exit(void)
{
struct task_local_storage *skel;
@@ -40,6 +55,95 @@ static void test_sys_enter_exit(void)
task_local_storage__destroy(skel);
}
+static struct user_data user_data __attribute__((aligned(16))) = {
+ .a = 1,
+ .b = 2,
+};
+
+static void test_uptr(void)
+{
+ struct task_ls_uptr *skel = NULL;
+ int task_fd = -1, ev_fd = -1;
+ struct value_type value;
+ int err, wstatus;
+ __u64 dummy = 1;
+ pid_t pid;
+
+ value.udata = &user_data;
+
+ task_fd = sys_pidfd_open(getpid(), 0);
+ if (!ASSERT_NEQ(task_fd, -1, "sys_pidfd_open"))
+ goto out;
+
+ ev_fd = eventfd(0, 0);
+ if (!ASSERT_NEQ(ev_fd, -1, "eventfd"))
+ goto out;
+
+ skel = task_ls_uptr__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "skel_open_and_load"))
+ goto out;
+
+ err = bpf_map_update_elem(bpf_map__fd(skel->maps.datamap), &task_fd, &value, 0);
+ if (!ASSERT_OK(err, "update_datamap"))
+ exit(1);
+
+ err = task_ls_uptr__attach(skel);
+ if (!ASSERT_OK(err, "skel_attach"))
+ goto out;
+
+ fflush(stdout);
+ fflush(stderr);
+
+ pid = fork();
+ if (pid < 0)
+ goto out;
+
+ /* Call syscall in the child process, but access the map value of
+ * the parent process in the BPF program to check if the user kptr
+ * is translated/mapped correctly.
+ */
+ if (pid == 0) {
+ /* child */
+
+ /* Overwrite the user_data in the child process to check if
+ * the BPF program accesses the user_data of the parent.
+ */
+ user_data.a = 0;
+ user_data.b = 0;
+
+ /* Wait for the parent to set child_pid */
+ read(ev_fd, &dummy, sizeof(dummy));
+
+ exit(0);
+ }
+
+ skel->bss->parent_pid = syscall(SYS_gettid);
+ skel->bss->child_pid = pid;
+
+ write(ev_fd, &dummy, sizeof(dummy));
+
+ err = waitpid(pid, &wstatus, 0);
+ ASSERT_EQ(err, pid, "waitpid");
+ skel->bss->child_pid = 0;
+
+ ASSERT_EQ(MAGIC_VALUE + user_data.a + user_data.b,
+ user_data.result, "result");
+
+ /* Check if user programs can access the value of user kptrs
+ * through bpf_map_lookup_elem(). Make sure the kernel value is not
+ * leaked.
+ */
+ err = bpf_map_lookup_elem(bpf_map__fd(skel->maps.datamap), &task_fd, &value);
+ if (!ASSERT_OK(err, "bpf_map_lookup_elem"))
+ goto out;
+ ASSERT_EQ(value.udata, NULL, "lookup_udata");
+
+out:
+ task_ls_uptr__destroy(skel);
+ close(ev_fd);
+ close(task_fd);
+}
+
static void test_exit_creds(void)
{
struct task_local_storage_exit_creds *skel;
@@ -237,4 +341,6 @@ void test_task_local_storage(void)
test_recursion();
if (test__start_subtest("nodeadlock"))
test_nodeadlock();
+ if (test__start_subtest("uptr"))
+ test_uptr();
}
diff --git a/tools/testing/selftests/bpf/progs/task_ls_uptr.c b/tools/testing/selftests/bpf/progs/task_ls_uptr.c
new file mode 100644
index 000000000000..473e6890d522
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/task_ls_uptr.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
+
+#include "vmlinux.h"
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_helpers.h>
+#include "task_kfunc_common.h"
+
+char _license[] SEC("license") = "GPL";
+
+struct user_data {
+ int a;
+ int b;
+ int result;
+};
+
+struct value_type {
+ struct user_data __uptr *udata;
+};
+
+struct {
+ __uint(type, BPF_MAP_TYPE_TASK_STORAGE);
+ __uint(map_flags, BPF_F_NO_PREALLOC);
+ __type(key, int);
+ __type(value, struct value_type);
+} datamap SEC(".maps");
+
+#define MAGIC_VALUE 0xabcd1234
+
+/* This is a workaround to avoid clang generating a forward reference for
+ * struct user_data. This is a known issue and will be fixed in the future.
+ */
+struct user_data __dummy;
+
+pid_t child_pid = 0;
+pid_t parent_pid = 0;
+
+SEC("tp_btf/sys_enter")
+int BPF_PROG(on_enter, struct pt_regs *regs, long id)
+{
+ struct task_struct *task, *data_task;
+ struct value_type *ptr;
+ struct user_data *udata;
+
+ task = bpf_get_current_task_btf();
+ if (task->pid != child_pid)
+ return 0;
+
+ data_task = bpf_task_from_pid(parent_pid);
+ if (!data_task)
+ return 0;
+
+ ptr = bpf_task_storage_get(&datamap, data_task, 0,
+ BPF_LOCAL_STORAGE_GET_F_CREATE);
+ bpf_task_release(data_task);
+ if (!ptr)
+ return 0;
+
+ udata = ptr->udata;
+ if (!udata)
+ return 0;
+ udata->result = MAGIC_VALUE + udata->a + udata->b;
+
+ return 0;
+}
--
2.34.1
prev parent reply other threads:[~2024-08-16 19:12 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-16 19:12 [RFC bpf-next v4 0/6] Share user memory to BPF program through task storage map Kui-Feng Lee
2024-08-16 19:12 ` [RFC bpf-next v4 1/6] bpf: define BPF_UPTR a new enumerator of btf_field_type Kui-Feng Lee
2024-08-16 19:12 ` [RFC bpf-next v4 2/6] bpf: Parse and support "uptr" tag Kui-Feng Lee
2024-08-16 19:12 ` [RFC bpf-next v4 3/6] bpf: Handle BPF_UPTR in verifier Kui-Feng Lee
2024-08-16 19:12 ` [RFC bpf-next v4 4/6] bpf: pin, translate, and unpin __uptr from syscalls Kui-Feng Lee
2024-08-28 23:24 ` Alexei Starovoitov
2024-09-04 22:21 ` Martin KaFai Lau
2024-09-06 20:11 ` Martin KaFai Lau
2024-09-06 23:44 ` Alexei Starovoitov
2024-09-07 1:32 ` Martin KaFai Lau
2024-09-07 4:03 ` Martin KaFai Lau
2024-08-16 19:12 ` [RFC bpf-next v4 5/6] libbpf: define __uptr Kui-Feng Lee
2024-08-27 23:13 ` Andrii Nakryiko
2024-08-28 17:53 ` Kui-Feng Lee
2024-08-16 19:12 ` Kui-Feng Lee [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240816191213.35573-7-thinker.li@gmail.com \
--to=thinker.li@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=kuifeng@meta.com \
--cc=martin.lau@linux.dev \
--cc=sinquersw@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.