mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 21:07:02 +09:00
Merge tag 'v4.9.144' of git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable into odroidn2-4.9.y
This is the 4.9.144 stable release
This commit is contained in:
@@ -540,10 +540,11 @@ static bool is_spillable_regtype(enum bpf_reg_type type)
|
||||
/* check_stack_read/write functions track spill/fill of registers,
|
||||
* stack boundary and alignment are checked in check_mem_access()
|
||||
*/
|
||||
static int check_stack_write(struct bpf_verifier_state *state, int off,
|
||||
int size, int value_regno)
|
||||
static int check_stack_write(struct bpf_verifier_env *env,
|
||||
struct bpf_verifier_state *state, int off,
|
||||
int size, int value_regno, int insn_idx)
|
||||
{
|
||||
int i;
|
||||
int i, spi = (MAX_BPF_STACK + off) / BPF_REG_SIZE;
|
||||
/* caller checked that off % size == 0 and -MAX_BPF_STACK <= off < 0,
|
||||
* so it's aligned access and [off, off + size) are within stack limits
|
||||
*/
|
||||
@@ -558,15 +559,37 @@ static int check_stack_write(struct bpf_verifier_state *state, int off,
|
||||
}
|
||||
|
||||
/* save register state */
|
||||
state->spilled_regs[(MAX_BPF_STACK + off) / BPF_REG_SIZE] =
|
||||
state->regs[value_regno];
|
||||
state->spilled_regs[spi] = state->regs[value_regno];
|
||||
|
||||
for (i = 0; i < BPF_REG_SIZE; i++)
|
||||
for (i = 0; i < BPF_REG_SIZE; i++) {
|
||||
if (state->stack_slot_type[MAX_BPF_STACK + off + i] == STACK_MISC &&
|
||||
!env->allow_ptr_leaks) {
|
||||
int *poff = &env->insn_aux_data[insn_idx].sanitize_stack_off;
|
||||
int soff = (-spi - 1) * BPF_REG_SIZE;
|
||||
|
||||
/* detected reuse of integer stack slot with a pointer
|
||||
* which means either llvm is reusing stack slot or
|
||||
* an attacker is trying to exploit CVE-2018-3639
|
||||
* (speculative store bypass)
|
||||
* Have to sanitize that slot with preemptive
|
||||
* store of zero.
|
||||
*/
|
||||
if (*poff && *poff != soff) {
|
||||
/* disallow programs where single insn stores
|
||||
* into two different stack slots, since verifier
|
||||
* cannot sanitize them
|
||||
*/
|
||||
verbose("insn %d cannot access two stack slots fp%d and fp%d",
|
||||
insn_idx, *poff, soff);
|
||||
return -EINVAL;
|
||||
}
|
||||
*poff = soff;
|
||||
}
|
||||
state->stack_slot_type[MAX_BPF_STACK + off + i] = STACK_SPILL;
|
||||
}
|
||||
} else {
|
||||
/* regular write of data into stack */
|
||||
state->spilled_regs[(MAX_BPF_STACK + off) / BPF_REG_SIZE] =
|
||||
(struct bpf_reg_state) {};
|
||||
state->spilled_regs[spi] = (struct bpf_reg_state) {};
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
state->stack_slot_type[MAX_BPF_STACK + off + i] = STACK_MISC;
|
||||
@@ -747,7 +770,7 @@ static int check_ptr_alignment(struct bpf_verifier_env *env,
|
||||
* if t==write && value_regno==-1, some unknown value is stored into memory
|
||||
* if t==read && value_regno==-1, don't care what we read from memory
|
||||
*/
|
||||
static int check_mem_access(struct bpf_verifier_env *env, u32 regno, int off,
|
||||
static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regno, int off,
|
||||
int bpf_size, enum bpf_access_type t,
|
||||
int value_regno)
|
||||
{
|
||||
@@ -843,7 +866,8 @@ static int check_mem_access(struct bpf_verifier_env *env, u32 regno, int off,
|
||||
verbose("attempt to corrupt spilled pointer on stack\n");
|
||||
return -EACCES;
|
||||
}
|
||||
err = check_stack_write(state, off, size, value_regno);
|
||||
err = check_stack_write(env, state, off, size,
|
||||
value_regno, insn_idx);
|
||||
} else {
|
||||
err = check_stack_read(state, off, size, value_regno);
|
||||
}
|
||||
@@ -877,7 +901,7 @@ static int check_mem_access(struct bpf_verifier_env *env, u32 regno, int off,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int check_xadd(struct bpf_verifier_env *env, struct bpf_insn *insn)
|
||||
static int check_xadd(struct bpf_verifier_env *env, int insn_idx, struct bpf_insn *insn)
|
||||
{
|
||||
struct bpf_reg_state *regs = env->cur_state.regs;
|
||||
int err;
|
||||
@@ -910,13 +934,13 @@ static int check_xadd(struct bpf_verifier_env *env, struct bpf_insn *insn)
|
||||
}
|
||||
|
||||
/* check whether atomic_add can read the memory */
|
||||
err = check_mem_access(env, insn->dst_reg, insn->off,
|
||||
err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
|
||||
BPF_SIZE(insn->code), BPF_READ, -1);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* check whether atomic_add can write into the same memory */
|
||||
return check_mem_access(env, insn->dst_reg, insn->off,
|
||||
return check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
|
||||
BPF_SIZE(insn->code), BPF_WRITE, -1);
|
||||
}
|
||||
|
||||
@@ -1272,7 +1296,7 @@ static int check_call(struct bpf_verifier_env *env, int func_id, int insn_idx)
|
||||
* is inferred from register state.
|
||||
*/
|
||||
for (i = 0; i < meta.access_size; i++) {
|
||||
err = check_mem_access(env, meta.regno, i, BPF_B, BPF_WRITE, -1);
|
||||
err = check_mem_access(env, insn_idx, meta.regno, i, BPF_B, BPF_WRITE, -1);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@@ -2938,7 +2962,7 @@ static int do_check(struct bpf_verifier_env *env)
|
||||
/* check that memory (src_reg + off) is readable,
|
||||
* the state of dst_reg will be updated by this func
|
||||
*/
|
||||
err = check_mem_access(env, insn->src_reg, insn->off,
|
||||
err = check_mem_access(env, insn_idx, insn->src_reg, insn->off,
|
||||
BPF_SIZE(insn->code), BPF_READ,
|
||||
insn->dst_reg);
|
||||
if (err)
|
||||
@@ -2978,7 +3002,7 @@ static int do_check(struct bpf_verifier_env *env)
|
||||
enum bpf_reg_type *prev_dst_type, dst_reg_type;
|
||||
|
||||
if (BPF_MODE(insn->code) == BPF_XADD) {
|
||||
err = check_xadd(env, insn);
|
||||
err = check_xadd(env, insn_idx, insn);
|
||||
if (err)
|
||||
return err;
|
||||
insn_idx++;
|
||||
@@ -2997,7 +3021,7 @@ static int do_check(struct bpf_verifier_env *env)
|
||||
dst_reg_type = regs[insn->dst_reg].type;
|
||||
|
||||
/* check that memory (dst_reg + off) is writeable */
|
||||
err = check_mem_access(env, insn->dst_reg, insn->off,
|
||||
err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
|
||||
BPF_SIZE(insn->code), BPF_WRITE,
|
||||
insn->src_reg);
|
||||
if (err)
|
||||
@@ -3032,7 +3056,7 @@ static int do_check(struct bpf_verifier_env *env)
|
||||
}
|
||||
|
||||
/* check that memory (dst_reg + off) is writeable */
|
||||
err = check_mem_access(env, insn->dst_reg, insn->off,
|
||||
err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
|
||||
BPF_SIZE(insn->code), BPF_WRITE,
|
||||
-1);
|
||||
if (err)
|
||||
@@ -3369,6 +3393,34 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
|
||||
else
|
||||
continue;
|
||||
|
||||
if (type == BPF_WRITE &&
|
||||
env->insn_aux_data[i + delta].sanitize_stack_off) {
|
||||
struct bpf_insn patch[] = {
|
||||
/* Sanitize suspicious stack slot with zero.
|
||||
* There are no memory dependencies for this store,
|
||||
* since it's only using frame pointer and immediate
|
||||
* constant of zero
|
||||
*/
|
||||
BPF_ST_MEM(BPF_DW, BPF_REG_FP,
|
||||
env->insn_aux_data[i + delta].sanitize_stack_off,
|
||||
0),
|
||||
/* the original STX instruction will immediately
|
||||
* overwrite the same stack slot with appropriate value
|
||||
*/
|
||||
*insn,
|
||||
};
|
||||
|
||||
cnt = ARRAY_SIZE(patch);
|
||||
new_prog = bpf_patch_insn_data(env, i + delta, patch, cnt);
|
||||
if (!new_prog)
|
||||
return -ENOMEM;
|
||||
|
||||
delta += cnt - 1;
|
||||
env->prog = new_prog;
|
||||
insn = new_prog->insnsi + i + delta;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (env->insn_aux_data[i + delta].ptr_type != PTR_TO_CTX)
|
||||
continue;
|
||||
|
||||
|
||||
@@ -129,13 +129,13 @@ int kdbnearsym(unsigned long addr, kdb_symtab_t *symtab)
|
||||
}
|
||||
if (i >= ARRAY_SIZE(kdb_name_table)) {
|
||||
debug_kfree(kdb_name_table[0]);
|
||||
memcpy(kdb_name_table, kdb_name_table+1,
|
||||
memmove(kdb_name_table, kdb_name_table+1,
|
||||
sizeof(kdb_name_table[0]) *
|
||||
(ARRAY_SIZE(kdb_name_table)-1));
|
||||
} else {
|
||||
debug_kfree(knt1);
|
||||
knt1 = kdb_name_table[i];
|
||||
memcpy(kdb_name_table+i, kdb_name_table+i+1,
|
||||
memmove(kdb_name_table+i, kdb_name_table+i+1,
|
||||
sizeof(kdb_name_table[0]) *
|
||||
(ARRAY_SIZE(kdb_name_table)-i-1));
|
||||
}
|
||||
|
||||
@@ -608,7 +608,7 @@ static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
|
||||
BUG_ON((uprobe->offset & ~PAGE_MASK) +
|
||||
UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
|
||||
|
||||
smp_wmb(); /* pairs with rmb() in find_active_uprobe() */
|
||||
smp_wmb(); /* pairs with the smp_rmb() in handle_swbp() */
|
||||
set_bit(UPROBE_COPY_INSN, &uprobe->flags);
|
||||
|
||||
out:
|
||||
@@ -1902,10 +1902,18 @@ static void handle_swbp(struct pt_regs *regs)
|
||||
* After we hit the bp, _unregister + _register can install the
|
||||
* new and not-yet-analyzed uprobe at the same address, restart.
|
||||
*/
|
||||
smp_rmb(); /* pairs with wmb() in install_breakpoint() */
|
||||
if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags)))
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Pairs with the smp_wmb() in prepare_uprobe().
|
||||
*
|
||||
* Guarantees that if we see the UPROBE_COPY_INSN bit set, then
|
||||
* we must also see the stores to &uprobe->arch performed by the
|
||||
* prepare_uprobe() call.
|
||||
*/
|
||||
smp_rmb();
|
||||
|
||||
/* Tracing handlers use ->utask to communicate with fetch methods */
|
||||
if (!get_utask())
|
||||
goto out;
|
||||
|
||||
Reference in New Issue
Block a user