@@ -737,81 +737,104 @@ static void print_verifier_state(struct bpf_verifier_env *env,
737737 verbose (env , "\n" );
738738}
739739
740- #define COPY_STATE_FN (NAME , COUNT , FIELD , SIZE ) \
741- static int copy_##NAME##_state(struct bpf_func_state *dst, \
742- const struct bpf_func_state *src) \
743- { \
744- if (!src->FIELD) \
745- return 0; \
746- if (WARN_ON_ONCE(dst->COUNT < src->COUNT)) { \
747- /* internal bug, make state invalid to reject the program */ \
748- memset (dst , 0 , sizeof (* dst )); \
749- return - EFAULT ; \
750- } \
751- memcpy (dst -> FIELD , src -> FIELD , \
752- sizeof (* src -> FIELD ) * (src -> COUNT / SIZE )); \
753- return 0 ; \
754- }
755- /* copy_reference_state() */
756- COPY_STATE_FN (reference , acquired_refs , refs , 1 )
757- /* copy_stack_state() */
758- COPY_STATE_FN (stack , allocated_stack , stack , BPF_REG_SIZE )
759- #undef COPY_STATE_FN
760-
761- #define REALLOC_STATE_FN (NAME , COUNT , FIELD , SIZE ) \
762- static int realloc_##NAME##_state(struct bpf_func_state *state, int size, \
763- bool copy_old) \
764- { \
765- u32 old_size = state->COUNT; \
766- struct bpf_##NAME##_state *new_##FIELD; \
767- int slot = size / SIZE; \
768- \
769- if (size <= old_size || !size) { \
770- if (copy_old) \
771- return 0; \
772- state->COUNT = slot * SIZE; \
773- if (!size && old_size) { \
774- kfree(state->FIELD); \
775- state->FIELD = NULL; \
776- } \
777- return 0; \
778- } \
779- new_##FIELD = kmalloc_array(slot, sizeof(struct bpf_##NAME##_state), \
780- GFP_KERNEL); \
781- if (!new_##FIELD) \
782- return -ENOMEM; \
783- if (copy_old) { \
784- if (state->FIELD) \
785- memcpy(new_##FIELD, state->FIELD, \
786- sizeof(*new_##FIELD) * (old_size / SIZE)); \
787- memset(new_##FIELD + old_size / SIZE, 0, \
788- sizeof(*new_##FIELD) * (size - old_size) / SIZE); \
789- } \
790- state->COUNT = slot * SIZE; \
791- kfree(state->FIELD); \
792- state->FIELD = new_##FIELD; \
793- return 0; \
794- }
795- /* realloc_reference_state() */
796- REALLOC_STATE_FN (reference , acquired_refs , refs , 1 )
797- /* realloc_stack_state() */
798- REALLOC_STATE_FN (stack , allocated_stack , stack , BPF_REG_SIZE )
799- #undef REALLOC_STATE_FN
800-
801- /* do_check() starts with zero-sized stack in struct bpf_verifier_state to
802- * make it consume minimal amount of memory. check_stack_write() access from
803- * the program calls into realloc_func_state() to grow the stack size.
804- * Note there is a non-zero 'parent' pointer inside bpf_verifier_state
805- * which realloc_stack_state() copies over. It points to previous
806- * bpf_verifier_state which is never reallocated.
740+ /* copy array src of length n * size bytes to dst. dst is reallocated if it's too
741+ * small to hold src. This is different from krealloc since we don't want to preserve
742+ * the contents of dst.
743+ *
744+ * Leaves dst untouched if src is NULL or length is zero. Returns NULL if memory could
745+ * not be allocated.
807746 */
808- static int realloc_func_state (struct bpf_func_state * state , int stack_size ,
809- int refs_size , bool copy_old )
747+ static void * copy_array (void * dst , const void * src , size_t n , size_t size , gfp_t flags )
810748{
811- int err = realloc_reference_state (state , refs_size , copy_old );
812- if (err )
813- return err ;
814- return realloc_stack_state (state , stack_size , copy_old );
749+ size_t bytes ;
750+
751+ if (ZERO_OR_NULL_PTR (src ))
752+ goto out ;
753+
754+ if (unlikely (check_mul_overflow (n , size , & bytes )))
755+ return NULL ;
756+
757+ if (ksize (dst ) < bytes ) {
758+ kfree (dst );
759+ dst = kmalloc_track_caller (bytes , flags );
760+ if (!dst )
761+ return NULL ;
762+ }
763+
764+ memcpy (dst , src , bytes );
765+ out :
766+ return dst ? dst : ZERO_SIZE_PTR ;
767+ }
768+
769+ /* resize an array from old_n items to new_n items. the array is reallocated if it's too
770+ * small to hold new_n items. new items are zeroed out if the array grows.
771+ *
772+ * Contrary to krealloc_array, does not free arr if new_n is zero.
773+ */
774+ static void * realloc_array (void * arr , size_t old_n , size_t new_n , size_t size )
775+ {
776+ if (!new_n || old_n == new_n )
777+ goto out ;
778+
779+ arr = krealloc_array (arr , new_n , size , GFP_KERNEL );
780+ if (!arr )
781+ return NULL ;
782+
783+ if (new_n > old_n )
784+ memset (arr + old_n * size , 0 , (new_n - old_n ) * size );
785+
786+ out :
787+ return arr ? arr : ZERO_SIZE_PTR ;
788+ }
789+
790+ static int copy_reference_state (struct bpf_func_state * dst , const struct bpf_func_state * src )
791+ {
792+ dst -> refs = copy_array (dst -> refs , src -> refs , src -> acquired_refs ,
793+ sizeof (struct bpf_reference_state ), GFP_KERNEL );
794+ if (!dst -> refs )
795+ return - ENOMEM ;
796+
797+ dst -> acquired_refs = src -> acquired_refs ;
798+ return 0 ;
799+ }
800+
801+ static int copy_stack_state (struct bpf_func_state * dst , const struct bpf_func_state * src )
802+ {
803+ size_t n = src -> allocated_stack / BPF_REG_SIZE ;
804+
805+ dst -> stack = copy_array (dst -> stack , src -> stack , n , sizeof (struct bpf_stack_state ),
806+ GFP_KERNEL );
807+ if (!dst -> stack )
808+ return - ENOMEM ;
809+
810+ dst -> allocated_stack = src -> allocated_stack ;
811+ return 0 ;
812+ }
813+
814+ static int resize_reference_state (struct bpf_func_state * state , size_t n )
815+ {
816+ state -> refs = realloc_array (state -> refs , state -> acquired_refs , n ,
817+ sizeof (struct bpf_reference_state ));
818+ if (!state -> refs )
819+ return - ENOMEM ;
820+
821+ state -> acquired_refs = n ;
822+ return 0 ;
823+ }
824+
825+ static int grow_stack_state (struct bpf_func_state * state , int size )
826+ {
827+ size_t old_n = state -> allocated_stack / BPF_REG_SIZE , n = size / BPF_REG_SIZE ;
828+
829+ if (old_n >= n )
830+ return 0 ;
831+
832+ state -> stack = realloc_array (state -> stack , old_n , n , sizeof (struct bpf_stack_state ));
833+ if (!state -> stack )
834+ return - ENOMEM ;
835+
836+ state -> allocated_stack = size ;
837+ return 0 ;
815838}
816839
817840/* Acquire a pointer id from the env and update the state->refs to include
@@ -825,7 +848,7 @@ static int acquire_reference_state(struct bpf_verifier_env *env, int insn_idx)
825848 int new_ofs = state -> acquired_refs ;
826849 int id , err ;
827850
828- err = realloc_reference_state (state , state -> acquired_refs + 1 , true );
851+ err = resize_reference_state (state , state -> acquired_refs + 1 );
829852 if (err )
830853 return err ;
831854 id = ++ env -> id_gen ;
@@ -854,18 +877,6 @@ static int release_reference_state(struct bpf_func_state *state, int ptr_id)
854877 return - EINVAL ;
855878}
856879
857- static int transfer_reference_state (struct bpf_func_state * dst ,
858- struct bpf_func_state * src )
859- {
860- int err = realloc_reference_state (dst , src -> acquired_refs , false);
861- if (err )
862- return err ;
863- err = copy_reference_state (dst , src );
864- if (err )
865- return err ;
866- return 0 ;
867- }
868-
869880static void free_func_state (struct bpf_func_state * state )
870881{
871882 if (!state )
@@ -904,10 +915,6 @@ static int copy_func_state(struct bpf_func_state *dst,
904915{
905916 int err ;
906917
907- err = realloc_func_state (dst , src -> allocated_stack , src -> acquired_refs ,
908- false);
909- if (err )
910- return err ;
911918 memcpy (dst , src , offsetof(struct bpf_func_state , acquired_refs ));
912919 err = copy_reference_state (dst , src );
913920 if (err )
@@ -2590,8 +2597,7 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
25902597 u32 dst_reg = env -> prog -> insnsi [insn_idx ].dst_reg ;
25912598 struct bpf_reg_state * reg = NULL ;
25922599
2593- err = realloc_func_state (state , round_up (slot + 1 , BPF_REG_SIZE ),
2594- state -> acquired_refs , true);
2600+ err = grow_stack_state (state , round_up (slot + 1 , BPF_REG_SIZE ));
25952601 if (err )
25962602 return err ;
25972603 /* caller checked that off % size == 0 and -MAX_BPF_STACK <= off < 0,
@@ -2753,8 +2759,7 @@ static int check_stack_write_var_off(struct bpf_verifier_env *env,
27532759 if (value_reg && register_is_null (value_reg ))
27542760 writing_zero = true;
27552761
2756- err = realloc_func_state (state , round_up (- min_off , BPF_REG_SIZE ),
2757- state -> acquired_refs , true);
2762+ err = grow_stack_state (state , round_up (- min_off , BPF_REG_SIZE ));
27582763 if (err )
27592764 return err ;
27602765
@@ -5629,7 +5634,7 @@ static int __check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn
56295634 subprog /* subprog number within this prog */ );
56305635
56315636 /* Transfer references to the callee */
5632- err = transfer_reference_state (callee , caller );
5637+ err = copy_reference_state (callee , caller );
56335638 if (err )
56345639 return err ;
56355640
@@ -5780,7 +5785,7 @@ static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx)
57805785 }
57815786
57825787 /* Transfer references to the caller */
5783- err = transfer_reference_state (caller , callee );
5788+ err = copy_reference_state (caller , callee );
57845789 if (err )
57855790 return err ;
57865791
0 commit comments