@@ -388,60 +388,74 @@ static void print_verifier_state(struct bpf_verifier_env *env,
388388 verbose (env , "\n" );
389389}
390390
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
405447
406448/* do_check() starts with zero-sized stack in struct bpf_verifier_state to
407449 * make it consume minimal amount of memory. check_stack_write() access from
408450 * 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.
412454 */
413455static int realloc_func_state (struct bpf_func_state * state , int size ,
414456 bool copy_old )
415457{
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 );
445459}
446460
447461static void free_func_state (struct bpf_func_state * state )
0 commit comments