Skip to content

Commit 8e4597c

Browse files
iamkafaiAlexei Starovoitov
authored and
Alexei Starovoitov
committed
bpf: Allow using bpf_sk_storage in FENTRY/FEXIT/RAW_TP
This patch enables the FENTRY/FEXIT/RAW_TP tracing program to use the bpf_sk_storage_(get|delete) helper, so those tracing programs can access the sk's bpf_local_storage and the later selftest will show some examples. The bpf_sk_storage is currently used in bpf-tcp-cc, tc, cg sockops...etc which is running either in softirq or task context. This patch adds bpf_sk_storage_get_tracing_proto and bpf_sk_storage_delete_tracing_proto. They will check in runtime that the helpers can only be called when serving softirq or running in a task context. That should enable most common tracing use cases on sk. During the load time, the new tracing_allowed() function will ensure the tracing prog using the bpf_sk_storage_(get|delete) helper is not tracing any bpf_sk_storage*() function itself. The sk is passed as "void *" when calling into bpf_local_storage. This patch only allows tracing a kernel function. Signed-off-by: Martin KaFai Lau <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Acked-by: Song Liu <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent e794bfd commit 8e4597c

File tree

3 files changed

+81
-0
lines changed

3 files changed

+81
-0
lines changed

include/net/bpf_sk_storage.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ void bpf_sk_storage_free(struct sock *sk);
2020

2121
extern const struct bpf_func_proto bpf_sk_storage_get_proto;
2222
extern const struct bpf_func_proto bpf_sk_storage_delete_proto;
23+
extern const struct bpf_func_proto bpf_sk_storage_get_tracing_proto;
24+
extern const struct bpf_func_proto bpf_sk_storage_delete_tracing_proto;
2325

2426
struct bpf_local_storage_elem;
2527
struct bpf_sk_storage_diag;

kernel/trace/bpf_trace.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/syscalls.h>
1717
#include <linux/error-injection.h>
1818
#include <linux/btf_ids.h>
19+
#include <net/bpf_sk_storage.h>
1920

2021
#include <uapi/linux/bpf.h>
2122
#include <uapi/linux/btf.h>
@@ -1735,6 +1736,10 @@ tracing_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
17351736
return &bpf_skc_to_tcp_request_sock_proto;
17361737
case BPF_FUNC_skc_to_udp6_sock:
17371738
return &bpf_skc_to_udp6_sock_proto;
1739+
case BPF_FUNC_sk_storage_get:
1740+
return &bpf_sk_storage_get_tracing_proto;
1741+
case BPF_FUNC_sk_storage_delete:
1742+
return &bpf_sk_storage_delete_tracing_proto;
17381743
#endif
17391744
case BPF_FUNC_seq_printf:
17401745
return prog->expected_attach_type == BPF_TRACE_ITER ?

net/core/bpf_sk_storage.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <linux/types.h>
77
#include <linux/spinlock.h>
88
#include <linux/bpf.h>
9+
#include <linux/btf.h>
910
#include <linux/btf_ids.h>
1011
#include <linux/bpf_local_storage.h>
1112
#include <net/bpf_sk_storage.h>
@@ -378,6 +379,79 @@ const struct bpf_func_proto bpf_sk_storage_delete_proto = {
378379
.arg2_type = ARG_PTR_TO_BTF_ID_SOCK_COMMON,
379380
};
380381

382+
static bool bpf_sk_storage_tracing_allowed(const struct bpf_prog *prog)
383+
{
384+
const struct btf *btf_vmlinux;
385+
const struct btf_type *t;
386+
const char *tname;
387+
u32 btf_id;
388+
389+
if (prog->aux->dst_prog)
390+
return false;
391+
392+
/* Ensure the tracing program is not tracing
393+
* any bpf_sk_storage*() function and also
394+
* use the bpf_sk_storage_(get|delete) helper.
395+
*/
396+
switch (prog->expected_attach_type) {
397+
case BPF_TRACE_RAW_TP:
398+
/* bpf_sk_storage has no trace point */
399+
return true;
400+
case BPF_TRACE_FENTRY:
401+
case BPF_TRACE_FEXIT:
402+
btf_vmlinux = bpf_get_btf_vmlinux();
403+
btf_id = prog->aux->attach_btf_id;
404+
t = btf_type_by_id(btf_vmlinux, btf_id);
405+
tname = btf_name_by_offset(btf_vmlinux, t->name_off);
406+
return !!strncmp(tname, "bpf_sk_storage",
407+
strlen("bpf_sk_storage"));
408+
default:
409+
return false;
410+
}
411+
412+
return false;
413+
}
414+
415+
BPF_CALL_4(bpf_sk_storage_get_tracing, struct bpf_map *, map, struct sock *, sk,
416+
void *, value, u64, flags)
417+
{
418+
if (!in_serving_softirq() && !in_task())
419+
return (unsigned long)NULL;
420+
421+
return (unsigned long)____bpf_sk_storage_get(map, sk, value, flags);
422+
}
423+
424+
BPF_CALL_2(bpf_sk_storage_delete_tracing, struct bpf_map *, map,
425+
struct sock *, sk)
426+
{
427+
if (!in_serving_softirq() && !in_task())
428+
return -EPERM;
429+
430+
return ____bpf_sk_storage_delete(map, sk);
431+
}
432+
433+
const struct bpf_func_proto bpf_sk_storage_get_tracing_proto = {
434+
.func = bpf_sk_storage_get_tracing,
435+
.gpl_only = false,
436+
.ret_type = RET_PTR_TO_MAP_VALUE_OR_NULL,
437+
.arg1_type = ARG_CONST_MAP_PTR,
438+
.arg2_type = ARG_PTR_TO_BTF_ID,
439+
.arg2_btf_id = &btf_sock_ids[BTF_SOCK_TYPE_SOCK_COMMON],
440+
.arg3_type = ARG_PTR_TO_MAP_VALUE_OR_NULL,
441+
.arg4_type = ARG_ANYTHING,
442+
.allowed = bpf_sk_storage_tracing_allowed,
443+
};
444+
445+
const struct bpf_func_proto bpf_sk_storage_delete_tracing_proto = {
446+
.func = bpf_sk_storage_delete_tracing,
447+
.gpl_only = false,
448+
.ret_type = RET_INTEGER,
449+
.arg1_type = ARG_CONST_MAP_PTR,
450+
.arg2_type = ARG_PTR_TO_BTF_ID,
451+
.arg2_btf_id = &btf_sock_ids[BTF_SOCK_TYPE_SOCK_COMMON],
452+
.allowed = bpf_sk_storage_tracing_allowed,
453+
};
454+
381455
struct bpf_sk_storage_diag {
382456
u32 nr_maps;
383457
struct bpf_map *maps[];

0 commit comments

Comments
 (0)