mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-25 06:03:36 -04:00
Linux 4.20-rc7
-----BEGIN PGP SIGNATURE----- iQFSBAABCAA8FiEEq68RxlopcLEwq+PEeb4+QwBBGIYFAlwW4/oeHHRvcnZhbGRz QGxpbnV4LWZvdW5kYXRpb24ub3JnAAoJEHm+PkMAQRiG2QMH/Rl6iMpTUX23tMHe eXQzAOSvQXaWlFoX25j1Jvt8nhS7Uy8vkdpYTCOI/7DF0Jg4O/6uxcZkErlwWxb8 MW1rMgpfO+OpDLSLXAO2GKxaKI3ArqF2BcOQA2mji1/jR2VUTqmIvBoudn5d+GYz 19aCyfdzmVTC38G9sBhhcqJ10EkxLiHe2K74bf4JxVuSf2EnTI4LYt5xJPDoT0/C 6fOeUNwVhvv5a4svvzJmortq7x7BwyxBQArc7PbO0MPhabLU4wyFUOTRszgsGd76 o5JuOFwgdIIHlSSacGla6rKq10nmkwR07fHfRFFwbvrfBOEHsXOP2hvzMZX+FLBK IXOzdtc= =XlMc -----END PGP SIGNATURE----- Merge tag 'v4.20-rc7' into perf/core, to pick up fixes Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
76aea1eeb9
437 changed files with 4850 additions and 2108 deletions
|
|
@ -5,6 +5,7 @@
|
|||
#include <uapi/linux/types.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/anon_inodes.h>
|
||||
|
|
@ -426,6 +427,30 @@ static bool btf_name_offset_valid(const struct btf *btf, u32 offset)
|
|||
offset < btf->hdr.str_len;
|
||||
}
|
||||
|
||||
/* Only C-style identifier is permitted. This can be relaxed if
|
||||
* necessary.
|
||||
*/
|
||||
static bool btf_name_valid_identifier(const struct btf *btf, u32 offset)
|
||||
{
|
||||
/* offset must be valid */
|
||||
const char *src = &btf->strings[offset];
|
||||
const char *src_limit;
|
||||
|
||||
if (!isalpha(*src) && *src != '_')
|
||||
return false;
|
||||
|
||||
/* set a limit on identifier length */
|
||||
src_limit = src + KSYM_NAME_LEN;
|
||||
src++;
|
||||
while (*src && src < src_limit) {
|
||||
if (!isalnum(*src) && *src != '_')
|
||||
return false;
|
||||
src++;
|
||||
}
|
||||
|
||||
return !*src;
|
||||
}
|
||||
|
||||
static const char *btf_name_by_offset(const struct btf *btf, u32 offset)
|
||||
{
|
||||
if (!offset)
|
||||
|
|
@ -1143,6 +1168,22 @@ static int btf_ref_type_check_meta(struct btf_verifier_env *env,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* typedef type must have a valid name, and other ref types,
|
||||
* volatile, const, restrict, should have a null name.
|
||||
*/
|
||||
if (BTF_INFO_KIND(t->info) == BTF_KIND_TYPEDEF) {
|
||||
if (!t->name_off ||
|
||||
!btf_name_valid_identifier(env->btf, t->name_off)) {
|
||||
btf_verifier_log_type(env, t, "Invalid name");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
if (t->name_off) {
|
||||
btf_verifier_log_type(env, t, "Invalid name");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
btf_verifier_log_type(env, t, NULL);
|
||||
|
||||
return 0;
|
||||
|
|
@ -1300,6 +1341,13 @@ static s32 btf_fwd_check_meta(struct btf_verifier_env *env,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* fwd type must have a valid name */
|
||||
if (!t->name_off ||
|
||||
!btf_name_valid_identifier(env->btf, t->name_off)) {
|
||||
btf_verifier_log_type(env, t, "Invalid name");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
btf_verifier_log_type(env, t, NULL);
|
||||
|
||||
return 0;
|
||||
|
|
@ -1356,6 +1404,12 @@ static s32 btf_array_check_meta(struct btf_verifier_env *env,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* array type should not have a name */
|
||||
if (t->name_off) {
|
||||
btf_verifier_log_type(env, t, "Invalid name");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (btf_type_vlen(t)) {
|
||||
btf_verifier_log_type(env, t, "vlen != 0");
|
||||
return -EINVAL;
|
||||
|
|
@ -1532,6 +1586,13 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* struct type either no name or a valid one */
|
||||
if (t->name_off &&
|
||||
!btf_name_valid_identifier(env->btf, t->name_off)) {
|
||||
btf_verifier_log_type(env, t, "Invalid name");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
btf_verifier_log_type(env, t, NULL);
|
||||
|
||||
last_offset = 0;
|
||||
|
|
@ -1543,6 +1604,12 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* struct member either no name or a valid one */
|
||||
if (member->name_off &&
|
||||
!btf_name_valid_identifier(btf, member->name_off)) {
|
||||
btf_verifier_log_member(env, t, member, "Invalid name");
|
||||
return -EINVAL;
|
||||
}
|
||||
/* A member cannot be in type void */
|
||||
if (!member->type || !BTF_TYPE_ID_VALID(member->type)) {
|
||||
btf_verifier_log_member(env, t, member,
|
||||
|
|
@ -1730,6 +1797,13 @@ static s32 btf_enum_check_meta(struct btf_verifier_env *env,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* enum type either no name or a valid one */
|
||||
if (t->name_off &&
|
||||
!btf_name_valid_identifier(env->btf, t->name_off)) {
|
||||
btf_verifier_log_type(env, t, "Invalid name");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
btf_verifier_log_type(env, t, NULL);
|
||||
|
||||
for (i = 0; i < nr_enums; i++) {
|
||||
|
|
@ -1739,6 +1813,14 @@ static s32 btf_enum_check_meta(struct btf_verifier_env *env,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* enum member must have a valid name */
|
||||
if (!enums[i].name_off ||
|
||||
!btf_name_valid_identifier(btf, enums[i].name_off)) {
|
||||
btf_verifier_log_type(env, t, "Invalid name");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
btf_verifier_log(env, "\t%s val=%d\n",
|
||||
btf_name_by_offset(btf, enums[i].name_off),
|
||||
enums[i].val);
|
||||
|
|
|
|||
|
|
@ -175,6 +175,7 @@ struct bpf_verifier_stack_elem {
|
|||
|
||||
#define BPF_COMPLEXITY_LIMIT_INSNS 131072
|
||||
#define BPF_COMPLEXITY_LIMIT_STACK 1024
|
||||
#define BPF_COMPLEXITY_LIMIT_STATES 64
|
||||
|
||||
#define BPF_MAP_PTR_UNPRIV 1UL
|
||||
#define BPF_MAP_PTR_POISON ((void *)((0xeB9FUL << 1) + \
|
||||
|
|
@ -3751,6 +3752,79 @@ static void find_good_pkt_pointers(struct bpf_verifier_state *vstate,
|
|||
}
|
||||
}
|
||||
|
||||
/* compute branch direction of the expression "if (reg opcode val) goto target;"
|
||||
* and return:
|
||||
* 1 - branch will be taken and "goto target" will be executed
|
||||
* 0 - branch will not be taken and fall-through to next insn
|
||||
* -1 - unknown. Example: "if (reg < 5)" is unknown when register value range [0,10]
|
||||
*/
|
||||
static int is_branch_taken(struct bpf_reg_state *reg, u64 val, u8 opcode)
|
||||
{
|
||||
if (__is_pointer_value(false, reg))
|
||||
return -1;
|
||||
|
||||
switch (opcode) {
|
||||
case BPF_JEQ:
|
||||
if (tnum_is_const(reg->var_off))
|
||||
return !!tnum_equals_const(reg->var_off, val);
|
||||
break;
|
||||
case BPF_JNE:
|
||||
if (tnum_is_const(reg->var_off))
|
||||
return !tnum_equals_const(reg->var_off, val);
|
||||
break;
|
||||
case BPF_JGT:
|
||||
if (reg->umin_value > val)
|
||||
return 1;
|
||||
else if (reg->umax_value <= val)
|
||||
return 0;
|
||||
break;
|
||||
case BPF_JSGT:
|
||||
if (reg->smin_value > (s64)val)
|
||||
return 1;
|
||||
else if (reg->smax_value < (s64)val)
|
||||
return 0;
|
||||
break;
|
||||
case BPF_JLT:
|
||||
if (reg->umax_value < val)
|
||||
return 1;
|
||||
else if (reg->umin_value >= val)
|
||||
return 0;
|
||||
break;
|
||||
case BPF_JSLT:
|
||||
if (reg->smax_value < (s64)val)
|
||||
return 1;
|
||||
else if (reg->smin_value >= (s64)val)
|
||||
return 0;
|
||||
break;
|
||||
case BPF_JGE:
|
||||
if (reg->umin_value >= val)
|
||||
return 1;
|
||||
else if (reg->umax_value < val)
|
||||
return 0;
|
||||
break;
|
||||
case BPF_JSGE:
|
||||
if (reg->smin_value >= (s64)val)
|
||||
return 1;
|
||||
else if (reg->smax_value < (s64)val)
|
||||
return 0;
|
||||
break;
|
||||
case BPF_JLE:
|
||||
if (reg->umax_value <= val)
|
||||
return 1;
|
||||
else if (reg->umin_value > val)
|
||||
return 0;
|
||||
break;
|
||||
case BPF_JSLE:
|
||||
if (reg->smax_value <= (s64)val)
|
||||
return 1;
|
||||
else if (reg->smin_value > (s64)val)
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Adjusts the register min/max values in the case that the dst_reg is the
|
||||
* variable register that we are working on, and src_reg is a constant or we're
|
||||
* simply doing a BPF_K check.
|
||||
|
|
@ -4152,21 +4226,15 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
|
|||
|
||||
dst_reg = ®s[insn->dst_reg];
|
||||
|
||||
/* detect if R == 0 where R was initialized to zero earlier */
|
||||
if (BPF_SRC(insn->code) == BPF_K &&
|
||||
(opcode == BPF_JEQ || opcode == BPF_JNE) &&
|
||||
dst_reg->type == SCALAR_VALUE &&
|
||||
tnum_is_const(dst_reg->var_off)) {
|
||||
if ((opcode == BPF_JEQ && dst_reg->var_off.value == insn->imm) ||
|
||||
(opcode == BPF_JNE && dst_reg->var_off.value != insn->imm)) {
|
||||
/* if (imm == imm) goto pc+off;
|
||||
* only follow the goto, ignore fall-through
|
||||
*/
|
||||
if (BPF_SRC(insn->code) == BPF_K) {
|
||||
int pred = is_branch_taken(dst_reg, insn->imm, opcode);
|
||||
|
||||
if (pred == 1) {
|
||||
/* only follow the goto, ignore fall-through */
|
||||
*insn_idx += insn->off;
|
||||
return 0;
|
||||
} else {
|
||||
/* if (imm != imm) goto pc+off;
|
||||
* only follow fall-through branch, since
|
||||
} else if (pred == 0) {
|
||||
/* only follow fall-through branch, since
|
||||
* that's where the program will go
|
||||
*/
|
||||
return 0;
|
||||
|
|
@ -4980,7 +5048,7 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
|
|||
struct bpf_verifier_state_list *new_sl;
|
||||
struct bpf_verifier_state_list *sl;
|
||||
struct bpf_verifier_state *cur = env->cur_state, *new;
|
||||
int i, j, err;
|
||||
int i, j, err, states_cnt = 0;
|
||||
|
||||
sl = env->explored_states[insn_idx];
|
||||
if (!sl)
|
||||
|
|
@ -5007,8 +5075,12 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
|
|||
return 1;
|
||||
}
|
||||
sl = sl->next;
|
||||
states_cnt++;
|
||||
}
|
||||
|
||||
if (!env->allow_ptr_leaks && states_cnt > BPF_COMPLEXITY_LIMIT_STATES)
|
||||
return 0;
|
||||
|
||||
/* there were no equivalent states, remember current one.
|
||||
* technically the current state is not proven to be safe yet,
|
||||
* but it will either reach outer most bpf_exit (which means it's safe)
|
||||
|
|
@ -5148,6 +5220,9 @@ static int do_check(struct bpf_verifier_env *env)
|
|||
goto process_bpf_exit;
|
||||
}
|
||||
|
||||
if (signal_pending(current))
|
||||
return -EAGAIN;
|
||||
|
||||
if (need_resched())
|
||||
cond_resched();
|
||||
|
||||
|
|
|
|||
|
|
@ -572,7 +572,9 @@ static void put_uprobe(struct uprobe *uprobe)
|
|||
* gets called, we don't get a chance to remove uprobe from
|
||||
* delayed_uprobe_list from remove_breakpoint(). Do it here.
|
||||
*/
|
||||
mutex_lock(&delayed_uprobe_lock);
|
||||
delayed_uprobe_remove(uprobe, NULL);
|
||||
mutex_unlock(&delayed_uprobe_lock);
|
||||
kfree(uprobe);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ asmlinkage void notrace stackleak_erase(void)
|
|||
}
|
||||
NOKPROBE_SYMBOL(stackleak_erase);
|
||||
|
||||
void __used stackleak_track_stack(void)
|
||||
void __used notrace stackleak_track_stack(void)
|
||||
{
|
||||
/*
|
||||
* N.B. stackleak_erase() fills the kernel stack with the poison value,
|
||||
|
|
|
|||
|
|
@ -5460,6 +5460,7 @@ void ftrace_destroy_filter_files(struct ftrace_ops *ops)
|
|||
if (ops->flags & FTRACE_OPS_FL_ENABLED)
|
||||
ftrace_shutdown(ops, 0);
|
||||
ops->flags |= FTRACE_OPS_FL_DELETED;
|
||||
ftrace_free_filter(ops);
|
||||
mutex_unlock(&ftrace_lock);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -570,11 +570,13 @@ predicate_parse(const char *str, int nr_parens, int nr_preds,
|
|||
}
|
||||
}
|
||||
|
||||
kfree(op_stack);
|
||||
kfree(inverts);
|
||||
return prog;
|
||||
out_free:
|
||||
kfree(op_stack);
|
||||
kfree(prog_stack);
|
||||
kfree(inverts);
|
||||
kfree(prog_stack);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
|
|
@ -1718,6 +1720,7 @@ static int create_filter(struct trace_event_call *call,
|
|||
err = process_preds(call, filter_string, *filterp, pe);
|
||||
if (err && set_str)
|
||||
append_filter_err(pe, *filterp);
|
||||
create_filter_finish(pe);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -732,8 +732,10 @@ int set_trigger_filter(char *filter_str,
|
|||
|
||||
/* The filter is for the 'trigger' event, not the triggered event */
|
||||
ret = create_event_filter(file->event_call, filter_str, false, &filter);
|
||||
if (ret)
|
||||
goto out;
|
||||
/*
|
||||
* If create_event_filter() fails, filter still needs to be freed.
|
||||
* Which the calling code will do with data->filter.
|
||||
*/
|
||||
assign:
|
||||
tmp = rcu_access_pointer(data->filter);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue