Skip to content

Commit

Permalink
libbpf: only reset sec_def handler when necessary
Browse files Browse the repository at this point in the history
Don't reset recorded sec_def handler unconditionally on
bpf_program__set_type(). There are two situations where this is wrong.

First, if the program type didn't actually change. In that case original
SEC handler should work just fine.

Second, catch-all custom SEC handler is supposed to work with any BPF
program type and SEC() annotation, so it also doesn't make sense to
reset that.

This patch fixes both issues. This was reported recently in the context
of breaking perf tool, which uses custom catch-all handler for fancy BPF
prologue generation logic. This patch should fix the issue.

  [0] https://lore.kernel.org/linux-perf-users/[email protected]/

Fixes: d6e6286 ("libbpf: disassociate section handler on explicit bpf_program__set_type() call")
Reported-by: Ravi Bangoria <[email protected]>
Signed-off-by: Andrii Nakryiko <[email protected]>
Acked-by: Stanislav Fomichev <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Alexei Starovoitov <[email protected]>
  • Loading branch information
anakryiko authored and Alexei Starovoitov committed Jul 9, 2023
1 parent 856fe03 commit c628747
Showing 1 changed file with 19 additions and 8 deletions.
27 changes: 19 additions & 8 deletions tools/lib/bpf/libbpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -8562,13 +8562,31 @@ enum bpf_prog_type bpf_program__type(const struct bpf_program *prog)
return prog->type;
}

static size_t custom_sec_def_cnt;
static struct bpf_sec_def *custom_sec_defs;
static struct bpf_sec_def custom_fallback_def;
static bool has_custom_fallback_def;
static int last_custom_sec_def_handler_id;

int bpf_program__set_type(struct bpf_program *prog, enum bpf_prog_type type)
{
if (prog->obj->loaded)
return libbpf_err(-EBUSY);

/* if type is not changed, do nothing */
if (prog->type == type)
return 0;

prog->type = type;
prog->sec_def = NULL;

/* If a program type was changed, we need to reset associated SEC()
* handler, as it will be invalid now. The only exception is a generic
* fallback handler, which by definition is program type-agnostic and
* is a catch-all custom handler, optionally set by the application,
* so should be able to handle any type of BPF program.
*/
if (prog->sec_def != &custom_fallback_def)
prog->sec_def = NULL;
return 0;
}

Expand Down Expand Up @@ -8744,13 +8762,6 @@ static const struct bpf_sec_def section_defs[] = {
SEC_DEF("netfilter", NETFILTER, BPF_NETFILTER, SEC_NONE),
};

static size_t custom_sec_def_cnt;
static struct bpf_sec_def *custom_sec_defs;
static struct bpf_sec_def custom_fallback_def;
static bool has_custom_fallback_def;

static int last_custom_sec_def_handler_id;

int libbpf_register_prog_handler(const char *sec,
enum bpf_prog_type prog_type,
enum bpf_attach_type exp_attach_type,
Expand Down

0 comments on commit c628747

Please sign in to comment.