Message ID | 20240229170409.365386-1-mic@digikod.net |
---|---|
Headers |
Return-Path: <linux-kernel+bounces-87139-ouuuleilei=gmail.com@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:2097:b0:108:e6aa:91d0 with SMTP id gs23csp543355dyb; Thu, 29 Feb 2024 09:07:42 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCWB1OKA2dhSiWLfk7kEitPK2d2dffLDTWBpeWndEEYeb+h3wDdzxpOyEpWULKjSAYJqIRuQe9yHIr2tn84Hz1CmgtTx0g== X-Google-Smtp-Source: AGHT+IH8iQ4y1xBpQ6KaxQTq+pqz1W0h7VXTSVWkAbGWWC7z89VwN9slsiEVxZoKoya5wS1MvqKo X-Received: by 2002:a17:90b:314d:b0:297:17fb:4d79 with SMTP id ip13-20020a17090b314d00b0029717fb4d79mr2808901pjb.2.1709226462510; Thu, 29 Feb 2024 09:07:42 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1709226462; cv=pass; d=google.com; s=arc-20160816; b=snYN3ISp81Tx0dylZW/ac16ycKZsoIzpj50fXygWcPvWeoSk5hvdcMhgRiFOZ+eHmc CLpFHo5TtsjhHbx9emM60AeXOQTWh1fIS1k52aES6Ozk7metGVY++CJjF8ahEPH5Sc3/ wTR+Z69Z+1ow6m77exi7RkuVunvtI0FUOz3sGz89XvtohCjoJXukAj7mjsa8XBh9OaNS FdXXn4COjR8QVy42HICoVNez+6kKwfdcDZvF3LgEiNlIUjjO9UjCwTXm08mF5Sgtyqzf s2qUahQllUxZJQ8Qn8uFlt5JjjyyE8Q6ysELerDvKh5W+EJPs5ZyaovHU7ZvqwhuuPtw 4b9Q== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:message-id:date:subject:cc:to :from:dkim-signature; bh=ZJ4iZR2qsWlZ4aapEky+vEYApfMYzxKzJ6l+O/T6keg=; fh=MR/wbEn34JHmT+rtzWNq5RVU/RKi8DhjSvb3ywiuLkE=; b=pHdICK8rDNFvFijPvq27dlZMs7lj9gWVIFfXgqfMYyj3MKVylGFJSyO1fk/2m7BXz6 ljC0+KzlC2+YQibY8EgkkzNt0UjIeELa8zyfab6N9nrXZpTH/SUViwKxIT+OHjY4yroI bzac95/C4vKN32rwmuD64cWaTPBphNu2JwuRca7y8i05XfogeIKSBkrXPEAUi4ECHRC0 CZdIWdXG5fwiQRpoH9tcuqEDKXxHpqlAl1n4ZUS2VG0Y3cPld8iEpG7oUkxSPL9E7SIs mr9vaYN5HuQ8CKnDfVKWp+4LHWQbzX8QvA4jA3TZ7kyCvGFZjEtXNURbD3YABbcTzjaQ jNyw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@digikod.net header.s=20191114 header.b=nlVkoodR; arc=pass (i=1 spf=pass spfdomain=digikod.net dkim=pass dkdomain=digikod.net); spf=pass (google.com: domain of linux-kernel+bounces-87139-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-87139-ouuuleilei=gmail.com@vger.kernel.org" Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id y16-20020a17090ad71000b00296944d82c8si3781530pju.151.2024.02.29.09.07.42 for <ouuuleilei@gmail.com> (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 29 Feb 2024 09:07:42 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-87139-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; dkim=pass header.i=@digikod.net header.s=20191114 header.b=nlVkoodR; arc=pass (i=1 spf=pass spfdomain=digikod.net dkim=pass dkdomain=digikod.net); spf=pass (google.com: domain of linux-kernel+bounces-87139-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-87139-ouuuleilei=gmail.com@vger.kernel.org" Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id C7AB728A1E0 for <ouuuleilei@gmail.com>; Thu, 29 Feb 2024 17:06:58 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 0162A134403; Thu, 29 Feb 2024 17:04:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=digikod.net header.i=@digikod.net header.b="nlVkoodR" Received: from smtp-42ad.mail.infomaniak.ch (smtp-42ad.mail.infomaniak.ch [84.16.66.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5F52636B1C for <linux-kernel@vger.kernel.org>; Thu, 29 Feb 2024 17:04:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=84.16.66.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709226278; cv=none; b=HUChTzTwL+mt+6joPJN2SBHSpkqmoiEPuumXjb5kAV41EzbpdtHEjTAJvo5v6ChQfYQY0nGWAQLPX3NGtzyJ54CyjCEmxtSftfUqJ+ixclomkIW5sARV6WsF+1Ot2QQErdva2JpHZCCGytCIxgmSJJsJz6lHtJw/Cxqj7OyzZWw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709226278; c=relaxed/simple; bh=4wDdbt4I56G5n6LSUJ2u1jaEVBMsm/64WWZPbsYi9U0=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Type; b=lo9Ubhsms1bau8PYOi4rrWQI/qmyEO6y1mLi/NT7LeCa3hfzlI/A++zfD9fLJ3jpExJ5ziGZdJlTyJ2mgEsFERRQ3jMcJ7VTJ7beJhN+NOZzNsM3CVvak7bxS1Zq7iYwh150G+5Qk8LSNDg+NBbbNbSM2hudHrQdzTlzcQILbRs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=digikod.net; spf=pass smtp.mailfrom=digikod.net; dkim=pass (1024-bit key) header.d=digikod.net header.i=@digikod.net header.b=nlVkoodR; arc=none smtp.client-ip=84.16.66.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=digikod.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=digikod.net Received: from smtp-4-0000.mail.infomaniak.ch (smtp-4-0000.mail.infomaniak.ch [10.7.10.107]) by smtp-4-3000.mail.infomaniak.ch (Postfix) with ESMTPS id 4TlyHp6JJMz5wk; Thu, 29 Feb 2024 18:04:22 +0100 (CET) Received: from unknown by smtp-4-0000.mail.infomaniak.ch (Postfix) with ESMTPA id 4TlyHm47S2zYBH; Thu, 29 Feb 2024 18:04:20 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=digikod.net; s=20191114; t=1709226262; bh=4wDdbt4I56G5n6LSUJ2u1jaEVBMsm/64WWZPbsYi9U0=; h=From:To:Cc:Subject:Date:From; b=nlVkoodRGG/+JH60co6QTYI+j/xS/kAvzRqTk/xdhkVfSSC5JtD7P7treNBKoqd0u U5gu49lO236cmDqZAiQi+oFIZbE1jszXjS2h0mslolmhNqIG4IKa/drMCKvMRTmYRX pKXV1VkrqQbG3nE+oEnjraDdG3Vrknapc8Mb93bc= From: =?utf-8?q?Micka=C3=ABl_Sala=C3=BCn?= <mic@digikod.net> To: Brendan Higgins <brendanhiggins@google.com>, David Gow <davidgow@google.com>, Kees Cook <keescook@chromium.org>, Rae Moar <rmoar@google.com>, Shuah Khan <skhan@linuxfoundation.org> Cc: =?utf-8?q?Micka=C3=ABl_Sala=C3=BCn?= <mic@digikod.net>, Alan Maguire <alan.maguire@oracle.com>, Borislav Petkov <bp@alien8.de>, Dave Hansen <dave.hansen@linux.intel.com>, "H . Peter Anvin" <hpa@zytor.com>, Ingo Molnar <mingo@redhat.com>, James Morris <jamorris@linux.microsoft.com>, Luis Chamberlain <mcgrof@kernel.org>, "Madhavan T . Venkataraman" <madvenka@linux.microsoft.com>, Marco Pagani <marpagan@redhat.com>, Paolo Bonzini <pbonzini@redhat.com>, Sean Christopherson <seanjc@google.com>, Stephen Boyd <sboyd@kernel.org>, Thara Gopinath <tgopinath@microsoft.com>, Thomas Gleixner <tglx@linutronix.de>, Vitaly Kuznetsov <vkuznets@redhat.com>, Wanpeng Li <wanpengli@tencent.com>, Zahra Tarkhani <ztarkhani@microsoft.com>, kvm@vger.kernel.org, linux-hardening@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org, linux-security-module@vger.kernel.org, linux-um@lists.infradead.org, x86@kernel.org Subject: [PATCH v1 0/8] Run KUnit tests late and handle faults Date: Thu, 29 Feb 2024 18:04:01 +0100 Message-ID: <20240229170409.365386-1-mic@digikod.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: <linux-kernel.vger.kernel.org> List-Subscribe: <mailto:linux-kernel+subscribe@vger.kernel.org> List-Unsubscribe: <mailto:linux-kernel+unsubscribe@vger.kernel.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Infomaniak-Routing: alpha X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1792253847346942179 X-GMAIL-MSGID: 1792253847346942179 |
Series |
Run KUnit tests late and handle faults
|
|
Message
Mickaël Salaün
Feb. 29, 2024, 5:04 p.m. UTC
Hi, This patch series moves KUnit test execution at the very end of kernel initialization, just before launching the init process. This opens the way to test any kernel code in its normal state (i.e. fully initialized). This patch series also teaches KUnit to handle kthread faults as errors, and it brings a few related fixes and improvements. New tests check NULL pointer dereference and read-only memory, which wasn't possible before. This is useful to test current kernel self-protection mechanisms or future ones such as Heki: https://github.com/heki-linux Regards, Mickaël Salaün (8): kunit: Run tests when the kernel is fully setup kunit: Handle thread creation error kunit: Fix kthread reference kunit: Fix timeout message kunit: Handle test faults kunit: Fix KUNIT_SUCCESS() calls in iov_iter tests kunit: Print last test location on fault kunit: Add tests for faults include/kunit/test.h | 24 +++++- include/kunit/try-catch.h | 3 - init/main.c | 4 +- lib/bitfield_kunit.c | 8 +- lib/checksum_kunit.c | 2 +- lib/kunit/executor.c | 81 ++++++++++++++------ lib/kunit/kunit-example-test.c | 6 +- lib/kunit/kunit-test.c | 115 +++++++++++++++++++++++++++- lib/kunit/try-catch.c | 33 +++++--- lib/kunit_iov_iter.c | 70 ++++++++--------- tools/testing/kunit/kunit_kernel.py | 6 +- 11 files changed, 261 insertions(+), 91 deletions(-) base-commit: d206a76d7d2726f3b096037f2079ce0bd3ba329b
Comments
On Thu, Feb 29, 2024 at 06:04:02PM +0100, Mickaël Salaün wrote: > Run all the KUnit tests just before the first userspace code is > launched. This makes it it possible to write new tests that check the > kernel in its final state i.e., with all async __init code called, > memory and RCU properly set up, and sysctl boot arguments evaluated. > > The initial motivation is to run hardening tests (e.g. memory > protection, Heki's CR-pinning), which require such security protection > to be fully setup (e.g. memory marked as read-only). > > Because the suite set could refer to init data, initialize the suite set > with late_initcall(), before kunit_run_all_tests(), if KUnit is built-in > and enabled at boot time. To make it more consistent and easier to > manage, whatever filters are used or not, always copy test suite entries > and free them after all tests are run. > > Because of the prepare_namespace() call, we need to have a valid root > filesystem. To make it simple, let's use tmpfs with an empty root. > Teach kunit_kernel.py:LinuxSourceTreeOperations*() about the related > kernel boot argument, and add this filesystem to the kunit.py's kernel > build requirements. > > Remove __init and __refdata markers from iov_iter, bitfield, checksum, > and the example KUnit tests. Without this change, the kernel tries to > execute NX-protected pages (because the pages are deallocated). I defer to the KUnit maintainers, but I'd find this patch easier to review if the __init and __refdata changes were a separate patch. But otherwise, I like the goals of this series! It should make adding a userspace memory region for porting the usercopy tests easier too. -Kees > > Tested with: > ./tools/testing/kunit/kunit.py run --alltests > ./tools/testing/kunit/kunit.py run --alltests --arch x86_64 > > Cc: Alan Maguire <alan.maguire@oracle.com> > Cc: Brendan Higgins <brendanhiggins@google.com> > Cc: David Gow <davidgow@google.com> > Cc: Kees Cook <keescook@chromium.org> > Cc: Luis Chamberlain <mcgrof@kernel.org> > Cc: Marco Pagani <marpagan@redhat.com> > Cc: Rae Moar <rmoar@google.com> > Cc: Shuah Khan <skhan@linuxfoundation.org> > Cc: Stephen Boyd <sboyd@kernel.org> > Signed-off-by: Mickaël Salaün <mic@digikod.net> > --- > init/main.c | 4 +- > lib/bitfield_kunit.c | 8 +-- > lib/checksum_kunit.c | 2 +- > lib/kunit/executor.c | 81 +++++++++++++++++++++-------- > lib/kunit/kunit-example-test.c | 6 +-- > lib/kunit_iov_iter.c | 52 +++++++++--------- > tools/testing/kunit/kunit_kernel.py | 6 ++- > 7 files changed, 96 insertions(+), 63 deletions(-) > > diff --git a/init/main.c b/init/main.c > index e24b0780fdff..b39d74727aad 100644 > --- a/init/main.c > +++ b/init/main.c > @@ -1463,6 +1463,8 @@ static int __ref kernel_init(void *unused) > > do_sysctl_args(); > > + kunit_run_all_tests(); > + > if (ramdisk_execute_command) { > ret = run_init_process(ramdisk_execute_command); > if (!ret) > @@ -1550,8 +1552,6 @@ static noinline void __init kernel_init_freeable(void) > > do_basic_setup(); > > - kunit_run_all_tests(); > - > wait_for_initramfs(); > console_on_rootfs(); > > diff --git a/lib/bitfield_kunit.c b/lib/bitfield_kunit.c > index 1473d8b4bf0f..71e9f2e96496 100644 > --- a/lib/bitfield_kunit.c > +++ b/lib/bitfield_kunit.c > @@ -57,7 +57,7 @@ > CHECK_ENC_GET_BE(tp, v, field, res); \ > } while (0) > > -static void __init test_bitfields_constants(struct kunit *context) > +static void test_bitfields_constants(struct kunit *context) > { > /* > * NOTE > @@ -100,7 +100,7 @@ static void __init test_bitfields_constants(struct kunit *context) > tp##_encode_bits(v, mask) != v << __ffs64(mask));\ > } while (0) > > -static void __init test_bitfields_variables(struct kunit *context) > +static void test_bitfields_variables(struct kunit *context) > { > CHECK(u8, 0x0f); > CHECK(u8, 0xf0); > @@ -126,7 +126,7 @@ static void __init test_bitfields_variables(struct kunit *context) > } > > #ifdef TEST_BITFIELD_COMPILE > -static void __init test_bitfields_compile(struct kunit *context) > +static void test_bitfields_compile(struct kunit *context) > { > /* these should fail compilation */ > CHECK_ENC_GET(16, 16, 0x0f00, 0x1000); > @@ -137,7 +137,7 @@ static void __init test_bitfields_compile(struct kunit *context) > } > #endif > > -static struct kunit_case __refdata bitfields_test_cases[] = { > +static struct kunit_case bitfields_test_cases[] = { > KUNIT_CASE(test_bitfields_constants), > KUNIT_CASE(test_bitfields_variables), > {} > diff --git a/lib/checksum_kunit.c b/lib/checksum_kunit.c > index 225bb7701460..41aaed3a4963 100644 > --- a/lib/checksum_kunit.c > +++ b/lib/checksum_kunit.c > @@ -620,7 +620,7 @@ static void test_csum_ipv6_magic(struct kunit *test) > #endif /* !CONFIG_NET */ > } > > -static struct kunit_case __refdata checksum_test_cases[] = { > +static struct kunit_case checksum_test_cases[] = { > KUNIT_CASE(test_csum_fixed_random_inputs), > KUNIT_CASE(test_csum_all_carry_inputs), > KUNIT_CASE(test_csum_no_carry_inputs), > diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c > index 689fff2b2b10..ff3e66ffa739 100644 > --- a/lib/kunit/executor.c > +++ b/lib/kunit/executor.c > @@ -15,6 +15,8 @@ extern struct kunit_suite * const __kunit_suites_end[]; > extern struct kunit_suite * const __kunit_init_suites_start[]; > extern struct kunit_suite * const __kunit_init_suites_end[]; > > +static struct kunit_suite_set final_suite_set = {}; > + > static char *action_param; > > module_param_named(action, action_param, charp, 0400); > @@ -233,6 +235,21 @@ kunit_filter_suites(const struct kunit_suite_set *suite_set, > if (!filtered_suite) > continue; > > + if (filtered_suite == suite_set->start[i]) { > + /* > + * To make memory allocation consistent whatever > + * filters are used or not, and to keep > + * kunit_free_suite_set() simple, always copy static > + * data. > + */ > + filtered_suite = kmemdup(filtered_suite, sizeof(*filtered_suite), > + GFP_KERNEL); > + if (!filtered_suite) { > + *err = -ENOMEM; > + goto free_parsed_filters; > + } > + } > + > *copy++ = filtered_suite; > } > filtered.start = copy_start; > @@ -348,7 +365,7 @@ static void kunit_handle_shutdown(void) > > } > > -int kunit_run_all_tests(void) > +static int kunit_init_suites(void) > { > struct kunit_suite_set suite_set = {NULL, NULL}; > struct kunit_suite_set filtered_suite_set = {NULL, NULL}; > @@ -361,6 +378,9 @@ int kunit_run_all_tests(void) > size_t init_num_suites = init_suite_set.end - init_suite_set.start; > int err = 0; > > + if (!kunit_enabled()) > + return 0; > + > if (init_num_suites > 0) { > suite_set = kunit_merge_suite_sets(init_suite_set, normal_suite_set); > if (!suite_set.start) > @@ -368,41 +388,56 @@ int kunit_run_all_tests(void) > } else > suite_set = normal_suite_set; > > - if (!kunit_enabled()) { > - pr_info("kunit: disabled\n"); > + filtered_suite_set = kunit_filter_suites(&suite_set, filter_glob_param, > + filter_param, filter_action_param, &err); > + > + /* Free original suite set before using filtered suite set */ > + if (init_num_suites > 0) > + kfree(suite_set.start); > + suite_set = filtered_suite_set; > + > + if (err) { > + pr_err("kunit executor: error filtering suites: %d\n", err); > goto free_out; > } > > - if (filter_glob_param || filter_param) { > - filtered_suite_set = kunit_filter_suites(&suite_set, filter_glob_param, > - filter_param, filter_action_param, &err); > + final_suite_set = suite_set; > + return 0; > > - /* Free original suite set before using filtered suite set */ > - if (init_num_suites > 0) > - kfree(suite_set.start); > - suite_set = filtered_suite_set; > +free_out: > + kunit_free_suite_set(suite_set); > > - if (err) { > - pr_err("kunit executor: error filtering suites: %d\n", err); > - goto free_out; > - } > +out: > + kunit_handle_shutdown(); > + return err; > +} > + > +late_initcall(kunit_init_suites); > + > +int kunit_run_all_tests(void) > +{ > + int err = 0; > + > + if (!kunit_enabled()) { > + pr_info("kunit: disabled\n"); > + goto out; > } > > + if (!final_suite_set.start) > + goto out; > + > if (!action_param) > - kunit_exec_run_tests(&suite_set, true); > + kunit_exec_run_tests(&final_suite_set, true); > else if (strcmp(action_param, "list") == 0) > - kunit_exec_list_tests(&suite_set, false); > + kunit_exec_list_tests(&final_suite_set, false); > else if (strcmp(action_param, "list_attr") == 0) > - kunit_exec_list_tests(&suite_set, true); > + kunit_exec_list_tests(&final_suite_set, true); > else > pr_err("kunit executor: unknown action '%s'\n", action_param); > > -free_out: > - if (filter_glob_param || filter_param) > - kunit_free_suite_set(suite_set); > - else if (init_num_suites > 0) > - /* Don't use kunit_free_suite_set because suites aren't individually allocated */ > - kfree(suite_set.start); > + kunit_free_suite_set(final_suite_set); > + final_suite_set.start = NULL; > + final_suite_set.end = NULL; > > out: > kunit_handle_shutdown(); > diff --git a/lib/kunit/kunit-example-test.c b/lib/kunit/kunit-example-test.c > index 798924f7cc86..248949eb3b16 100644 > --- a/lib/kunit/kunit-example-test.c > +++ b/lib/kunit/kunit-example-test.c > @@ -337,7 +337,7 @@ static struct kunit_suite example_test_suite = { > */ > kunit_test_suites(&example_test_suite); > > -static int __init init_add(int x, int y) > +static int init_add(int x, int y) > { > return (x + y); > } > @@ -345,7 +345,7 @@ static int __init init_add(int x, int y) > /* > * This test should always pass. Can be used to test init suites. > */ > -static void __init example_init_test(struct kunit *test) > +static void example_init_test(struct kunit *test) > { > KUNIT_EXPECT_EQ(test, init_add(1, 1), 2); > } > @@ -354,7 +354,7 @@ static void __init example_init_test(struct kunit *test) > * The kunit_case struct cannot be marked as __initdata as this will be > * used in debugfs to retrieve results after test has run > */ > -static struct kunit_case __refdata example_init_test_cases[] = { > +static struct kunit_case example_init_test_cases[] = { > KUNIT_CASE(example_init_test), > {} > }; > diff --git a/lib/kunit_iov_iter.c b/lib/kunit_iov_iter.c > index 859b67c4d697..a77991a9bffb 100644 > --- a/lib/kunit_iov_iter.c > +++ b/lib/kunit_iov_iter.c > @@ -44,9 +44,8 @@ static void iov_kunit_unmap(void *data) > vunmap(data); > } > > -static void *__init iov_kunit_create_buffer(struct kunit *test, > - struct page ***ppages, > - size_t npages) > +static void *iov_kunit_create_buffer(struct kunit *test, struct page ***ppages, > + size_t npages) > { > struct page **pages; > unsigned long got; > @@ -69,11 +68,10 @@ static void *__init iov_kunit_create_buffer(struct kunit *test, > return buffer; > } > > -static void __init iov_kunit_load_kvec(struct kunit *test, > - struct iov_iter *iter, int dir, > - struct kvec *kvec, unsigned int kvmax, > - void *buffer, size_t bufsize, > - const struct kvec_test_range *pr) > +static void iov_kunit_load_kvec(struct kunit *test, struct iov_iter *iter, > + int dir, struct kvec *kvec, unsigned int kvmax, > + void *buffer, size_t bufsize, > + const struct kvec_test_range *pr) > { > size_t size = 0; > int i; > @@ -95,7 +93,7 @@ static void __init iov_kunit_load_kvec(struct kunit *test, > /* > * Test copying to a ITER_KVEC-type iterator. > */ > -static void __init iov_kunit_copy_to_kvec(struct kunit *test) > +static void iov_kunit_copy_to_kvec(struct kunit *test) > { > const struct kvec_test_range *pr; > struct iov_iter iter; > @@ -145,7 +143,7 @@ static void __init iov_kunit_copy_to_kvec(struct kunit *test) > /* > * Test copying from a ITER_KVEC-type iterator. > */ > -static void __init iov_kunit_copy_from_kvec(struct kunit *test) > +static void iov_kunit_copy_from_kvec(struct kunit *test) > { > const struct kvec_test_range *pr; > struct iov_iter iter; > @@ -213,12 +211,11 @@ static const struct bvec_test_range bvec_test_ranges[] = { > { -1, -1, -1 } > }; > > -static void __init iov_kunit_load_bvec(struct kunit *test, > - struct iov_iter *iter, int dir, > - struct bio_vec *bvec, unsigned int bvmax, > - struct page **pages, size_t npages, > - size_t bufsize, > - const struct bvec_test_range *pr) > +static void iov_kunit_load_bvec(struct kunit *test, struct iov_iter *iter, > + int dir, struct bio_vec *bvec, > + unsigned int bvmax, struct page **pages, > + size_t npages, size_t bufsize, > + const struct bvec_test_range *pr) > { > struct page *can_merge = NULL, *page; > size_t size = 0; > @@ -254,7 +251,7 @@ static void __init iov_kunit_load_bvec(struct kunit *test, > /* > * Test copying to a ITER_BVEC-type iterator. > */ > -static void __init iov_kunit_copy_to_bvec(struct kunit *test) > +static void iov_kunit_copy_to_bvec(struct kunit *test) > { > const struct bvec_test_range *pr; > struct iov_iter iter; > @@ -308,7 +305,7 @@ static void __init iov_kunit_copy_to_bvec(struct kunit *test) > /* > * Test copying from a ITER_BVEC-type iterator. > */ > -static void __init iov_kunit_copy_from_bvec(struct kunit *test) > +static void iov_kunit_copy_from_bvec(struct kunit *test) > { > const struct bvec_test_range *pr; > struct iov_iter iter; > @@ -370,10 +367,9 @@ static void iov_kunit_destroy_xarray(void *data) > kfree(xarray); > } > > -static void __init iov_kunit_load_xarray(struct kunit *test, > - struct iov_iter *iter, int dir, > - struct xarray *xarray, > - struct page **pages, size_t npages) > +static void iov_kunit_load_xarray(struct kunit *test, struct iov_iter *iter, > + int dir, struct xarray *xarray, > + struct page **pages, size_t npages) > { > size_t size = 0; > int i; > @@ -401,7 +397,7 @@ static struct xarray *iov_kunit_create_xarray(struct kunit *test) > /* > * Test copying to a ITER_XARRAY-type iterator. > */ > -static void __init iov_kunit_copy_to_xarray(struct kunit *test) > +static void iov_kunit_copy_to_xarray(struct kunit *test) > { > const struct kvec_test_range *pr; > struct iov_iter iter; > @@ -459,7 +455,7 @@ static void __init iov_kunit_copy_to_xarray(struct kunit *test) > /* > * Test copying from a ITER_XARRAY-type iterator. > */ > -static void __init iov_kunit_copy_from_xarray(struct kunit *test) > +static void iov_kunit_copy_from_xarray(struct kunit *test) > { > const struct kvec_test_range *pr; > struct iov_iter iter; > @@ -522,7 +518,7 @@ static void __init iov_kunit_copy_from_xarray(struct kunit *test) > /* > * Test the extraction of ITER_KVEC-type iterators. > */ > -static void __init iov_kunit_extract_pages_kvec(struct kunit *test) > +static void iov_kunit_extract_pages_kvec(struct kunit *test) > { > const struct kvec_test_range *pr; > struct iov_iter iter; > @@ -602,7 +598,7 @@ static void __init iov_kunit_extract_pages_kvec(struct kunit *test) > /* > * Test the extraction of ITER_BVEC-type iterators. > */ > -static void __init iov_kunit_extract_pages_bvec(struct kunit *test) > +static void iov_kunit_extract_pages_bvec(struct kunit *test) > { > const struct bvec_test_range *pr; > struct iov_iter iter; > @@ -680,7 +676,7 @@ static void __init iov_kunit_extract_pages_bvec(struct kunit *test) > /* > * Test the extraction of ITER_XARRAY-type iterators. > */ > -static void __init iov_kunit_extract_pages_xarray(struct kunit *test) > +static void iov_kunit_extract_pages_xarray(struct kunit *test) > { > const struct kvec_test_range *pr; > struct iov_iter iter; > @@ -756,7 +752,7 @@ static void __init iov_kunit_extract_pages_xarray(struct kunit *test) > KUNIT_SUCCEED(); > } > > -static struct kunit_case __refdata iov_kunit_cases[] = { > +static struct kunit_case iov_kunit_cases[] = { > KUNIT_CASE(iov_kunit_copy_to_kvec), > KUNIT_CASE(iov_kunit_copy_from_kvec), > KUNIT_CASE(iov_kunit_copy_to_bvec), > diff --git a/tools/testing/kunit/kunit_kernel.py b/tools/testing/kunit/kunit_kernel.py > index 0b6488efed47..e1980ea58118 100644 > --- a/tools/testing/kunit/kunit_kernel.py > +++ b/tools/testing/kunit/kunit_kernel.py > @@ -104,12 +104,13 @@ class LinuxSourceTreeOperationsQemu(LinuxSourceTreeOperations): > self._kconfig = qemu_arch_params.kconfig > self._qemu_arch = qemu_arch_params.qemu_arch > self._kernel_path = qemu_arch_params.kernel_path > - self._kernel_command_line = qemu_arch_params.kernel_command_line + ' kunit_shutdown=reboot' > + self._kernel_command_line = qemu_arch_params.kernel_command_line + ' kunit_shutdown=reboot rootfstype=tmpfs' > self._extra_qemu_params = qemu_arch_params.extra_qemu_params > self._serial = qemu_arch_params.serial > > def make_arch_config(self, base_kunitconfig: kunit_config.Kconfig) -> kunit_config.Kconfig: > kconfig = kunit_config.parse_from_string(self._kconfig) > + kconfig.add_entry('TMPFS', 'y') > kconfig.merge_in_entries(base_kunitconfig) > return kconfig > > @@ -139,13 +140,14 @@ class LinuxSourceTreeOperationsUml(LinuxSourceTreeOperations): > > def make_arch_config(self, base_kunitconfig: kunit_config.Kconfig) -> kunit_config.Kconfig: > kconfig = kunit_config.parse_file(UML_KCONFIG_PATH) > + kconfig.add_entry('TMPFS', 'y') > kconfig.merge_in_entries(base_kunitconfig) > return kconfig > > def start(self, params: List[str], build_dir: str) -> subprocess.Popen: > """Runs the Linux UML binary. Must be named 'linux'.""" > linux_bin = os.path.join(build_dir, 'linux') > - params.extend(['mem=1G', 'console=tty', 'kunit_shutdown=halt']) > + params.extend(['mem=1G', 'console=tty', 'kunit_shutdown=halt', 'rootfstype=tmpfs']) > return subprocess.Popen([linux_bin] + params, > stdin=subprocess.PIPE, > stdout=subprocess.PIPE, > -- > 2.44.0 >
On Fri, 1 Mar 2024 at 01:04, Mickaël Salaün <mic@digikod.net> wrote: > > Hi, > Thanks very much. I think there's a lot going on in this series, and it'd probably be easier to address if it were broken up a bit more. To take things one at a time: > This patch series moves KUnit test execution at the very end of kernel > initialization, just before launching the init process. This opens the > way to test any kernel code in its normal state (i.e. fully > initialized). I like the general idea here, but there are a few things to keep in mind: - We can already do this with tests built as modules. - We have explicit support for testing __init code, so if we want to keep that (and I think we do), we'll need to make sure that there remains a way to run tests before __init. - Behaviour changes here will need to be documented and tested well across all tests and architectures, so it's not something I'd want to land quickly. - The requirement to have a root filesystem set up is another thing we'll want to handle carefully. - As-is, the patch seems to break arm64. > > This patch series also teaches KUnit to handle kthread faults as errors, > and it brings a few related fixes and improvements. These seem very good overall. I want to look at the last location stuff in a bit more detail, but otherwise this is okay. Personally, I'd like to see this split out into a separate series, partly because I don't want to delay it while we sort the other parts of this series out, and partly because I have some other changes to the thread context stuff I think we need to make. > > New tests check NULL pointer dereference and read-only memory, which > wasn't possible before. These look interesting, but I don't like that they are listed as x86-specific. > > This is useful to test current kernel self-protection mechanisms or > future ones such as Heki: https://github.com/heki-linux > > Regards, Thanks again. I'll do a more detailed review of the individual patches next week, but I'm excited to see this overall. Cheers, -- David > > Mickaël Salaün (8): > kunit: Run tests when the kernel is fully setup > kunit: Handle thread creation error > kunit: Fix kthread reference > kunit: Fix timeout message > kunit: Handle test faults > kunit: Fix KUNIT_SUCCESS() calls in iov_iter tests > kunit: Print last test location on fault > kunit: Add tests for faults > > include/kunit/test.h | 24 +++++- > include/kunit/try-catch.h | 3 - > init/main.c | 4 +- > lib/bitfield_kunit.c | 8 +- > lib/checksum_kunit.c | 2 +- > lib/kunit/executor.c | 81 ++++++++++++++------ > lib/kunit/kunit-example-test.c | 6 +- > lib/kunit/kunit-test.c | 115 +++++++++++++++++++++++++++- > lib/kunit/try-catch.c | 33 +++++--- > lib/kunit_iov_iter.c | 70 ++++++++--------- > tools/testing/kunit/kunit_kernel.py | 6 +- > 11 files changed, 261 insertions(+), 91 deletions(-) > > > base-commit: d206a76d7d2726f3b096037f2079ce0bd3ba329b > -- > 2.44.0 >
On Fri, Mar 01, 2024 at 03:15:08PM +0800, David Gow wrote: > On Fri, 1 Mar 2024 at 01:04, Mickaël Salaün <mic@digikod.net> wrote: > > > > Hi, > > > > Thanks very much. I think there's a lot going on in this series, and > it'd probably be easier to address if it were broken up a bit more. > > To take things one at a time: > > > This patch series moves KUnit test execution at the very end of kernel > > initialization, just before launching the init process. This opens the > > way to test any kernel code in its normal state (i.e. fully > > initialized). > > I like the general idea here, but there are a few things to keep in mind: > - We can already do this with tests built as modules. > - We have explicit support for testing __init code, so if we want to > keep that (and I think we do), we'll need to make sure that there > remains a way to run tests before __init. > - Behaviour changes here will need to be documented and tested well > across all tests and architectures, so it's not something I'd want to > land quickly. > - The requirement to have a root filesystem set up is another thing > we'll want to handle carefully. > - As-is, the patch seems to break arm64. Fair, I'll remove this patch from the next series. > > > > > This patch series also teaches KUnit to handle kthread faults as errors, > > and it brings a few related fixes and improvements. > > These seem very good overall. I want to look at the last location > stuff in a bit more detail, but otherwise this is okay. Thanks! > > Personally, I'd like to see this split out into a separate series, > partly because I don't want to delay it while we sort the other parts > of this series out, and partly because I have some other changes to > the thread context stuff I think we need to make. I'll do that today. > > > > > New tests check NULL pointer dereference and read-only memory, which > > wasn't possible before. > > These look interesting, but I don't like that they are listed as x86-specific. I was reluctant to make it more broadly available because I only tested on x86... > > > > > This is useful to test current kernel self-protection mechanisms or > > future ones such as Heki: https://github.com/heki-linux > > > > Regards, > > Thanks again. I'll do a more detailed review of the individual patches > next week, but I'm excited to see this overall. Good, you'll review the v2 then. > > Cheers, > -- David > > > > > > Mickaël Salaün (8): > > kunit: Run tests when the kernel is fully setup > > kunit: Handle thread creation error > > kunit: Fix kthread reference > > kunit: Fix timeout message > > kunit: Handle test faults > > kunit: Fix KUNIT_SUCCESS() calls in iov_iter tests > > kunit: Print last test location on fault > > kunit: Add tests for faults > > > > include/kunit/test.h | 24 +++++- > > include/kunit/try-catch.h | 3 - > > init/main.c | 4 +- > > lib/bitfield_kunit.c | 8 +- > > lib/checksum_kunit.c | 2 +- > > lib/kunit/executor.c | 81 ++++++++++++++------ > > lib/kunit/kunit-example-test.c | 6 +- > > lib/kunit/kunit-test.c | 115 +++++++++++++++++++++++++++- > > lib/kunit/try-catch.c | 33 +++++--- > > lib/kunit_iov_iter.c | 70 ++++++++--------- > > tools/testing/kunit/kunit_kernel.py | 6 +- > > 11 files changed, 261 insertions(+), 91 deletions(-) > > > > > > base-commit: d206a76d7d2726f3b096037f2079ce0bd3ba329b > > -- > > 2.44.0 > >