Commit 9df1c28b authored by Matt Mullins's avatar Matt Mullins Committed by Alexei Starovoitov
Browse files

bpf: add writable context for raw tracepoints



This is an opt-in interface that allows a tracepoint to provide a safe
buffer that can be written from a BPF_PROG_TYPE_RAW_TRACEPOINT program.
The size of the buffer must be a compile-time constant, and is checked
before allowing a BPF program to attach to a tracepoint that uses this
feature.

The pointer to this buffer will be the first argument of tracepoints
that opt in; the pointer is valid and can be bpf_probe_read() by both
BPF_PROG_TYPE_RAW_TRACEPOINT and BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE
programs that attach to such a tracepoint, but the buffer to which it
points may only be written by the latter.

Signed-off-by: default avatarMatt Mullins <mmullins@fb.com>
Acked-by: default avatarYonghong Song <yhs@fb.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 34b8ab09
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -272,6 +272,7 @@ enum bpf_reg_type {
	PTR_TO_SOCK_COMMON_OR_NULL, /* reg points to sock_common or NULL */
	PTR_TO_SOCK_COMMON_OR_NULL, /* reg points to sock_common or NULL */
	PTR_TO_TCP_SOCK,	 /* reg points to struct tcp_sock */
	PTR_TO_TCP_SOCK,	 /* reg points to struct tcp_sock */
	PTR_TO_TCP_SOCK_OR_NULL, /* reg points to struct tcp_sock or NULL */
	PTR_TO_TCP_SOCK_OR_NULL, /* reg points to struct tcp_sock or NULL */
	PTR_TO_TP_BUFFER,	 /* reg points to a writable raw tp's buffer */
};
};


/* The information passed from prog-specific *_is_valid_access
/* The information passed from prog-specific *_is_valid_access
@@ -361,6 +362,7 @@ struct bpf_prog_aux {
	u32 used_map_cnt;
	u32 used_map_cnt;
	u32 max_ctx_offset;
	u32 max_ctx_offset;
	u32 max_pkt_offset;
	u32 max_pkt_offset;
	u32 max_tp_access;
	u32 stack_depth;
	u32 stack_depth;
	u32 id;
	u32 id;
	u32 func_cnt; /* used by non-func prog as the number of func progs */
	u32 func_cnt; /* used by non-func prog as the number of func progs */
+1 −0
Original line number Original line Diff line number Diff line
@@ -25,6 +25,7 @@ BPF_PROG_TYPE(BPF_PROG_TYPE_KPROBE, kprobe)
BPF_PROG_TYPE(BPF_PROG_TYPE_TRACEPOINT, tracepoint)
BPF_PROG_TYPE(BPF_PROG_TYPE_TRACEPOINT, tracepoint)
BPF_PROG_TYPE(BPF_PROG_TYPE_PERF_EVENT, perf_event)
BPF_PROG_TYPE(BPF_PROG_TYPE_PERF_EVENT, perf_event)
BPF_PROG_TYPE(BPF_PROG_TYPE_RAW_TRACEPOINT, raw_tracepoint)
BPF_PROG_TYPE(BPF_PROG_TYPE_RAW_TRACEPOINT, raw_tracepoint)
BPF_PROG_TYPE(BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE, raw_tracepoint_writable)
#endif
#endif
#ifdef CONFIG_CGROUP_BPF
#ifdef CONFIG_CGROUP_BPF
BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_DEVICE, cg_dev)
BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_DEVICE, cg_dev)
+1 −0
Original line number Original line Diff line number Diff line
@@ -45,6 +45,7 @@ struct bpf_raw_event_map {
	struct tracepoint	*tp;
	struct tracepoint	*tp;
	void			*bpf_func;
	void			*bpf_func;
	u32			num_args;
	u32			num_args;
	u32			writable_size;
} __aligned(32);
} __aligned(32);


#endif
#endif
+25 −2
Original line number Original line Diff line number Diff line
@@ -69,8 +69,7 @@ __bpf_trace_##call(void *__data, proto) \
 * to make sure that if the tracepoint handling changes, the
 * to make sure that if the tracepoint handling changes, the
 * bpf probe will fail to compile unless it too is updated.
 * bpf probe will fail to compile unless it too is updated.
 */
 */
#undef DEFINE_EVENT
#define __DEFINE_EVENT(template, call, proto, args, size)		\
#define DEFINE_EVENT(template, call, proto, args)			\
static inline void bpf_test_probe_##call(void)				\
static inline void bpf_test_probe_##call(void)				\
{									\
{									\
	check_trace_callback_type_##call(__bpf_trace_##template);	\
	check_trace_callback_type_##call(__bpf_trace_##template);	\
@@ -81,12 +80,36 @@ __bpf_trace_tp_map_##call = { \
	.tp		= &__tracepoint_##call,				\
	.tp		= &__tracepoint_##call,				\
	.bpf_func	= (void *)__bpf_trace_##template,		\
	.bpf_func	= (void *)__bpf_trace_##template,		\
	.num_args	= COUNT_ARGS(args),				\
	.num_args	= COUNT_ARGS(args),				\
	.writable_size	= size,						\
};
};


#define FIRST(x, ...) x

#undef DEFINE_EVENT_WRITABLE
#define DEFINE_EVENT_WRITABLE(template, call, proto, args, size)	\
static inline void bpf_test_buffer_##call(void)				\
{									\
	/* BUILD_BUG_ON() is ignored if the code is completely eliminated, but \
	 * BUILD_BUG_ON_ZERO() uses a different mechanism that is not	\
	 * dead-code-eliminated.					\
	 */								\
	FIRST(proto);							\
	(void)BUILD_BUG_ON_ZERO(size != sizeof(*FIRST(args)));		\
}									\
__DEFINE_EVENT(template, call, PARAMS(proto), PARAMS(args), size)

#undef DEFINE_EVENT
#define DEFINE_EVENT(template, call, proto, args)			\
	__DEFINE_EVENT(template, call, PARAMS(proto), PARAMS(args), 0)


#undef DEFINE_EVENT_PRINT
#undef DEFINE_EVENT_PRINT
#define DEFINE_EVENT_PRINT(template, name, proto, args, print)	\
#define DEFINE_EVENT_PRINT(template, name, proto, args, print)	\
	DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
	DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))


#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)

#undef DEFINE_EVENT_WRITABLE
#undef __DEFINE_EVENT
#undef FIRST

#endif /* CONFIG_BPF_EVENTS */
#endif /* CONFIG_BPF_EVENTS */
+1 −0
Original line number Original line Diff line number Diff line
@@ -168,6 +168,7 @@ enum bpf_prog_type {
	BPF_PROG_TYPE_SK_REUSEPORT,
	BPF_PROG_TYPE_SK_REUSEPORT,
	BPF_PROG_TYPE_FLOW_DISSECTOR,
	BPF_PROG_TYPE_FLOW_DISSECTOR,
	BPF_PROG_TYPE_CGROUP_SYSCTL,
	BPF_PROG_TYPE_CGROUP_SYSCTL,
	BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE,
};
};


enum bpf_attach_type {
enum bpf_attach_type {
Loading