@@ -156,7 +156,29 @@ struct bpf_verifier_stack_elem {
156
156
#define BPF_COMPLEXITY_LIMIT_INSNS 131072
157
157
#define BPF_COMPLEXITY_LIMIT_STACK 1024
158
158
159
- #define BPF_MAP_PTR_POISON ((void *)0xeB9F + POISON_POINTER_DELTA)
159
+ #define BPF_MAP_PTR_UNPRIV 1UL
160
+ #define BPF_MAP_PTR_POISON ((void *)((0xeB9FUL << 1) + \
161
+ POISON_POINTER_DELTA))
162
+ #define BPF_MAP_PTR (X ) ((struct bpf_map *)((X) & ~BPF_MAP_PTR_UNPRIV))
163
+
164
+ static bool bpf_map_ptr_poisoned (const struct bpf_insn_aux_data * aux )
165
+ {
166
+ return BPF_MAP_PTR (aux -> map_state ) == BPF_MAP_PTR_POISON ;
167
+ }
168
+
169
+ static bool bpf_map_ptr_unpriv (const struct bpf_insn_aux_data * aux )
170
+ {
171
+ return aux -> map_state & BPF_MAP_PTR_UNPRIV ;
172
+ }
173
+
174
+ static void bpf_map_ptr_store (struct bpf_insn_aux_data * aux ,
175
+ const struct bpf_map * map , bool unpriv )
176
+ {
177
+ BUILD_BUG_ON ((unsigned long )BPF_MAP_PTR_POISON & BPF_MAP_PTR_UNPRIV );
178
+ unpriv |= bpf_map_ptr_unpriv (aux );
179
+ aux -> map_state = (unsigned long )map |
180
+ (unpriv ? BPF_MAP_PTR_UNPRIV : 0UL );
181
+ }
160
182
161
183
struct bpf_call_arg_meta {
162
184
struct bpf_map * map_ptr ;
@@ -2333,6 +2355,29 @@ static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx)
2333
2355
return 0 ;
2334
2356
}
2335
2357
2358
+ static int
2359
+ record_func_map (struct bpf_verifier_env * env , struct bpf_call_arg_meta * meta ,
2360
+ int func_id , int insn_idx )
2361
+ {
2362
+ struct bpf_insn_aux_data * aux = & env -> insn_aux_data [insn_idx ];
2363
+
2364
+ if (func_id != BPF_FUNC_tail_call &&
2365
+ func_id != BPF_FUNC_map_lookup_elem )
2366
+ return 0 ;
2367
+ if (meta -> map_ptr == NULL ) {
2368
+ verbose (env , "kernel subsystem misconfigured verifier\n" );
2369
+ return - EINVAL ;
2370
+ }
2371
+
2372
+ if (!BPF_MAP_PTR (aux -> map_state ))
2373
+ bpf_map_ptr_store (aux , meta -> map_ptr ,
2374
+ meta -> map_ptr -> unpriv_array );
2375
+ else if (BPF_MAP_PTR (aux -> map_state ) != meta -> map_ptr )
2376
+ bpf_map_ptr_store (aux , BPF_MAP_PTR_POISON ,
2377
+ meta -> map_ptr -> unpriv_array );
2378
+ return 0 ;
2379
+ }
2380
+
2336
2381
static int check_helper_call (struct bpf_verifier_env * env , int func_id , int insn_idx )
2337
2382
{
2338
2383
const struct bpf_func_proto * fn = NULL ;
@@ -2387,13 +2432,6 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn
2387
2432
err = check_func_arg (env , BPF_REG_2 , fn -> arg2_type , & meta );
2388
2433
if (err )
2389
2434
return err ;
2390
- if (func_id == BPF_FUNC_tail_call ) {
2391
- if (meta .map_ptr == NULL ) {
2392
- verbose (env , "verifier bug\n" );
2393
- return - EINVAL ;
2394
- }
2395
- env -> insn_aux_data [insn_idx ].map_ptr = meta .map_ptr ;
2396
- }
2397
2435
err = check_func_arg (env , BPF_REG_3 , fn -> arg3_type , & meta );
2398
2436
if (err )
2399
2437
return err ;
@@ -2404,6 +2442,10 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn
2404
2442
if (err )
2405
2443
return err ;
2406
2444
2445
+ err = record_func_map (env , & meta , func_id , insn_idx );
2446
+ if (err )
2447
+ return err ;
2448
+
2407
2449
/* Mark slots with STACK_MISC in case of raw mode, stack offset
2408
2450
* is inferred from register state.
2409
2451
*/
@@ -2428,8 +2470,6 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn
2428
2470
} else if (fn -> ret_type == RET_VOID ) {
2429
2471
regs [BPF_REG_0 ].type = NOT_INIT ;
2430
2472
} else if (fn -> ret_type == RET_PTR_TO_MAP_VALUE_OR_NULL ) {
2431
- struct bpf_insn_aux_data * insn_aux ;
2432
-
2433
2473
regs [BPF_REG_0 ].type = PTR_TO_MAP_VALUE_OR_NULL ;
2434
2474
/* There is no offset yet applied, variable or fixed */
2435
2475
mark_reg_known_zero (env , regs , BPF_REG_0 );
@@ -2445,11 +2485,6 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn
2445
2485
}
2446
2486
regs [BPF_REG_0 ].map_ptr = meta .map_ptr ;
2447
2487
regs [BPF_REG_0 ].id = ++ env -> id_gen ;
2448
- insn_aux = & env -> insn_aux_data [insn_idx ];
2449
- if (!insn_aux -> map_ptr )
2450
- insn_aux -> map_ptr = meta .map_ptr ;
2451
- else if (insn_aux -> map_ptr != meta .map_ptr )
2452
- insn_aux -> map_ptr = BPF_MAP_PTR_POISON ;
2453
2488
} else {
2454
2489
verbose (env , "unknown return type %d of func %s#%d\n" ,
2455
2490
fn -> ret_type , func_id_name (func_id ), func_id );
@@ -5417,6 +5452,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
5417
5452
struct bpf_insn * insn = prog -> insnsi ;
5418
5453
const struct bpf_func_proto * fn ;
5419
5454
const int insn_cnt = prog -> len ;
5455
+ struct bpf_insn_aux_data * aux ;
5420
5456
struct bpf_insn insn_buf [16 ];
5421
5457
struct bpf_prog * new_prog ;
5422
5458
struct bpf_map * map_ptr ;
@@ -5491,19 +5527,22 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
5491
5527
insn -> imm = 0 ;
5492
5528
insn -> code = BPF_JMP | BPF_TAIL_CALL ;
5493
5529
5530
+ aux = & env -> insn_aux_data [i + delta ];
5531
+ if (!bpf_map_ptr_unpriv (aux ))
5532
+ continue ;
5533
+
5494
5534
/* instead of changing every JIT dealing with tail_call
5495
5535
* emit two extra insns:
5496
5536
* if (index >= max_entries) goto out;
5497
5537
* index &= array->index_mask;
5498
5538
* to avoid out-of-bounds cpu speculation
5499
5539
*/
5500
- map_ptr = env -> insn_aux_data [i + delta ].map_ptr ;
5501
- if (map_ptr == BPF_MAP_PTR_POISON ) {
5540
+ if (bpf_map_ptr_poisoned (aux )) {
5502
5541
verbose (env , "tail_call abusing map_ptr\n" );
5503
5542
return - EINVAL ;
5504
5543
}
5505
- if (! map_ptr -> unpriv_array )
5506
- continue ;
5544
+
5545
+ map_ptr = BPF_MAP_PTR ( aux -> map_state ) ;
5507
5546
insn_buf [0 ] = BPF_JMP_IMM (BPF_JGE , BPF_REG_3 ,
5508
5547
map_ptr -> max_entries , 2 );
5509
5548
insn_buf [1 ] = BPF_ALU32_IMM (BPF_AND , BPF_REG_3 ,
@@ -5527,9 +5566,12 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
5527
5566
*/
5528
5567
if (prog -> jit_requested && BITS_PER_LONG == 64 &&
5529
5568
insn -> imm == BPF_FUNC_map_lookup_elem ) {
5530
- map_ptr = env -> insn_aux_data [i + delta ].map_ptr ;
5531
- if (map_ptr == BPF_MAP_PTR_POISON ||
5532
- !map_ptr -> ops -> map_gen_lookup )
5569
+ aux = & env -> insn_aux_data [i + delta ];
5570
+ if (bpf_map_ptr_poisoned (aux ))
5571
+ goto patch_call_imm ;
5572
+
5573
+ map_ptr = BPF_MAP_PTR (aux -> map_state );
5574
+ if (!map_ptr -> ops -> map_gen_lookup )
5533
5575
goto patch_call_imm ;
5534
5576
5535
5577
cnt = map_ptr -> ops -> map_gen_lookup (map_ptr , insn_buf );
0 commit comments