]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
perf: Make perf_event_output() propagate the output() return
authorArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 11 Jan 2019 16:20:20 +0000 (13:20 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 21 Jan 2019 20:00:57 +0000 (17:00 -0300)
For the original mode of operation it isn't needed, since we report back
errors via PERF_RECORD_LOST records in the ring buffer, but for use in
bpf_perf_event_output() it is convenient to return the errors, basically
-ENOSPC.

Currently bpf_perf_event_output() returns an error indication, the last
thing it does, which is to push it to the ring buffer is that can fail
and if so, this failure won't be reported back to its users, fix it.

Reported-by: Jamal Hadi Salim <jhs@mojatatu.com>
Tested-by: Jamal Hadi Salim <jhs@mojatatu.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexei Starovoitov <alexei.starovoitov@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: https://lkml.kernel.org/r/20190118150938.GN5823@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
include/linux/perf_event.h
kernel/events/core.c
kernel/trace/bpf_trace.c
tools/perf/examples/bpf/augmented_raw_syscalls.c
tools/perf/examples/bpf/augmented_syscalls.c
tools/perf/examples/bpf/etcsnoop.c

index f8ec3619771818128930b592d2ca973033d75616..4eb88065a9b54a2fd6c1c435fe1f26d59c35f271 100644 (file)
@@ -978,9 +978,9 @@ extern void perf_event_output_forward(struct perf_event *event,
 extern void perf_event_output_backward(struct perf_event *event,
                                       struct perf_sample_data *data,
                                       struct pt_regs *regs);
-extern void perf_event_output(struct perf_event *event,
-                             struct perf_sample_data *data,
-                             struct pt_regs *regs);
+extern int perf_event_output(struct perf_event *event,
+                            struct perf_sample_data *data,
+                            struct pt_regs *regs);
 
 static inline bool
 is_default_overflow_handler(struct perf_event *event)
index fbe59b793b36cab70c2bb8de845127d7547044a8..bc525cd1615c48fb611899575834ebeac8033259 100644 (file)
@@ -6489,7 +6489,7 @@ void perf_prepare_sample(struct perf_event_header *header,
                data->phys_addr = perf_virt_to_phys(data->addr);
 }
 
-static __always_inline void
+static __always_inline int
 __perf_event_output(struct perf_event *event,
                    struct perf_sample_data *data,
                    struct pt_regs *regs,
@@ -6499,13 +6499,15 @@ __perf_event_output(struct perf_event *event,
 {
        struct perf_output_handle handle;
        struct perf_event_header header;
+       int err;
 
        /* protect the callchain buffers */
        rcu_read_lock();
 
        perf_prepare_sample(&header, data, event, regs);
 
-       if (output_begin(&handle, event, header.size))
+       err = output_begin(&handle, event, header.size);
+       if (err)
                goto exit;
 
        perf_output_sample(&handle, &header, data, event);
@@ -6514,6 +6516,7 @@ __perf_event_output(struct perf_event *event,
 
 exit:
        rcu_read_unlock();
+       return err;
 }
 
 void
@@ -6532,12 +6535,12 @@ perf_event_output_backward(struct perf_event *event,
        __perf_event_output(event, data, regs, perf_output_begin_backward);
 }
 
-void
+int
 perf_event_output(struct perf_event *event,
                  struct perf_sample_data *data,
                  struct pt_regs *regs)
 {
-       __perf_event_output(event, data, regs, perf_output_begin);
+       return __perf_event_output(event, data, regs, perf_output_begin);
 }
 
 /*
index 8b068adb9da1ce23538eeb3bdf3fc7fbd94f2f59..088c2032ceaf8ee45af06051139df889f1403969 100644 (file)
@@ -431,8 +431,7 @@ __bpf_perf_event_output(struct pt_regs *regs, struct bpf_map *map,
        if (unlikely(event->oncpu != cpu))
                return -EOPNOTSUPP;
 
-       perf_event_output(event, sd, regs);
-       return 0;
+       return perf_event_output(event, sd, regs);
 }
 
 BPF_CALL_5(bpf_perf_event_output, struct pt_regs *, regs, struct bpf_map *, map,
index 53c233370fae003801d9731633335da420d52962..9e9d4c66e53c53ed961294a1629dd3d9f53cbafb 100644 (file)
@@ -141,8 +141,8 @@ int sys_enter(struct syscall_enter_args *args)
                len = sizeof(augmented_args.args);
        }
 
-       perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, &augmented_args, len);
-       return 0;
+       /* If perf_event_output fails, return non-zero so that it gets recorded unaugmented */
+       return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, &augmented_args, len);
 }
 
 SEC("raw_syscalls:sys_exit")
index 2ae44813ef2d130c68bcac29f7daaaf41b1256b1..b7dba114e36c6ccf2495876451eb150ee05d7ea7 100644 (file)
@@ -55,9 +55,9 @@ int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args)                               \
                len -= sizeof(augmented_args.filename.value) - augmented_args.filename.size;    \
                len &= sizeof(augmented_args.filename.value) - 1;                               \
        }                                                                                       \
-       perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU,                     \
-                         &augmented_args, len);                                                \
-       return 0;                                                                               \
+       /* If perf_event_output fails, return non-zero so that it gets recorded unaugmented */  \
+       return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU,              \
+                                &augmented_args, len);                                         \
 }                                                                                              \
 int syscall_exit(syscall)(struct syscall_exit_args *args)                                      \
 {                                                                                              \
@@ -125,10 +125,10 @@ int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args)                           \
 /*             addrlen = augmented_args.args.addrlen;                               */         \
 /*                                                                                  */         \
        probe_read(&augmented_args.addr, addrlen, args->addr_ptr);                              \
-       perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU,                     \
-                         &augmented_args,                                                      \
-                         sizeof(augmented_args) - sizeof(augmented_args.addr) + addrlen);      \
-       return 0;                                                                               \
+       /* If perf_event_output fails, return non-zero so that it gets recorded unaugmented */  \
+       return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU,              \
+                                &augmented_args,                                               \
+                               sizeof(augmented_args) - sizeof(augmented_args.addr) + addrlen);\
 }                                                                                              \
 int syscall_exit(syscall)(struct syscall_exit_args *args)                                      \
 {                                                                                              \
index b59e8812ee8c6cc5875278c7c9491e52040da4bc..550e69c2e8d10afdfcbb4d6cf1ff914088cd82da 100644 (file)
@@ -49,11 +49,11 @@ int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args)                             \
                                                      args->filename_ptr);                      \
        if (__builtin_memcmp(augmented_args.filename.value, etc, 4) != 0)                       \
                return 0;                                                                       \
-       perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU,                     \
-                         &augmented_args,                                                      \
-                         (sizeof(augmented_args) - sizeof(augmented_args.filename.value) +     \
-                          augmented_args.filename.size));                                      \
-       return 0;                                                                               \
+       /* If perf_event_output fails, return non-zero so that it gets recorded unaugmented */  \
+       return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU,              \
+                                &augmented_args,                                               \
+                                (sizeof(augmented_args) - sizeof(augmented_args.filename.value) + \
+                                augmented_args.filename.size));                                \
 }
 
 struct syscall_enter_openat_args {