Merge tag 'v5.7-rc7' into perf/core, to pick up fixes
[linux-2.6-microblaze.git] / kernel / trace / bpf_trace.c
index 68250d4..92ba69b 100644 (file)
@@ -83,7 +83,7 @@ unsigned int trace_call_bpf(struct trace_event_call *call, void *ctx)
        if (in_nmi()) /* not supported yet */
                return 1;
 
-       preempt_disable();
+       cant_sleep();
 
        if (unlikely(__this_cpu_inc_return(bpf_prog_active) != 1)) {
                /*
@@ -115,11 +115,9 @@ unsigned int trace_call_bpf(struct trace_event_call *call, void *ctx)
 
  out:
        __this_cpu_dec(bpf_prog_active);
-       preempt_enable();
 
        return ret;
 }
-EXPORT_SYMBOL_GPL(trace_call_bpf);
 
 #ifdef CONFIG_BPF_KPROBE_OVERRIDE
 BPF_CALL_2(bpf_override_return, struct pt_regs *, regs, unsigned long, rc)
@@ -325,17 +323,15 @@ static const struct bpf_func_proto *bpf_get_probe_write_proto(void)
 
 /*
  * Only limited trace_printk() conversion specifiers allowed:
- * %d %i %u %x %ld %li %lu %lx %lld %lli %llu %llx %p %s
+ * %d %i %u %x %ld %li %lu %lx %lld %lli %llu %llx %p %pks %pus %s
  */
 BPF_CALL_5(bpf_trace_printk, char *, fmt, u32, fmt_size, u64, arg1,
           u64, arg2, u64, arg3)
 {
+       int i, mod[3] = {}, fmt_cnt = 0;
+       char buf[64], fmt_ptype;
+       void *unsafe_ptr = NULL;
        bool str_seen = false;
-       int mod[3] = {};
-       int fmt_cnt = 0;
-       u64 unsafe_addr;
-       char buf[64];
-       int i;
 
        /*
         * bpf_check()->check_func_arg()->check_stack_boundary()
@@ -361,40 +357,71 @@ BPF_CALL_5(bpf_trace_printk, char *, fmt, u32, fmt_size, u64, arg1,
                if (fmt[i] == 'l') {
                        mod[fmt_cnt]++;
                        i++;
-               } else if (fmt[i] == 'p' || fmt[i] == 's') {
+               } else if (fmt[i] == 'p') {
                        mod[fmt_cnt]++;
+                       if ((fmt[i + 1] == 'k' ||
+                            fmt[i + 1] == 'u') &&
+                           fmt[i + 2] == 's') {
+                               fmt_ptype = fmt[i + 1];
+                               i += 2;
+                               goto fmt_str;
+                       }
+
                        /* disallow any further format extensions */
                        if (fmt[i + 1] != 0 &&
                            !isspace(fmt[i + 1]) &&
                            !ispunct(fmt[i + 1]))
                                return -EINVAL;
-                       fmt_cnt++;
-                       if (fmt[i] == 's') {
-                               if (str_seen)
-                                       /* allow only one '%s' per fmt string */
-                                       return -EINVAL;
-                               str_seen = true;
-
-                               switch (fmt_cnt) {
-                               case 1:
-                                       unsafe_addr = arg1;
-                                       arg1 = (long) buf;
-                                       break;
-                               case 2:
-                                       unsafe_addr = arg2;
-                                       arg2 = (long) buf;
-                                       break;
-                               case 3:
-                                       unsafe_addr = arg3;
-                                       arg3 = (long) buf;
-                                       break;
-                               }
-                               buf[0] = 0;
-                               strncpy_from_unsafe(buf,
-                                                   (void *) (long) unsafe_addr,
+
+                       goto fmt_next;
+               } else if (fmt[i] == 's') {
+                       mod[fmt_cnt]++;
+                       fmt_ptype = fmt[i];
+fmt_str:
+                       if (str_seen)
+                               /* allow only one '%s' per fmt string */
+                               return -EINVAL;
+                       str_seen = true;
+
+                       if (fmt[i + 1] != 0 &&
+                           !isspace(fmt[i + 1]) &&
+                           !ispunct(fmt[i + 1]))
+                               return -EINVAL;
+
+                       switch (fmt_cnt) {
+                       case 0:
+                               unsafe_ptr = (void *)(long)arg1;
+                               arg1 = (long)buf;
+                               break;
+                       case 1:
+                               unsafe_ptr = (void *)(long)arg2;
+                               arg2 = (long)buf;
+                               break;
+                       case 2:
+                               unsafe_ptr = (void *)(long)arg3;
+                               arg3 = (long)buf;
+                               break;
+                       }
+
+                       buf[0] = 0;
+                       switch (fmt_ptype) {
+                       case 's':
+#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
+                               strncpy_from_unsafe(buf, unsafe_ptr,
                                                    sizeof(buf));
+                               break;
+#endif
+                       case 'k':
+                               strncpy_from_unsafe_strict(buf, unsafe_ptr,
+                                                          sizeof(buf));
+                               break;
+                       case 'u':
+                               strncpy_from_unsafe_user(buf,
+                                       (__force void __user *)unsafe_ptr,
+                                                        sizeof(buf));
+                               break;
                        }
-                       continue;
+                       goto fmt_next;
                }
 
                if (fmt[i] == 'l') {
@@ -405,6 +432,7 @@ BPF_CALL_5(bpf_trace_printk, char *, fmt, u32, fmt_size, u64, arg1,
                if (fmt[i] != 'i' && fmt[i] != 'd' &&
                    fmt[i] != 'u' && fmt[i] != 'x')
                        return -EINVAL;
+fmt_next:
                fmt_cnt++;
        }
 
@@ -781,8 +809,8 @@ static const struct bpf_func_proto bpf_send_signal_thread_proto = {
        .arg1_type      = ARG_ANYTHING,
 };
 
-static const struct bpf_func_proto *
-tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
+const struct bpf_func_proto *
+bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 {
        switch (func_id) {
        case BPF_FUNC_map_lookup_elem:
@@ -827,14 +855,16 @@ tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
                return &bpf_probe_read_user_proto;
        case BPF_FUNC_probe_read_kernel:
                return &bpf_probe_read_kernel_proto;
-       case BPF_FUNC_probe_read:
-               return &bpf_probe_read_compat_proto;
        case BPF_FUNC_probe_read_user_str:
                return &bpf_probe_read_user_str_proto;
        case BPF_FUNC_probe_read_kernel_str:
                return &bpf_probe_read_kernel_str_proto;
+#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
+       case BPF_FUNC_probe_read:
+               return &bpf_probe_read_compat_proto;
        case BPF_FUNC_probe_read_str:
                return &bpf_probe_read_compat_str_proto;
+#endif
 #ifdef CONFIG_CGROUPS
        case BPF_FUNC_get_current_cgroup_id:
                return &bpf_get_current_cgroup_id_proto;
@@ -843,6 +873,10 @@ tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
                return &bpf_send_signal_proto;
        case BPF_FUNC_send_signal_thread:
                return &bpf_send_signal_thread_proto;
+       case BPF_FUNC_perf_event_read_value:
+               return &bpf_perf_event_read_value_proto;
+       case BPF_FUNC_get_ns_current_pid_tgid:
+               return &bpf_get_ns_current_pid_tgid_proto;
        default:
                return NULL;
        }
@@ -858,14 +892,12 @@ kprobe_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
                return &bpf_get_stackid_proto;
        case BPF_FUNC_get_stack:
                return &bpf_get_stack_proto;
-       case BPF_FUNC_perf_event_read_value:
-               return &bpf_perf_event_read_value_proto;
 #ifdef CONFIG_BPF_KPROBE_OVERRIDE
        case BPF_FUNC_override_return:
                return &bpf_override_return_proto;
 #endif
        default:
-               return tracing_func_proto(func_id, prog);
+               return bpf_tracing_func_proto(func_id, prog);
        }
 }
 
@@ -975,7 +1007,7 @@ tp_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
        case BPF_FUNC_get_stack:
                return &bpf_get_stack_proto_tp;
        default:
-               return tracing_func_proto(func_id, prog);
+               return bpf_tracing_func_proto(func_id, prog);
        }
 }
 
@@ -1028,6 +1060,45 @@ static const struct bpf_func_proto bpf_perf_prog_read_value_proto = {
          .arg3_type      = ARG_CONST_SIZE,
 };
 
+BPF_CALL_4(bpf_read_branch_records, struct bpf_perf_event_data_kern *, ctx,
+          void *, buf, u32, size, u64, flags)
+{
+#ifndef CONFIG_X86
+       return -ENOENT;
+#else
+       static const u32 br_entry_size = sizeof(struct perf_branch_entry);
+       struct perf_branch_stack *br_stack = ctx->data->br_stack;
+       u32 to_copy;
+
+       if (unlikely(flags & ~BPF_F_GET_BRANCH_RECORDS_SIZE))
+               return -EINVAL;
+
+       if (unlikely(!br_stack))
+               return -EINVAL;
+
+       if (flags & BPF_F_GET_BRANCH_RECORDS_SIZE)
+               return br_stack->nr * br_entry_size;
+
+       if (!buf || (size % br_entry_size != 0))
+               return -EINVAL;
+
+       to_copy = min_t(u32, br_stack->nr * br_entry_size, size);
+       memcpy(buf, br_stack->entries, to_copy);
+
+       return to_copy;
+#endif
+}
+
+static const struct bpf_func_proto bpf_read_branch_records_proto = {
+       .func           = bpf_read_branch_records,
+       .gpl_only       = true,
+       .ret_type       = RET_INTEGER,
+       .arg1_type      = ARG_PTR_TO_CTX,
+       .arg2_type      = ARG_PTR_TO_MEM_OR_NULL,
+       .arg3_type      = ARG_CONST_SIZE_OR_ZERO,
+       .arg4_type      = ARG_ANYTHING,
+};
+
 static const struct bpf_func_proto *
 pe_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 {
@@ -1040,8 +1111,10 @@ pe_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
                return &bpf_get_stack_proto_tp;
        case BPF_FUNC_perf_prog_read_value:
                return &bpf_perf_prog_read_value_proto;
+       case BPF_FUNC_read_branch_records:
+               return &bpf_read_branch_records_proto;
        default:
-               return tracing_func_proto(func_id, prog);
+               return bpf_tracing_func_proto(func_id, prog);
        }
 }
 
@@ -1104,6 +1177,7 @@ static const struct bpf_func_proto bpf_perf_event_output_proto_raw_tp = {
 };
 
 extern const struct bpf_func_proto bpf_skb_output_proto;
+extern const struct bpf_func_proto bpf_xdp_output_proto;
 
 BPF_CALL_3(bpf_get_stackid_raw_tp, struct bpf_raw_tracepoint_args *, args,
           struct bpf_map *, map, u64, flags)
@@ -1168,7 +1242,7 @@ raw_tp_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
        case BPF_FUNC_get_stack:
                return &bpf_get_stack_proto_raw_tp;
        default:
-               return tracing_func_proto(func_id, prog);
+               return bpf_tracing_func_proto(func_id, prog);
        }
 }
 
@@ -1179,6 +1253,8 @@ tracing_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 #ifdef CONFIG_NET
        case BPF_FUNC_skb_output:
                return &bpf_skb_output_proto;
+       case BPF_FUNC_xdp_output:
+               return &bpf_xdp_output_proto;
 #endif
        default:
                return raw_tp_prog_func_proto(func_id, prog);
@@ -1213,6 +1289,13 @@ static bool tracing_prog_is_valid_access(int off, int size,
        return btf_ctx_access(off, size, type, prog, info);
 }
 
+int __weak bpf_prog_test_run_tracing(struct bpf_prog *prog,
+                                    const union bpf_attr *kattr,
+                                    union bpf_attr __user *uattr)
+{
+       return -ENOTSUPP;
+}
+
 const struct bpf_verifier_ops raw_tracepoint_verifier_ops = {
        .get_func_proto  = raw_tp_prog_func_proto,
        .is_valid_access = raw_tp_prog_is_valid_access,
@@ -1227,6 +1310,7 @@ const struct bpf_verifier_ops tracing_verifier_ops = {
 };
 
 const struct bpf_prog_ops tracing_prog_ops = {
+       .test_run = bpf_prog_test_run_tracing,
 };
 
 static bool raw_tp_writable_prog_is_valid_access(int off, int size,
@@ -1416,7 +1500,7 @@ int perf_event_query_prog_array(struct perf_event *event, void __user *info)
        u32 *ids, prog_cnt, ids_len;
        int ret;
 
-       if (!capable(CAP_SYS_ADMIN))
+       if (!perfmon_capable())
                return -EPERM;
        if (event->attr.type != PERF_TYPE_TRACEPOINT)
                return -EINVAL;
@@ -1475,10 +1559,9 @@ void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp)
 static __always_inline
 void __bpf_trace_run(struct bpf_prog *prog, u64 *args)
 {
+       cant_sleep();
        rcu_read_lock();
-       preempt_disable();
        (void) BPF_PROG_RUN(prog, args);
-       preempt_enable();
        rcu_read_unlock();
 }