Skip to content

Commit 0ad67ad

Browse files
jrifeKernel Patches Daemon
authored andcommitted
bpf: Enable BPF_LINK_UPDATE for fentry/fexit/fmod_ret links
Implement program update for other link types supported by bpf_tracing_link_lops (fentry, fexit, fmod_ret, ...). I wanted to make the implementation generic so that no architecture-specific support would be required, but couldn't think of a good way to do this: * I considered updating link.prog before calling bpf_trampoline_update and reverting it back to the old prog if the update fails, but this could create inconsistencies with concurrent operations that read links where they see the uncommitted program associated with the link. * I considered making a deep copy of the link whose program is being updated and putting a pointer to that copy into tlinks when calling bpf_trampoline_get_progs where the copy references the new program instead of the current program. This would avoid updating the original link.prog before the update was committed; however, this seemed slightly hacky and I wasn't sure if this was better than just making the architecture-specific layer aware of the intent to update one of the link programs. This patch sets up the scaffolding for trampoline program updates while subsequent patches enable this for various architectures. For now, only x86, arm64, and s390 are implemented since that's what I could test in CI. Add update_link and update_prog to bpf_tramp_links. When these are set, arch_bpf_trampoline_size() and arch_prepare_bpf_trampoline() use update_prog in place of update_link->link.prog when calculating the trampoline size and constructing a new trampoline image. link.prog is only updated after the trampoline update is successfully committed. If the current architecture does not support program updates (i.e. bpf_trampoline_supports_update_prog() is not implemented) then the BPF_LINK_UPDATE operation will return -ENOTSUPP. Signed-off-by: Jordan Rife <[email protected]>
1 parent e4f4b92 commit 0ad67ad

File tree

2 files changed

+39
-4
lines changed

2 files changed

+39
-4
lines changed

include/linux/bpf.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,6 +1215,8 @@ enum {
12151215

12161216
struct bpf_tramp_links {
12171217
struct bpf_tramp_link *links[BPF_MAX_TRAMP_LINKS];
1218+
struct bpf_tramp_link *update_link;
1219+
struct bpf_prog *update_prog;
12181220
int nr_links;
12191221
};
12201222

@@ -1245,6 +1247,7 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i
12451247
const struct btf_func_model *m, u32 flags,
12461248
struct bpf_tramp_links *tlinks,
12471249
void *func_addr);
1250+
bool bpf_trampoline_supports_update_prog(void);
12481251
void *arch_alloc_bpf_trampoline(unsigned int size);
12491252
void arch_free_bpf_trampoline(void *image, unsigned int size);
12501253
int __must_check arch_protect_bpf_trampoline(void *image, unsigned int size);
@@ -1840,6 +1843,13 @@ struct bpf_tramp_link {
18401843
u64 cookie;
18411844
};
18421845

1846+
static inline struct bpf_prog *
1847+
bpf_tramp_links_prog(struct bpf_tramp_links *tl, int i)
1848+
{
1849+
return tl->links[i] == tl->update_link ? tl->update_prog :
1850+
tl->links[i]->link.prog;
1851+
}
1852+
18431853
struct bpf_shim_tramp_link {
18441854
struct bpf_tramp_link link;
18451855
struct bpf_trampoline *trampoline;

kernel/bpf/trampoline.c

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,10 @@ static int register_fentry(struct bpf_trampoline *tr, void *new_addr)
232232
}
233233

234234
static struct bpf_tramp_links *
235-
bpf_trampoline_get_progs(const struct bpf_trampoline *tr, int *total, bool *ip_arg)
235+
bpf_trampoline_get_progs(const struct bpf_trampoline *tr,
236+
struct bpf_tramp_link *update_link,
237+
struct bpf_prog *update_prog,
238+
int *total, bool *ip_arg)
236239
{
237240
struct bpf_tramp_link *link;
238241
struct bpf_tramp_links *tlinks;
@@ -252,6 +255,11 @@ bpf_trampoline_get_progs(const struct bpf_trampoline *tr, int *total, bool *ip_a
252255
hlist_for_each_entry(link, &tr->progs_hlist[kind], tramp_hlist) {
253256
*ip_arg |= link->link.prog->call_get_func_ip;
254257
*links++ = link;
258+
if (link == update_link) {
259+
*ip_arg |= update_prog->call_get_func_ip;
260+
tlinks[kind].update_link = update_link;
261+
tlinks[kind].update_prog = update_prog;
262+
}
255263
}
256264
}
257265
return tlinks;
@@ -397,15 +405,22 @@ static struct bpf_tramp_image *bpf_tramp_image_alloc(u64 key, int size)
397405
return ERR_PTR(err);
398406
}
399407

400-
static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mutex)
408+
static int __bpf_trampoline_update(struct bpf_trampoline *tr,
409+
struct bpf_tramp_link *update_link,
410+
struct bpf_prog *update_prog,
411+
bool lock_direct_mutex)
401412
{
402413
struct bpf_tramp_image *im;
403414
struct bpf_tramp_links *tlinks;
404415
u32 orig_flags = tr->flags;
405416
bool ip_arg = false;
406417
int err, total, size;
407418

408-
tlinks = bpf_trampoline_get_progs(tr, &total, &ip_arg);
419+
if (update_link && !bpf_trampoline_supports_update_prog())
420+
return -ENOTSUPP;
421+
422+
tlinks = bpf_trampoline_get_progs(tr, update_link, update_prog,
423+
&total, &ip_arg);
409424
if (IS_ERR(tlinks))
410425
return PTR_ERR(tlinks);
411426

@@ -503,6 +518,11 @@ static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mut
503518
goto out;
504519
}
505520

521+
static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mutex)
522+
{
523+
return __bpf_trampoline_update(tr, NULL, NULL, lock_direct_mutex);
524+
}
525+
506526
static enum bpf_tramp_prog_type bpf_attach_type_to_tramp(struct bpf_prog *prog)
507527
{
508528
switch (prog->expected_attach_type) {
@@ -626,7 +646,7 @@ static int __bpf_trampoline_update_prog(struct bpf_tramp_link *link,
626646
return 0;
627647
}
628648

629-
return -ENOTSUPP;
649+
return __bpf_trampoline_update(tr, link, new_prog, true);
630650
}
631651

632652
int bpf_trampoline_update_prog(struct bpf_tramp_link *link,
@@ -1136,6 +1156,11 @@ arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *image
11361156
return -ENOTSUPP;
11371157
}
11381158

1159+
bool __weak bpf_trampoline_supports_update_prog(void)
1160+
{
1161+
return false;
1162+
}
1163+
11391164
void * __weak arch_alloc_bpf_trampoline(unsigned int size)
11401165
{
11411166
void *image;

0 commit comments

Comments
 (0)