Skip to content

Commit a4f0377

Browse files
committed
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: David S. Miller <[email protected]>
2 parents 7ea6cd1 + 973377f commit a4f0377

File tree

10 files changed

+115
-16
lines changed

10 files changed

+115
-16
lines changed

kernel/bpf/verifier.c

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6483,6 +6483,27 @@ struct bpf_sanitize_info {
64836483
bool mask_to_left;
64846484
};
64856485

6486+
static struct bpf_verifier_state *
6487+
sanitize_speculative_path(struct bpf_verifier_env *env,
6488+
const struct bpf_insn *insn,
6489+
u32 next_idx, u32 curr_idx)
6490+
{
6491+
struct bpf_verifier_state *branch;
6492+
struct bpf_reg_state *regs;
6493+
6494+
branch = push_stack(env, next_idx, curr_idx, true);
6495+
if (branch && insn) {
6496+
regs = branch->frame[branch->curframe]->regs;
6497+
if (BPF_SRC(insn->code) == BPF_K) {
6498+
mark_reg_unknown(env, regs, insn->dst_reg);
6499+
} else if (BPF_SRC(insn->code) == BPF_X) {
6500+
mark_reg_unknown(env, regs, insn->dst_reg);
6501+
mark_reg_unknown(env, regs, insn->src_reg);
6502+
}
6503+
}
6504+
return branch;
6505+
}
6506+
64866507
static int sanitize_ptr_alu(struct bpf_verifier_env *env,
64876508
struct bpf_insn *insn,
64886509
const struct bpf_reg_state *ptr_reg,
@@ -6566,12 +6587,26 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
65666587
tmp = *dst_reg;
65676588
*dst_reg = *ptr_reg;
65686589
}
6569-
ret = push_stack(env, env->insn_idx + 1, env->insn_idx, true);
6590+
ret = sanitize_speculative_path(env, NULL, env->insn_idx + 1,
6591+
env->insn_idx);
65706592
if (!ptr_is_dst_reg && ret)
65716593
*dst_reg = tmp;
65726594
return !ret ? REASON_STACK : 0;
65736595
}
65746596

6597+
static void sanitize_mark_insn_seen(struct bpf_verifier_env *env)
6598+
{
6599+
struct bpf_verifier_state *vstate = env->cur_state;
6600+
6601+
/* If we simulate paths under speculation, we don't update the
6602+
* insn as 'seen' such that when we verify unreachable paths in
6603+
* the non-speculative domain, sanitize_dead_code() can still
6604+
* rewrite/sanitize them.
6605+
*/
6606+
if (!vstate->speculative)
6607+
env->insn_aux_data[env->insn_idx].seen = env->pass_cnt;
6608+
}
6609+
65756610
static int sanitize_err(struct bpf_verifier_env *env,
65766611
const struct bpf_insn *insn, int reason,
65776612
const struct bpf_reg_state *off_reg,
@@ -8750,14 +8785,28 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
87508785
if (err)
87518786
return err;
87528787
}
8788+
87538789
if (pred == 1) {
8754-
/* only follow the goto, ignore fall-through */
8790+
/* Only follow the goto, ignore fall-through. If needed, push
8791+
* the fall-through branch for simulation under speculative
8792+
* execution.
8793+
*/
8794+
if (!env->bypass_spec_v1 &&
8795+
!sanitize_speculative_path(env, insn, *insn_idx + 1,
8796+
*insn_idx))
8797+
return -EFAULT;
87558798
*insn_idx += insn->off;
87568799
return 0;
87578800
} else if (pred == 0) {
8758-
/* only follow fall-through branch, since
8759-
* that's where the program will go
8801+
/* Only follow the fall-through branch, since that's where the
8802+
* program will go. If needed, push the goto branch for
8803+
* simulation under speculative execution.
87608804
*/
8805+
if (!env->bypass_spec_v1 &&
8806+
!sanitize_speculative_path(env, insn,
8807+
*insn_idx + insn->off + 1,
8808+
*insn_idx))
8809+
return -EFAULT;
87618810
return 0;
87628811
}
87638812

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

1063210681
regs = cur_regs(env);
10633-
env->insn_aux_data[env->insn_idx].seen = env->pass_cnt;
10682+
sanitize_mark_insn_seen(env);
1063410683
prev_insn_idx = env->insn_idx;
1063510684

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

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

@@ -11386,7 +11436,8 @@ static int adjust_insn_aux_data(struct bpf_verifier_env *env,
1138611436
memcpy(new_data + off + cnt - 1, old_data + off,
1138711437
sizeof(struct bpf_insn_aux_data) * (prog_len - off - cnt + 1));
1138811438
for (i = off; i < off + cnt - 1; i++) {
11389-
new_data[i].seen = env->pass_cnt;
11439+
/* Expand insni[off]'s seen count to the patched range. */
11440+
new_data[i].seen = old_seen;
1139011441
new_data[i].zext_dst = insn_has_def32(env, insn + i);
1139111442
}
1139211443
env->insn_aux_data = new_data;
@@ -12710,6 +12761,9 @@ static void free_states(struct bpf_verifier_env *env)
1271012761
* insn_aux_data was touched. These variables are compared to clear temporary
1271112762
* data from failed pass. For testing and experiments do_check_common() can be
1271212763
* run multiple times even when prior attempt to verify is unsuccessful.
12764+
*
12765+
* Note that special handling is needed on !env->bypass_spec_v1 if this is
12766+
* ever called outside of error path with subsequent program rejection.
1271312767
*/
1271412768
static void sanitize_insn_aux_data(struct bpf_verifier_env *env)
1271512769
{

tools/lib/bpf/xsk.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1094,7 +1094,7 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr,
10941094
goto out_put_ctx;
10951095
}
10961096
if (xsk->fd == umem->fd)
1097-
umem->rx_ring_setup_done = true;
1097+
umem->tx_ring_setup_done = true;
10981098
}
10991099

11001100
err = xsk_get_mmap_offsets(xsk->fd, &off);

tools/testing/selftests/bpf/test_verifier.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1147,7 +1147,7 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
11471147
}
11481148
}
11491149

1150-
if (test->insn_processed) {
1150+
if (!unpriv && test->insn_processed) {
11511151
uint32_t insn_processed;
11521152
char *proc;
11531153

tools/testing/selftests/bpf/verifier/and.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@
6161
BPF_MOV64_IMM(BPF_REG_0, 0),
6262
BPF_EXIT_INSN(),
6363
},
64+
.errstr_unpriv = "R1 !read_ok",
65+
.result_unpriv = REJECT,
6466
.result = ACCEPT,
6567
.retval = 0
6668
},

tools/testing/selftests/bpf/verifier/bounds.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,8 @@
508508
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, -1),
509509
BPF_EXIT_INSN(),
510510
},
511+
.errstr_unpriv = "R0 invalid mem access 'inv'",
512+
.result_unpriv = REJECT,
511513
.result = ACCEPT
512514
},
513515
{
@@ -528,6 +530,8 @@
528530
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, -1),
529531
BPF_EXIT_INSN(),
530532
},
533+
.errstr_unpriv = "R0 invalid mem access 'inv'",
534+
.result_unpriv = REJECT,
531535
.result = ACCEPT
532536
},
533537
{
@@ -569,6 +573,8 @@
569573
BPF_MOV64_IMM(BPF_REG_0, 0),
570574
BPF_EXIT_INSN(),
571575
},
576+
.errstr_unpriv = "R0 min value is outside of the allowed memory range",
577+
.result_unpriv = REJECT,
572578
.fixup_map_hash_8b = { 3 },
573579
.result = ACCEPT,
574580
},
@@ -589,6 +595,8 @@
589595
BPF_MOV64_IMM(BPF_REG_0, 0),
590596
BPF_EXIT_INSN(),
591597
},
598+
.errstr_unpriv = "R0 min value is outside of the allowed memory range",
599+
.result_unpriv = REJECT,
592600
.fixup_map_hash_8b = { 3 },
593601
.result = ACCEPT,
594602
},
@@ -609,6 +617,8 @@
609617
BPF_MOV64_IMM(BPF_REG_0, 0),
610618
BPF_EXIT_INSN(),
611619
},
620+
.errstr_unpriv = "R0 min value is outside of the allowed memory range",
621+
.result_unpriv = REJECT,
612622
.fixup_map_hash_8b = { 3 },
613623
.result = ACCEPT,
614624
},
@@ -674,6 +684,8 @@
674684
BPF_MOV64_IMM(BPF_REG_0, 0),
675685
BPF_EXIT_INSN(),
676686
},
687+
.errstr_unpriv = "R0 min value is outside of the allowed memory range",
688+
.result_unpriv = REJECT,
677689
.fixup_map_hash_8b = { 3 },
678690
.result = ACCEPT,
679691
},
@@ -695,6 +707,8 @@
695707
BPF_MOV64_IMM(BPF_REG_0, 0),
696708
BPF_EXIT_INSN(),
697709
},
710+
.errstr_unpriv = "R0 min value is outside of the allowed memory range",
711+
.result_unpriv = REJECT,
698712
.fixup_map_hash_8b = { 3 },
699713
.result = ACCEPT,
700714
},

tools/testing/selftests/bpf/verifier/dead_code.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 10, -4),
99
BPF_EXIT_INSN(),
1010
},
11+
.errstr_unpriv = "R9 !read_ok",
12+
.result_unpriv = REJECT,
1113
.result = ACCEPT,
1214
.retval = 7,
1315
},

tools/testing/selftests/bpf/verifier/jmp32.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@
8787
BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
8888
BPF_EXIT_INSN(),
8989
},
90+
.errstr_unpriv = "R9 !read_ok",
91+
.result_unpriv = REJECT,
9092
.result = ACCEPT,
9193
},
9294
{
@@ -150,6 +152,8 @@
150152
BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
151153
BPF_EXIT_INSN(),
152154
},
155+
.errstr_unpriv = "R9 !read_ok",
156+
.result_unpriv = REJECT,
153157
.result = ACCEPT,
154158
},
155159
{
@@ -213,6 +217,8 @@
213217
BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
214218
BPF_EXIT_INSN(),
215219
},
220+
.errstr_unpriv = "R9 !read_ok",
221+
.result_unpriv = REJECT,
216222
.result = ACCEPT,
217223
},
218224
{
@@ -280,6 +286,8 @@
280286
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
281287
BPF_EXIT_INSN(),
282288
},
289+
.errstr_unpriv = "R0 invalid mem access 'inv'",
290+
.result_unpriv = REJECT,
283291
.result = ACCEPT,
284292
.retval = 2,
285293
},
@@ -348,6 +356,8 @@
348356
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
349357
BPF_EXIT_INSN(),
350358
},
359+
.errstr_unpriv = "R0 invalid mem access 'inv'",
360+
.result_unpriv = REJECT,
351361
.result = ACCEPT,
352362
.retval = 2,
353363
},
@@ -416,6 +426,8 @@
416426
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
417427
BPF_EXIT_INSN(),
418428
},
429+
.errstr_unpriv = "R0 invalid mem access 'inv'",
430+
.result_unpriv = REJECT,
419431
.result = ACCEPT,
420432
.retval = 2,
421433
},
@@ -484,6 +496,8 @@
484496
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
485497
BPF_EXIT_INSN(),
486498
},
499+
.errstr_unpriv = "R0 invalid mem access 'inv'",
500+
.result_unpriv = REJECT,
487501
.result = ACCEPT,
488502
.retval = 2,
489503
},
@@ -552,6 +566,8 @@
552566
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
553567
BPF_EXIT_INSN(),
554568
},
569+
.errstr_unpriv = "R0 invalid mem access 'inv'",
570+
.result_unpriv = REJECT,
555571
.result = ACCEPT,
556572
.retval = 2,
557573
},
@@ -620,6 +636,8 @@
620636
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
621637
BPF_EXIT_INSN(),
622638
},
639+
.errstr_unpriv = "R0 invalid mem access 'inv'",
640+
.result_unpriv = REJECT,
623641
.result = ACCEPT,
624642
.retval = 2,
625643
},
@@ -688,6 +706,8 @@
688706
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
689707
BPF_EXIT_INSN(),
690708
},
709+
.errstr_unpriv = "R0 invalid mem access 'inv'",
710+
.result_unpriv = REJECT,
691711
.result = ACCEPT,
692712
.retval = 2,
693713
},
@@ -756,6 +776,8 @@
756776
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
757777
BPF_EXIT_INSN(),
758778
},
779+
.errstr_unpriv = "R0 invalid mem access 'inv'",
780+
.result_unpriv = REJECT,
759781
.result = ACCEPT,
760782
.retval = 2,
761783
},

tools/testing/selftests/bpf/verifier/jset.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@
8282
BPF_EXIT_INSN(),
8383
},
8484
.prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
85-
.retval_unpriv = 1,
86-
.result_unpriv = ACCEPT,
85+
.errstr_unpriv = "R9 !read_ok",
86+
.result_unpriv = REJECT,
8787
.retval = 1,
8888
.result = ACCEPT,
8989
},
@@ -141,7 +141,8 @@
141141
BPF_EXIT_INSN(),
142142
},
143143
.prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
144-
.result_unpriv = ACCEPT,
144+
.errstr_unpriv = "R9 !read_ok",
145+
.result_unpriv = REJECT,
145146
.result = ACCEPT,
146147
},
147148
{
@@ -162,6 +163,7 @@
162163
BPF_EXIT_INSN(),
163164
},
164165
.prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
165-
.result_unpriv = ACCEPT,
166+
.errstr_unpriv = "R9 !read_ok",
167+
.result_unpriv = REJECT,
166168
.result = ACCEPT,
167169
},

tools/testing/selftests/bpf/verifier/unpriv.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,8 @@
420420
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_7, 0),
421421
BPF_EXIT_INSN(),
422422
},
423+
.errstr_unpriv = "R7 invalid mem access 'inv'",
424+
.result_unpriv = REJECT,
423425
.result = ACCEPT,
424426
.retval = 0,
425427
},

tools/testing/selftests/bpf/verifier/value_ptr_arith.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@
120120
.fixup_map_array_48b = { 1 },
121121
.result = ACCEPT,
122122
.result_unpriv = REJECT,
123-
.errstr_unpriv = "R2 tried to add from different maps, paths or scalars",
123+
.errstr_unpriv = "R2 pointer comparison prohibited",
124124
.retval = 0,
125125
},
126126
{
@@ -159,15 +159,16 @@
159159
BPF_MOV64_IMM(BPF_REG_0, 0),
160160
BPF_EXIT_INSN(),
161161
// fake-dead code; targeted from branch A to
162-
// prevent dead code sanitization
162+
// prevent dead code sanitization, rejected
163+
// via branch B however
163164
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
164165
BPF_MOV64_IMM(BPF_REG_0, 0),
165166
BPF_EXIT_INSN(),
166167
},
167168
.fixup_map_array_48b = { 1 },
168169
.result = ACCEPT,
169170
.result_unpriv = REJECT,
170-
.errstr_unpriv = "R2 tried to add from different maps, paths or scalars",
171+
.errstr_unpriv = "R0 invalid mem access 'inv'",
171172
.retval = 0,
172173
},
173174
{

0 commit comments

Comments
 (0)