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


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
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ void cgroup_bpf_offline(struct cgroup *cgrp)
 */
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);
	enum bpf_cgroup_storage_type stype;
	struct bpf_prog_array *old_array;
@@ -65,6 +65,9 @@ static void cgroup_bpf_release(struct work_struct *work)

	mutex_unlock(&cgroup_mutex);

	for (p = cgroup_parent(cgrp); p; p = cgroup_parent(p))
		cgroup_bpf_put(p);

	percpu_ref_exit(&cgrp->bpf.refcnt);
	cgroup_put(cgrp);
}
@@ -199,6 +202,7 @@ int cgroup_bpf_inherit(struct cgroup *cgrp)
 */
#define	NR ARRAY_SIZE(cgrp->bpf.effective)
	struct bpf_prog_array *arrays[NR] = {};
	struct cgroup *p;
	int ret, i;

	ret = percpu_ref_init(&cgrp->bpf.refcnt, cgroup_bpf_release_fn, 0,
@@ -206,6 +210,9 @@ int cgroup_bpf_inherit(struct cgroup *cgrp)
	if (ret)
		return ret;

	for (p = cgroup_parent(cgrp); p; p = cgroup_parent(p))
		cgroup_bpf_get(p);

	for (i = 0; i < NR; i++)
		INIT_LIST_HEAD(&cgrp->bpf.progs[i]);

+7 −2
Original line number Diff line number Diff line
@@ -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)
{
	struct bpf_reg_state *regs = cur_regs(env);
	static const int ctx_reg = BPF_REG_6;
	u8 mode = BPF_MODE(insn->code);
	int i, err;

@@ -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 */
	err = check_reg_arg(env, BPF_REG_6, SRC_OP);
	err = check_reg_arg(env, ctx_reg, SRC_OP);
	if (err)
		return err;

@@ -6316,7 +6317,7 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
		return -EINVAL;
	}

	if (regs[BPF_REG_6].type != PTR_TO_CTX) {
	if (regs[ctx_reg].type != PTR_TO_CTX) {
		verbose(env,
			"at the time of BPF_LD_ABS|IND R6 != pointer to skb\n");
		return -EINVAL;
@@ -6329,6 +6330,10 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
			return err;
	}

	err = check_ctx_reg(env, &regs[ctx_reg], ctx_reg);
	if (err < 0)
		return err;

	/* reset caller saved regs to unreadable */
	for (i = 0; i < CALLER_SAVED_REGS; i++) {
		mark_reg_not_init(env, regs, caller_saved[i]);