diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index 07bfa72f9649..ca165fa44ace 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -2688,6 +2688,27 @@ __bpf_kfunc struct task_struct *bpf_task_from_pid(s32 pid) return p; } +/* + * bpf_get_task_cmdline - Get the cmdline to a buffer + * + * @task: The task whose cmdline to get. + * @buffer: The buffer to save cmdline info. + * @len: The length of the buffer. + * + * Return: the size of the cmdline field copied. Note that the copy does + * not guarantee an ending NULL byte. A negative error code on failure. + */ +__bpf_kfunc int bpf_get_task_cmdline(struct task_struct *task, char *buffer, size_t len) +{ + int ret; + + ret = get_cmdline(task, buffer, len); + if (ret < 0) + memset(buffer, 0, len); + + return ret; +} + /** * bpf_task_from_vpid - Find a struct task_struct from its vpid by looking it up * in the pid namespace of the current task. If a task is returned, it must @@ -4428,6 +4449,7 @@ BTF_ID_FLAGS(func, bpf_task_get_cgroup1, KF_ACQUIRE | KF_RCU | KF_RET_NULL) BTF_ID_FLAGS(func, bpf_task_from_pid, KF_ACQUIRE | KF_RET_NULL) BTF_ID_FLAGS(func, bpf_task_from_vpid, KF_ACQUIRE | KF_RET_NULL) BTF_ID_FLAGS(func, bpf_throw) +BTF_ID_FLAGS(func, bpf_get_task_cmdline, KF_SLEEPABLE | KF_TRUSTED_ARGS) #ifdef CONFIG_BPF_EVENTS BTF_ID_FLAGS(func, bpf_send_signal_task, KF_TRUSTED_ARGS) #endif diff --git a/tools/testing/selftests/bpf/prog_tests/task_kfunc.c b/tools/testing/selftests/bpf/prog_tests/task_kfunc.c index 83b90335967a..c23c0be357d7 100644 --- a/tools/testing/selftests/bpf/prog_tests/task_kfunc.c +++ b/tools/testing/selftests/bpf/prog_tests/task_kfunc.c @@ -156,6 +156,10 @@ static const char * const vpid_success_tests[] = { "test_task_from_vpid_invalid", }; +static const char * const cmdline_success_tests[] = { + "test_get_task_cmdline", +}; + void test_task_kfunc(void) { int i; @@ -174,5 +178,12 @@ void test_task_kfunc(void) run_vpid_success_test(vpid_success_tests[i]); } + for (i = 0; i < ARRAY_SIZE(cmdline_success_tests); i++) { + if (!test__start_subtest(cmdline_success_tests[i])) + continue; + + run_success_test(cmdline_success_tests[i]); + } + RUN_TESTS(task_kfunc_failure); } diff --git a/tools/testing/selftests/bpf/progs/task_kfunc_success.c b/tools/testing/selftests/bpf/progs/task_kfunc_success.c index 5fb4fc19d26a..a7c42e693dae 100644 --- a/tools/testing/selftests/bpf/progs/task_kfunc_success.c +++ b/tools/testing/selftests/bpf/progs/task_kfunc_success.c @@ -367,6 +367,19 @@ int BPF_PROG(task_kfunc_acquire_trusted_walked, struct task_struct *task, u64 cl return 0; } +SEC("lsm.s/task_alloc") +int BPF_PROG(test_get_task_cmdline, struct task_struct *task) +{ + char buf[64]; + int ret; + + ret = bpf_get_task_cmdline(task, buf, sizeof(buf)); + if (ret < 0) + err = 1; + + return 0; +} + SEC("syscall") int test_task_from_vpid_current(const void *ctx) {