Re: [PATCH v2 1/7] kunit: Handle thread creation error
On Fri, Mar 1, 2024 at 2:40 PM Mickaël Salaün wrote: > > Previously, if a thread creation failed (e.g. -ENOMEM), the function was > called (kunit_catch_run_case or kunit_catch_run_case_cleanup) without > marking the test as failed. Instead, fill try_result with the error > code returned by kthread_run(), which will mark the test as failed and > print "internal error occurred...". Hello! I have tested this and this fix looks good to me. Thanks! -Rae Reviewed-by: Rae Moar > > Cc: Brendan Higgins > Cc: David Gow > Cc: Rae Moar > Cc: Shuah Khan > Reviewed-by: Kees Cook > Signed-off-by: Mickaël Salaün > Link: https://lore.kernel.org/r/20240301194037.532117-2-...@digikod.net > --- > > Changes since v1: > * Added Kees's Reviewed-by. > --- > lib/kunit/try-catch.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/lib/kunit/try-catch.c b/lib/kunit/try-catch.c > index f7825991d576..a5cb2ef70a25 100644 > --- a/lib/kunit/try-catch.c > +++ b/lib/kunit/try-catch.c > @@ -69,6 +69,7 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, > void *context) > try_catch, > "kunit_try_catch_thread"); > if (IS_ERR(task_struct)) { > + try_catch->try_result = PTR_ERR(task_struct); > try_catch->catch(try_catch->context); > return; > } > -- > 2.44.0 >
Re: [PATCH v2 2/7] kunit: Fix kthread reference
On Fri, Mar 1, 2024 at 2:40 PM Mickaël Salaün wrote: > > There is a race condition when a kthread finishes after the deadline and > before the call to kthread_stop(), which may lead to use after free. Hello! I have tested this patch and it looks good to me. Thanks! -Rae Reviewed-by: Rae Moar > > Cc: Brendan Higgins > Cc: David Gow > Cc: Rae Moar > Cc: Shuah Khan > Reviewed-by: Kees Cook > Signed-off-by: Mickaël Salaün > Link: https://lore.kernel.org/r/20240301194037.532117-3-...@digikod.net > --- > > Changes since v1: > * Added Kees's Reviewed-by. > --- > lib/kunit/try-catch.c | 9 ++--- > 1 file changed, 6 insertions(+), 3 deletions(-) > > diff --git a/lib/kunit/try-catch.c b/lib/kunit/try-catch.c > index a5cb2ef70a25..73f5007f20ea 100644 > --- a/lib/kunit/try-catch.c > +++ b/lib/kunit/try-catch.c > @@ -11,6 +11,7 @@ > #include > #include > #include > +#include > > #include "try-catch-impl.h" > > @@ -65,14 +66,15 @@ void kunit_try_catch_run(struct kunit_try_catch > *try_catch, void *context) > try_catch->context = context; > try_catch->try_completion = &try_completion; > try_catch->try_result = 0; > - task_struct = kthread_run(kunit_generic_run_threadfn_adapter, > - try_catch, > - "kunit_try_catch_thread"); > + task_struct = kthread_create(kunit_generic_run_threadfn_adapter, > +try_catch, "kunit_try_catch_thread"); > if (IS_ERR(task_struct)) { > try_catch->try_result = PTR_ERR(task_struct); > try_catch->catch(try_catch->context); > return; > } > + get_task_struct(task_struct); > + wake_up_process(task_struct); > > time_remaining = wait_for_completion_timeout(&try_completion, > kunit_test_timeout()); > @@ -82,6 +84,7 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, > void *context) > kthread_stop(task_struct); > } > > + put_task_struct(task_struct); > exit_code = try_catch->try_result; > > if (!exit_code) > -- > 2.44.0 >
Re: [PATCH v2 3/7] kunit: Fix timeout message
On Fri, Mar 1, 2024 at 2:40 PM Mickaël Salaün wrote: > > The exit code is always checked, so let's properly handle the -ETIMEDOUT > error code. Hello! This change looks good to me. Thanks! -Rae Reviewed-by: Rae Moar > > Cc: Brendan Higgins > Cc: David Gow > Cc: Rae Moar > Cc: Shuah Khan > Reviewed-by: Kees Cook > Signed-off-by: Mickaël Salaün > Link: https://lore.kernel.org/r/20240301194037.532117-4-...@digikod.net > --- > > Changes since v1: > * Added Kees's Reviewed-by. > --- > lib/kunit/try-catch.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/lib/kunit/try-catch.c b/lib/kunit/try-catch.c > index 73f5007f20ea..cab8b24b5d5a 100644 > --- a/lib/kunit/try-catch.c > +++ b/lib/kunit/try-catch.c > @@ -79,7 +79,6 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, > void *context) > time_remaining = wait_for_completion_timeout(&try_completion, > kunit_test_timeout()); > if (time_remaining == 0) { > - kunit_err(test, "try timed out\n"); > try_catch->try_result = -ETIMEDOUT; > kthread_stop(task_struct); > } > @@ -94,6 +93,8 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, > void *context) > try_catch->try_result = 0; > else if (exit_code == -EINTR) > kunit_err(test, "wake_up_process() was never called\n"); > + else if (exit_code == -ETIMEDOUT) > + kunit_err(test, "try timed out\n"); > else if (exit_code) > kunit_err(test, "Unknown error: %d\n", exit_code); > > -- > 2.44.0 >
Re: [PATCH v2 4/7] kunit: Handle test faults
On Fri, Mar 1, 2024 at 2:40 PM Mickaël Salaün wrote: > > Previously, when a kernel test thread crashed (e.g. NULL pointer > dereference, general protection fault), the KUnit test hanged for 30 > seconds and exited with a timeout error. > > Fix this issue by waiting on task_struct->vfork_done instead of the > custom kunit_try_catch.try_completion, and track the execution state by > initially setting try_result with -EFAULT and only setting it to 0 if Hello! Thanks for your patch! This has been tested and seems pretty good to me but I just have a few questions. First, do you mean here "setting try_result with -EINTR" instead? But happy to add the tested-by. Tested-by: Rae Moar Thanks! -Rae > the test passed. > > Fix kunit_generic_run_threadfn_adapter() signature by returning 0 > instead of calling kthread_complete_and_exit(). Because thread's exit > code is never checked, always set it to 0 to make it clear. > > Fix the -EINTR error message, which couldn't be reached until now. > > This is tested with a following patch. > > Cc: Brendan Higgins > Cc: David Gow > Cc: Rae Moar > Cc: Shuah Khan > Reviewed-by: Kees Cook > Signed-off-by: Mickaël Salaün > Link: https://lore.kernel.org/r/20240301194037.532117-5-...@digikod.net > --- > > Changes since v1: > * Added Kees's Reviewed-by. > --- > include/kunit/try-catch.h | 3 --- > lib/kunit/try-catch.c | 14 +++--- > 2 files changed, 7 insertions(+), 10 deletions(-) > > diff --git a/include/kunit/try-catch.h b/include/kunit/try-catch.h > index c507dd43119d..7c966a1adbd3 100644 > --- a/include/kunit/try-catch.h > +++ b/include/kunit/try-catch.h > @@ -14,13 +14,11 @@ > > typedef void (*kunit_try_catch_func_t)(void *); > > -struct completion; > struct kunit; > > /** > * struct kunit_try_catch - provides a generic way to run code which might > fail. > * @test: The test case that is currently being executed. > - * @try_completion: Completion that the control thread waits on while test > runs. > * @try_result: Contains any errno obtained while running test case. > * @try: The function, the test case, to attempt to run. > * @catch: The function called if @try bails out. > @@ -46,7 +44,6 @@ struct kunit; > struct kunit_try_catch { > /* private: internal use only. */ > struct kunit *test; > - struct completion *try_completion; > int try_result; > kunit_try_catch_func_t try; > kunit_try_catch_func_t catch; > diff --git a/lib/kunit/try-catch.c b/lib/kunit/try-catch.c > index cab8b24b5d5a..c6ee4db0b3bd 100644 > --- a/lib/kunit/try-catch.c > +++ b/lib/kunit/try-catch.c > @@ -18,7 +18,7 @@ > void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch) > { > try_catch->try_result = -EFAULT; > - kthread_complete_and_exit(try_catch->try_completion, -EFAULT); > + kthread_exit(0); > } > EXPORT_SYMBOL_GPL(kunit_try_catch_throw); > > @@ -26,9 +26,12 @@ static int kunit_generic_run_threadfn_adapter(void *data) > { > struct kunit_try_catch *try_catch = data; > > + try_catch->try_result = -EINTR; > try_catch->try(try_catch->context); > + if (try_catch->try_result == -EINTR) > + try_catch->try_result = 0; > > - kthread_complete_and_exit(try_catch->try_completion, 0); > + return 0; Really my only question is why we do not need to still do a kthread_exit(0) here? I realize we are not checking the thread's exit code but isn't it safer to call kthread_exit(). I'm new to kthread so I am not too sure. > } > > static unsigned long kunit_test_timeout(void) > @@ -58,13 +61,11 @@ static unsigned long kunit_test_timeout(void) > > void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context) > { > - DECLARE_COMPLETION_ONSTACK(try_completion); > struct kunit *test = try_catch->test; > struct task_struct *task_struct; > int exit_code, time_remaining; > > try_catch->context = context; > - try_catch->try_completion = &try_completion; > try_catch->try_result = 0; > task_struct = kthread_create(kunit_generic_run_threadfn_adapter, > try_catch, "kunit_try_catch_thread"); > @@ -75,8 +76,7 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, > void *context) > } > get_task_struct(task_struct); > wake_up_process(task_struct); > - > - time_remaining = wait_for_completion_timeout(&try_completion, > + time_remaining = wait_for_completion_timeout(task_struc