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


Daniel Borkmann says:

====================
pull-request: bpf 2021-06-15

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

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

The main changes are:

1) Fix marking incorrect umem ring as done in libbpf's
   xsk_socket__create_shared() helper, from Kev Jackson.

2) Fix oob leakage under a spectre v1 type confusion
   attack, from Daniel Borkmann.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 7ea6cd16 973377ff
Loading
Loading
Loading
Loading
+61 −7
Original line number Diff line number Diff line
@@ -6483,6 +6483,27 @@ struct bpf_sanitize_info {
	bool mask_to_left;
};

static struct bpf_verifier_state *
sanitize_speculative_path(struct bpf_verifier_env *env,
			  const struct bpf_insn *insn,
			  u32 next_idx, u32 curr_idx)
{
	struct bpf_verifier_state *branch;
	struct bpf_reg_state *regs;

	branch = push_stack(env, next_idx, curr_idx, true);
	if (branch && insn) {
		regs = branch->frame[branch->curframe]->regs;
		if (BPF_SRC(insn->code) == BPF_K) {
			mark_reg_unknown(env, regs, insn->dst_reg);
		} else if (BPF_SRC(insn->code) == BPF_X) {
			mark_reg_unknown(env, regs, insn->dst_reg);
			mark_reg_unknown(env, regs, insn->src_reg);
		}
	}
	return branch;
}

static int sanitize_ptr_alu(struct bpf_verifier_env *env,
			    struct bpf_insn *insn,
			    const struct bpf_reg_state *ptr_reg,
@@ -6566,12 +6587,26 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
		tmp = *dst_reg;
		*dst_reg = *ptr_reg;
	}
	ret = push_stack(env, env->insn_idx + 1, env->insn_idx, true);
	ret = sanitize_speculative_path(env, NULL, env->insn_idx + 1,
					env->insn_idx);
	if (!ptr_is_dst_reg && ret)
		*dst_reg = tmp;
	return !ret ? REASON_STACK : 0;
}

static void sanitize_mark_insn_seen(struct bpf_verifier_env *env)
{
	struct bpf_verifier_state *vstate = env->cur_state;

	/* If we simulate paths under speculation, we don't update the
	 * insn as 'seen' such that when we verify unreachable paths in
	 * the non-speculative domain, sanitize_dead_code() can still
	 * rewrite/sanitize them.
	 */
	if (!vstate->speculative)
		env->insn_aux_data[env->insn_idx].seen = env->pass_cnt;
}

static int sanitize_err(struct bpf_verifier_env *env,
			const struct bpf_insn *insn, int reason,
			const struct bpf_reg_state *off_reg,
@@ -8750,14 +8785,28 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
		if (err)
			return err;
	}

	if (pred == 1) {
		/* only follow the goto, ignore fall-through */
		/* Only follow the goto, ignore fall-through. If needed, push
		 * the fall-through branch for simulation under speculative
		 * execution.
		 */
		if (!env->bypass_spec_v1 &&
		    !sanitize_speculative_path(env, insn, *insn_idx + 1,
					       *insn_idx))
			return -EFAULT;
		*insn_idx += insn->off;
		return 0;
	} else if (pred == 0) {
		/* only follow fall-through branch, since
		 * that's where the program will go
		 */
		/* Only follow the fall-through branch, since that's where the
		 * program will go. If needed, push the goto branch for
		 * simulation under speculative execution.
		 */
		if (!env->bypass_spec_v1 &&
		    !sanitize_speculative_path(env, insn,
					       *insn_idx + insn->off + 1,
					       *insn_idx))
			return -EFAULT;
		return 0;
	}

@@ -10630,7 +10679,7 @@ static int do_check(struct bpf_verifier_env *env)
		}

		regs = cur_regs(env);
		env->insn_aux_data[env->insn_idx].seen = env->pass_cnt;
		sanitize_mark_insn_seen(env);
		prev_insn_idx = env->insn_idx;

		if (class == BPF_ALU || class == BPF_ALU64) {
@@ -10857,7 +10906,7 @@ static int do_check(struct bpf_verifier_env *env)
					return err;

				env->insn_idx++;
				env->insn_aux_data[env->insn_idx].seen = env->pass_cnt;
				sanitize_mark_insn_seen(env);
			} else {
				verbose(env, "invalid BPF_LD mode\n");
				return -EINVAL;
@@ -11366,6 +11415,7 @@ static int adjust_insn_aux_data(struct bpf_verifier_env *env,
{
	struct bpf_insn_aux_data *new_data, *old_data = env->insn_aux_data;
	struct bpf_insn *insn = new_prog->insnsi;
	u32 old_seen = old_data[off].seen;
	u32 prog_len;
	int i;

@@ -11386,7 +11436,8 @@ static int adjust_insn_aux_data(struct bpf_verifier_env *env,
	memcpy(new_data + off + cnt - 1, old_data + off,
	       sizeof(struct bpf_insn_aux_data) * (prog_len - off - cnt + 1));
	for (i = off; i < off + cnt - 1; i++) {
		new_data[i].seen = env->pass_cnt;
		/* Expand insni[off]'s seen count to the patched range. */
		new_data[i].seen = old_seen;
		new_data[i].zext_dst = insn_has_def32(env, insn + i);
	}
	env->insn_aux_data = new_data;
@@ -12710,6 +12761,9 @@ static void free_states(struct bpf_verifier_env *env)
 * insn_aux_data was touched. These variables are compared to clear temporary
 * data from failed pass. For testing and experiments do_check_common() can be
 * run multiple times even when prior attempt to verify is unsuccessful.
 *
 * Note that special handling is needed on !env->bypass_spec_v1 if this is
 * ever called outside of error path with subsequent program rejection.
 */
static void sanitize_insn_aux_data(struct bpf_verifier_env *env)
{
+1 −1
Original line number Diff line number Diff line
@@ -1094,7 +1094,7 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr,
			goto out_put_ctx;
		}
		if (xsk->fd == umem->fd)
			umem->rx_ring_setup_done = true;
			umem->tx_ring_setup_done = true;
	}

	err = xsk_get_mmap_offsets(xsk->fd, &off);
+1 −1
Original line number Diff line number Diff line
@@ -1147,7 +1147,7 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
		}
	}

	if (test->insn_processed) {
	if (!unpriv && test->insn_processed) {
		uint32_t insn_processed;
		char *proc;

+2 −0
Original line number Diff line number Diff line
@@ -61,6 +61,8 @@
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_EXIT_INSN(),
	},
	.errstr_unpriv = "R1 !read_ok",
	.result_unpriv = REJECT,
	.result = ACCEPT,
	.retval = 0
},
+14 −0
Original line number Diff line number Diff line
@@ -508,6 +508,8 @@
	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, -1),
	BPF_EXIT_INSN(),
	},
	.errstr_unpriv = "R0 invalid mem access 'inv'",
	.result_unpriv = REJECT,
	.result = ACCEPT
},
{
@@ -528,6 +530,8 @@
	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, -1),
	BPF_EXIT_INSN(),
	},
	.errstr_unpriv = "R0 invalid mem access 'inv'",
	.result_unpriv = REJECT,
	.result = ACCEPT
},
{
@@ -569,6 +573,8 @@
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_EXIT_INSN(),
	},
	.errstr_unpriv = "R0 min value is outside of the allowed memory range",
	.result_unpriv = REJECT,
	.fixup_map_hash_8b = { 3 },
	.result = ACCEPT,
},
@@ -589,6 +595,8 @@
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_EXIT_INSN(),
	},
	.errstr_unpriv = "R0 min value is outside of the allowed memory range",
	.result_unpriv = REJECT,
	.fixup_map_hash_8b = { 3 },
	.result = ACCEPT,
},
@@ -609,6 +617,8 @@
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_EXIT_INSN(),
	},
	.errstr_unpriv = "R0 min value is outside of the allowed memory range",
	.result_unpriv = REJECT,
	.fixup_map_hash_8b = { 3 },
	.result = ACCEPT,
},
@@ -674,6 +684,8 @@
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_EXIT_INSN(),
	},
	.errstr_unpriv = "R0 min value is outside of the allowed memory range",
	.result_unpriv = REJECT,
	.fixup_map_hash_8b = { 3 },
	.result = ACCEPT,
},
@@ -695,6 +707,8 @@
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_EXIT_INSN(),
	},
	.errstr_unpriv = "R0 min value is outside of the allowed memory range",
	.result_unpriv = REJECT,
	.fixup_map_hash_8b = { 3 },
	.result = ACCEPT,
},
Loading