All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kumar Kartikeya Dwivedi <memxor@gmail.com>
To: bpf@vger.kernel.org
Cc: Alexei Starovoitov <ast@kernel.org>,
	Andrii Nakryiko <andrii@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>,
	Eduard Zingerman <eddyz87@gmail.com>,
	Emil Tsalapatis <emil@etsalapatis.com>,
	Nicholas Carlini <npc@anthropic.com>,
	kkd@meta.com, kernel-team@meta.com
Subject: [PATCH bpf v1 2/8] selftests/bpf: Test killing a loader during instruction rewrites
Date: Sat,  5 Sep 2026 08:59:53 +0200	[thread overview]
Message-ID: <20260905070003.3193366-3-memxor@gmail.com> (raw)
In-Reply-To: <20260905070003.3193366-1-memxor@gmail.com>

Exercise fatal-signal handling after verifier exploration has completed. Load
a 32768-instruction control program to estimate the time needed for linear
verification, then load the same-sized program made of unconditional jumps by
zero in a child process.

The latter reaches the quadratic bpf_opt_remove_nops() rewrite. Send SIGKILL
after four control-load durations and require the child to be reaped within
one second. Without cancellation points in the rewrite helpers, the killed
child stays in BPF_PROG_LOAD until all no-ops have been removed.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
---
 .../bpf/prog_tests/prog_load_signal.c         | 131 ++++++++++++++++++
 1 file changed, 131 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/prog_load_signal.c

diff --git a/tools/testing/selftests/bpf/prog_tests/prog_load_signal.c b/tools/testing/selftests/bpf/prog_tests/prog_load_signal.c
new file mode 100644
index 000000000000..0f78db3bccc7
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/prog_load_signal.c
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */
+#include <test_progs.h>
+
+#define NOP_CNT		32768
+#define MIN_KILL_DELAY_NS	(100ULL * 1000 * 1000)
+#define REAP_TIMEOUT_NS		(1000ULL * 1000 * 1000)
+
+static __u64 monotonic_ns(void)
+{
+	struct timespec ts;
+
+	clock_gettime(CLOCK_MONOTONIC, &ts);
+	return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
+}
+
+static void sleep_ns(__u64 duration)
+{
+	struct timespec ts = {
+		.tv_sec = duration / 1000000000ULL,
+		.tv_nsec = duration % 1000000000ULL,
+	};
+
+	while (nanosleep(&ts, &ts) && errno == EINTR)
+		;
+}
+
+static int waitpid_timeout(pid_t pid, int *status, __u64 timeout)
+{
+	__u64 deadline = monotonic_ns() + timeout;
+	int ret;
+
+	do {
+		ret = waitpid(pid, status, WNOHANG);
+		if (ret)
+			return ret;
+		usleep(1000);
+	} while (monotonic_ns() < deadline);
+
+	return 0;
+}
+
+void test_prog_load_signal(void)
+{
+	struct bpf_insn *insns = NULL;
+	__u64 start, control_time, kill_delay;
+	int pipefd[2] = { -1, -1 };
+	int prog_fd = -1, status = 0;
+	pid_t pid = -1;
+	char byte;
+	int i, ret;
+
+	insns = calloc(NOP_CNT + 2, sizeof(*insns));
+	if (!ASSERT_OK_PTR(insns, "calloc"))
+		return;
+
+	for (i = 0; i < NOP_CNT; i++)
+		insns[i] = BPF_MOV64_REG(BPF_REG_1, BPF_REG_1);
+	insns[NOP_CNT] = BPF_MOV64_IMM(BPF_REG_0, 0);
+	insns[NOP_CNT + 1] = BPF_EXIT_INSN();
+
+	start = monotonic_ns();
+	prog_fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL",
+				insns, NOP_CNT + 2, NULL);
+	control_time = monotonic_ns() - start;
+	if (!ASSERT_GE(prog_fd, 0, "control_prog_load"))
+		goto cleanup;
+	close(prog_fd);
+	prog_fd = -1;
+
+	for (i = 0; i < NOP_CNT; i++)
+		insns[i] = BPF_JMP_IMM(BPF_JA, 0, 0, 0);
+
+	if (!ASSERT_OK(pipe(pipefd), "pipe"))
+		goto cleanup;
+
+	pid = fork();
+	if (!ASSERT_GE(pid, 0, "fork"))
+		goto cleanup;
+	if (!pid) {
+		close(pipefd[0]);
+		if (write(pipefd[1], "x", 1) != 1)
+			_exit(1);
+		close(pipefd[1]);
+		prog_fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL",
+					insns, NOP_CNT + 2, NULL);
+		if (prog_fd >= 0)
+			close(prog_fd);
+		_exit(prog_fd < 0);
+	}
+
+	close(pipefd[1]);
+	pipefd[1] = -1;
+	ret = read(pipefd[0], &byte, 1);
+	if (!ASSERT_EQ(ret, 1, "child_ready"))
+		goto cleanup;
+
+	/*
+	 * Allow linear verification to finish before sending SIGKILL. The nop
+	 * removal pass is quadratic, so four control-load times still leaves a
+	 * wide window in which an affected kernel is rewriting instructions.
+	 */
+	kill_delay = MAX(control_time * 4, MIN_KILL_DELAY_NS);
+	sleep_ns(kill_delay);
+	if (!ASSERT_OK(kill(pid, SIGKILL), "kill"))
+		goto cleanup;
+
+	start = monotonic_ns();
+	ret = waitpid_timeout(pid, &status, REAP_TIMEOUT_NS);
+	if (!ASSERT_EQ(ret, pid, "prog_load_killable")) {
+		fprintf(stderr, "control load %llu us, child still alive %llu us after SIGKILL\n",
+			control_time / 1000, (monotonic_ns() - start) / 1000);
+		goto cleanup;
+	}
+	pid = -1;
+	ASSERT_TRUE(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL,
+		    "killed_by_sigkill");
+
+cleanup:
+	if (prog_fd >= 0)
+		close(prog_fd);
+	if (pipefd[0] >= 0)
+		close(pipefd[0]);
+	if (pipefd[1] >= 0)
+		close(pipefd[1]);
+	if (pid > 0) {
+		kill(pid, SIGKILL);
+		waitpid(pid, &status, 0);
+	}
+	free(insns);
+}
-- 
2.53.0


  parent reply	other threads:[~2026-09-05  7:00 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-05  6:59 [PATCH bpf v1 0/8] Misc bug fixes - part 5 Kumar Kartikeya Dwivedi
2026-09-05  6:59 ` [PATCH bpf v1 1/8] bpf: Make post-verification instruction rewrites killable Kumar Kartikeya Dwivedi
2026-09-05  8:02   ` bot+bpf-ci
2026-09-05  6:59 ` Kumar Kartikeya Dwivedi [this message]
2026-09-05  7:13   ` [PATCH bpf v1 2/8] selftests/bpf: Test killing a loader during instruction rewrites sashiko-bot
2026-09-05  7:15     ` Kumar Kartikeya Dwivedi
2026-09-05  8:02   ` bot+bpf-ci
2026-09-05  6:59 ` [PATCH bpf v1 3/8] bpf: Preserve packet pointer class displacement in regsafe() Kumar Kartikeya Dwivedi
2026-09-05  8:02   ` bot+bpf-ci
2026-09-05  6:59 ` [PATCH bpf v1 4/8] selftests/bpf: Test packet pointer class displacement pruning Kumar Kartikeya Dwivedi
2026-09-05  8:02   ` bot+bpf-ci
2026-09-05  6:59 ` [PATCH bpf v1 5/8] bpf: Reject fall-through across subprogram boundaries Kumar Kartikeya Dwivedi
2026-09-05  6:59 ` [PATCH bpf v1 6/8] selftests/bpf: Test poisoned subprogram terminator Kumar Kartikeya Dwivedi
2026-09-05  8:16   ` bot+bpf-ci
2026-09-05  6:59 ` [PATCH bpf v1 7/8] bpf: Assign lock identity to callback map values Kumar Kartikeya Dwivedi
2026-09-05  7:21   ` sashiko-bot
2026-09-05  7:32     ` Kumar Kartikeya Dwivedi
2026-09-05  6:59 ` [PATCH bpf v1 8/8] selftests/bpf: Check callback map value lock identity Kumar Kartikeya Dwivedi

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=20260905070003.3193366-3-memxor@gmail.com \
    --to=memxor@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=emil@etsalapatis.com \
    --cc=kernel-team@meta.com \
    --cc=kkd@meta.com \
    --cc=npc@anthropic.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.