@@ -388,60 +388,74 @@ static void print_verifier_state(struct bpf_verifier_env *env,
388
388
verbose (env , "\n" );
389
389
}
390
390
391
- static int copy_stack_state (struct bpf_func_state * dst ,
392
- const struct bpf_func_state * src )
393
- {
394
- if (!src -> stack )
395
- return 0 ;
396
- if (WARN_ON_ONCE (dst -> allocated_stack < src -> allocated_stack )) {
397
- /* internal bug, make state invalid to reject the program */
398
- memset (dst , 0 , sizeof (* dst ));
399
- return - EFAULT ;
400
- }
401
- memcpy (dst -> stack , src -> stack ,
402
- sizeof (* src -> stack ) * (src -> allocated_stack / BPF_REG_SIZE ));
403
- return 0 ;
404
- }
391
+ #define COPY_STATE_FN (NAME , COUNT , FIELD , SIZE ) \
392
+ static int copy_##NAME##_state(struct bpf_func_state *dst, \
393
+ const struct bpf_func_state *src) \
394
+ { \
395
+ if (!src->FIELD) \
396
+ return 0; \
397
+ if (WARN_ON_ONCE(dst->COUNT < src->COUNT)) { \
398
+ /* internal bug, make state invalid to reject the program */ \
399
+ memset (dst , 0 , sizeof (* dst )); \
400
+ return - EFAULT ; \
401
+ } \
402
+ memcpy (dst -> FIELD , src -> FIELD , \
403
+ sizeof (* src -> FIELD ) * (src -> COUNT / SIZE )); \
404
+ return 0 ; \
405
+ }
406
+ /* copy_stack_state() */
407
+ COPY_STATE_FN (stack , allocated_stack , stack , BPF_REG_SIZE )
408
+ #undef COPY_STATE_FN
409
+
410
+ #define REALLOC_STATE_FN (NAME , COUNT , FIELD , SIZE ) \
411
+ static int realloc_##NAME##_state(struct bpf_func_state *state, int size, \
412
+ bool copy_old) \
413
+ { \
414
+ u32 old_size = state->COUNT; \
415
+ struct bpf_##NAME##_state *new_##FIELD; \
416
+ int slot = size / SIZE; \
417
+ \
418
+ if (size <= old_size || !size) { \
419
+ if (copy_old) \
420
+ return 0; \
421
+ state->COUNT = slot * SIZE; \
422
+ if (!size && old_size) { \
423
+ kfree(state->FIELD); \
424
+ state->FIELD = NULL; \
425
+ } \
426
+ return 0; \
427
+ } \
428
+ new_##FIELD = kmalloc_array(slot, sizeof(struct bpf_##NAME##_state), \
429
+ GFP_KERNEL); \
430
+ if (!new_##FIELD) \
431
+ return -ENOMEM; \
432
+ if (copy_old) { \
433
+ if (state->FIELD) \
434
+ memcpy(new_##FIELD, state->FIELD, \
435
+ sizeof(*new_##FIELD) * (old_size / SIZE)); \
436
+ memset(new_##FIELD + old_size / SIZE, 0, \
437
+ sizeof(*new_##FIELD) * (size - old_size) / SIZE); \
438
+ } \
439
+ state->COUNT = slot * SIZE; \
440
+ kfree(state->FIELD); \
441
+ state->FIELD = new_##FIELD; \
442
+ return 0; \
443
+ }
444
+ /* realloc_stack_state() */
445
+ REALLOC_STATE_FN (stack , allocated_stack , stack , BPF_REG_SIZE )
446
+ #undef REALLOC_STATE_FN
405
447
406
448
/* do_check() starts with zero-sized stack in struct bpf_verifier_state to
407
449
* make it consume minimal amount of memory. check_stack_write() access from
408
450
* the program calls into realloc_func_state() to grow the stack size.
409
- * Note there is a non-zero parent pointer inside each reg of bpf_verifier_state
410
- * which this function copies over. It points to corresponding reg in previous
411
- * bpf_verifier_state which is never reallocated
451
+ * Note there is a non-zero ' parent' pointer inside bpf_verifier_state
452
+ * which realloc_stack_state() copies over. It points to previous
453
+ * bpf_verifier_state which is never reallocated.
412
454
*/
413
455
static int realloc_func_state (struct bpf_func_state * state , int size ,
414
456
bool copy_old )
415
457
{
416
- u32 old_size = state -> allocated_stack ;
417
- struct bpf_stack_state * new_stack ;
418
- int slot = size / BPF_REG_SIZE ;
419
-
420
- if (size <= old_size || !size ) {
421
- if (copy_old )
422
- return 0 ;
423
- state -> allocated_stack = slot * BPF_REG_SIZE ;
424
- if (!size && old_size ) {
425
- kfree (state -> stack );
426
- state -> stack = NULL ;
427
- }
428
- return 0 ;
429
- }
430
- new_stack = kmalloc_array (slot , sizeof (struct bpf_stack_state ),
431
- GFP_KERNEL );
432
- if (!new_stack )
433
- return - ENOMEM ;
434
- if (copy_old ) {
435
- if (state -> stack )
436
- memcpy (new_stack , state -> stack ,
437
- sizeof (* new_stack ) * (old_size / BPF_REG_SIZE ));
438
- memset (new_stack + old_size / BPF_REG_SIZE , 0 ,
439
- sizeof (* new_stack ) * (size - old_size ) / BPF_REG_SIZE );
440
- }
441
- state -> allocated_stack = slot * BPF_REG_SIZE ;
442
- kfree (state -> stack );
443
- state -> stack = new_stack ;
444
- return 0 ;
458
+ return realloc_stack_state (state , size , copy_old );
445
459
}
446
460
447
461
static void free_func_state (struct bpf_func_state * state )
0 commit comments