summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDavid Gow <davidgow@google.com>2024-04-12 05:59:01 +0300
committerShuah Khan <skhan@linuxfoundation.org>2024-05-06 23:22:02 +0300
commit1eb69ded805103ce3ddc8b1a207abd8c24ca9e63 (patch)
tree9e8afefdc5a53cb728cb11881ce3f8786d024f64 /lib
parent170c31737cf31770916c6cbadab04c5134f0d961 (diff)
downloadlinux-1eb69ded805103ce3ddc8b1a207abd8c24ca9e63.tar.xz
kunit: Fix race condition in try-catch completion
KUnit's try-catch infrastructure now uses vfork_done, which is always set to a valid completion when a kthread is created, but which is set to NULL once the thread terminates. This creates a race condition, where the kthread exits before we can wait on it. Keep a copy of vfork_done, which is taken before we wake_up_process() and so valid, and wait on that instead. Fixes: 93533996100c ("kunit: Handle test faults") Reported-by: Linux Kernel Functional Testing <lkft@linaro.org> Closes: https://lore.kernel.org/lkml/20240410102710.35911-1-naresh.kamboju@linaro.org/ Tested-by: Linux Kernel Functional Testing <lkft@linaro.org> Acked-by: Mickaël Salaün <mic@digikod.net> Signed-off-by: David Gow <davidgow@google.com> Reviewed-by: Rae Moar <rmoar@google.com> Tested-by: Miguel Ojeda <ojeda@kernel.org> Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/kunit/try-catch.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/lib/kunit/try-catch.c b/lib/kunit/try-catch.c
index fa687278ccc9..6bbe0025b079 100644
--- a/lib/kunit/try-catch.c
+++ b/lib/kunit/try-catch.c
@@ -63,6 +63,7 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
{
struct kunit *test = try_catch->test;
struct task_struct *task_struct;
+ struct completion *task_done;
int exit_code, time_remaining;
try_catch->context = context;
@@ -75,13 +76,16 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
return;
}
get_task_struct(task_struct);
- wake_up_process(task_struct);
/*
* As for a vfork(2), task_struct->vfork_done (pointing to the
* underlying kthread->exited) can be used to wait for the end of a
- * kernel thread.
+ * kernel thread. It is set to NULL when the thread exits, so we
+ * keep a copy here.
*/
- time_remaining = wait_for_completion_timeout(task_struct->vfork_done,
+ task_done = task_struct->vfork_done;
+ wake_up_process(task_struct);
+
+ time_remaining = wait_for_completion_timeout(task_done,
kunit_test_timeout());
if (time_remaining == 0) {
try_catch->try_result = -ETIMEDOUT;