Commit 96b11e93 authored by David S. Miller's avatar David S. Miller

Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf

Daniel Borkmann says:

====================
pull-request: bpf 2020-01-07

The following pull-request contains BPF updates for your *net* tree.

We've added 2 non-merge commits during the last 1 day(s) which contain
a total of 2 files changed, 16 insertions(+), 4 deletions(-).

The main changes are:

1) Fix a use-after-free in cgroup BPF due to auto-detachment, from Roman Gushchin.

2) Fix skb out-of-bounds access in ld_abs/ind instruction, from Daniel Borkmann.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 481a7d15 6d4f151a
...@@ -35,7 +35,7 @@ void cgroup_bpf_offline(struct cgroup *cgrp) ...@@ -35,7 +35,7 @@ void cgroup_bpf_offline(struct cgroup *cgrp)
*/ */
static void cgroup_bpf_release(struct work_struct *work) static void cgroup_bpf_release(struct work_struct *work)
{ {
struct cgroup *cgrp = container_of(work, struct cgroup, struct cgroup *p, *cgrp = container_of(work, struct cgroup,
bpf.release_work); bpf.release_work);
enum bpf_cgroup_storage_type stype; enum bpf_cgroup_storage_type stype;
struct bpf_prog_array *old_array; struct bpf_prog_array *old_array;
...@@ -65,6 +65,9 @@ static void cgroup_bpf_release(struct work_struct *work) ...@@ -65,6 +65,9 @@ static void cgroup_bpf_release(struct work_struct *work)
mutex_unlock(&cgroup_mutex); mutex_unlock(&cgroup_mutex);
for (p = cgroup_parent(cgrp); p; p = cgroup_parent(p))
cgroup_bpf_put(p);
percpu_ref_exit(&cgrp->bpf.refcnt); percpu_ref_exit(&cgrp->bpf.refcnt);
cgroup_put(cgrp); cgroup_put(cgrp);
} }
...@@ -199,6 +202,7 @@ int cgroup_bpf_inherit(struct cgroup *cgrp) ...@@ -199,6 +202,7 @@ int cgroup_bpf_inherit(struct cgroup *cgrp)
*/ */
#define NR ARRAY_SIZE(cgrp->bpf.effective) #define NR ARRAY_SIZE(cgrp->bpf.effective)
struct bpf_prog_array *arrays[NR] = {}; struct bpf_prog_array *arrays[NR] = {};
struct cgroup *p;
int ret, i; int ret, i;
ret = percpu_ref_init(&cgrp->bpf.refcnt, cgroup_bpf_release_fn, 0, ret = percpu_ref_init(&cgrp->bpf.refcnt, cgroup_bpf_release_fn, 0,
...@@ -206,6 +210,9 @@ int cgroup_bpf_inherit(struct cgroup *cgrp) ...@@ -206,6 +210,9 @@ int cgroup_bpf_inherit(struct cgroup *cgrp)
if (ret) if (ret)
return ret; return ret;
for (p = cgroup_parent(cgrp); p; p = cgroup_parent(p))
cgroup_bpf_get(p);
for (i = 0; i < NR; i++) for (i = 0; i < NR; i++)
INIT_LIST_HEAD(&cgrp->bpf.progs[i]); INIT_LIST_HEAD(&cgrp->bpf.progs[i]);
......
...@@ -6264,6 +6264,7 @@ static bool may_access_skb(enum bpf_prog_type type) ...@@ -6264,6 +6264,7 @@ static bool may_access_skb(enum bpf_prog_type type)
static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn) static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
{ {
struct bpf_reg_state *regs = cur_regs(env); struct bpf_reg_state *regs = cur_regs(env);
static const int ctx_reg = BPF_REG_6;
u8 mode = BPF_MODE(insn->code); u8 mode = BPF_MODE(insn->code);
int i, err; int i, err;
...@@ -6297,7 +6298,7 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn) ...@@ -6297,7 +6298,7 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
} }
/* check whether implicit source operand (register R6) is readable */ /* check whether implicit source operand (register R6) is readable */
err = check_reg_arg(env, BPF_REG_6, SRC_OP); err = check_reg_arg(env, ctx_reg, SRC_OP);
if (err) if (err)
return err; return err;
...@@ -6316,7 +6317,7 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn) ...@@ -6316,7 +6317,7 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
return -EINVAL; return -EINVAL;
} }
if (regs[BPF_REG_6].type != PTR_TO_CTX) { if (regs[ctx_reg].type != PTR_TO_CTX) {
verbose(env, verbose(env,
"at the time of BPF_LD_ABS|IND R6 != pointer to skb\n"); "at the time of BPF_LD_ABS|IND R6 != pointer to skb\n");
return -EINVAL; return -EINVAL;
...@@ -6329,6 +6330,10 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn) ...@@ -6329,6 +6330,10 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
return err; return err;
} }
err = check_ctx_reg(env, &regs[ctx_reg], ctx_reg);
if (err < 0)
return err;
/* reset caller saved regs to unreadable */ /* reset caller saved regs to unreadable */
for (i = 0; i < CALLER_SAVED_REGS; i++) { for (i = 0; i < CALLER_SAVED_REGS; i++) {
mark_reg_not_init(env, regs, caller_saved[i]); mark_reg_not_init(env, regs, caller_saved[i]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment