Commit 1eb69ded authored by David Gow's avatar David Gow Committed by Shuah Khan
Browse files

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: default avatarLinux Kernel Functional Testing <lkft@linaro.org>
Closes: https://lore.kernel.org/lkml/20240410102710.35911-1-naresh.kamboju@linaro.org/


Tested-by: default avatarLinux Kernel Functional Testing <lkft@linaro.org>
Acked-by: default avatarMickaël Salaün <mic@digikod.net>
Signed-off-by: default avatarDavid Gow <davidgow@google.com>
Reviewed-by: default avatarRae Moar <rmoar@google.com>
Tested-by: default avatarMiguel Ojeda <ojeda@kernel.org>
Signed-off-by: default avatarShuah Khan <skhan@linuxfoundation.org>
parent 170c3173
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -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;