bpf: bpf_prog_array_copy() should return -ENOENT if exclude_prog not found
authorSean Young <sean@mess.org>
Sun, 27 May 2018 11:24:08 +0000 (12:24 +0100)
committerDaniel Borkmann <daniel@iogearbox.net>
Wed, 30 May 2018 10:37:38 +0000 (12:37 +0200)
This makes is it possible for bpf prog detach to return -ENOENT.

Acked-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
kernel/bpf/core.c
kernel/trace/bpf_trace.c

index b574dddc05b82be34c1212cf0a839fe48bae60b0..527587de8a67a4bae28c5015e994af01c15a82e8 100644 (file)
@@ -1616,6 +1616,7 @@ int bpf_prog_array_copy(struct bpf_prog_array __rcu *old_array,
        int new_prog_cnt, carry_prog_cnt = 0;
        struct bpf_prog **existing_prog;
        struct bpf_prog_array *array;
+       bool found_exclude = false;
        int new_prog_idx = 0;
 
        /* Figure out how many existing progs we need to carry over to
@@ -1624,14 +1625,20 @@ int bpf_prog_array_copy(struct bpf_prog_array __rcu *old_array,
        if (old_array) {
                existing_prog = old_array->progs;
                for (; *existing_prog; existing_prog++) {
-                       if (*existing_prog != exclude_prog &&
-                           *existing_prog != &dummy_bpf_prog.prog)
+                       if (*existing_prog == exclude_prog) {
+                               found_exclude = true;
+                               continue;
+                       }
+                       if (*existing_prog != &dummy_bpf_prog.prog)
                                carry_prog_cnt++;
                        if (*existing_prog == include_prog)
                                return -EEXIST;
                }
        }
 
+       if (exclude_prog && !found_exclude)
+               return -ENOENT;
+
        /* How many progs (not NULL) will be in the new array? */
        new_prog_cnt = carry_prog_cnt;
        if (include_prog)
index 81fdf2fc94ac9a954702f5d312a415a33972a012..af1486d9a0ed6aff0a8d41c6921a73e2d0ac4f8a 100644 (file)
@@ -1006,6 +1006,8 @@ void perf_event_detach_bpf_prog(struct perf_event *event)
 
        old_array = event->tp_event->prog_array;
        ret = bpf_prog_array_copy(old_array, event->prog, NULL, &new_array);
+       if (ret == -ENOENT)
+               goto unlock;
        if (ret < 0) {
                bpf_prog_array_delete_safe(old_array, event->prog);
        } else {