Skip to content

Commit 93dafa9

Browse files
committed
Merge branch 'Attach a cookie to a tracing program.'
Kui-Feng Lee says: ==================== Allow users to attach a 64-bits cookie to a bpf_link of fentry, fexit, or fmod_ret. This patchset includes several major changes. - Define struct bpf_tramp_links to replace bpf_tramp_prog. struct bpf_tramp_links collects bpf_links of a trampoline - Generate a trampoline to call bpf_progs of given bpf_links. - Trampolines always set/reset bpf_run_ctx before/after calling/leaving a tracing program. - Attach a cookie to a bpf_link of fentry/fexit/fmod_ret/lsm. The value will be available when running the associated bpf_prog. Th major differences from v6: - bpf_link_create() can create links of BPF_LSM_MAC attach type. - Add a test for lsm. - Add function proto of bpf_get_attach_cookie() for lsm. - Check BPF_LSM_MAC in bpf_prog_has_trampoline(). - Adapt to the changes of LINK_CREATE made by Andrii. The major differences from v7: - Change stack_size instead of pushing/popping run_ctx. - Move cookie to bpf_tramp_link from bpf_tracing_link.. v1: https://lore.kernel.org/all/20220126214809.3868787-1-kuifeng@fb.com/ v2: https://lore.kernel.org/bpf/20220316004231.1103318-1-kuifeng@fb.com/ v3: https://lore.kernel.org/bpf/20220407192552.2343076-1-kuifeng@fb.com/ v4: https://lore.kernel.org/bpf/20220411173429.4139609-1-kuifeng@fb.com/ v5: https://lore.kernel.org/bpf/20220412165555.4146407-1-kuifeng@fb.com/ v6: https://lore.kernel.org/bpf/20220416042940.656344-1-kuifeng@fb.com/ v7: https://lore.kernel.org/bpf/20220508032117.2783209-1-kuifeng@fb.com/ ==================== Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
2 parents cb41154 + ddc0027 commit 93dafa9

File tree

19 files changed

+468
-138
lines changed

19 files changed

+468
-138
lines changed

arch/x86/net/bpf_jit_comp.c

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1762,13 +1762,32 @@ static void restore_regs(const struct btf_func_model *m, u8 **prog, int nr_args,
17621762
}
17631763

17641764
static int invoke_bpf_prog(const struct btf_func_model *m, u8 **pprog,
1765-
struct bpf_prog *p, int stack_size, bool save_ret)
1765+
struct bpf_tramp_link *l, int stack_size,
1766+
int run_ctx_off, bool save_ret)
17661767
{
17671768
u8 *prog = *pprog;
17681769
u8 *jmp_insn;
1770+
int ctx_cookie_off = offsetof(struct bpf_tramp_run_ctx, bpf_cookie);
1771+
struct bpf_prog *p = l->link.prog;
1772+
u64 cookie = l->cookie;
1773+
1774+
/* mov rdi, cookie */
1775+
emit_mov_imm64(&prog, BPF_REG_1, (long) cookie >> 32, (u32) (long) cookie);
1776+
1777+
/* Prepare struct bpf_tramp_run_ctx.
1778+
*
1779+
* bpf_tramp_run_ctx is already preserved by
1780+
* arch_prepare_bpf_trampoline().
1781+
*
1782+
* mov QWORD PTR [rbp - run_ctx_off + ctx_cookie_off], rdi
1783+
*/
1784+
emit_stx(&prog, BPF_DW, BPF_REG_FP, BPF_REG_1, -run_ctx_off + ctx_cookie_off);
17691785

17701786
/* arg1: mov rdi, progs[i] */
17711787
emit_mov_imm64(&prog, BPF_REG_1, (long) p >> 32, (u32) (long) p);
1788+
/* arg2: lea rsi, [rbp - ctx_cookie_off] */
1789+
EMIT4(0x48, 0x8D, 0x75, -run_ctx_off);
1790+
17721791
if (emit_call(&prog,
17731792
p->aux->sleepable ? __bpf_prog_enter_sleepable :
17741793
__bpf_prog_enter, prog))
@@ -1814,6 +1833,8 @@ static int invoke_bpf_prog(const struct btf_func_model *m, u8 **pprog,
18141833
emit_mov_imm64(&prog, BPF_REG_1, (long) p >> 32, (u32) (long) p);
18151834
/* arg2: mov rsi, rbx <- start time in nsec */
18161835
emit_mov_reg(&prog, true, BPF_REG_2, BPF_REG_6);
1836+
/* arg3: lea rdx, [rbp - run_ctx_off] */
1837+
EMIT4(0x48, 0x8D, 0x55, -run_ctx_off);
18171838
if (emit_call(&prog,
18181839
p->aux->sleepable ? __bpf_prog_exit_sleepable :
18191840
__bpf_prog_exit, prog))
@@ -1850,24 +1871,24 @@ static int emit_cond_near_jump(u8 **pprog, void *func, void *ip, u8 jmp_cond)
18501871
}
18511872

18521873
static int invoke_bpf(const struct btf_func_model *m, u8 **pprog,
1853-
struct bpf_tramp_progs *tp, int stack_size,
1854-
bool save_ret)
1874+
struct bpf_tramp_links *tl, int stack_size,
1875+
int run_ctx_off, bool save_ret)
18551876
{
18561877
int i;
18571878
u8 *prog = *pprog;
18581879

1859-
for (i = 0; i < tp->nr_progs; i++) {
1860-
if (invoke_bpf_prog(m, &prog, tp->progs[i], stack_size,
1861-
save_ret))
1880+
for (i = 0; i < tl->nr_links; i++) {
1881+
if (invoke_bpf_prog(m, &prog, tl->links[i], stack_size,
1882+
run_ctx_off, save_ret))
18621883
return -EINVAL;
18631884
}
18641885
*pprog = prog;
18651886
return 0;
18661887
}
18671888

18681889
static int invoke_bpf_mod_ret(const struct btf_func_model *m, u8 **pprog,
1869-
struct bpf_tramp_progs *tp, int stack_size,
1870-
u8 **branches)
1890+
struct bpf_tramp_links *tl, int stack_size,
1891+
int run_ctx_off, u8 **branches)
18711892
{
18721893
u8 *prog = *pprog;
18731894
int i;
@@ -1877,8 +1898,8 @@ static int invoke_bpf_mod_ret(const struct btf_func_model *m, u8 **pprog,
18771898
*/
18781899
emit_mov_imm32(&prog, false, BPF_REG_0, 0);
18791900
emit_stx(&prog, BPF_DW, BPF_REG_FP, BPF_REG_0, -8);
1880-
for (i = 0; i < tp->nr_progs; i++) {
1881-
if (invoke_bpf_prog(m, &prog, tp->progs[i], stack_size, true))
1901+
for (i = 0; i < tl->nr_links; i++) {
1902+
if (invoke_bpf_prog(m, &prog, tl->links[i], stack_size, run_ctx_off, true))
18821903
return -EINVAL;
18831904

18841905
/* mod_ret prog stored return value into [rbp - 8]. Emit:
@@ -1980,14 +2001,14 @@ static bool is_valid_bpf_tramp_flags(unsigned int flags)
19802001
*/
19812002
int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *image_end,
19822003
const struct btf_func_model *m, u32 flags,
1983-
struct bpf_tramp_progs *tprogs,
2004+
struct bpf_tramp_links *tlinks,
19842005
void *orig_call)
19852006
{
19862007
int ret, i, nr_args = m->nr_args;
1987-
int regs_off, ip_off, args_off, stack_size = nr_args * 8;
1988-
struct bpf_tramp_progs *fentry = &tprogs[BPF_TRAMP_FENTRY];
1989-
struct bpf_tramp_progs *fexit = &tprogs[BPF_TRAMP_FEXIT];
1990-
struct bpf_tramp_progs *fmod_ret = &tprogs[BPF_TRAMP_MODIFY_RETURN];
2008+
int regs_off, ip_off, args_off, stack_size = nr_args * 8, run_ctx_off;
2009+
struct bpf_tramp_links *fentry = &tlinks[BPF_TRAMP_FENTRY];
2010+
struct bpf_tramp_links *fexit = &tlinks[BPF_TRAMP_FEXIT];
2011+
struct bpf_tramp_links *fmod_ret = &tlinks[BPF_TRAMP_MODIFY_RETURN];
19912012
u8 **branches = NULL;
19922013
u8 *prog;
19932014
bool save_ret;
@@ -2014,6 +2035,8 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i
20142035
* RBP - args_off [ args count ] always
20152036
*
20162037
* RBP - ip_off [ traced function ] BPF_TRAMP_F_IP_ARG flag
2038+
*
2039+
* RBP - run_ctx_off [ bpf_tramp_run_ctx ]
20172040
*/
20182041

20192042
/* room for return value of orig_call or fentry prog */
@@ -2032,6 +2055,9 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i
20322055

20332056
ip_off = stack_size;
20342057

2058+
stack_size += (sizeof(struct bpf_tramp_run_ctx) + 7) & ~0x7;
2059+
run_ctx_off = stack_size;
2060+
20352061
if (flags & BPF_TRAMP_F_SKIP_FRAME) {
20362062
/* skip patched call instruction and point orig_call to actual
20372063
* body of the kernel function.
@@ -2078,19 +2104,19 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i
20782104
}
20792105
}
20802106

2081-
if (fentry->nr_progs)
2082-
if (invoke_bpf(m, &prog, fentry, regs_off,
2107+
if (fentry->nr_links)
2108+
if (invoke_bpf(m, &prog, fentry, regs_off, run_ctx_off,
20832109
flags & BPF_TRAMP_F_RET_FENTRY_RET))
20842110
return -EINVAL;
20852111

2086-
if (fmod_ret->nr_progs) {
2087-
branches = kcalloc(fmod_ret->nr_progs, sizeof(u8 *),
2112+
if (fmod_ret->nr_links) {
2113+
branches = kcalloc(fmod_ret->nr_links, sizeof(u8 *),
20882114
GFP_KERNEL);
20892115
if (!branches)
20902116
return -ENOMEM;
20912117

20922118
if (invoke_bpf_mod_ret(m, &prog, fmod_ret, regs_off,
2093-
branches)) {
2119+
run_ctx_off, branches)) {
20942120
ret = -EINVAL;
20952121
goto cleanup;
20962122
}
@@ -2111,7 +2137,7 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i
21112137
prog += X86_PATCH_SIZE;
21122138
}
21132139

2114-
if (fmod_ret->nr_progs) {
2140+
if (fmod_ret->nr_links) {
21152141
/* From Intel 64 and IA-32 Architectures Optimization
21162142
* Reference Manual, 3.4.1.4 Code Alignment, Assembly/Compiler
21172143
* Coding Rule 11: All branch targets should be 16-byte
@@ -2121,13 +2147,13 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i
21212147
/* Update the branches saved in invoke_bpf_mod_ret with the
21222148
* aligned address of do_fexit.
21232149
*/
2124-
for (i = 0; i < fmod_ret->nr_progs; i++)
2150+
for (i = 0; i < fmod_ret->nr_links; i++)
21252151
emit_cond_near_jump(&branches[i], prog, branches[i],
21262152
X86_JNE);
21272153
}
21282154

2129-
if (fexit->nr_progs)
2130-
if (invoke_bpf(m, &prog, fexit, regs_off, false)) {
2155+
if (fexit->nr_links)
2156+
if (invoke_bpf(m, &prog, fexit, regs_off, run_ctx_off, false)) {
21312157
ret = -EINVAL;
21322158
goto cleanup;
21332159
}

include/linux/bpf.h

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -723,13 +723,15 @@ struct btf_func_model {
723723
/* Each call __bpf_prog_enter + call bpf_func + call __bpf_prog_exit is ~50
724724
* bytes on x86. Pick a number to fit into BPF_IMAGE_SIZE / 2
725725
*/
726-
#define BPF_MAX_TRAMP_PROGS 38
726+
#define BPF_MAX_TRAMP_LINKS 38
727727

728-
struct bpf_tramp_progs {
729-
struct bpf_prog *progs[BPF_MAX_TRAMP_PROGS];
730-
int nr_progs;
728+
struct bpf_tramp_links {
729+
struct bpf_tramp_link *links[BPF_MAX_TRAMP_LINKS];
730+
int nr_links;
731731
};
732732

733+
struct bpf_tramp_run_ctx;
734+
733735
/* Different use cases for BPF trampoline:
734736
* 1. replace nop at the function entry (kprobe equivalent)
735737
* flags = BPF_TRAMP_F_RESTORE_REGS
@@ -753,13 +755,14 @@ struct bpf_tramp_progs {
753755
struct bpf_tramp_image;
754756
int arch_prepare_bpf_trampoline(struct bpf_tramp_image *tr, void *image, void *image_end,
755757
const struct btf_func_model *m, u32 flags,
756-
struct bpf_tramp_progs *tprogs,
758+
struct bpf_tramp_links *tlinks,
757759
void *orig_call);
758760
/* these two functions are called from generated trampoline */
759-
u64 notrace __bpf_prog_enter(struct bpf_prog *prog);
760-
void notrace __bpf_prog_exit(struct bpf_prog *prog, u64 start);
761-
u64 notrace __bpf_prog_enter_sleepable(struct bpf_prog *prog);
762-
void notrace __bpf_prog_exit_sleepable(struct bpf_prog *prog, u64 start);
761+
u64 notrace __bpf_prog_enter(struct bpf_prog *prog, struct bpf_tramp_run_ctx *run_ctx);
762+
void notrace __bpf_prog_exit(struct bpf_prog *prog, u64 start, struct bpf_tramp_run_ctx *run_ctx);
763+
u64 notrace __bpf_prog_enter_sleepable(struct bpf_prog *prog, struct bpf_tramp_run_ctx *run_ctx);
764+
void notrace __bpf_prog_exit_sleepable(struct bpf_prog *prog, u64 start,
765+
struct bpf_tramp_run_ctx *run_ctx);
763766
void notrace __bpf_tramp_enter(struct bpf_tramp_image *tr);
764767
void notrace __bpf_tramp_exit(struct bpf_tramp_image *tr);
765768

@@ -852,9 +855,10 @@ static __always_inline __nocfi unsigned int bpf_dispatcher_nop_func(
852855
{
853856
return bpf_func(ctx, insnsi);
854857
}
858+
855859
#ifdef CONFIG_BPF_JIT
856-
int bpf_trampoline_link_prog(struct bpf_prog *prog, struct bpf_trampoline *tr);
857-
int bpf_trampoline_unlink_prog(struct bpf_prog *prog, struct bpf_trampoline *tr);
860+
int bpf_trampoline_link_prog(struct bpf_tramp_link *link, struct bpf_trampoline *tr);
861+
int bpf_trampoline_unlink_prog(struct bpf_tramp_link *link, struct bpf_trampoline *tr);
858862
struct bpf_trampoline *bpf_trampoline_get(u64 key,
859863
struct bpf_attach_target_info *tgt_info);
860864
void bpf_trampoline_put(struct bpf_trampoline *tr);
@@ -905,12 +909,12 @@ int bpf_jit_charge_modmem(u32 size);
905909
void bpf_jit_uncharge_modmem(u32 size);
906910
bool bpf_prog_has_trampoline(const struct bpf_prog *prog);
907911
#else
908-
static inline int bpf_trampoline_link_prog(struct bpf_prog *prog,
912+
static inline int bpf_trampoline_link_prog(struct bpf_tramp_link *link,
909913
struct bpf_trampoline *tr)
910914
{
911915
return -ENOTSUPP;
912916
}
913-
static inline int bpf_trampoline_unlink_prog(struct bpf_prog *prog,
917+
static inline int bpf_trampoline_unlink_prog(struct bpf_tramp_link *link,
914918
struct bpf_trampoline *tr)
915919
{
916920
return -ENOTSUPP;
@@ -1009,7 +1013,6 @@ struct bpf_prog_aux {
10091013
bool tail_call_reachable;
10101014
bool xdp_has_frags;
10111015
bool use_bpf_prog_pack;
1012-
struct hlist_node tramp_hlist;
10131016
/* BTF_KIND_FUNC_PROTO for valid attach_btf_id */
10141017
const struct btf_type *attach_func_proto;
10151018
/* function name for valid attach_btf_id */
@@ -1096,6 +1099,19 @@ struct bpf_link_ops {
10961099
struct bpf_link_info *info);
10971100
};
10981101

1102+
struct bpf_tramp_link {
1103+
struct bpf_link link;
1104+
struct hlist_node tramp_hlist;
1105+
u64 cookie;
1106+
};
1107+
1108+
struct bpf_tracing_link {
1109+
struct bpf_tramp_link link;
1110+
enum bpf_attach_type attach_type;
1111+
struct bpf_trampoline *trampoline;
1112+
struct bpf_prog *tgt_prog;
1113+
};
1114+
10991115
struct bpf_link_primer {
11001116
struct bpf_link *link;
11011117
struct file *file;
@@ -1133,8 +1149,8 @@ bool bpf_struct_ops_get(const void *kdata);
11331149
void bpf_struct_ops_put(const void *kdata);
11341150
int bpf_struct_ops_map_sys_lookup_elem(struct bpf_map *map, void *key,
11351151
void *value);
1136-
int bpf_struct_ops_prepare_trampoline(struct bpf_tramp_progs *tprogs,
1137-
struct bpf_prog *prog,
1152+
int bpf_struct_ops_prepare_trampoline(struct bpf_tramp_links *tlinks,
1153+
struct bpf_tramp_link *link,
11381154
const struct btf_func_model *model,
11391155
void *image, void *image_end);
11401156
static inline bool bpf_try_module_get(const void *data, struct module *owner)
@@ -1339,6 +1355,12 @@ struct bpf_trace_run_ctx {
13391355
u64 bpf_cookie;
13401356
};
13411357

1358+
struct bpf_tramp_run_ctx {
1359+
struct bpf_run_ctx run_ctx;
1360+
u64 bpf_cookie;
1361+
struct bpf_run_ctx *saved_run_ctx;
1362+
};
1363+
13421364
static inline struct bpf_run_ctx *bpf_set_run_ctx(struct bpf_run_ctx *new_ctx)
13431365
{
13441366
struct bpf_run_ctx *old_ctx = NULL;

include/linux/bpf_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,4 @@ BPF_LINK_TYPE(BPF_LINK_TYPE_XDP, xdp)
141141
BPF_LINK_TYPE(BPF_LINK_TYPE_PERF_EVENT, perf)
142142
#endif
143143
BPF_LINK_TYPE(BPF_LINK_TYPE_KPROBE_MULTI, kprobe_multi)
144+
BPF_LINK_TYPE(BPF_LINK_TYPE_STRUCT_OPS, struct_ops)

include/uapi/linux/bpf.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,7 @@ enum bpf_link_type {
10131013
BPF_LINK_TYPE_XDP = 6,
10141014
BPF_LINK_TYPE_PERF_EVENT = 7,
10151015
BPF_LINK_TYPE_KPROBE_MULTI = 8,
1016+
BPF_LINK_TYPE_STRUCT_OPS = 9,
10161017

10171018
MAX_BPF_LINK_TYPE,
10181019
};
@@ -1489,6 +1490,15 @@ union bpf_attr {
14891490
__aligned_u64 addrs;
14901491
__aligned_u64 cookies;
14911492
} kprobe_multi;
1493+
struct {
1494+
/* this is overlaid with the target_btf_id above. */
1495+
__u32 target_btf_id;
1496+
/* black box user-provided value passed through
1497+
* to BPF program at the execution time and
1498+
* accessible through bpf_get_attach_cookie() BPF helper
1499+
*/
1500+
__u64 cookie;
1501+
} tracing;
14921502
};
14931503
} link_create;
14941504

kernel/bpf/bpf_lsm.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,21 @@ static const struct bpf_func_proto bpf_ima_file_hash_proto = {
117117
.allowed = bpf_ima_inode_hash_allowed,
118118
};
119119

120+
BPF_CALL_1(bpf_get_attach_cookie, void *, ctx)
121+
{
122+
struct bpf_trace_run_ctx *run_ctx;
123+
124+
run_ctx = container_of(current->bpf_ctx, struct bpf_trace_run_ctx, run_ctx);
125+
return run_ctx->bpf_cookie;
126+
}
127+
128+
static const struct bpf_func_proto bpf_get_attach_cookie_proto = {
129+
.func = bpf_get_attach_cookie,
130+
.gpl_only = false,
131+
.ret_type = RET_INTEGER,
132+
.arg1_type = ARG_PTR_TO_CTX,
133+
};
134+
120135
static const struct bpf_func_proto *
121136
bpf_lsm_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
122137
{
@@ -141,6 +156,8 @@ bpf_lsm_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
141156
return prog->aux->sleepable ? &bpf_ima_inode_hash_proto : NULL;
142157
case BPF_FUNC_ima_file_hash:
143158
return prog->aux->sleepable ? &bpf_ima_file_hash_proto : NULL;
159+
case BPF_FUNC_get_attach_cookie:
160+
return bpf_prog_has_trampoline(prog) ? &bpf_get_attach_cookie_proto : NULL;
144161
default:
145162
return tracing_prog_func_proto(func_id, prog);
146163
}

0 commit comments

Comments
 (0)