OSDN Git Service

selftests/bpf: Add additional tests for bpf_lookup_*_key()
authorRoberto Sassu <roberto.sassu@huawei.com>
Tue, 20 Sep 2022 07:59:49 +0000 (09:59 +0200)
committerAlexei Starovoitov <ast@kernel.org>
Thu, 22 Sep 2022 00:33:42 +0000 (17:33 -0700)
Add a test to ensure that bpf_lookup_user_key() creates a referenced
special keyring when the KEY_LOOKUP_CREATE flag is passed to this function.

Ensure that the kfunc rejects invalid flags.

Ensure that a keyring can be obtained from bpf_lookup_system_key() when one
of the pre-determined keyring IDs is provided.

The test is currently blacklisted for s390x (JIT does not support calling
kernel function).

Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
Link: https://lore.kernel.org/r/20220920075951.929132-12-roberto.sassu@huaweicloud.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/DENYLIST.s390x
tools/testing/selftests/bpf/prog_tests/lookup_key.c [new file with mode: 0644]
tools/testing/selftests/bpf/progs/test_lookup_key.c [new file with mode: 0644]

index 981c2be..a6ac5dc 100644 (file)
@@ -72,3 +72,4 @@ cgroup_hierarchical_stats                # JIT does not support calling kernel f
 htab_update                              # failed to attach: ERROR: strerror_r(-524)=22                                (trampoline)
 tracing_struct                           # failed to auto-attach: -524                                                 (trampoline)
 user_ringbuf                             # failed to find kernel BTF type ID of '__s390x_sys_prctl': -3                (?)
+lookup_key                               # JIT does not support calling kernel function                                (kfunc)
diff --git a/tools/testing/selftests/bpf/prog_tests/lookup_key.c b/tools/testing/selftests/bpf/prog_tests/lookup_key.c
new file mode 100644 (file)
index 0000000..68025e8
--- /dev/null
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright (C) 2022 Huawei Technologies Duesseldorf GmbH
+ *
+ * Author: Roberto Sassu <roberto.sassu@huawei.com>
+ */
+
+#include <linux/keyctl.h>
+#include <test_progs.h>
+
+#include "test_lookup_key.skel.h"
+
+#define KEY_LOOKUP_CREATE      0x01
+#define KEY_LOOKUP_PARTIAL     0x02
+
+static bool kfunc_not_supported;
+
+static int libbpf_print_cb(enum libbpf_print_level level, const char *fmt,
+                          va_list args)
+{
+       char *func;
+
+       if (strcmp(fmt, "libbpf: extern (func ksym) '%s': not found in kernel or module BTFs\n"))
+               return 0;
+
+       func = va_arg(args, char *);
+
+       if (strcmp(func, "bpf_lookup_user_key") && strcmp(func, "bpf_key_put") &&
+           strcmp(func, "bpf_lookup_system_key"))
+               return 0;
+
+       kfunc_not_supported = true;
+       return 0;
+}
+
+void test_lookup_key(void)
+{
+       libbpf_print_fn_t old_print_cb;
+       struct test_lookup_key *skel;
+       __u32 next_id;
+       int ret;
+
+       skel = test_lookup_key__open();
+       if (!ASSERT_OK_PTR(skel, "test_lookup_key__open"))
+               return;
+
+       old_print_cb = libbpf_set_print(libbpf_print_cb);
+       ret = test_lookup_key__load(skel);
+       libbpf_set_print(old_print_cb);
+
+       if (ret < 0 && kfunc_not_supported) {
+               printf("%s:SKIP:bpf_lookup_*_key(), bpf_key_put() kfuncs not supported\n",
+                      __func__);
+               test__skip();
+               goto close_prog;
+       }
+
+       if (!ASSERT_OK(ret, "test_lookup_key__load"))
+               goto close_prog;
+
+       ret = test_lookup_key__attach(skel);
+       if (!ASSERT_OK(ret, "test_lookup_key__attach"))
+               goto close_prog;
+
+       skel->bss->monitored_pid = getpid();
+       skel->bss->key_serial = KEY_SPEC_THREAD_KEYRING;
+
+       /* The thread-specific keyring does not exist, this test fails. */
+       skel->bss->flags = 0;
+
+       ret = bpf_prog_get_next_id(0, &next_id);
+       if (!ASSERT_LT(ret, 0, "bpf_prog_get_next_id"))
+               goto close_prog;
+
+       /* Force creation of the thread-specific keyring, this test succeeds. */
+       skel->bss->flags = KEY_LOOKUP_CREATE;
+
+       ret = bpf_prog_get_next_id(0, &next_id);
+       if (!ASSERT_OK(ret, "bpf_prog_get_next_id"))
+               goto close_prog;
+
+       /* Pass both lookup flags for parameter validation. */
+       skel->bss->flags = KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL;
+
+       ret = bpf_prog_get_next_id(0, &next_id);
+       if (!ASSERT_OK(ret, "bpf_prog_get_next_id"))
+               goto close_prog;
+
+       /* Pass invalid flags. */
+       skel->bss->flags = UINT64_MAX;
+
+       ret = bpf_prog_get_next_id(0, &next_id);
+       if (!ASSERT_LT(ret, 0, "bpf_prog_get_next_id"))
+               goto close_prog;
+
+       skel->bss->key_serial = 0;
+       skel->bss->key_id = 1;
+
+       ret = bpf_prog_get_next_id(0, &next_id);
+       if (!ASSERT_OK(ret, "bpf_prog_get_next_id"))
+               goto close_prog;
+
+       skel->bss->key_id = UINT32_MAX;
+
+       ret = bpf_prog_get_next_id(0, &next_id);
+       ASSERT_LT(ret, 0, "bpf_prog_get_next_id");
+
+close_prog:
+       skel->bss->monitored_pid = 0;
+       test_lookup_key__destroy(skel);
+}
diff --git a/tools/testing/selftests/bpf/progs/test_lookup_key.c b/tools/testing/selftests/bpf/progs/test_lookup_key.c
new file mode 100644 (file)
index 0000000..c737769
--- /dev/null
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright (C) 2022 Huawei Technologies Duesseldorf GmbH
+ *
+ * Author: Roberto Sassu <roberto.sassu@huawei.com>
+ */
+
+#include "vmlinux.h"
+#include <errno.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+
+char _license[] SEC("license") = "GPL";
+
+__u32 monitored_pid;
+__u32 key_serial;
+__u32 key_id;
+__u64 flags;
+
+extern struct bpf_key *bpf_lookup_user_key(__u32 serial, __u64 flags) __ksym;
+extern struct bpf_key *bpf_lookup_system_key(__u64 id) __ksym;
+extern void bpf_key_put(struct bpf_key *key) __ksym;
+
+SEC("lsm.s/bpf")
+int BPF_PROG(bpf, int cmd, union bpf_attr *attr, unsigned int size)
+{
+       struct bpf_key *bkey;
+       __u32 pid;
+
+       pid = bpf_get_current_pid_tgid() >> 32;
+       if (pid != monitored_pid)
+               return 0;
+
+       if (key_serial)
+               bkey = bpf_lookup_user_key(key_serial, flags);
+       else
+               bkey = bpf_lookup_system_key(key_id);
+
+       if (!bkey)
+               return -ENOENT;
+
+       bpf_key_put(bkey);
+
+       return 0;
+}