diff options
-rw-r--r-- | kernel/bpf/syscall.c | 28 |
1 files changed, 17 insertions, 11 deletions
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 118e3a8fc764..6e544e364821 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -1454,19 +1454,25 @@ static int bpf_prog_load(union bpf_attr *attr) if (err) goto free_used_maps; + /* Upon success of bpf_prog_alloc_id(), the BPF prog is + * effectively publicly exposed. However, retrieving via + * bpf_prog_get_fd_by_id() will take another reference, + * therefore it cannot be gone underneath us. + * + * Only for the time /after/ successful bpf_prog_new_fd() + * and before returning to userspace, we might just hold + * one reference and any parallel close on that fd could + * rip everything out. Hence, below notifications must + * happen before bpf_prog_new_fd(). + * + * Also, any failure handling from this point onwards must + * be using bpf_prog_put() given the program is exposed. + */ + bpf_prog_kallsyms_add(prog); + err = bpf_prog_new_fd(prog); - if (err < 0) { - /* failed to allocate fd. - * bpf_prog_put() is needed because the above - * bpf_prog_alloc_id() has published the prog - * to the userspace and the userspace may - * have refcnt-ed it through BPF_PROG_GET_FD_BY_ID. - */ + if (err < 0) bpf_prog_put(prog); - return err; - } - - bpf_prog_kallsyms_add(prog); return err; free_used_maps: |