2022-07-11 08:42:07

by Artem Savkov

[permalink] [raw]
Subject: [RFC PATCH bpf-next 0/4] bpf_panic() helper

eBPF is often used for kernel debugging, and one of the widely used and
powerful debugging techniques is post-mortem debugging with a full memory dump.
Triggering a panic at exactly the right moment allows the user to get such a
dump and thus a better view at the system's state. This patchset adds
bpf_panic() helper to do exactly that.

I realize that even though there are multiple guards present, a helper like
this is contrary to BPF being "safe", so this is sent as RFC to have a
discussion on whether adding destructive capabilities is deemed acceptable.

Artem Savkov (4):
bpf: add a sysctl to enable destructive bpf helpers
bpf: add BPF_F_DESTRUCTIVE flag for BPF_PROG_LOAD
bpf: add bpf_panic() helper
selftests/bpf: bpf_panic selftest

include/linux/bpf.h | 8 +
include/uapi/linux/bpf.h | 13 ++
kernel/bpf/core.c | 1 +
kernel/bpf/helpers.c | 13 ++
kernel/bpf/syscall.c | 33 +++-
kernel/bpf/verifier.c | 7 +
kernel/trace/bpf_trace.c | 2 +
tools/include/uapi/linux/bpf.h | 13 ++
.../selftests/bpf/prog_tests/bpf_panic.c | 144 ++++++++++++++++++
9 files changed, 233 insertions(+), 1 deletion(-)
create mode 100644 tools/testing/selftests/bpf/prog_tests/bpf_panic.c

--
2.35.3


2022-07-11 09:07:49

by Artem Savkov

[permalink] [raw]
Subject: [RFC PATCH bpf-next 2/4] bpf: add BPF_F_DESTRUCTIVE flag for BPF_PROG_LOAD

Add a BPF_F_DESTRUCTIVE will be required to be supplied to
BPF_PROG_LOAD for programs to utilize destructive helpers such as
bpf_panic().

Signed-off-by: Artem Savkov <[email protected]>
---
include/linux/bpf.h | 1 +
include/uapi/linux/bpf.h | 6 ++++++
kernel/bpf/syscall.c | 4 +++-
tools/include/uapi/linux/bpf.h | 6 ++++++
4 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 77972724bed7..43c008e3587a 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -1041,6 +1041,7 @@ struct bpf_prog_aux {
bool sleepable;
bool tail_call_reachable;
bool xdp_has_frags;
+ bool destructive;
bool use_bpf_prog_pack;
/* BTF_KIND_FUNC_PROTO for valid attach_btf_id */
const struct btf_type *attach_func_proto;
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index e81362891596..4423874b5da4 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -1121,6 +1121,12 @@ enum bpf_link_type {
*/
#define BPF_F_XDP_HAS_FRAGS (1U << 5)

+/* If BPF_F_DESTRUCTIVE is used in BPF_PROG_LOAD command, the loaded program
+ * will be able to perform destructive operations such as calling bpf_panic()
+ * helper.
+ */
+#define BPF_F_DESTRUCTIVE (1U << 6)
+
/* link_create.kprobe_multi.flags used in LINK_CREATE command for
* BPF_TRACE_KPROBE_MULTI attach type to create return probe.
*/
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 1ce6541d90e1..779feac2dc7d 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -2449,7 +2449,8 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr)
BPF_F_TEST_STATE_FREQ |
BPF_F_SLEEPABLE |
BPF_F_TEST_RND_HI32 |
- BPF_F_XDP_HAS_FRAGS))
+ BPF_F_XDP_HAS_FRAGS |
+ BPF_F_DESTRUCTIVE))
return -EINVAL;

if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) &&
@@ -2536,6 +2537,7 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr)
prog->aux->offload_requested = !!attr->prog_ifindex;
prog->aux->sleepable = attr->prog_flags & BPF_F_SLEEPABLE;
prog->aux->xdp_has_frags = attr->prog_flags & BPF_F_XDP_HAS_FRAGS;
+ prog->aux->destructive = attr->prog_flags & BPF_F_DESTRUCTIVE;

err = security_bpf_prog_alloc(prog->aux);
if (err)
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index e81362891596..4423874b5da4 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -1121,6 +1121,12 @@ enum bpf_link_type {
*/
#define BPF_F_XDP_HAS_FRAGS (1U << 5)

+/* If BPF_F_DESTRUCTIVE is used in BPF_PROG_LOAD command, the loaded program
+ * will be able to perform destructive operations such as calling bpf_panic()
+ * helper.
+ */
+#define BPF_F_DESTRUCTIVE (1U << 6)
+
/* link_create.kprobe_multi.flags used in LINK_CREATE command for
* BPF_TRACE_KPROBE_MULTI attach type to create return probe.
*/
--
2.35.3

2022-07-11 09:08:42

by Artem Savkov

[permalink] [raw]
Subject: [RFC PATCH bpf-next 4/4] selftests/bpf: bpf_panic selftest

Add a selftest for bpf_panic() checking that the program will only load
if all the prerequisites are met.

Signed-off-by: Artem Savkov <[email protected]>
---
.../selftests/bpf/prog_tests/bpf_panic.c | 144 ++++++++++++++++++
1 file changed, 144 insertions(+)
create mode 100644 tools/testing/selftests/bpf/prog_tests/bpf_panic.c

diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_panic.c b/tools/testing/selftests/bpf/prog_tests/bpf_panic.c
new file mode 100644
index 000000000000..9d008c0a5140
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/bpf_panic.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2022 Red Hat, Inc. */
+
+#include <test_progs.h>
+#include <bpf/btf.h>
+
+#include "cap_helpers.h"
+
+static int sysctl_get(const char *sysctl_path, char *old_val)
+{
+ int ret = 0;
+ FILE *fp;
+
+ fp = fopen(sysctl_path, "r");
+ if (!fp)
+ return -errno;
+
+ if (fscanf(fp, "%s", old_val) <= 0)
+ ret = -ENOENT;
+
+ fclose(fp);
+
+ return ret;
+}
+
+static int sysctl_set(const char *sysctl_path, const char *new_val)
+{
+ int ret = 0;
+ FILE *fp;
+
+ fp = fopen(sysctl_path, "w");
+ if (!fp)
+ return -errno;
+
+ if (fprintf(fp, "%s", new_val) < 0)
+ ret = -errno;
+
+ fclose(fp);
+
+ return ret;
+}
+
+static char bpf_vlog[UINT_MAX >> 8];
+
+static void test_bpf_panic_conditions(void)
+{
+ int fd_prog;
+ int map_fd;
+ struct bpf_insn prog_insns[] = {
+ BPF_LD_MAP_VALUE(BPF_REG_1, 0, 0),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_panic),
+ BPF_MOV64_IMM(BPF_REG_0, 0),
+ BPF_EXIT_INSN(),
+ };
+ const size_t prog_insn_cnt = sizeof(prog_insns) / sizeof(struct bpf_insn);
+ LIBBPF_OPTS(bpf_prog_load_opts, load_opts);
+ LIBBPF_OPTS(bpf_map_create_opts, map_create_opts);
+ int attach_btf_id;
+ __u64 save_caps = 0;
+
+ if (!ASSERT_OK(sysctl_set("/proc/sys/kernel/destructive_bpf_enabled",
+ "1"), "set destructive_bpf_enabled"))
+ return;
+
+ load_opts.log_level = 1;
+ load_opts.log_buf = bpf_vlog;
+ load_opts.log_size = sizeof(bpf_vlog);
+ load_opts.expected_attach_type = BPF_TRACE_FENTRY;
+
+ attach_btf_id = libbpf_find_vmlinux_btf_id("dentry_open", load_opts.expected_attach_type);
+ if (!ASSERT_GE(attach_btf_id, 0, "attach_btf_id"))
+ return;
+
+ load_opts.attach_btf_id = attach_btf_id;
+
+ map_create_opts.map_flags = BPF_F_RDONLY_PROG;
+ map_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, NULL, 4, 8, 1, &map_create_opts);
+ if (!ASSERT_GE(map_fd, 0, "bpf_map_create"))
+ return;
+ ASSERT_OK(bpf_map_freeze(map_fd), "bpf_map_freeze");
+
+ prog_insns[0].imm = map_fd;
+
+ fd_prog = bpf_prog_load(BPF_PROG_TYPE_TRACING, "bpf_panic", "GPL", prog_insns, prog_insn_cnt, &load_opts);
+
+ if (ASSERT_EQ(fd_prog, -EACCES, "BPF_F_DESTRUCTIVE required")) {
+ if (!ASSERT_OK_PTR(
+ strstr(bpf_vlog, "require BPF_F_DESTRUCTIVE"),
+ "BPF_F_DESTRUCTIVE verifier log")) {
+ printf("verifier log:\n%s\n", bpf_vlog);
+ }
+ }
+
+ load_opts.prog_flags = BPF_F_DESTRUCTIVE;
+ fd_prog = bpf_prog_load(BPF_PROG_TYPE_TRACING, "bpf_panic", "GPL", prog_insns, prog_insn_cnt, &load_opts);
+
+ if (ASSERT_GE(fd_prog, 0, "successful load")) {
+ close(fd_prog);
+ } else {
+ printf("verifier log:\n%s\n", bpf_vlog);
+ }
+
+
+ if (ASSERT_OK(cap_disable_effective(1ULL << CAP_SYS_BOOT, &save_caps), "disable caps")) {
+ fd_prog = bpf_prog_load(BPF_PROG_TYPE_TRACING, "bpf_panic", "GPL", prog_insns, prog_insn_cnt, &load_opts);
+ ASSERT_EQ(fd_prog, -EINVAL, "CAP_SYS_BOOT required");
+ if (!ASSERT_OK_PTR(
+ strstr(bpf_vlog, "unknown func bpf_panic"),
+ "CAP_SYS_BOOT verifier log")) {
+ printf("verifier log:\n%s\n", bpf_vlog);
+ }
+ cap_enable_effective(save_caps, NULL);
+ }
+
+ if (ASSERT_OK(sysctl_set("/proc/sys/kernel/destructive_bpf_enabled",
+ "0"), "unset destructive_bpf_enabled")) {
+ fd_prog = bpf_prog_load(BPF_PROG_TYPE_TRACING, "bpf_panic", "GPL", prog_insns, prog_insn_cnt, &load_opts);
+ ASSERT_EQ(fd_prog, -EINVAL, "!destructive_bpf_enabled");
+ if (!ASSERT_OK_PTR(
+ strstr(bpf_vlog, "unknown func bpf_panic"),
+ "!destructive_bpf_enabled verifier log")) {
+ printf("verifier log:\n%s\n", bpf_vlog);
+ }
+ }
+ close(map_fd);
+}
+
+void test_bpf_panic(void)
+{
+ char destructive_bpf_enabled_orig[32] = {};
+
+ if (!ASSERT_OK(sysctl_get("/proc/sys/kernel/destructive_bpf_enabled",
+ destructive_bpf_enabled_orig), "read destructive_bpf_enabled"))
+ goto cleanup;
+
+ libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
+ if (test__start_subtest("bpf_panic_conditions"))
+ test_bpf_panic_conditions();
+
+cleanup:
+ if (strlen(destructive_bpf_enabled_orig) > 0)
+ sysctl_set("/proc/sys/kernel/destructive_bpf_enabled",
+ destructive_bpf_enabled_orig);
+}
--
2.35.3

2022-07-11 09:11:06

by Artem Savkov

[permalink] [raw]
Subject: [RFC PATCH bpf-next 3/4] bpf: add bpf_panic() helper

Add a helper that will make the kernel panic immediately with specified
message. Using this helper requires kernel.destructive_bpf_enabled sysctl
to be enabled, BPF_F_DESTRUCTIVE flag to be supplied on program load as
well as CAP_SYS_BOOT capabilities.

Signed-off-by: Artem Savkov <[email protected]>
---
include/linux/bpf.h | 1 +
include/uapi/linux/bpf.h | 7 +++++++
kernel/bpf/core.c | 1 +
kernel/bpf/helpers.c | 13 +++++++++++++
kernel/bpf/verifier.c | 7 +++++++
kernel/trace/bpf_trace.c | 2 ++
tools/include/uapi/linux/bpf.h | 7 +++++++
7 files changed, 38 insertions(+)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 43c008e3587a..77c20ba9ca8e 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -2339,6 +2339,7 @@ extern const struct bpf_func_proto bpf_strtol_proto;
extern const struct bpf_func_proto bpf_strtoul_proto;
extern const struct bpf_func_proto bpf_tcp_sock_proto;
extern const struct bpf_func_proto bpf_jiffies64_proto;
+extern const struct bpf_func_proto bpf_panic_proto;
extern const struct bpf_func_proto bpf_get_ns_current_pid_tgid_proto;
extern const struct bpf_func_proto bpf_event_output_data_proto;
extern const struct bpf_func_proto bpf_ringbuf_output_proto;
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 4423874b5da4..e2e2c4de44ee 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -3927,6 +3927,12 @@ union bpf_attr {
* Return
* The 64 bit jiffies
*
+ * void bpf_panic(const char *msg)
+ * Description
+ * Make the kernel panic immediately
+ * Return
+ * void
+ *
* long bpf_read_branch_records(struct bpf_perf_event_data *ctx, void *buf, u32 size, u64 flags)
* Description
* For an eBPF program attached to a perf event, retrieve the
@@ -5452,6 +5458,7 @@ union bpf_attr {
FN(tcp_send_ack), \
FN(send_signal_thread), \
FN(jiffies64), \
+ FN(panic), \
FN(read_branch_records), \
FN(get_ns_current_pid_tgid), \
FN(xdp_output), \
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index b5ffebcce6cc..0f333a0e85a5 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -2649,6 +2649,7 @@ const struct bpf_func_proto bpf_map_lookup_percpu_elem_proto __weak;
const struct bpf_func_proto bpf_spin_lock_proto __weak;
const struct bpf_func_proto bpf_spin_unlock_proto __weak;
const struct bpf_func_proto bpf_jiffies64_proto __weak;
+const struct bpf_func_proto bpf_panic_proto __weak;

const struct bpf_func_proto bpf_get_prandom_u32_proto __weak;
const struct bpf_func_proto bpf_get_smp_processor_id_proto __weak;
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index a1c84d256f83..5cb90208a264 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -374,6 +374,19 @@ const struct bpf_func_proto bpf_jiffies64_proto = {
.ret_type = RET_INTEGER,
};

+BPF_CALL_1(bpf_panic, const char *, msg)
+{
+ panic(msg);
+ return 0;
+}
+
+const struct bpf_func_proto bpf_panic_proto = {
+ .func = bpf_panic,
+ .gpl_only = false,
+ .ret_type = RET_VOID,
+ .arg1_type = ARG_PTR_TO_CONST_STR,
+};
+
#ifdef CONFIG_CGROUPS
BPF_CALL_0(bpf_get_current_cgroup_id)
{
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 2859901ffbe3..f49c026917c5 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -7285,6 +7285,13 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
reg_type_str(env, regs[BPF_REG_1].type));
return -EACCES;
}
+ break;
+ case BPF_FUNC_panic:
+ struct bpf_prog_aux *aux = env->prog->aux;
+ if (!aux->destructive) {
+ verbose(env, "bpf_panic() calls require BPF_F_DESTRUCTIVE flag\n");
+ return -EACCES;
+ }
}

if (err)
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 4be976cf7d63..3ee888507795 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -1304,6 +1304,8 @@ bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
return &bpf_find_vma_proto;
case BPF_FUNC_trace_vprintk:
return bpf_get_trace_vprintk_proto();
+ case BPF_FUNC_panic:
+ return capable(CAP_SYS_BOOT) && destructive_ebpf_enabled() ? &bpf_panic_proto : NULL;
default:
return bpf_base_func_proto(func_id);
}
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 4423874b5da4..e2e2c4de44ee 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -3927,6 +3927,12 @@ union bpf_attr {
* Return
* The 64 bit jiffies
*
+ * void bpf_panic(const char *msg)
+ * Description
+ * Make the kernel panic immediately
+ * Return
+ * void
+ *
* long bpf_read_branch_records(struct bpf_perf_event_data *ctx, void *buf, u32 size, u64 flags)
* Description
* For an eBPF program attached to a perf event, retrieve the
@@ -5452,6 +5458,7 @@ union bpf_attr {
FN(tcp_send_ack), \
FN(send_signal_thread), \
FN(jiffies64), \
+ FN(panic), \
FN(read_branch_records), \
FN(get_ns_current_pid_tgid), \
FN(xdp_output), \
--
2.35.3

2022-07-11 11:26:17

by Jiri Olsa

[permalink] [raw]
Subject: Re: [RFC PATCH bpf-next 3/4] bpf: add bpf_panic() helper

On Mon, Jul 11, 2022 at 10:32:19AM +0200, Artem Savkov wrote:

SNIP

> diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
> index 4423874b5da4..e2e2c4de44ee 100644
> --- a/tools/include/uapi/linux/bpf.h
> +++ b/tools/include/uapi/linux/bpf.h
> @@ -3927,6 +3927,12 @@ union bpf_attr {
> * Return
> * The 64 bit jiffies
> *
> + * void bpf_panic(const char *msg)
> + * Description
> + * Make the kernel panic immediately
> + * Return
> + * void
> + *
> * long bpf_read_branch_records(struct bpf_perf_event_data *ctx, void *buf, u32 size, u64 flags)
> * Description
> * For an eBPF program attached to a perf event, retrieve the
> @@ -5452,6 +5458,7 @@ union bpf_attr {
> FN(tcp_send_ack), \
> FN(send_signal_thread), \
> FN(jiffies64), \
> + FN(panic), \
> FN(read_branch_records), \
> FN(get_ns_current_pid_tgid), \
> FN(xdp_output), \

new helper needs to be added at the end of the list

jirka

2022-07-11 11:42:50

by Jiri Olsa

[permalink] [raw]
Subject: Re: [RFC PATCH bpf-next 0/4] bpf_panic() helper

On Mon, Jul 11, 2022 at 10:32:16AM +0200, Artem Savkov wrote:
> eBPF is often used for kernel debugging, and one of the widely used and
> powerful debugging techniques is post-mortem debugging with a full memory dump.
> Triggering a panic at exactly the right moment allows the user to get such a
> dump and thus a better view at the system's state. This patchset adds
> bpf_panic() helper to do exactly that.

FWIW I was asked for such helper some time ago from Daniel Vacek, cc-ed

jirka

>
> I realize that even though there are multiple guards present, a helper like
> this is contrary to BPF being "safe", so this is sent as RFC to have a
> discussion on whether adding destructive capabilities is deemed acceptable.
>
> Artem Savkov (4):
> bpf: add a sysctl to enable destructive bpf helpers
> bpf: add BPF_F_DESTRUCTIVE flag for BPF_PROG_LOAD
> bpf: add bpf_panic() helper
> selftests/bpf: bpf_panic selftest
>
> include/linux/bpf.h | 8 +
> include/uapi/linux/bpf.h | 13 ++
> kernel/bpf/core.c | 1 +
> kernel/bpf/helpers.c | 13 ++
> kernel/bpf/syscall.c | 33 +++-
> kernel/bpf/verifier.c | 7 +
> kernel/trace/bpf_trace.c | 2 +
> tools/include/uapi/linux/bpf.h | 13 ++
> .../selftests/bpf/prog_tests/bpf_panic.c | 144 ++++++++++++++++++
> 9 files changed, 233 insertions(+), 1 deletion(-)
> create mode 100644 tools/testing/selftests/bpf/prog_tests/bpf_panic.c
>
> --
> 2.35.3
>

2022-07-11 11:53:52

by Jiri Olsa

[permalink] [raw]
Subject: Re: [RFC PATCH bpf-next 2/4] bpf: add BPF_F_DESTRUCTIVE flag for BPF_PROG_LOAD

On Mon, Jul 11, 2022 at 10:32:18AM +0200, Artem Savkov wrote:
> Add a BPF_F_DESTRUCTIVE will be required to be supplied to
> BPF_PROG_LOAD for programs to utilize destructive helpers such as
> bpf_panic().

I'd think that having kernel.destructive_bpf_enabled sysctl knob enabled
would be enough to enable that helper from any program, not sure having
extra load flag adds more security

jirka

>
> Signed-off-by: Artem Savkov <[email protected]>
> ---
> include/linux/bpf.h | 1 +
> include/uapi/linux/bpf.h | 6 ++++++
> kernel/bpf/syscall.c | 4 +++-
> tools/include/uapi/linux/bpf.h | 6 ++++++
> 4 files changed, 16 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index 77972724bed7..43c008e3587a 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -1041,6 +1041,7 @@ struct bpf_prog_aux {
> bool sleepable;
> bool tail_call_reachable;
> bool xdp_has_frags;
> + bool destructive;
> bool use_bpf_prog_pack;
> /* BTF_KIND_FUNC_PROTO for valid attach_btf_id */
> const struct btf_type *attach_func_proto;
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index e81362891596..4423874b5da4 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -1121,6 +1121,12 @@ enum bpf_link_type {
> */
> #define BPF_F_XDP_HAS_FRAGS (1U << 5)
>
> +/* If BPF_F_DESTRUCTIVE is used in BPF_PROG_LOAD command, the loaded program
> + * will be able to perform destructive operations such as calling bpf_panic()
> + * helper.
> + */
> +#define BPF_F_DESTRUCTIVE (1U << 6)
> +
> /* link_create.kprobe_multi.flags used in LINK_CREATE command for
> * BPF_TRACE_KPROBE_MULTI attach type to create return probe.
> */
> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> index 1ce6541d90e1..779feac2dc7d 100644
> --- a/kernel/bpf/syscall.c
> +++ b/kernel/bpf/syscall.c
> @@ -2449,7 +2449,8 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr)
> BPF_F_TEST_STATE_FREQ |
> BPF_F_SLEEPABLE |
> BPF_F_TEST_RND_HI32 |
> - BPF_F_XDP_HAS_FRAGS))
> + BPF_F_XDP_HAS_FRAGS |
> + BPF_F_DESTRUCTIVE))
> return -EINVAL;
>
> if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) &&
> @@ -2536,6 +2537,7 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr)
> prog->aux->offload_requested = !!attr->prog_ifindex;
> prog->aux->sleepable = attr->prog_flags & BPF_F_SLEEPABLE;
> prog->aux->xdp_has_frags = attr->prog_flags & BPF_F_XDP_HAS_FRAGS;
> + prog->aux->destructive = attr->prog_flags & BPF_F_DESTRUCTIVE;
>
> err = security_bpf_prog_alloc(prog->aux);
> if (err)
> diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
> index e81362891596..4423874b5da4 100644
> --- a/tools/include/uapi/linux/bpf.h
> +++ b/tools/include/uapi/linux/bpf.h
> @@ -1121,6 +1121,12 @@ enum bpf_link_type {
> */
> #define BPF_F_XDP_HAS_FRAGS (1U << 5)
>
> +/* If BPF_F_DESTRUCTIVE is used in BPF_PROG_LOAD command, the loaded program
> + * will be able to perform destructive operations such as calling bpf_panic()
> + * helper.
> + */
> +#define BPF_F_DESTRUCTIVE (1U << 6)
> +
> /* link_create.kprobe_multi.flags used in LINK_CREATE command for
> * BPF_TRACE_KPROBE_MULTI attach type to create return probe.
> */
> --
> 2.35.3
>

2022-07-11 11:56:44

by Artem Savkov

[permalink] [raw]
Subject: Re: [RFC PATCH bpf-next 2/4] bpf: add BPF_F_DESTRUCTIVE flag for BPF_PROG_LOAD

On Mon, Jul 11, 2022 at 12:56:28PM +0200, Jiri Olsa wrote:
> On Mon, Jul 11, 2022 at 10:32:18AM +0200, Artem Savkov wrote:
> > Add a BPF_F_DESTRUCTIVE will be required to be supplied to
> > BPF_PROG_LOAD for programs to utilize destructive helpers such as
> > bpf_panic().
>
> I'd think that having kernel.destructive_bpf_enabled sysctl knob enabled
> would be enough to enable that helper from any program, not sure having
> extra load flag adds more security

I agree it doesn't add more security. The idea was to have a way for a
developer to explicitly state he understand this will be dangerous. This
flag can also translate well into something like a --destructive option
for bpftrace without needing to keep a list of destructive helpers on
their side.

--
Artem

2022-07-12 18:03:35

by Song Liu

[permalink] [raw]
Subject: Re: [RFC PATCH bpf-next 3/4] bpf: add bpf_panic() helper

On Mon, Jul 11, 2022 at 1:32 AM Artem Savkov <[email protected]> wrote:
>
> Add a helper that will make the kernel panic immediately with specified
> message. Using this helper requires kernel.destructive_bpf_enabled sysctl
> to be enabled, BPF_F_DESTRUCTIVE flag to be supplied on program load as
> well as CAP_SYS_BOOT capabilities.
>
> Signed-off-by: Artem Savkov <[email protected]>
> ---
> include/linux/bpf.h | 1 +
> include/uapi/linux/bpf.h | 7 +++++++
> kernel/bpf/core.c | 1 +
> kernel/bpf/helpers.c | 13 +++++++++++++
> kernel/bpf/verifier.c | 7 +++++++
> kernel/trace/bpf_trace.c | 2 ++
> tools/include/uapi/linux/bpf.h | 7 +++++++
> 7 files changed, 38 insertions(+)
>
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index 43c008e3587a..77c20ba9ca8e 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -2339,6 +2339,7 @@ extern const struct bpf_func_proto bpf_strtol_proto;
> extern const struct bpf_func_proto bpf_strtoul_proto;
> extern const struct bpf_func_proto bpf_tcp_sock_proto;
> extern const struct bpf_func_proto bpf_jiffies64_proto;
> +extern const struct bpf_func_proto bpf_panic_proto;
> extern const struct bpf_func_proto bpf_get_ns_current_pid_tgid_proto;
> extern const struct bpf_func_proto bpf_event_output_data_proto;
> extern const struct bpf_func_proto bpf_ringbuf_output_proto;
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index 4423874b5da4..e2e2c4de44ee 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -3927,6 +3927,12 @@ union bpf_attr {
> * Return
> * The 64 bit jiffies
> *
> + * void bpf_panic(const char *msg)
> + * Description
> + * Make the kernel panic immediately
> + * Return
> + * void
> + *
> * long bpf_read_branch_records(struct bpf_perf_event_data *ctx, void *buf, u32 size, u64 flags)
> * Description
> * For an eBPF program attached to a perf event, retrieve the
> @@ -5452,6 +5458,7 @@ union bpf_attr {
> FN(tcp_send_ack), \
> FN(send_signal_thread), \
> FN(jiffies64), \
> + FN(panic), \
> FN(read_branch_records), \
> FN(get_ns_current_pid_tgid), \
> FN(xdp_output), \
> diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
> index b5ffebcce6cc..0f333a0e85a5 100644
> --- a/kernel/bpf/core.c
> +++ b/kernel/bpf/core.c
> @@ -2649,6 +2649,7 @@ const struct bpf_func_proto bpf_map_lookup_percpu_elem_proto __weak;
> const struct bpf_func_proto bpf_spin_lock_proto __weak;
> const struct bpf_func_proto bpf_spin_unlock_proto __weak;
> const struct bpf_func_proto bpf_jiffies64_proto __weak;
> +const struct bpf_func_proto bpf_panic_proto __weak;
>
> const struct bpf_func_proto bpf_get_prandom_u32_proto __weak;
> const struct bpf_func_proto bpf_get_smp_processor_id_proto __weak;
> diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> index a1c84d256f83..5cb90208a264 100644
> --- a/kernel/bpf/helpers.c
> +++ b/kernel/bpf/helpers.c
> @@ -374,6 +374,19 @@ const struct bpf_func_proto bpf_jiffies64_proto = {
> .ret_type = RET_INTEGER,
> };
>
> +BPF_CALL_1(bpf_panic, const char *, msg)
> +{
> + panic(msg);

I think we should also check

capable(CAP_SYS_BOOT) && destructive_ebpf_enabled()

here. Or at least, destructive_ebpf_enabled(). Otherwise, we
may trigger panic after the sysctl is disabled.

In general, I don't think sysctl is a good API, as it is global, and
the user can easily forget to turn it back off. If possible, I would
rather avoid adding new BPF related sysctls.

Thanks,
Song


> + return 0;
> +}
> +
> +const struct bpf_func_proto bpf_panic_proto = {
> + .func = bpf_panic,
> + .gpl_only = false,
> + .ret_type = RET_VOID,
> + .arg1_type = ARG_PTR_TO_CONST_STR,
> +};
> +
> #ifdef CONFIG_CGROUPS
> BPF_CALL_0(bpf_get_current_cgroup_id)
> {
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 2859901ffbe3..f49c026917c5 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -7285,6 +7285,13 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
> reg_type_str(env, regs[BPF_REG_1].type));
> return -EACCES;
> }
> + break;
> + case BPF_FUNC_panic:
> + struct bpf_prog_aux *aux = env->prog->aux;
> + if (!aux->destructive) {
> + verbose(env, "bpf_panic() calls require BPF_F_DESTRUCTIVE flag\n");
> + return -EACCES;
> + }
> }
>
> if (err)
> diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
> index 4be976cf7d63..3ee888507795 100644
> --- a/kernel/trace/bpf_trace.c
> +++ b/kernel/trace/bpf_trace.c
> @@ -1304,6 +1304,8 @@ bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
> return &bpf_find_vma_proto;
> case BPF_FUNC_trace_vprintk:
> return bpf_get_trace_vprintk_proto();
> + case BPF_FUNC_panic:
> + return capable(CAP_SYS_BOOT) && destructive_ebpf_enabled() ? &bpf_panic_proto : NULL;
> default:
> return bpf_base_func_proto(func_id);
> }
> diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
> index 4423874b5da4..e2e2c4de44ee 100644
> --- a/tools/include/uapi/linux/bpf.h
> +++ b/tools/include/uapi/linux/bpf.h
> @@ -3927,6 +3927,12 @@ union bpf_attr {
> * Return
> * The 64 bit jiffies
> *
> + * void bpf_panic(const char *msg)
> + * Description
> + * Make the kernel panic immediately
> + * Return
> + * void
> + *
> * long bpf_read_branch_records(struct bpf_perf_event_data *ctx, void *buf, u32 size, u64 flags)
> * Description
> * For an eBPF program attached to a perf event, retrieve the
> @@ -5452,6 +5458,7 @@ union bpf_attr {
> FN(tcp_send_ack), \
> FN(send_signal_thread), \
> FN(jiffies64), \
> + FN(panic), \
> FN(read_branch_records), \
> FN(get_ns_current_pid_tgid), \
> FN(xdp_output), \
> --
> 2.35.3
>

2022-07-12 18:17:55

by Alexei Starovoitov

[permalink] [raw]
Subject: Re: [RFC PATCH bpf-next 3/4] bpf: add bpf_panic() helper

On Tue, Jul 12, 2022 at 10:53 AM Song Liu <[email protected]> wrote:
>
> >
> > +BPF_CALL_1(bpf_panic, const char *, msg)
> > +{
> > + panic(msg);
>
> I think we should also check
>
> capable(CAP_SYS_BOOT) && destructive_ebpf_enabled()
>
> here. Or at least, destructive_ebpf_enabled(). Otherwise, we
> may trigger panic after the sysctl is disabled.
>
> In general, I don't think sysctl is a good API, as it is global, and
> the user can easily forget to turn it back off. If possible, I would
> rather avoid adding new BPF related sysctls.

+1. New syscal isn't warranted here.
Just CAP_SYS_BOOT would be enough here.

Also full blown panic() seems unnecessary.
If the motivation is to get a memory dump then crash_kexec() helper
would be more suitable.
If the goal is to reboot the system then the wrapper of sys_reboot()
is better.
Unfortunately the cover letter lacks these details.
Why this destructive action cannot be delegated to user space?

btw, we should avoid adding new uapi helpers in most cases.
Ideally all of them should be added as new kfunc-s, because they're
unstable and we can rip them out later if our judgement call
turns out to be problematic for whatever reason.

2022-07-13 13:39:43

by Artem Savkov

[permalink] [raw]
Subject: Re: [RFC PATCH bpf-next 3/4] bpf: add bpf_panic() helper

On Tue, Jul 12, 2022 at 11:08:54AM -0700, Alexei Starovoitov wrote:
> On Tue, Jul 12, 2022 at 10:53 AM Song Liu <[email protected]> wrote:
> >
> > >
> > > +BPF_CALL_1(bpf_panic, const char *, msg)
> > > +{
> > > + panic(msg);
> >
> > I think we should also check
> >
> > capable(CAP_SYS_BOOT) && destructive_ebpf_enabled()
> >
> > here. Or at least, destructive_ebpf_enabled(). Otherwise, we
> > may trigger panic after the sysctl is disabled.
> >
> > In general, I don't think sysctl is a good API, as it is global, and
> > the user can easily forget to turn it back off. If possible, I would
> > rather avoid adding new BPF related sysctls.
>
> +1. New syscal isn't warranted here.
> Just CAP_SYS_BOOT would be enough here.

Point taken, I'll remove sysctl knob in any further versions.

> Also full blown panic() seems unnecessary.
> If the motivation is to get a memory dump then crash_kexec() helper
> would be more suitable.
> If the goal is to reboot the system then the wrapper of sys_reboot()
> is better.
> Unfortunately the cover letter lacks these details.

The main goal is to get the memory dump, so crash_kexec() should be enough.
However panic() is a bit more versatile and it's consequences are configurable
to some extent. Are there any downsides to using it?

> Why this destructive action cannot be delegated to user space?

Going through userspace adds delays and makes it impossible to hit "exactly
the right moment" thus making it unusable in most cases.

I'll add this to the cover letter.

> btw, we should avoid adding new uapi helpers in most cases.
> Ideally all of them should be added as new kfunc-s, because they're
> unstable and we can rip them out later if our judgement call
> turns out to be problematic for whatever reason.

Ok, I'll look into doing it this way.

--
Regards,
Artem

2022-07-13 22:58:16

by Alexei Starovoitov

[permalink] [raw]
Subject: Re: [RFC PATCH bpf-next 3/4] bpf: add bpf_panic() helper

On Wed, Jul 13, 2022 at 6:31 AM Artem Savkov <[email protected]> wrote:
>
> On Tue, Jul 12, 2022 at 11:08:54AM -0700, Alexei Starovoitov wrote:
> > On Tue, Jul 12, 2022 at 10:53 AM Song Liu <[email protected]> wrote:
> > >
> > > >
> > > > +BPF_CALL_1(bpf_panic, const char *, msg)
> > > > +{
> > > > + panic(msg);
> > >
> > > I think we should also check
> > >
> > > capable(CAP_SYS_BOOT) && destructive_ebpf_enabled()
> > >
> > > here. Or at least, destructive_ebpf_enabled(). Otherwise, we
> > > may trigger panic after the sysctl is disabled.
> > >
> > > In general, I don't think sysctl is a good API, as it is global, and
> > > the user can easily forget to turn it back off. If possible, I would
> > > rather avoid adding new BPF related sysctls.
> >
> > +1. New syscal isn't warranted here.
> > Just CAP_SYS_BOOT would be enough here.
>
> Point taken, I'll remove sysctl knob in any further versions.
>
> > Also full blown panic() seems unnecessary.
> > If the motivation is to get a memory dump then crash_kexec() helper
> > would be more suitable.
> > If the goal is to reboot the system then the wrapper of sys_reboot()
> > is better.
> > Unfortunately the cover letter lacks these details.
>
> The main goal is to get the memory dump, so crash_kexec() should be enough.
> However panic() is a bit more versatile and it's consequences are configurable
> to some extent. Are there any downsides to using it?

versatile? In what sense? That it does a lot more than kexec?
That's a disadvantage.
We should provide bpf with minimal building blocks and let
bpf program decide what to do.
If dmesg (that is part of panic) is useful it should be its
own kfunc.
If halt is necessary -> separate kfunc as well.
reboot -> another kfunc.

Also panic() is not guaranteed to do kexec and just
panic is not what you stated is the goal of the helper.

>
> > Why this destructive action cannot be delegated to user space?
>
> Going through userspace adds delays and makes it impossible to hit "exactly
> the right moment" thus making it unusable in most cases.

What would be an example of that?
kexec is not instant either.

> I'll add this to the cover letter.
>
> > btw, we should avoid adding new uapi helpers in most cases.
> > Ideally all of them should be added as new kfunc-s, because they're
> > unstable and we can rip them out later if our judgement call
> > turns out to be problematic for whatever reason.
>
> Ok, I'll look into doing it this way.
>
> --
> Regards,
> Artem
>

2022-07-15 13:28:10

by Artem Savkov

[permalink] [raw]
Subject: Re: [RFC PATCH bpf-next 3/4] bpf: add bpf_panic() helper

On Wed, Jul 13, 2022 at 03:20:22PM -0700, Alexei Starovoitov wrote:
> On Wed, Jul 13, 2022 at 6:31 AM Artem Savkov <[email protected]> wrote:
> >
> > On Tue, Jul 12, 2022 at 11:08:54AM -0700, Alexei Starovoitov wrote:
> > > On Tue, Jul 12, 2022 at 10:53 AM Song Liu <[email protected]> wrote:
> > > >
> > > > >
> > > > > +BPF_CALL_1(bpf_panic, const char *, msg)
> > > > > +{
> > > > > + panic(msg);
> > > >
> > > > I think we should also check
> > > >
> > > > capable(CAP_SYS_BOOT) && destructive_ebpf_enabled()
> > > >
> > > > here. Or at least, destructive_ebpf_enabled(). Otherwise, we
> > > > may trigger panic after the sysctl is disabled.
> > > >
> > > > In general, I don't think sysctl is a good API, as it is global, and
> > > > the user can easily forget to turn it back off. If possible, I would
> > > > rather avoid adding new BPF related sysctls.
> > >
> > > +1. New syscal isn't warranted here.
> > > Just CAP_SYS_BOOT would be enough here.
> >
> > Point taken, I'll remove sysctl knob in any further versions.
> >
> > > Also full blown panic() seems unnecessary.
> > > If the motivation is to get a memory dump then crash_kexec() helper
> > > would be more suitable.
> > > If the goal is to reboot the system then the wrapper of sys_reboot()
> > > is better.
> > > Unfortunately the cover letter lacks these details.
> >
> > The main goal is to get the memory dump, so crash_kexec() should be enough.
> > However panic() is a bit more versatile and it's consequences are configurable
> > to some extent. Are there any downsides to using it?
>
> versatile? In what sense? That it does a lot more than kexec?
> That's a disadvantage.
> We should provide bpf with minimal building blocks and let
> bpf program decide what to do.
> If dmesg (that is part of panic) is useful it should be its
> own kfunc.
> If halt is necessary -> separate kfunc as well.
> reboot -> another kfunc.
>
> Also panic() is not guaranteed to do kexec and just
> panic is not what you stated is the goal of the helper.

Alright, if the aim is to provide the smallest building blocks then
crash_kexec() is a better choice.

> >
> > > Why this destructive action cannot be delegated to user space?
> >
> > Going through userspace adds delays and makes it impossible to hit "exactly
> > the right moment" thus making it unusable in most cases.
>
> What would be an example of that?
> kexec is not instant either.

With kexec at least the thread it got called in is in a proper state. I
guess it is possible to achieve this by signalling userspace to do
kexec/panic and then block the thread somehow but that won't work in a
single-cpu case. Or am I missing something?

--
Artem

2022-07-18 21:13:19

by Alexei Starovoitov

[permalink] [raw]
Subject: Re: [RFC PATCH bpf-next 3/4] bpf: add bpf_panic() helper

On Fri, Jul 15, 2022 at 5:52 AM Artem Savkov <[email protected]> wrote:
>
> On Wed, Jul 13, 2022 at 03:20:22PM -0700, Alexei Starovoitov wrote:
> > On Wed, Jul 13, 2022 at 6:31 AM Artem Savkov <[email protected]> wrote:
> > >
> > > On Tue, Jul 12, 2022 at 11:08:54AM -0700, Alexei Starovoitov wrote:
> > > > On Tue, Jul 12, 2022 at 10:53 AM Song Liu <[email protected]> wrote:
> > > > >
> > > > > >
> > > > > > +BPF_CALL_1(bpf_panic, const char *, msg)
> > > > > > +{
> > > > > > + panic(msg);
> > > > >
> > > > > I think we should also check
> > > > >
> > > > > capable(CAP_SYS_BOOT) && destructive_ebpf_enabled()
> > > > >
> > > > > here. Or at least, destructive_ebpf_enabled(). Otherwise, we
> > > > > may trigger panic after the sysctl is disabled.
> > > > >
> > > > > In general, I don't think sysctl is a good API, as it is global, and
> > > > > the user can easily forget to turn it back off. If possible, I would
> > > > > rather avoid adding new BPF related sysctls.
> > > >
> > > > +1. New syscal isn't warranted here.
> > > > Just CAP_SYS_BOOT would be enough here.
> > >
> > > Point taken, I'll remove sysctl knob in any further versions.
> > >
> > > > Also full blown panic() seems unnecessary.
> > > > If the motivation is to get a memory dump then crash_kexec() helper
> > > > would be more suitable.
> > > > If the goal is to reboot the system then the wrapper of sys_reboot()
> > > > is better.
> > > > Unfortunately the cover letter lacks these details.
> > >
> > > The main goal is to get the memory dump, so crash_kexec() should be enough.
> > > However panic() is a bit more versatile and it's consequences are configurable
> > > to some extent. Are there any downsides to using it?
> >
> > versatile? In what sense? That it does a lot more than kexec?
> > That's a disadvantage.
> > We should provide bpf with minimal building blocks and let
> > bpf program decide what to do.
> > If dmesg (that is part of panic) is useful it should be its
> > own kfunc.
> > If halt is necessary -> separate kfunc as well.
> > reboot -> another kfunc.
> >
> > Also panic() is not guaranteed to do kexec and just
> > panic is not what you stated is the goal of the helper.
>
> Alright, if the aim is to provide the smallest building blocks then
> crash_kexec() is a better choice.
>
> > >
> > > > Why this destructive action cannot be delegated to user space?
> > >
> > > Going through userspace adds delays and makes it impossible to hit "exactly
> > > the right moment" thus making it unusable in most cases.
> >
> > What would be an example of that?
> > kexec is not instant either.
>
> With kexec at least the thread it got called in is in a proper state. I
> guess it is possible to achieve this by signalling userspace to do
> kexec/panic and then block the thread somehow but that won't work in a
> single-cpu case. Or am I missing something?

Something like this.
We can extend bpf_send_signal to send a signal to pid 1
or another user agent.
It's still not clear to me why you want that memory dump.

2022-08-01 14:05:15

by Daniel Vacek

[permalink] [raw]
Subject: Re: [RFC PATCH bpf-next 0/4] bpf_panic() helper

On Mon, Jul 11, 2022 at 12:51 PM Jiri Olsa <[email protected]> wrote:
>
> On Mon, Jul 11, 2022 at 10:32:16AM +0200, Artem Savkov wrote:
> > eBPF is often used for kernel debugging, and one of the widely used and
> > powerful debugging techniques is post-mortem debugging with a full memory dump.
> > Triggering a panic at exactly the right moment allows the user to get such a
> > dump and thus a better view at the system's state. This patchset adds
> > bpf_panic() helper to do exactly that.
>
> FWIW I was asked for such helper some time ago from Daniel Vacek, cc-ed

Nice :-)
This is totally welcome. Though, IIRC, I was asking if I could do a
NULL pointer dereference within perf probe (or ftrace) back then.
Still, the outcome is similar. So kudos to Artem.

--nX

> jirka
>
> >
> > I realize that even though there are multiple guards present, a helper like
> > this is contrary to BPF being "safe", so this is sent as RFC to have a
> > discussion on whether adding destructive capabilities is deemed acceptable.
> >
> > Artem Savkov (4):
> > bpf: add a sysctl to enable destructive bpf helpers
> > bpf: add BPF_F_DESTRUCTIVE flag for BPF_PROG_LOAD
> > bpf: add bpf_panic() helper
> > selftests/bpf: bpf_panic selftest
> >
> > include/linux/bpf.h | 8 +
> > include/uapi/linux/bpf.h | 13 ++
> > kernel/bpf/core.c | 1 +
> > kernel/bpf/helpers.c | 13 ++
> > kernel/bpf/syscall.c | 33 +++-
> > kernel/bpf/verifier.c | 7 +
> > kernel/trace/bpf_trace.c | 2 +
> > tools/include/uapi/linux/bpf.h | 13 ++
> > .../selftests/bpf/prog_tests/bpf_panic.c | 144 ++++++++++++++++++
> > 9 files changed, 233 insertions(+), 1 deletion(-)
> > create mode 100644 tools/testing/selftests/bpf/prog_tests/bpf_panic.c
> >
> > --
> > 2.35.3
> >
>