Add raw tracepoint writable coverage for buffer accesses involving
negative constant pointer adjustments.

The verifier case checks that a negative effective offset is rejected.
The attach-time case adds incremental coverage beyond the existing nbd
test and the verifier rejection case: it uses a negative var_off and a
positive instruction offset whose effective offset remains non-negative.
This exercises the checked access_end accounting path and verifies that
the resulting max_tp_access is still checked against nbd_send_request's
writable size at attach time.

Signed-off-by: Sun Jian <[email protected]>
---
 .../raw_tp_writable_reject_nbd_invalid.c      | 58 +++++++++++--------
 .../bpf/progs/verifier_raw_tp_writable.c      | 16 +++++
 2 files changed, 51 insertions(+), 23 deletions(-)

diff --git 
a/tools/testing/selftests/bpf/prog_tests/raw_tp_writable_reject_nbd_invalid.c 
b/tools/testing/selftests/bpf/prog_tests/raw_tp_writable_reject_nbd_invalid.c
index 216b0dfac0fe..efe4cad47b28 100644
--- 
a/tools/testing/selftests/bpf/prog_tests/raw_tp_writable_reject_nbd_invalid.c
+++ 
b/tools/testing/selftests/bpf/prog_tests/raw_tp_writable_reject_nbd_invalid.c
@@ -4,12 +4,31 @@
 #include <linux/nbd.h>
 #include "bpf_util.h"
 
-void test_raw_tp_writable_reject_nbd_invalid(void)
+static void check_nbd_attach_reject(const char *name,
+                                   const struct bpf_insn *program, size_t 
prog_len)
 {
-       __u32 duration = 0;
+       LIBBPF_OPTS(bpf_prog_load_opts, opts);
        char error[4096];
-       int bpf_fd = -1, tp_fd = -1;
+       int bpf_fd, tp_fd;
+
+       opts.log_level = 2;
+       opts.log_buf = error;
+       opts.log_size = sizeof(error);
+
+       bpf_fd = bpf_prog_load(BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE, NULL, 
"GPL v2",
+                              program, prog_len, &opts);
+       if (!ASSERT_GE(bpf_fd, 0, "prog_load"))
+               return;
+
+       tp_fd = bpf_raw_tracepoint_open("nbd_send_request", bpf_fd);
+       if (!ASSERT_LT(tp_fd, 0, name))
+               close(tp_fd);
+
+       close(bpf_fd);
+}
 
+void test_raw_tp_writable_reject_nbd_invalid(void)
+{
        const struct bpf_insn program[] = {
                /* r6 is our tp buffer */
                BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0),
@@ -19,25 +38,18 @@ void test_raw_tp_writable_reject_nbd_invalid(void)
                BPF_EXIT_INSN(),
        };
 
-       LIBBPF_OPTS(bpf_prog_load_opts, opts,
-               .log_level = 2,
-               .log_buf = error,
-               .log_size = sizeof(error),
-       );
-
-       bpf_fd = bpf_prog_load(BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE, NULL, 
"GPL v2",
-                              program, ARRAY_SIZE(program),
-                              &opts);
-       if (CHECK(bpf_fd < 0, "bpf_raw_tracepoint_writable load",
-                 "failed: %d errno %d\n", bpf_fd, errno))
-               return;
-
-       tp_fd = bpf_raw_tracepoint_open("nbd_send_request", bpf_fd);
-       if (CHECK(tp_fd >= 0, "bpf_raw_tracepoint_writable open",
-                 "erroneously succeeded\n"))
-               goto out_bpffd;
+       const struct bpf_insn negative_var_off_program[] = {
+               BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0),
+               /* make var_off negative, but keep the effective access offset 
non-negative */
+               BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
+               /* one byte beyond the end of the nbd_request struct */
+               BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_6,
+                           sizeof(struct nbd_request) + 8),
+               BPF_EXIT_INSN(),
+       };
 
-       close(tp_fd);
-out_bpffd:
-       close(bpf_fd);
+       check_nbd_attach_reject("nbd_invalid", program, ARRAY_SIZE(program));
+       check_nbd_attach_reject("nbd_invalid_negative_var_off",
+                               negative_var_off_program,
+                               ARRAY_SIZE(negative_var_off_program));
 }
diff --git a/tools/testing/selftests/bpf/progs/verifier_raw_tp_writable.c 
b/tools/testing/selftests/bpf/progs/verifier_raw_tp_writable.c
index 14a0172e2141..4055a6443bc2 100644
--- a/tools/testing/selftests/bpf/progs/verifier_raw_tp_writable.c
+++ b/tools/testing/selftests/bpf/progs/verifier_raw_tp_writable.c
@@ -47,4 +47,20 @@ l0_%=:       /* shift the buffer pointer to a variable 
location */\
        : __clobber_all);
 }
 
+SEC("raw_tracepoint.w")
+__description("raw_tracepoint_writable: reject negative const offset")
+__failure
+__msg("invalid negative tracepoint buffer offset")
+__naked void tracepoint_writable_reject_negative_const_offset(void)
+{
+       asm volatile ("                                 \
+       r6 = *(u64 *)(r1 + 0);                          \
+       r6 += -8;                                       \
+       r0 = *(u64 *)(r6 + 0);                          \
+       exit;                                           \
+"      :
+       :
+       : __clobber_all);
+}
+
 char _license[] SEC("license") = "GPL";
-- 
2.43.0


Reply via email to