Skip to content

Commit

Permalink
bpf: Fix memleak due to fentry attach failure
Browse files Browse the repository at this point in the history
If it fails to attach fentry, the allocated bpf trampoline image will be
left in the system. That can be verified by checking /proc/kallsyms.

This meamleak can be verified by a simple bpf program as follows:

  SEC("fentry/trap_init")
  int fentry_run()
  {
      return 0;
  }

It will fail to attach trap_init because this function is freed after
kernel init, and then we can find the trampoline image is left in the
system by checking /proc/kallsyms.

  $ tail /proc/kallsyms
  ffffffffc0613000 t bpf_trampoline_6442453466_1  [bpf]
  ffffffffc06c3000 t bpf_trampoline_6442453466_1  [bpf]

  $ bpftool btf dump file /sys/kernel/btf/vmlinux | grep "FUNC 'trap_init'"
  [2522] FUNC 'trap_init' type_id=119 linkage=static

  $ echo $((6442453466 & 0x7fffffff))
  2522

Note that there are two left bpf trampoline images, that is because the
libbpf will fallback to raw tracepoint if -EINVAL is returned.

Fixes: e21aa34 ("bpf: Fix fexit trampoline.")
Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Song Liu <song@kernel.org>
Cc: Jiri Olsa <olsajiri@gmail.com>
Link: https://lore.kernel.org/bpf/20230515130849.57502-2-laoar.shao@gmail.com
  • Loading branch information
Yafang Shao authored and Daniel Borkmann committed May 15, 2023
1 parent 47e79cb commit 108598c
Showing 1 changed file with 15 additions and 6 deletions.
21 changes: 15 additions & 6 deletions kernel/bpf/trampoline.c
Original file line number Diff line number Diff line change
@@ -251,18 +251,23 @@ bpf_trampoline_get_progs(const struct bpf_trampoline *tr, int *total, bool *ip_a
return tlinks;
}

static void __bpf_tramp_image_put_deferred(struct work_struct *work)
static void bpf_tramp_image_free(struct bpf_tramp_image *im)
{
struct bpf_tramp_image *im;

im = container_of(work, struct bpf_tramp_image, work);
bpf_image_ksym_del(&im->ksym);
bpf_jit_free_exec(im->image);
bpf_jit_uncharge_modmem(PAGE_SIZE);
percpu_ref_exit(&im->pcref);
kfree_rcu(im, rcu);
}

static void __bpf_tramp_image_put_deferred(struct work_struct *work)
{
struct bpf_tramp_image *im;

im = container_of(work, struct bpf_tramp_image, work);
bpf_tramp_image_free(im);
}

/* callback, fexit step 3 or fentry step 2 */
static void __bpf_tramp_image_put_rcu(struct rcu_head *rcu)
{
@@ -437,7 +442,7 @@ static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mut
&tr->func.model, tr->flags, tlinks,
tr->func.addr);
if (err < 0)
goto out;
goto out_free;

set_memory_rox((long)im->image, 1);

@@ -466,7 +471,7 @@ static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mut
}
#endif
if (err)
goto out;
goto out_free;

if (tr->cur_image)
bpf_tramp_image_put(tr->cur_image);
@@ -477,6 +482,10 @@ static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mut
tr->flags = orig_flags;
kfree(tlinks);
return err;

out_free:
bpf_tramp_image_free(im);
goto out;
}

static enum bpf_tramp_prog_type bpf_attach_type_to_tramp(struct bpf_prog *prog)

0 comments on commit 108598c

Please sign in to comment.