Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'Allow attaching to bare tracepoints'

Qais Yousef says:

====================

Changes in v3:
* Fix not returning error value correctly in
trigger_module_test_write() (Yonghong)
* Add Yonghong acked-by to patch 1.

Changes in v2:
* Fix compilation error. (Andrii)
* Make the new test use write() instead of read() (Andrii)

Add some missing glue logic to teach bpf about bare tracepoints - tracepoints
without any trace event associated with them.

Bare tracepoints are declare with DECLARE_TRACE(). Full tracepoints are declare
with TRACE_EVENT().

BPF can attach to these tracepoints as RAW_TRACEPOINT() only as there're no
events in tracefs created with them.
====================

Signed-off-by: Alexei Starovoitov <ast@kernel.org>

+85 -3
+6
Documentation/bpf/bpf_design_QA.rst
··· 208 208 kernel internals are subject to change and can break with newer kernels 209 209 such that the program needs to be adapted accordingly. 210 210 211 + Q: Are tracepoints part of the stable ABI? 212 + ------------------------------------------ 213 + A: NO. Tracepoints are tied to internal implementation details hence they are 214 + subject to change and can break with newer kernels. BPF programs need to change 215 + accordingly when this happens. 216 + 211 217 Q: How much stack space a BPF program uses? 212 218 ------------------------------------------- 213 219 A: Currently all program types are limited to 512 bytes of stack
+10 -2
include/trace/bpf_probe.h
··· 55 55 /* tracepoints with more than 12 arguments will hit build error */ 56 56 #define CAST_TO_U64(...) CONCATENATE(__CAST, COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__) 57 57 58 - #undef DECLARE_EVENT_CLASS 59 - #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ 58 + #define __BPF_DECLARE_TRACE(call, proto, args) \ 60 59 static notrace void \ 61 60 __bpf_trace_##call(void *__data, proto) \ 62 61 { \ 63 62 struct bpf_prog *prog = __data; \ 64 63 CONCATENATE(bpf_trace_run, COUNT_ARGS(args))(prog, CAST_TO_U64(args)); \ 65 64 } 65 + 66 + #undef DECLARE_EVENT_CLASS 67 + #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ 68 + __BPF_DECLARE_TRACE(call, PARAMS(proto), PARAMS(args)) 66 69 67 70 /* 68 71 * This part is compiled out, it is only here as a build time check ··· 113 110 #undef DEFINE_EVENT_PRINT 114 111 #define DEFINE_EVENT_PRINT(template, name, proto, args, print) \ 115 112 DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args)) 113 + 114 + #undef DECLARE_TRACE 115 + #define DECLARE_TRACE(call, proto, args) \ 116 + __BPF_DECLARE_TRACE(call, PARAMS(proto), PARAMS(args)) \ 117 + __DEFINE_EVENT(call, call, PARAMS(proto), PARAMS(args), 0) 116 118 117 119 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 118 120
+6
tools/testing/selftests/bpf/bpf_testmod/bpf_testmod-events.h
··· 28 28 __entry->pid, __entry->comm, __entry->off, __entry->len) 29 29 ); 30 30 31 + /* A bare tracepoint with no event associated with it */ 32 + DECLARE_TRACE(bpf_testmod_test_write_bare, 33 + TP_PROTO(struct task_struct *task, struct bpf_testmod_test_write_ctx *ctx), 34 + TP_ARGS(task, ctx) 35 + ); 36 + 31 37 #endif /* _BPF_TESTMOD_EVENTS_H */ 32 38 33 39 #undef TRACE_INCLUDE_PATH
+20 -1
tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c
··· 31 31 EXPORT_SYMBOL(bpf_testmod_test_read); 32 32 ALLOW_ERROR_INJECTION(bpf_testmod_test_read, ERRNO); 33 33 34 + noinline ssize_t 35 + bpf_testmod_test_write(struct file *file, struct kobject *kobj, 36 + struct bin_attribute *bin_attr, 37 + char *buf, loff_t off, size_t len) 38 + { 39 + struct bpf_testmod_test_write_ctx ctx = { 40 + .buf = buf, 41 + .off = off, 42 + .len = len, 43 + }; 44 + 45 + trace_bpf_testmod_test_write_bare(current, &ctx); 46 + 47 + return -EIO; /* always fail */ 48 + } 49 + EXPORT_SYMBOL(bpf_testmod_test_write); 50 + ALLOW_ERROR_INJECTION(bpf_testmod_test_write, ERRNO); 51 + 34 52 static struct bin_attribute bin_attr_bpf_testmod_file __ro_after_init = { 35 - .attr = { .name = "bpf_testmod", .mode = 0444, }, 53 + .attr = { .name = "bpf_testmod", .mode = 0666, }, 36 54 .read = bpf_testmod_test_read, 55 + .write = bpf_testmod_test_write, 37 56 }; 38 57 39 58 static int bpf_testmod_init(void)
+6
tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.h
··· 11 11 size_t len; 12 12 }; 13 13 14 + struct bpf_testmod_test_write_ctx { 15 + char *buf; 16 + loff_t off; 17 + size_t len; 18 + }; 19 + 14 20 #endif /* _BPF_TESTMOD_H */
+27
tools/testing/selftests/bpf/prog_tests/module_attach.c
··· 21 21 return 0; 22 22 } 23 23 24 + static int trigger_module_test_write(int write_sz) 25 + { 26 + int fd, err; 27 + char *buf = malloc(write_sz); 28 + 29 + if (!buf) 30 + return -ENOMEM; 31 + 32 + memset(buf, 'a', write_sz); 33 + buf[write_sz-1] = '\0'; 34 + 35 + fd = open("/sys/kernel/bpf_testmod", O_WRONLY); 36 + err = -errno; 37 + if (CHECK(fd < 0, "testmod_file_open", "failed: %d\n", err)) { 38 + free(buf); 39 + return err; 40 + } 41 + 42 + write(fd, buf, write_sz); 43 + close(fd); 44 + free(buf); 45 + return 0; 46 + } 47 + 24 48 void test_module_attach(void) 25 49 { 26 50 const int READ_SZ = 456; 51 + const int WRITE_SZ = 457; 27 52 struct test_module_attach* skel; 28 53 struct test_module_attach__bss *bss; 29 54 int err; ··· 73 48 74 49 /* trigger tracepoint */ 75 50 ASSERT_OK(trigger_module_test_read(READ_SZ), "trigger_read"); 51 + ASSERT_OK(trigger_module_test_write(WRITE_SZ), "trigger_write"); 76 52 77 53 ASSERT_EQ(bss->raw_tp_read_sz, READ_SZ, "raw_tp"); 54 + ASSERT_EQ(bss->raw_tp_bare_write_sz, WRITE_SZ, "raw_tp_bare"); 78 55 ASSERT_EQ(bss->tp_btf_read_sz, READ_SZ, "tp_btf"); 79 56 ASSERT_EQ(bss->fentry_read_sz, READ_SZ, "fentry"); 80 57 ASSERT_EQ(bss->fentry_manual_read_sz, READ_SZ, "fentry_manual");
+10
tools/testing/selftests/bpf/progs/test_module_attach.c
··· 17 17 return 0; 18 18 } 19 19 20 + __u32 raw_tp_bare_write_sz = 0; 21 + 22 + SEC("raw_tp/bpf_testmod_test_write_bare") 23 + int BPF_PROG(handle_raw_tp_bare, 24 + struct task_struct *task, struct bpf_testmod_test_write_ctx *write_ctx) 25 + { 26 + raw_tp_bare_write_sz = BPF_CORE_READ(write_ctx, len); 27 + return 0; 28 + } 29 + 20 30 __u32 tp_btf_read_sz = 0; 21 31 22 32 SEC("tp_btf/bpf_testmod_test_read")