diff options
Diffstat (limited to 'kernel/trace/bpf_trace.c')
| -rw-r--r-- | kernel/trace/bpf_trace.c | 36 | 
1 files changed, 31 insertions, 5 deletions
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index ca1255d14576..44bd08f2443b 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -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;  |