An upcoming commit will need very similar copy/realloc boilerplate, so
refactor the existing stack copy/realloc functions into macros to
simplify it.

Signed-off-by: Joe Stringer <j...@wand.net.nz>
Acked-by: Alexei Starovoitov <a...@kernel.org>
---
 kernel/bpf/verifier.c | 106 ++++++++++++++++++++++++------------------
 1 file changed, 60 insertions(+), 46 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 1fee63d82290..311340360aa3 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -388,60 +388,74 @@ static void print_verifier_state(struct bpf_verifier_env 
*env,
        verbose(env, "\n");
 }
 
-static int copy_stack_state(struct bpf_func_state *dst,
-                           const struct bpf_func_state *src)
-{
-       if (!src->stack)
-               return 0;
-       if (WARN_ON_ONCE(dst->allocated_stack < src->allocated_stack)) {
-               /* internal bug, make state invalid to reject the program */
-               memset(dst, 0, sizeof(*dst));
-               return -EFAULT;
-       }
-       memcpy(dst->stack, src->stack,
-              sizeof(*src->stack) * (src->allocated_stack / BPF_REG_SIZE));
-       return 0;
-}
+#define COPY_STATE_FN(NAME, COUNT, FIELD, SIZE)                                
\
+static int copy_##NAME##_state(struct bpf_func_state *dst,             \
+                              const struct bpf_func_state *src)        \
+{                                                                      \
+       if (!src->FIELD)                                                \
+               return 0;                                               \
+       if (WARN_ON_ONCE(dst->COUNT < src->COUNT)) {                    \
+               /* internal bug, make state invalid to reject the program */ \
+               memset(dst, 0, sizeof(*dst));                           \
+               return -EFAULT;                                         \
+       }                                                               \
+       memcpy(dst->FIELD, src->FIELD,                                  \
+              sizeof(*src->FIELD) * (src->COUNT / SIZE));              \
+       return 0;                                                       \
+}
+/* copy_stack_state() */
+COPY_STATE_FN(stack, allocated_stack, stack, BPF_REG_SIZE)
+#undef COPY_STATE_FN
+
+#define REALLOC_STATE_FN(NAME, COUNT, FIELD, SIZE)                     \
+static int realloc_##NAME##_state(struct bpf_func_state *state, int size, \
+                                 bool copy_old)                        \
+{                                                                      \
+       u32 old_size = state->COUNT;                                    \
+       struct bpf_##NAME##_state *new_##FIELD;                         \
+       int slot = size / SIZE;                                         \
+                                                                       \
+       if (size <= old_size || !size) {                                \
+               if (copy_old)                                           \
+                       return 0;                                       \
+               state->COUNT = slot * SIZE;                             \
+               if (!size && old_size) {                                \
+                       kfree(state->FIELD);                            \
+                       state->FIELD = NULL;                            \
+               }                                                       \
+               return 0;                                               \
+       }                                                               \
+       new_##FIELD = kmalloc_array(slot, sizeof(struct bpf_##NAME##_state), \
+                                   GFP_KERNEL);                        \
+       if (!new_##FIELD)                                               \
+               return -ENOMEM;                                         \
+       if (copy_old) {                                                 \
+               if (state->FIELD)                                       \
+                       memcpy(new_##FIELD, state->FIELD,               \
+                              sizeof(*new_##FIELD) * (old_size / SIZE)); \
+               memset(new_##FIELD + old_size / SIZE, 0,                \
+                      sizeof(*new_##FIELD) * (size - old_size) / SIZE); \
+       }                                                               \
+       state->COUNT = slot * SIZE;                                     \
+       kfree(state->FIELD);                                            \
+       state->FIELD = new_##FIELD;                                     \
+       return 0;                                                       \
+}
+/* realloc_stack_state() */
+REALLOC_STATE_FN(stack, allocated_stack, stack, BPF_REG_SIZE)
+#undef REALLOC_STATE_FN
 
 /* do_check() starts with zero-sized stack in struct bpf_verifier_state to
  * make it consume minimal amount of memory. check_stack_write() access from
  * the program calls into realloc_func_state() to grow the stack size.
- * Note there is a non-zero parent pointer inside each reg of 
bpf_verifier_state
- * which this function copies over. It points to corresponding reg in previous
- * bpf_verifier_state which is never reallocated
+ * Note there is a non-zero 'parent' pointer inside bpf_verifier_state
+ * which realloc_stack_state() copies over. It points to previous
+ * bpf_verifier_state which is never reallocated.
  */
 static int realloc_func_state(struct bpf_func_state *state, int size,
                              bool copy_old)
 {
-       u32 old_size = state->allocated_stack;
-       struct bpf_stack_state *new_stack;
-       int slot = size / BPF_REG_SIZE;
-
-       if (size <= old_size || !size) {
-               if (copy_old)
-                       return 0;
-               state->allocated_stack = slot * BPF_REG_SIZE;
-               if (!size && old_size) {
-                       kfree(state->stack);
-                       state->stack = NULL;
-               }
-               return 0;
-       }
-       new_stack = kmalloc_array(slot, sizeof(struct bpf_stack_state),
-                                 GFP_KERNEL);
-       if (!new_stack)
-               return -ENOMEM;
-       if (copy_old) {
-               if (state->stack)
-                       memcpy(new_stack, state->stack,
-                              sizeof(*new_stack) * (old_size / BPF_REG_SIZE));
-               memset(new_stack + old_size / BPF_REG_SIZE, 0,
-                      sizeof(*new_stack) * (size - old_size) / BPF_REG_SIZE);
-       }
-       state->allocated_stack = slot * BPF_REG_SIZE;
-       kfree(state->stack);
-       state->stack = new_stack;
-       return 0;
+       return realloc_stack_state(state, size, copy_old);
 }
 
 static void free_func_state(struct bpf_func_state *state)
-- 
2.17.1

Reply via email to