[PATCH bpf v2 2/2] bpf: new verifier tests for stack access

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds tests for the previous patch, checking the tracking of
the maximum stack size and checking that accesses to uninit stack memory
are allowed.

They are a separate patch for review purposes; whoever merges them can
consider squashing.

Signed-off-by: Andrei Matei <andreimatei1@xxxxxxxxx>
---
 tools/testing/selftests/bpf/test_verifier.c  | 24 ++++++++++++
 tools/testing/selftests/bpf/verifier/stack.c | 40 ++++++++++++++++++++
 2 files changed, 64 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/verifier/stack.c

diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index 98107e0452d3..a62610585ee4 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -135,6 +135,10 @@ struct bpf_test {
 	const char *errstr;
 	const char *errstr_unpriv;
 	uint32_t insn_processed;
+	/* Expected maximum stack depth for the main subprogram. Not checked if 0.
+	 * Only checked if the program is accepted.
+	 */
+	uint16_t max_stack_depth;
 	int prog_len;
 	enum {
 		UNDEF,
@@ -1703,6 +1707,26 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
 		}
 	}
 
+	/* Check the stack size if the test configured an expecation and the program
+	 * was loaded successfully.
+	 */
+	if (test->max_stack_depth && fd_prog >= 0) {
+		uint32_t max_stack;
+		char *s;
+
+		s = strstr(bpf_vlog, "stack depth ");
+		if (s == NULL) {
+			printf("FAIL\nstack depth result not found in verifier output\n");
+			goto fail_log;
+		}
+		max_stack = atoi(s + 12);
+		if (test->max_stack_depth != max_stack) {
+			printf("FAIL\nUnexpected max stack %u vs %u\n",
+			       max_stack, test->max_stack_depth);
+			goto fail_log;
+		}
+	}
+
 	if (verbose)
 		printf(", verifier log:\n%s", bpf_vlog);
 
diff --git a/tools/testing/selftests/bpf/verifier/stack.c b/tools/testing/selftests/bpf/verifier/stack.c
new file mode 100644
index 000000000000..ac571783c05e
--- /dev/null
+++ b/tools/testing/selftests/bpf/verifier/stack.c
@@ -0,0 +1,40 @@
+{
+	/* Check that reading unitialized stack memory is allowed only in privileged
+	 * mode. Also check that such reads maintain the max stack depth.
+	 */
+	"read uninit stack",
+	.insns = {
+		BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -504),
+		/* exit(0); */
+		BPF_MOV32_IMM(BPF_REG_0, 0),
+		BPF_EXIT_INSN(),
+	},
+	.result = ACCEPT,
+	.result_unpriv = REJECT,
+	.errstr_unpriv = "invalid read from stack",
+    .max_stack_depth = 504,
+},
+{
+    /* Check that indirect accesses to stack maintain the max stack depth. */
+	"read (indirect) uninit stack",
+	.insns = {
+		/* We'll use probe_read_user as an arbitrary helper that can access the
+		 * stack. We're going to read into *(fp-104).
+		 */
+		BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
+		BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -104),
+		BPF_MOV32_IMM(BPF_REG_2, 8),
+        /* read from a random address */
+		BPF_MOV32_IMM(BPF_REG_3, 0x4242),
+        BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_probe_read_user),
+        BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
+	    BPF_EXIT_INSN(),
+		/* exit(0); */
+		BPF_MOV32_IMM(BPF_REG_0, 0),
+		BPF_EXIT_INSN(),
+	},
+	.result = ACCEPT,
+	.result_unpriv = REJECT,
+	.errstr_unpriv = "",
+    .max_stack_depth = 104,
+},
\ No newline at end of file
-- 
2.40.1





[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux