Commit a4f0377d 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 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
...@@ -6483,6 +6483,27 @@ struct bpf_sanitize_info { ...@@ -6483,6 +6483,27 @@ struct bpf_sanitize_info {
bool mask_to_left; 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, static int sanitize_ptr_alu(struct bpf_verifier_env *env,
struct bpf_insn *insn, struct bpf_insn *insn,
const struct bpf_reg_state *ptr_reg, const struct bpf_reg_state *ptr_reg,
...@@ -6566,12 +6587,26 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env, ...@@ -6566,12 +6587,26 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
tmp = *dst_reg; tmp = *dst_reg;
*dst_reg = *ptr_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) if (!ptr_is_dst_reg && ret)
*dst_reg = tmp; *dst_reg = tmp;
return !ret ? REASON_STACK : 0; 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, static int sanitize_err(struct bpf_verifier_env *env,
const struct bpf_insn *insn, int reason, const struct bpf_insn *insn, int reason,
const struct bpf_reg_state *off_reg, const struct bpf_reg_state *off_reg,
...@@ -8750,14 +8785,28 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env, ...@@ -8750,14 +8785,28 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
if (err) if (err)
return err; return err;
} }
if (pred == 1) { 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; *insn_idx += insn->off;
return 0; return 0;
} else if (pred == 0) { } else if (pred == 0) {
/* only follow fall-through branch, since /* Only follow the fall-through branch, since that's where the
* that's where the program will go * 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; return 0;
} }
...@@ -10630,7 +10679,7 @@ static int do_check(struct bpf_verifier_env *env) ...@@ -10630,7 +10679,7 @@ static int do_check(struct bpf_verifier_env *env)
} }
regs = cur_regs(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; prev_insn_idx = env->insn_idx;
if (class == BPF_ALU || class == BPF_ALU64) { if (class == BPF_ALU || class == BPF_ALU64) {
...@@ -10857,7 +10906,7 @@ static int do_check(struct bpf_verifier_env *env) ...@@ -10857,7 +10906,7 @@ static int do_check(struct bpf_verifier_env *env)
return err; return err;
env->insn_idx++; env->insn_idx++;
env->insn_aux_data[env->insn_idx].seen = env->pass_cnt; sanitize_mark_insn_seen(env);
} else { } else {
verbose(env, "invalid BPF_LD mode\n"); verbose(env, "invalid BPF_LD mode\n");
return -EINVAL; return -EINVAL;
...@@ -11366,6 +11415,7 @@ static int adjust_insn_aux_data(struct bpf_verifier_env *env, ...@@ -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_aux_data *new_data, *old_data = env->insn_aux_data;
struct bpf_insn *insn = new_prog->insnsi; struct bpf_insn *insn = new_prog->insnsi;
u32 old_seen = old_data[off].seen;
u32 prog_len; u32 prog_len;
int i; int i;
...@@ -11386,7 +11436,8 @@ static int adjust_insn_aux_data(struct bpf_verifier_env *env, ...@@ -11386,7 +11436,8 @@ static int adjust_insn_aux_data(struct bpf_verifier_env *env,
memcpy(new_data + off + cnt - 1, old_data + off, memcpy(new_data + off + cnt - 1, old_data + off,
sizeof(struct bpf_insn_aux_data) * (prog_len - off - cnt + 1)); sizeof(struct bpf_insn_aux_data) * (prog_len - off - cnt + 1));
for (i = off; i < off + cnt - 1; i++) { 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); new_data[i].zext_dst = insn_has_def32(env, insn + i);
} }
env->insn_aux_data = new_data; env->insn_aux_data = new_data;
...@@ -12710,6 +12761,9 @@ static void free_states(struct bpf_verifier_env *env) ...@@ -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 * 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 * data from failed pass. For testing and experiments do_check_common() can be
* run multiple times even when prior attempt to verify is unsuccessful. * 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) static void sanitize_insn_aux_data(struct bpf_verifier_env *env)
{ {
......
...@@ -1094,7 +1094,7 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr, ...@@ -1094,7 +1094,7 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr,
goto out_put_ctx; goto out_put_ctx;
} }
if (xsk->fd == umem->fd) 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); err = xsk_get_mmap_offsets(xsk->fd, &off);
......
...@@ -1147,7 +1147,7 @@ static void do_test_single(struct bpf_test *test, bool unpriv, ...@@ -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; uint32_t insn_processed;
char *proc; char *proc;
......
...@@ -61,6 +61,8 @@ ...@@ -61,6 +61,8 @@
BPF_MOV64_IMM(BPF_REG_0, 0), BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr_unpriv = "R1 !read_ok",
.result_unpriv = REJECT,
.result = ACCEPT, .result = ACCEPT,
.retval = 0 .retval = 0
}, },
...@@ -508,6 +508,8 @@ ...@@ -508,6 +508,8 @@
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, -1), BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, -1),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr_unpriv = "R0 invalid mem access 'inv'",
.result_unpriv = REJECT,
.result = ACCEPT .result = ACCEPT
}, },
{ {
...@@ -528,6 +530,8 @@ ...@@ -528,6 +530,8 @@
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, -1), BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, -1),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr_unpriv = "R0 invalid mem access 'inv'",
.result_unpriv = REJECT,
.result = ACCEPT .result = ACCEPT
}, },
{ {
...@@ -569,6 +573,8 @@ ...@@ -569,6 +573,8 @@
BPF_MOV64_IMM(BPF_REG_0, 0), BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr_unpriv = "R0 min value is outside of the allowed memory range",
.result_unpriv = REJECT,
.fixup_map_hash_8b = { 3 }, .fixup_map_hash_8b = { 3 },
.result = ACCEPT, .result = ACCEPT,
}, },
...@@ -589,6 +595,8 @@ ...@@ -589,6 +595,8 @@
BPF_MOV64_IMM(BPF_REG_0, 0), BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr_unpriv = "R0 min value is outside of the allowed memory range",
.result_unpriv = REJECT,
.fixup_map_hash_8b = { 3 }, .fixup_map_hash_8b = { 3 },
.result = ACCEPT, .result = ACCEPT,
}, },
...@@ -609,6 +617,8 @@ ...@@ -609,6 +617,8 @@
BPF_MOV64_IMM(BPF_REG_0, 0), BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr_unpriv = "R0 min value is outside of the allowed memory range",
.result_unpriv = REJECT,
.fixup_map_hash_8b = { 3 }, .fixup_map_hash_8b = { 3 },
.result = ACCEPT, .result = ACCEPT,
}, },
...@@ -674,6 +684,8 @@ ...@@ -674,6 +684,8 @@
BPF_MOV64_IMM(BPF_REG_0, 0), BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr_unpriv = "R0 min value is outside of the allowed memory range",
.result_unpriv = REJECT,
.fixup_map_hash_8b = { 3 }, .fixup_map_hash_8b = { 3 },
.result = ACCEPT, .result = ACCEPT,
}, },
...@@ -695,6 +707,8 @@ ...@@ -695,6 +707,8 @@
BPF_MOV64_IMM(BPF_REG_0, 0), BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr_unpriv = "R0 min value is outside of the allowed memory range",
.result_unpriv = REJECT,
.fixup_map_hash_8b = { 3 }, .fixup_map_hash_8b = { 3 },
.result = ACCEPT, .result = ACCEPT,
}, },
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 10, -4), BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 10, -4),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr_unpriv = "R9 !read_ok",
.result_unpriv = REJECT,
.result = ACCEPT, .result = ACCEPT,
.retval = 7, .retval = 7,
}, },
......
...@@ -87,6 +87,8 @@ ...@@ -87,6 +87,8 @@
BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0), BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr_unpriv = "R9 !read_ok",
.result_unpriv = REJECT,
.result = ACCEPT, .result = ACCEPT,
}, },
{ {
...@@ -150,6 +152,8 @@ ...@@ -150,6 +152,8 @@
BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0), BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr_unpriv = "R9 !read_ok",
.result_unpriv = REJECT,
.result = ACCEPT, .result = ACCEPT,
}, },
{ {
...@@ -213,6 +217,8 @@ ...@@ -213,6 +217,8 @@
BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0), BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr_unpriv = "R9 !read_ok",
.result_unpriv = REJECT,
.result = ACCEPT, .result = ACCEPT,
}, },
{ {
...@@ -280,6 +286,8 @@ ...@@ -280,6 +286,8 @@
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0), BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr_unpriv = "R0 invalid mem access 'inv'",
.result_unpriv = REJECT,
.result = ACCEPT, .result = ACCEPT,
.retval = 2, .retval = 2,
}, },
...@@ -348,6 +356,8 @@ ...@@ -348,6 +356,8 @@
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0), BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr_unpriv = "R0 invalid mem access 'inv'",
.result_unpriv = REJECT,
.result = ACCEPT, .result = ACCEPT,
.retval = 2, .retval = 2,
}, },
...@@ -416,6 +426,8 @@ ...@@ -416,6 +426,8 @@
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0), BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr_unpriv = "R0 invalid mem access 'inv'",
.result_unpriv = REJECT,
.result = ACCEPT, .result = ACCEPT,
.retval = 2, .retval = 2,
}, },
...@@ -484,6 +496,8 @@ ...@@ -484,6 +496,8 @@
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0), BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr_unpriv = "R0 invalid mem access 'inv'",
.result_unpriv = REJECT,
.result = ACCEPT, .result = ACCEPT,
.retval = 2, .retval = 2,
}, },
...@@ -552,6 +566,8 @@ ...@@ -552,6 +566,8 @@
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0), BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr_unpriv = "R0 invalid mem access 'inv'",
.result_unpriv = REJECT,
.result = ACCEPT, .result = ACCEPT,
.retval = 2, .retval = 2,
}, },
...@@ -620,6 +636,8 @@ ...@@ -620,6 +636,8 @@
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0), BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr_unpriv = "R0 invalid mem access 'inv'",
.result_unpriv = REJECT,
.result = ACCEPT, .result = ACCEPT,
.retval = 2, .retval = 2,
}, },
...@@ -688,6 +706,8 @@ ...@@ -688,6 +706,8 @@
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0), BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr_unpriv = "R0 invalid mem access 'inv'",
.result_unpriv = REJECT,
.result = ACCEPT, .result = ACCEPT,
.retval = 2, .retval = 2,
}, },
...@@ -756,6 +776,8 @@ ...@@ -756,6 +776,8 @@
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0), BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr_unpriv = "R0 invalid mem access 'inv'",
.result_unpriv = REJECT,
.result = ACCEPT, .result = ACCEPT,
.retval = 2, .retval = 2,
}, },
......
...@@ -82,8 +82,8 @@ ...@@ -82,8 +82,8 @@
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.prog_type = BPF_PROG_TYPE_SOCKET_FILTER, .prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
.retval_unpriv = 1, .errstr_unpriv = "R9 !read_ok",
.result_unpriv = ACCEPT, .result_unpriv = REJECT,
.retval = 1, .retval = 1,
.result = ACCEPT, .result = ACCEPT,
}, },
...@@ -141,7 +141,8 @@ ...@@ -141,7 +141,8 @@
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.prog_type = BPF_PROG_TYPE_SOCKET_FILTER, .prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
.result_unpriv = ACCEPT, .errstr_unpriv = "R9 !read_ok",
.result_unpriv = REJECT,
.result = ACCEPT, .result = ACCEPT,
}, },
{ {
...@@ -162,6 +163,7 @@ ...@@ -162,6 +163,7 @@
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.prog_type = BPF_PROG_TYPE_SOCKET_FILTER, .prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
.result_unpriv = ACCEPT, .errstr_unpriv = "R9 !read_ok",
.result_unpriv = REJECT,
.result = ACCEPT, .result = ACCEPT,
}, },
...@@ -420,6 +420,8 @@ ...@@ -420,6 +420,8 @@
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_7, 0), BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_7, 0),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr_unpriv = "R7 invalid mem access 'inv'",
.result_unpriv = REJECT,
.result = ACCEPT, .result = ACCEPT,
.retval = 0, .retval = 0,
}, },
......
...@@ -120,7 +120,7 @@ ...@@ -120,7 +120,7 @@
.fixup_map_array_48b = { 1 }, .fixup_map_array_48b = { 1 },
.result = ACCEPT, .result = ACCEPT,
.result_unpriv = REJECT, .result_unpriv = REJECT,
.errstr_unpriv = "R2 tried to add from different maps, paths or scalars", .errstr_unpriv = "R2 pointer comparison prohibited",
.retval = 0, .retval = 0,
}, },
{ {
...@@ -159,7 +159,8 @@ ...@@ -159,7 +159,8 @@
BPF_MOV64_IMM(BPF_REG_0, 0), BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
// fake-dead code; targeted from branch A to // fake-dead code; targeted from branch A to
// prevent dead code sanitization // prevent dead code sanitization, rejected
// via branch B however
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0), BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
BPF_MOV64_IMM(BPF_REG_0, 0), BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
...@@ -167,7 +168,7 @@ ...@@ -167,7 +168,7 @@
.fixup_map_array_48b = { 1 }, .fixup_map_array_48b = { 1 },
.result = ACCEPT, .result = ACCEPT,
.result_unpriv = REJECT, .result_unpriv = REJECT,
.errstr_unpriv = "R2 tried to add from different maps, paths or scalars", .errstr_unpriv = "R0 invalid mem access 'inv'",
.retval = 0, .retval = 0,
}, },
{ {
......
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