If debug_regs.c is built with newer gcc, e.g., 8.3.1 on my side, then the generated
binary looks like over-optimized by gcc:
asm volatile("ss_start: "
"xor %%rax,%%rax\n\t"
"cpuid\n\t"
"movl $0x1a0,%%ecx\n\t"
"rdmsr\n\t"
: : : "rax", "ecx");
is translated to :
000000000040194e <ss_start>:
40194e: 31 c0 xor %eax,%eax <----- rax->eax?
401950: 0f a2 cpuid
401952: b9 a0 01 00 00 mov $0x1a0,%ecx
401957: 0f 32 rdmsr
As you can see rax is replaced with eax in taret binary code.
But if I replace %%rax with %%r8 or any GPR from r8~15, then I get below
expected binary:
0000000000401950 <ss_start>:
401950: 45 31 ff xor %r15d,%r15d
401953: 0f a2 cpuid
401955: b9 a0 01 00 00 mov $0x1a0,%ecx
40195a: 0f 32 rdmsr
The difference is the length of xor instruction(2 Byte vs 3 Byte),
so this makes below hard-coded instruction length cannot pass runtime check:
/* Instruction lengths starting at ss_start */
int ss_size[4] = {
3, /* xor */ <-------- 2 or 3?
2, /* cpuid */
5, /* mov */
2, /* rdmsr */
};
Note:
Use 8.2.1 or older gcc, it generates expected 3 bytes xor target code.
I use the default Makefile to build the binaries, and I cannot figure out why this
happens, so it comes this patch, maybe you have better solution to resolve the
issue. If you know how things work in this way, please let me know, thanks!
Below is the capture from my environments:
========================================================================
gcc (GCC) 8.3.1 20190223 (Red Hat 8.3.1-2)
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
0000000000401950 <ss_start>:
401950: 45 31 ff xor %r15d,%r15d
401953: 0f a2 cpuid
401955: b9 a0 01 00 00 mov $0x1a0,%ecx
40195a: 0f 32 rdmsr
000000000040194f <ss_start>:
40194f: 31 db xor %ebx,%ebx
401951: 0f a2 cpuid
401953: b9 a0 01 00 00 mov $0x1a0,%ecx
401958: 0f 32 rdmsr
000000000040194e <ss_start>:
40194e: 31 c0 xor %eax,%eax
401950: 0f a2 cpuid
401952: b9 a0 01 00 00 mov $0x1a0,%ecx
401957: 0f 32 rdmsr
==========================================================================
gcc (GCC) 8.2.1 20180905 (Red Hat 8.2.1-3)
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
0000000000401750 <ss_start>:
401750: 48 31 c0 xor %rax,%rax
401753: 0f a2 cpuid
401755: b9 a0 01 00 00 mov $0x1a0,%ecx
40175a: 0f 32 rdmsr
Signed-off-by: Yang Weijiang <weijiang.yang(a)intel.com>
---
tools/testing/selftests/kvm/x86_64/debug_regs.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/kvm/x86_64/debug_regs.c b/tools/testing/selftests/kvm/x86_64/debug_regs.c
index 8162c58a1234..74641cfa8ace 100644
--- a/tools/testing/selftests/kvm/x86_64/debug_regs.c
+++ b/tools/testing/selftests/kvm/x86_64/debug_regs.c
@@ -40,11 +40,11 @@ static void guest_code(void)
/* Single step test, covers 2 basic instructions and 2 emulated */
asm volatile("ss_start: "
- "xor %%rax,%%rax\n\t"
+ "xor %%r15,%%r15\n\t"
"cpuid\n\t"
"movl $0x1a0,%%ecx\n\t"
"rdmsr\n\t"
- : : : "rax", "ecx");
+ : : : "r15", "ecx");
/* DR6.BD test */
asm volatile("bd_start: mov %%dr0, %%rax" : : : "rax");
--
2.17.2
Hi Andrew,
This fixes an errno change for execve() of directories, noticed by Marc
Zyngier[1]. Along with the fix, include a regression test to avoid seeing
this return in the future.
Thanks!
-Kees
[1] https://lore.kernel.org/lkml/20200813151305.6191993b@why
Kees Cook (2):
exec: Restore EACCES of S_ISDIR execve()
selftests/exec: Add file type errno tests
fs/namei.c | 4 +-
tools/testing/selftests/exec/.gitignore | 1 +
tools/testing/selftests/exec/Makefile | 5 +-
tools/testing/selftests/exec/non-regular.c | 196 +++++++++++++++++++++
4 files changed, 203 insertions(+), 3 deletions(-)
create mode 100755 tools/testing/selftests/exec/non-regular.c
--
2.25.1
KUnit will fail tests upon observing a lockdep failure. Because lockdep
turns itself off after its first failure, only fail the first test and
warn users to not expect any future failures from lockdep.
Similar to lib/locking-selftest [1], we check if the status of
debug_locks has changed after the execution of a test case. However, we
do not reset lockdep afterwards.
Like the locking selftests, we also fix possible preemption count
corruption from lock bugs.
Depends on kunit: support failure from dynamic analysis tools [2]
[1] https://elixir.bootlin.com/linux/v5.7.12/source/lib/locking-selftest.c#L1137
[2] https://lore.kernel.org/linux-kselftest/20200806174326.3577537-1-urielguaja…
Signed-off-by: Uriel Guajardo <urielguajardo(a)google.com>
---
v2 Changes:
- Removed lockdep_reset
- Added warning to users about lockdep shutting off
---
lib/kunit/test.c | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/lib/kunit/test.c b/lib/kunit/test.c
index d8189d827368..7e477482457b 100644
--- a/lib/kunit/test.c
+++ b/lib/kunit/test.c
@@ -11,6 +11,7 @@
#include <linux/kref.h>
#include <linux/sched/debug.h>
#include <linux/sched.h>
+#include <linux/debug_locks.h>
#include "debugfs.h"
#include "string-stream.h"
@@ -22,6 +23,26 @@ void kunit_fail_current_test(void)
kunit_set_failure(current->kunit_test);
}
+static void kunit_check_locking_bugs(struct kunit *test,
+ unsigned long saved_preempt_count,
+ bool saved_debug_locks)
+{
+ preempt_count_set(saved_preempt_count);
+#ifdef CONFIG_TRACE_IRQFLAGS
+ if (softirq_count())
+ current->softirqs_enabled = 0;
+ else
+ current->softirqs_enabled = 1;
+#endif
+#if IS_ENABLED(CONFIG_LOCKDEP)
+ if (saved_debug_locks && !debug_locks) {
+ kunit_set_failure(test);
+ kunit_warn(test, "Dynamic analysis tool failure from LOCKDEP.");
+ kunit_warn(test, "Further tests will have LOCKDEP disabled.");
+ }
+#endif
+}
+
static void kunit_print_tap_version(void)
{
static bool kunit_has_printed_tap_version;
@@ -290,6 +311,9 @@ static void kunit_try_run_case(void *data)
struct kunit_suite *suite = ctx->suite;
struct kunit_case *test_case = ctx->test_case;
+ unsigned long saved_preempt_count = preempt_count();
+ bool saved_debug_locks = debug_locks;
+
current->kunit_test = test;
/*
@@ -298,7 +322,8 @@ static void kunit_try_run_case(void *data)
* thread will resume control and handle any necessary clean up.
*/
kunit_run_case_internal(test, suite, test_case);
- /* This line may never be reached. */
+ /* These lines may never be reached. */
+ kunit_check_locking_bugs(test, saved_preempt_count, saved_debug_locks);
kunit_run_case_cleanup(test, suite);
}
--
2.28.0.236.gb10cc79966-goog
This patchset contains everything needed to integrate KASAN and KUnit.
KUnit will be able to:
(1) Fail tests when an unexpected KASAN error occurs
(2) Pass tests when an expected KASAN error occurs
Convert KASAN tests to KUnit with the exception of copy_user_test
because KUnit is unable to test those.
Add documentation on how to run the KASAN tests with KUnit and what to
expect when running these tests.
This patchset depends on:
- "kunit: extend kunit resources API" [1]
- This is included in the KUnit 5.9-rci pull request[8]
Sorry for spamming you all with all these revisions.
I'd _really_ like to get this into 5.9 if possible: we also have some
other changes which depend on some things here.
Changes from v11:
- Rebased on top of latest -next (20200810)
- Fixed a redundant memchr() call in kasan_memchr()
- Added Andrey's "Tested-by" to everything.
Changes from v10:
- Fixed some whitespace issues in patch 2.
- Split out the renaming of the KUnit test suite into a separate patch.
Changes from v9:
- Rebased on top of linux-next (20200731) + kselftest/kunit and [7]
- Note that the kasan_rcu_uaf test has not been ported to KUnit, and
remains in test_kasan_module. This is because:
(a) KUnit's expect failure will not check if the RCU stacktraces
show.
(b) KUnit is unable to link the failure to the test, as it occurs in
an RCU callback.
Changes from v8:
- Rebased on top of kselftest/kunit
- (Which, with this patchset, should rebase cleanly on 5.8-rc7)
- Renamed the KUnit test suite, config name to patch the proposed
naming guidelines for KUnit tests[6]
Changes from v7:
- Rebased on top of kselftest/kunit
- Rebased on top of v4 of the kunit resources API[1]
- Rebased on top of v4 of the FORTIFY_SOURCE fix[2,3,4]
- Updated the Kconfig entry to support KUNIT_ALL_TESTS
Changes from v6:
- Rebased on top of kselftest/kunit
- Rebased on top of Daniel Axtens' fix for FORTIFY_SOURCE
incompatibilites [2]
- Removed a redundant report_enabled() check.
- Fixed some places with out of date Kconfig names in the
documentation.
Changes from v5:
- Split out the panic_on_warn changes to a separate patch.
- Fix documentation to fewer to the new Kconfig names.
- Fix some changes which were in the wrong patch.
- Rebase on top of kselftest/kunit (currently identical to 5.7-rc1)
Changes from v4:
- KASAN no longer will panic on errors if both panic_on_warn and
kasan_multishot are enabled.
- As a result, the KASAN tests will no-longer disable panic_on_warn.
- This also means panic_on_warn no-longer needs to be exported.
- The use of temporary "kasan_data" variables has been cleaned up
somewhat.
- A potential refcount/resource leak should multiple KASAN errors
appear during an assertion was fixed.
- Some wording changes to the KASAN test Kconfig entries.
Changes from v3:
- KUNIT_SET_KASAN_DATA and KUNIT_DO_EXPECT_KASAN_FAIL have been
combined and included in KUNIT_DO_EXPECT_KASAN_FAIL() instead.
- Reordered logic in kasan_update_kunit_status() in report.c to be
easier to read.
- Added comment to not use the name "kasan_data" for any kunit tests
outside of KUNIT_EXPECT_KASAN_FAIL().
Changes since v2:
- Due to Alan's changes in [1], KUnit can be built as a module.
- The name of the tests that could not be run with KUnit has been
changed to be more generic: test_kasan_module.
- Documentation on how to run the new KASAN tests and what to expect
when running them has been added.
- Some variables and functions are now static.
- Now save/restore panic_on_warn in a similar way to kasan_multi_shot
and renamed the init/exit functions to be more generic to accommodate.
- Due to [4] in kasan_strings, kasan_memchr, and
kasan_memcmp will fail if CONFIG_AMD_MEM_ENCRYPT is enabled so return
early and print message explaining this circumstance.
- Changed preprocessor checks to C checks where applicable.
Changes since v1:
- Make use of Alan Maguire's suggestion to use his patch that allows
static resources for integration instead of adding a new attribute to
the kunit struct
- All KUNIT_EXPECT_KASAN_FAIL statements are local to each test
- The definition of KUNIT_EXPECT_KASAN_FAIL is local to the
test_kasan.c file since it seems this is the only place this will
be used.
- Integration relies on KUnit being builtin
- copy_user_test has been separated into its own file since KUnit
is unable to test these. This can be run as a module just as before,
using CONFIG_TEST_KASAN_USER
- The addition to the current task has been separated into its own
patch as this is a significant enough change to be on its own.
[1] https://lore.kernel.org/linux-kselftest/CAFd5g46Uu_5TG89uOm0Dj5CMq+11cwjBns…
[2] https://lore.kernel.org/linux-mm/20200424145521.8203-1-dja@axtens.net/
[3] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?…
[4] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?…
[5] https://bugzilla.kernel.org/show_bug.cgi?id=206337
[6] https://lore.kernel.org/linux-kselftest/20200620054944.167330-1-davidgow@go…
[7] https://lkml.org/lkml/2020/7/31/571
[8] https://lore.kernel.org/linux-kselftest/8d43e88e-1356-cd63-9152-209b81b1674…
David Gow (2):
kasan: test: Make KASAN KUnit test comply with naming guidelines
mm: kasan: Do not panic if both panic_on_warn and kasan_multishot set
Patricia Alfonso (4):
Add KUnit Struct to Current Task
KUnit: KASAN Integration
KASAN: Port KASAN Tests to KUnit
KASAN: Testing Documentation
Documentation/dev-tools/kasan.rst | 70 +++
include/kunit/test.h | 5 +
include/linux/kasan.h | 6 +
include/linux/sched.h | 4 +
lib/Kconfig.kasan | 22 +-
lib/Makefile | 7 +-
lib/kasan_kunit.c | 769 +++++++++++++++++++++++++
lib/kunit/test.c | 13 +-
lib/test_kasan.c | 903 ------------------------------
lib/test_kasan_module.c | 111 ++++
mm/kasan/report.c | 34 +-
11 files changed, 1027 insertions(+), 917 deletions(-)
create mode 100644 lib/kasan_kunit.c
delete mode 100644 lib/test_kasan.c
create mode 100644 lib/test_kasan_module.c
--
2.28.0.236.gb10cc79966-goog
From: Uriel Guajardo <urielguajardo(a)google.com>
KUnit tests will now fail if lockdep detects an error during a test
case.
The idea comes from how lib/locking-selftest [1] checks for lock errors: we
first if lock debugging is turned on. If not, an error must have
occurred, so we fail the test and restart lockdep for the next test case.
Like the locking selftests, we also fix possible preemption count
corruption from lock bugs.
Depends on kunit: support failure from dynamic analysis tools [2]
[1] https://elixir.bootlin.com/linux/v5.7.12/source/lib/locking-selftest.c#L1137
[2] https://lore.kernel.org/linux-kselftest/20200806174326.3577537-1-urielguaja…
Signed-off-by: Uriel Guajardo <urielguajardo(a)google.com>
---
lib/kunit/test.c | 26 +++++++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/lib/kunit/test.c b/lib/kunit/test.c
index d8189d827368..0838ececa005 100644
--- a/lib/kunit/test.c
+++ b/lib/kunit/test.c
@@ -11,6 +11,8 @@
#include <linux/kref.h>
#include <linux/sched/debug.h>
#include <linux/sched.h>
+#include <linux/lockdep.h>
+#include <linux/debug_locks.h>
#include "debugfs.h"
#include "string-stream.h"
@@ -22,6 +24,26 @@ void kunit_fail_current_test(void)
kunit_set_failure(current->kunit_test);
}
+static inline void kunit_check_locking_bugs(struct kunit *test,
+ unsigned long saved_preempt_count)
+{
+ preempt_count_set(saved_preempt_count);
+#ifdef CONFIG_TRACE_IRQFLAGS
+ if (softirq_count())
+ current->softirqs_enabled = 0;
+ else
+ current->softirqs_enabled = 1;
+#endif
+#if IS_ENABLED(CONFIG_LOCKDEP)
+ local_irq_disable();
+ if (!debug_locks) {
+ kunit_set_failure(test);
+ lockdep_reset();
+ }
+ local_irq_enable();
+#endif
+}
+
static void kunit_print_tap_version(void)
{
static bool kunit_has_printed_tap_version;
@@ -289,6 +311,7 @@ static void kunit_try_run_case(void *data)
struct kunit *test = ctx->test;
struct kunit_suite *suite = ctx->suite;
struct kunit_case *test_case = ctx->test_case;
+ unsigned long saved_preempt_count = preempt_count();
current->kunit_test = test;
@@ -298,7 +321,8 @@ static void kunit_try_run_case(void *data)
* thread will resume control and handle any necessary clean up.
*/
kunit_run_case_internal(test, suite, test_case);
- /* This line may never be reached. */
+ /* These lines may never be reached. */
+ kunit_check_locking_bugs(test, saved_preempt_count);
kunit_run_case_cleanup(test, suite);
}
--
2.28.0.236.gb10cc79966-goog
Currently kunit_tool does not work correctly when executed from a path
outside of the kernel tree, so make sure that the current working
directory is correct and the kunit_dir is properly initialized before
running.
Signed-off-by: Brendan Higgins <brendanhiggins(a)google.com>
---
tools/testing/kunit/kunit.py | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/tools/testing/kunit/kunit.py b/tools/testing/kunit/kunit.py
index 425ef40067e7..96344a11ff1f 100755
--- a/tools/testing/kunit/kunit.py
+++ b/tools/testing/kunit/kunit.py
@@ -237,9 +237,14 @@ def main(argv, linux=None):
cli_args = parser.parse_args(argv)
+ if get_kernel_root_path():
+ print('cd ' + get_kernel_root_path())
+ os.chdir(get_kernel_root_path())
+
if cli_args.subcommand == 'run':
if not os.path.exists(cli_args.build_dir):
os.mkdir(cli_args.build_dir)
+ create_default_kunitconfig()
if not linux:
linux = kunit_kernel.LinuxSourceTree()
@@ -257,6 +262,7 @@ def main(argv, linux=None):
if cli_args.build_dir:
if not os.path.exists(cli_args.build_dir):
os.mkdir(cli_args.build_dir)
+ create_default_kunitconfig()
if not linux:
linux = kunit_kernel.LinuxSourceTree()
@@ -273,6 +279,7 @@ def main(argv, linux=None):
if cli_args.build_dir:
if not os.path.exists(cli_args.build_dir):
os.mkdir(cli_args.build_dir)
+ create_default_kunitconfig()
if not linux:
linux = kunit_kernel.LinuxSourceTree()
@@ -291,6 +298,7 @@ def main(argv, linux=None):
if cli_args.build_dir:
if not os.path.exists(cli_args.build_dir):
os.mkdir(cli_args.build_dir)
+ create_default_kunitconfig()
if not linux:
linux = kunit_kernel.LinuxSourceTree()
base-commit: 30185b69a2d533c4ba6ca926b8390ce7de495e29
--
2.28.0.236.gb10cc79966-goog