]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - kernel/trace/bpf_trace.c
Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux...
[linux.git] / kernel / trace / bpf_trace.c
index ca1255d145766af019c19d4e58d22e894b52152e..44bd08f2443b3bec8928ab5c9f9080af1c8a4c02 100644 (file)
@@ -142,8 +142,13 @@ BPF_CALL_3(bpf_probe_read, void *, dst, u32, size, const void *, unsafe_ptr)
 {
        int ret;
 
+       ret = security_locked_down(LOCKDOWN_BPF_READ);
+       if (ret < 0)
+               goto out;
+
        ret = probe_kernel_read(dst, unsafe_ptr, size);
        if (unlikely(ret < 0))
+out:
                memset(dst, 0, size);
 
        return ret;
@@ -500,14 +505,17 @@ static const struct bpf_func_proto bpf_perf_event_output_proto = {
        .arg5_type      = ARG_CONST_SIZE_OR_ZERO,
 };
 
-static DEFINE_PER_CPU(struct pt_regs, bpf_pt_regs);
-static DEFINE_PER_CPU(struct perf_sample_data, bpf_misc_sd);
+static DEFINE_PER_CPU(int, bpf_event_output_nest_level);
+struct bpf_nested_pt_regs {
+       struct pt_regs regs[3];
+};
+static DEFINE_PER_CPU(struct bpf_nested_pt_regs, bpf_pt_regs);
+static DEFINE_PER_CPU(struct bpf_trace_sample_data, bpf_misc_sds);
 
 u64 bpf_event_output(struct bpf_map *map, u64 flags, void *meta, u64 meta_size,
                     void *ctx, u64 ctx_size, bpf_ctx_copy_t ctx_copy)
 {
-       struct perf_sample_data *sd = this_cpu_ptr(&bpf_misc_sd);
-       struct pt_regs *regs = this_cpu_ptr(&bpf_pt_regs);
+       int nest_level = this_cpu_inc_return(bpf_event_output_nest_level);
        struct perf_raw_frag frag = {
                .copy           = ctx_copy,
                .size           = ctx_size,
@@ -522,12 +530,25 @@ u64 bpf_event_output(struct bpf_map *map, u64 flags, void *meta, u64 meta_size,
                        .data   = meta,
                },
        };
+       struct perf_sample_data *sd;
+       struct pt_regs *regs;
+       u64 ret;
+
+       if (WARN_ON_ONCE(nest_level > ARRAY_SIZE(bpf_misc_sds.sds))) {
+               ret = -EBUSY;
+               goto out;
+       }
+       sd = this_cpu_ptr(&bpf_misc_sds.sds[nest_level - 1]);
+       regs = this_cpu_ptr(&bpf_pt_regs.regs[nest_level - 1]);
 
        perf_fetch_caller_regs(regs);
        perf_sample_data_init(sd, 0, 0);
        sd->raw = &raw;
 
-       return __bpf_perf_event_output(regs, map, flags, sd);
+       ret = __bpf_perf_event_output(regs, map, flags, sd);
+out:
+       this_cpu_dec(bpf_event_output_nest_level);
+       return ret;
 }
 
 BPF_CALL_0(bpf_get_current_task)
@@ -569,6 +590,10 @@ BPF_CALL_3(bpf_probe_read_str, void *, dst, u32, size,
 {
        int ret;
 
+       ret = security_locked_down(LOCKDOWN_BPF_READ);
+       if (ret < 0)
+               goto out;
+
        /*
         * The strncpy_from_unsafe() call will likely not fill the entire
         * buffer, but that's okay in this circumstance as we're probing
@@ -580,6 +605,7 @@ BPF_CALL_3(bpf_probe_read_str, void *, dst, u32, size,
         */
        ret = strncpy_from_unsafe(dst, unsafe_ptr, size);
        if (unlikely(ret < 0))
+out:
                memset(dst, 0, size);
 
        return ret;