On Kunit, if we allocate a resource A and B on this order, with its
deferred actions to free them. The resource stack would be something
like this:

         +---------+
         | free(B) |
         +---------+
         |   ...   |
         +---------+
         | free(A) |
         +---------+

If the deferred action of A accesses B, this would cause a
use-after-free bug. To solve that, we need a way to change the order
of actions.

Create a function to move an action to the top of the resource stack,
as shown in the diagram below.

         +---------+    +---------+
         | free(B) |    | free(A) |
         +---------+    +---------+
         |   ...   | -> | free(B) |
         +---------+    +---------+
         | free(A) |    |   ...   |
         +---------+    +---------+

Signed-off-by: Arthur Grillo <arthurgri...@riseup.net>
---
 include/kunit/resource.h | 17 +++++++++++++++++
 lib/kunit/resource.c     | 19 +++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/include/kunit/resource.h b/include/kunit/resource.h
index c7383e90f5c9..c598b23680e3 100644
--- a/include/kunit/resource.h
+++ b/include/kunit/resource.h
@@ -479,4 +479,21 @@ void kunit_remove_action(struct kunit *test,
 void kunit_release_action(struct kunit *test,
                          kunit_action_t *action,
                          void *ctx);
+
+/**
+ * kunit_move_action_to_top_or_reset - Move a previously added action to the 
top
+ *                                    of the order of actions calls.
+ * @test: Test case to associate the action with.
+ * @action: The function to run on test exit
+ * @ctx: Data passed into @func
+ *
+ * Reorder the action stack, by moving the desired action to the top.
+ *
+ * Returns:
+ *   0 on success, an error if the action could not be inserted on the top.
+ */
+int kunit_move_action_to_top_or_reset(struct kunit *test,
+                                     kunit_action_t *action,
+                                     void *ctx);
+
 #endif /* _KUNIT_RESOURCE_H */
diff --git a/lib/kunit/resource.c b/lib/kunit/resource.c
index f0209252b179..fe40a34b62a6 100644
--- a/lib/kunit/resource.c
+++ b/lib/kunit/resource.c
@@ -176,3 +176,22 @@ void kunit_release_action(struct kunit *test,
        }
 }
 EXPORT_SYMBOL_GPL(kunit_release_action);
+
+int kunit_move_action_to_top_or_reset(struct kunit *test,
+                                     kunit_action_t *action,
+                                     void *ctx)
+{
+       struct kunit_action_ctx match_ctx;
+       struct kunit_resource *res;
+
+       match_ctx.func = action;
+       match_ctx.ctx = ctx;
+       res = kunit_find_resource(test, __kunit_action_match, &match_ctx);
+       if (res) {
+               kunit_remove_action(test, action, ctx);
+               return kunit_add_action_or_reset(test, action, ctx);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(kunit_move_action_to_top_or_reset);

-- 
2.41.0

Reply via email to