From: Jinjie Ruan <ruanjinjie@huawei.com>
To: <linux-kselftest@vger.kernel.org>, <kunit-dev@googlegroups.com>,
Brendan Higgins <brendan.higgins@linux.dev>,
David Gow <davidgow@google.com>,
Shuah Khan <skhan@linuxfoundation.org>,
Maxime Ripard <mripard@kernel.org>,
Benjamin Berg <benjamin.berg@intel.com>
Cc: <ruanjinjie@huawei.com>
Subject: [PATCH] kunit: Fix a null-ptr-deref bug in kunit_run_case_catch_errors()
Date: Fri, 15 Sep 2023 15:41:10 +0800 [thread overview]
Message-ID: <20230915074110.2854382-1-ruanjinjie@huawei.com> (raw)
Inject fault while probing kunit-test.ko, the below null-ptr-deref
occurs.
In kunit_run_case_catch_errors(), if the first kunit_try_catch_run()
fails in kthread_run(), the kunit_try_run_case() will not run, so the
kunit_resource_test_init() and kunit_resource_test_cases() will not
run. And if the second call of kunit_try_catch_run() succeeds, it
will call kunit_resource_test_exit(), but the test->priv is NULL, call
kunit_cleanup() will cause below null-ptr-deref.
So just return the error code if the first kunit_try_catch_run()
fails.
BUG: KASAN: null-ptr-deref in _raw_spin_lock_irqsave+0x7e/0xe0
Write of size 4 at addr 0000000000000054 by task kunit_try_catch/10476
CPU: 2 PID: 10476 Comm: kunit_try_catch Tainted: G W N 6.6.0-rc1+ #77
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014
Call Trace:
<TASK>
dump_stack_lvl+0x33/0x50
print_report+0x3e5/0x600
? dequeue_entity+0x3c1/0x11e0
? rcu_trc_cmpxchg_need_qs+0x5e/0xa0
? _raw_spin_lock_irqsave+0x7e/0xe0
kasan_report+0x90/0xc0
? _raw_spin_lock_irqsave+0x7e/0xe0
kasan_check_range+0xe9/0x190
_raw_spin_lock_irqsave+0x7e/0xe0
? _raw_read_lock_bh+0x40/0x40
? _raw_spin_lock_irqsave+0x8d/0xe0
kunit_cleanup+0x77/0x110
kunit_resource_test_exit+0x2c/0x50 [kunit_test]
? __kthread_parkme+0x8b/0x160
kunit_try_run_case_cleanup+0xac/0xe0
? kunit_cleanup+0x110/0x110
kunit_generic_run_threadfn_adapter+0x4a/0x90
? kunit_try_catch_throw+0x80/0x80
kthread+0x2b6/0x380
? kthread_complete_and_exit+0x20/0x20
ret_from_fork+0x2d/0x70
? kthread_complete_and_exit+0x20/0x20
ret_from_fork_asm+0x11/0x20
</TASK>
==================================================================
Disabling lock debugging due to kernel taint
BUG: kernel NULL pointer dereference, address: 0000000000000054
#PF: supervisor write access in kernel mode
#PF: error_code(0x0002) - not-present page
PGD 0 P4D 0
Oops: 0002 [#1] PREEMPT SMP KASAN
CPU: 2 PID: 10476 Comm: kunit_try_catch Tainted: G B W N 6.6.0-rc1+ #77
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014
RIP: 0010:_raw_spin_lock_irqsave+0x96/0xe0
Code: 00 00 48 89 ef c7 44 24 20 00 00 00 00 e8 c2 02 88 fd be 04 00 00 00 48 8d 7c 24 20 e8 b3 02 88 fd ba 01 00 00 00 8b 44 24 20 <f0> 0f b1 55 00 75 2e 48 b8 00 00 00 00 00 fc ff df 48 c7 04 03 00
RSP: 0018:ffff888108d07de0 EFLAGS: 00010097
RAX: 0000000000000000 RBX: 1ffff110211a0fbc RCX: ffffffff840a0c9d
RDX: 0000000000000001 RSI: 0000000000000004 RDI: ffff888108d07e00
RBP: 0000000000000054 R08: ffffed10211a0fc0 R09: ffffed10211a0fc1
R10: ffffed10211a0fc0 R11: 0000000000000003 R12: 0000000000000246
R13: dffffc0000000000 R14: ffff88810dbdf590 R15: 0000000000000054
FS: 0000000000000000(0000) GS:ffff888119f00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000054 CR3: 0000000107a31002 CR4: 0000000000170ee0
DR0: ffffffff8faefce8 DR1: ffffffff8faefce9 DR2: ffffffff8faefcea
DR3: ffffffff8faefceb DR6: 00000000ffff0ff0 DR7: 0000000000000600
Call Trace:
<TASK>
? __die_body+0x1b/0x60
? page_fault_oops+0x238/0x760
? page_fault_oops+0x760/0x760
? spurious_kernel_fault+0x2d0/0x2d0
? search_bpf_extables+0x134/0x190
? fixup_exception+0x4a/0xa20
? do_user_addr_fault+0xaa/0x1180
? exc_page_fault+0x5a/0xd0
? asm_exc_page_fault+0x22/0x30
? _raw_spin_lock_irqsave+0x8d/0xe0
? _raw_spin_lock_irqsave+0x96/0xe0
? _raw_read_lock_bh+0x40/0x40
? _raw_spin_lock_irqsave+0x8d/0xe0
kunit_cleanup+0x77/0x110
kunit_resource_test_exit+0x2c/0x50 [kunit_test]
? __kthread_parkme+0x8b/0x160
kunit_try_run_case_cleanup+0xac/0xe0
? kunit_cleanup+0x110/0x110
kunit_generic_run_threadfn_adapter+0x4a/0x90
? kunit_try_catch_throw+0x80/0x80
kthread+0x2b6/0x380
? kthread_complete_and_exit+0x20/0x20
ret_from_fork+0x2d/0x70
? kthread_complete_and_exit+0x20/0x20
ret_from_fork_asm+0x11/0x20
</TASK>
Modules linked in: kunit_test(+) [last unloaded: kunit_test]
Dumping ftrace buffer:
(ftrace buffer empty)
CR2: 0000000000000054
---[ end trace 0000000000000000 ]---
RIP: 0010:_raw_spin_lock_irqsave+0x96/0xe0
Code: 00 00 48 89 ef c7 44 24 20 00 00 00 00 e8 c2 02 88 fd be 04 00 00 00 48 8d 7c 24 20 e8 b3 02 88 fd ba 01 00 00 00 8b 44 24 20 <f0> 0f b1 55 00 75 2e 48 b8 00 00 00 00 00 fc ff df 48 c7 04 03 00
RSP: 0018:ffff888108d07de0 EFLAGS: 00010097
RAX: 0000000000000000 RBX: 1ffff110211a0fbc RCX: ffffffff840a0c9d
RDX: 0000000000000001 RSI: 0000000000000004 RDI: ffff888108d07e00
RBP: 0000000000000054 R08: ffffed10211a0fc0 R09: ffffed10211a0fc1
R10: ffffed10211a0fc0 R11: 0000000000000003 R12: 0000000000000246
R13: dffffc0000000000 R14: ffff88810dbdf590 R15: 0000000000000054
FS: 0000000000000000(0000) GS:ffff888119f00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000054 CR3: 0000000107a31002 CR4: 0000000000170ee0
DR0: ffffffff8faefce8 DR1: ffffffff8faefce9 DR2: ffffffff8faefcea
DR3: ffffffff8faefceb DR6: 00000000ffff0ff0 DR7: 0000000000000600
Kernel panic - not syncing: Fatal exception
Dumping ftrace buffer:
(ftrace buffer empty)
Kernel Offset: disabled
Rebooting in 1 seconds..
Fixes: 55e8c1b49ac5 ("kunit: Always run cleanup from a test kthread")
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
include/kunit/try-catch.h | 2 +-
lib/kunit/test.c | 6 +++++-
lib/kunit/try-catch.c | 9 ++++++---
3 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/include/kunit/try-catch.h b/include/kunit/try-catch.h
index c507dd43119d..5192b8e0aac6 100644
--- a/include/kunit/try-catch.h
+++ b/include/kunit/try-catch.h
@@ -53,7 +53,7 @@ struct kunit_try_catch {
void *context;
};
-void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context);
+int kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context);
void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch);
diff --git a/lib/kunit/test.c b/lib/kunit/test.c
index 421f13981412..f20cce96a971 100644
--- a/lib/kunit/test.c
+++ b/lib/kunit/test.c
@@ -512,6 +512,7 @@ static void kunit_run_case_catch_errors(struct kunit_suite *suite,
{
struct kunit_try_catch_context context;
struct kunit_try_catch *try_catch;
+ int ret = 0;
try_catch = &test->try_catch;
@@ -522,7 +523,9 @@ static void kunit_run_case_catch_errors(struct kunit_suite *suite,
context.test = test;
context.suite = suite;
context.test_case = test_case;
- kunit_try_catch_run(try_catch, &context);
+ ret = kunit_try_catch_run(try_catch, &context);
+ if (ret)
+ goto out;
/* Now run the cleanup */
kunit_try_catch_init(try_catch,
@@ -531,6 +534,7 @@ static void kunit_run_case_catch_errors(struct kunit_suite *suite,
kunit_catch_run_case_cleanup);
kunit_try_catch_run(try_catch, &context);
+out:
/* Propagate the parameter result to the test case. */
if (test->status == KUNIT_FAILURE)
test_case->status = KUNIT_FAILURE;
diff --git a/lib/kunit/try-catch.c b/lib/kunit/try-catch.c
index f7825991d576..b937da7ec0a4 100644
--- a/lib/kunit/try-catch.c
+++ b/lib/kunit/try-catch.c
@@ -55,7 +55,7 @@ static unsigned long kunit_test_timeout(void)
return 300 * msecs_to_jiffies(MSEC_PER_SEC); /* 5 min */
}
-void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
+int kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
{
DECLARE_COMPLETION_ONSTACK(try_completion);
struct kunit *test = try_catch->test;
@@ -70,7 +70,8 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
"kunit_try_catch_thread");
if (IS_ERR(task_struct)) {
try_catch->catch(try_catch->context);
- return;
+ try_catch->try_result = -EINTR;
+ return PTR_ERR(task_struct);
}
time_remaining = wait_for_completion_timeout(&try_completion,
@@ -84,7 +85,7 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
exit_code = try_catch->try_result;
if (!exit_code)
- return;
+ return 0;
if (exit_code == -EFAULT)
try_catch->try_result = 0;
@@ -94,5 +95,7 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
kunit_err(test, "Unknown error: %d\n", exit_code);
try_catch->catch(try_catch->context);
+
+ return 0;
}
EXPORT_SYMBOL_GPL(kunit_try_catch_run);
--
2.34.1
next reply other threads:[~2023-09-15 7:42 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-09-15 7:41 Jinjie Ruan [this message]
2023-09-26 7:33 ` [PATCH] kunit: Fix a null-ptr-deref bug in kunit_run_case_catch_errors() Ruan Jinjie
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230915074110.2854382-1-ruanjinjie@huawei.com \
--to=ruanjinjie@huawei.com \
--cc=benjamin.berg@intel.com \
--cc=brendan.higgins@linux.dev \
--cc=davidgow@google.com \
--cc=kunit-dev@googlegroups.com \
--cc=linux-kselftest@vger.kernel.org \
--cc=mripard@kernel.org \
--cc=skhan@linuxfoundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.