One of the desirable features in security is the ability to restrict import
of data to a given system based on data authenticity. If data import can be
restricted, it would be possible to enforce a system-wide policy based on
the signing keys the system owner trusts.
This feature is widely used in the kernel. For example, if the restriction
is enabled, kernel modules can be plugged in only if they are signed with a
key whose public part is in the primary or secondary keyring.
For eBPF, it can be useful as well. For example, it might be useful to
authenticate data an eBPF program makes security decisions on.
After a discussion in the eBPF mailing list, it was decided that the stated
goal should be accomplished by introducing a new helper:
bpf_verify_pkcs7_signature(), dedicated to verify PKCS#7 signatures. More
helpers will be introduced later, as necessary.
The job of bpf_verify_pkcs7_signature() is simply to call the corresponding
signature verification function verify_pkcs7_signature(). Data and
signature can be provided to the new helper with two dynamic pointers, to
reduce the number of parameters.
The keyring can be provided from its serial number, with the new helper
bpf_lookup_user_key(). Since it acquires a reference of the found key, the
corresponding release helper bpf_key_put() has been introduced to decrement
the reference count. The eBPF verifier has been enhanced to ensure that the
key reference count is always decreased, when incremented, or otherwise it
refuses to load the program. This ability is being verified with the
lookup_user_key_norelease test.
While the new helpers provide great flexibility, they seem to be suboptimal
in terms of security guarantees. If the goal is to do signature
verification with system-provided keys (e.g. from the built-in keyring),
the eBPF program would have to rely on the user space counterpart to search
the correct keyring and to pass its serial. If only the eBPF program is
signed and verified, there is not certainty that this operation is done
correctly by unverified code.
Instead, since verify_pkcs7_signature() understands a pre-determined set of
struct key pointer values, which translates into the corresponding system
keyrings, the keyring ID parameter has been added as well to the eBPF
helper. It is considered only if the passed struct key pointer is NULL.
That would guaranteed, assuming that the keyring ID is hardcoded, that
signature verification is always done with the desired keys.
The introduced helpers can be called only from sleepable programs, because
of memory allocation (with key flag KEY_LOOKUP_CREATE) and crypto
operations. For example, the lsm.s/bpf attach point is suitable,
fexit/array_map_update_elem is not.
A test was added to check the ability of bpf_verify_pkcs7_signature() to
verify PKCS#7 signatures from the session keyring, a newly-created keyring,
and from the secondary keyring (taking an existing kernel module for the
verification). The test does not fail if a suitable kernel module is not
found (needs support from the CI).
The patch set is organized as follows.
Patch 1 exports bpf_dynptr_get_size(), to obtain the real size of data
carried by a dynamic pointer. Patch 2 introduces the
bpf_lookup_user_key() and bpf_key_put() helpers. Patch 3 introduces the
bpf_verify_pkcs7_signature() helper. Patches 4 and 5 respectively add the
test for the first and the last helper.
Changelog
v4:
- Remove bpf_request_key_by_id(), don't return an invalid pointer that
other helpers can use
- Pass the keyring ID (without ULONG_MAX, suggested by Alexei) to
bpf_verify_pkcs7_signature()
- Introduce bpf_lookup_user_key() and bpf_key_put() helpers (suggested by
Alexei)
- Add lookup_key_norelease test, to ensure that the verifier blocks eBPF
programs which don't decrement the key reference count
- Parse raw PKCS#7 signature instead of module-style signature in the
verify_pkcs7_signature test (suggested by Alexei)
- Parse kernel module in user space and pass raw PKCS#7 signature to the
eBPF program for signature verification
v3:
- Rename bpf_verify_signature() back to bpf_verify_pkcs7_signature() to
avoid managing different parameters for each signature verification
function in one helper (suggested by Daniel)
- Use dynamic pointers and export bpf_dynptr_get_size() (suggested by
Alexei)
- Introduce bpf_request_key_by_id() to give more flexibility to the caller
of bpf_verify_pkcs7_signature() to retrieve the appropriate keyring
(suggested by Alexei)
- Fix test by reordering the gcc command line, always compile sign-file
- Improve helper support check mechanism in the test
v2:
- Rename bpf_verify_pkcs7_signature() to a more generic
bpf_verify_signature() and pass the signature type (suggested by KP)
- Move the helper and prototype declaration under #ifdef so that user
space can probe for support for the helper (suggested by Daniel)
- Describe better the keyring types (suggested by Daniel)
- Include linux/bpf.h instead of vmlinux.h to avoid implicit or
redeclaration
- Make the test selfcontained (suggested by Alexei)
v1:
- Don't define new map flag but introduce simple wrapper of
verify_pkcs7_signature() (suggested by Alexei and KP)
Roberto Sassu (5):
bpf: Export bpf_dynptr_get_size()
bpf: Add bpf_lookup_user_key() and bpf_key_put() helpers
bpf: Add bpf_verify_pkcs7_signature() helper
selftests/bpf: Add test for unreleased key references
selftests/bpf: Add test for bpf_verify_pkcs7_signature() helper
include/linux/bpf.h | 1 +
include/uapi/linux/bpf.h | 33 ++
kernel/bpf/bpf_lsm.c | 85 +++++
kernel/bpf/helpers.c | 2 +-
kernel/bpf/verifier.c | 6 +-
scripts/bpf_doc.py | 2 +
tools/include/uapi/linux/bpf.h | 33 ++
tools/testing/selftests/bpf/Makefile | 14 +-
tools/testing/selftests/bpf/config | 2 +
.../prog_tests/lookup_user_key_norelease.c | 52 +++
.../bpf/prog_tests/verify_pkcs7_sig.c | 341 ++++++++++++++++++
.../progs/test_lookup_user_key_norelease.c | 24 ++
.../bpf/progs/test_verify_pkcs7_sig.c | 90 +++++
.../testing/selftests/bpf/verify_sig_setup.sh | 104 ++++++
14 files changed, 783 insertions(+), 6 deletions(-)
create mode 100644 tools/testing/selftests/bpf/prog_tests/lookup_user_key_norelease.c
create mode 100644 tools/testing/selftests/bpf/prog_tests/verify_pkcs7_sig.c
create mode 100644 tools/testing/selftests/bpf/progs/test_lookup_user_key_norelease.c
create mode 100644 tools/testing/selftests/bpf/progs/test_verify_pkcs7_sig.c
create mode 100755 tools/testing/selftests/bpf/verify_sig_setup.sh
--
2.25.1
It's come up a few times that it would be useful to have --kunitconfig
be repeatable [1][2].
This could be done before with a bit of shell-fu, e.g.
$ find fs/ -name '.kunitconfig' -exec cat {} + | \
./tools/testing/kunit/kunit.py run --kunitconfig=/dev/stdin
or equivalently:
$ cat fs/ext4/.kunitconfig fs/fat/.kunitconfig | \
./tools/testing/kunit/kunit.py run --kunitconfig=/dev/stdin
But this can be fairly clunky to use in practice.
And having explicit support in kunit.py opens the door to having more
config fragments of interest, e.g. options for PCI on UML [1], UML
coverage [2], variants of tests [3].
There's another argument to be made that users can just use multiple
--kconfig_add's, but this gets very clunky very fast (e.g. [2]).
Note: there's a big caveat here that some kconfig options might be
incompatible. We try to give a clearish error message in the simple case
where the same option appears multiple times with conflicting values,
but more subtle ones (e.g. mutually exclusive options) will be
potentially very confusing for the user. I don't know we can do better.
Note 2: if you want to combine a --kunitconfig with the default, you
either have to do to specify the current build_dir
> --kunitconfig=.kunit --kunitconfig=additional.config
or
> --kunitconfig=tools/testing/kunit/configs/default.config --kunitconifg=additional.config
each of which have their downsides (former depends on --build_dir,
doesn't work if you don't have a .kunitconfig yet), etc.
Example with conflicting values:
> $ ./tools/testing/kunit/kunit.py config --kunitconfig=lib/kunit --kunitconfig=/dev/stdin <<EOF
> CONFIG_KUNIT_TEST=n
> CONFIG_KUNIT=m
> EOF
> ...
> kunit_kernel.ConfigError: Multiple values specified for 2 options in kunitconfig:
> CONFIG_KUNIT=y
> vs from /dev/stdin
> CONFIG_KUNIT=m
>
> CONFIG_KUNIT_TEST=y
> vs from /dev/stdin
> # CONFIG_KUNIT_TEST is not set
[1] https://lists.freedesktop.org/archives/dri-devel/2022-June/357616.html
[2] https://lore.kernel.org/linux-kselftest/CAFd5g45f3X3xF2vz2BkTHRqOC4uW6GZxtU…
[3] https://lore.kernel.org/linux-kselftest/CANpmjNOdSy6DuO6CYZ4UxhGxqhjzx4tn0s…
Signed-off-by: Daniel Latypov <dlatypov(a)google.com>
---
NOTE: this series is based on https://lore.kernel.org/linux-kselftest/20220520224200.3764027-1-dlatypov@g…
That patch redoes kunitconfig parsing, so we'd have merge conflicts
either way we order these.
---
tools/testing/kunit/kunit.py | 13 ++++---
tools/testing/kunit/kunit_config.py | 11 +++++-
tools/testing/kunit/kunit_kernel.py | 38 ++++++++++++------
tools/testing/kunit/kunit_tool_test.py | 54 +++++++++++++++++++++++---
4 files changed, 91 insertions(+), 25 deletions(-)
diff --git a/tools/testing/kunit/kunit.py b/tools/testing/kunit/kunit.py
index 13bd72e47da8..163f6b8ac464 100755
--- a/tools/testing/kunit/kunit.py
+++ b/tools/testing/kunit/kunit.py
@@ -291,8 +291,9 @@ def add_common_opts(parser) -> None:
parser.add_argument('--kunitconfig',
help='Path to Kconfig fragment that enables KUnit tests.'
' If given a directory, (e.g. lib/kunit), "/.kunitconfig" '
- 'will get automatically appended.',
- metavar='PATH')
+ 'will get automatically appended. If repeated, the files '
+ 'blindly concatenated, which might not work in all cases.',
+ action='append', metavar='PATHS')
parser.add_argument('--kconfig_add',
help='Additional Kconfig options to append to the '
'.kunitconfig, e.g. CONFIG_KASAN=y. Can be repeated.',
@@ -414,7 +415,7 @@ def main(argv, linux=None):
if not linux:
linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir,
- kunitconfig_path=cli_args.kunitconfig,
+ kunitconfig_paths=cli_args.kunitconfig,
kconfig_add=cli_args.kconfig_add,
arch=cli_args.arch,
cross_compile=cli_args.cross_compile,
@@ -440,7 +441,7 @@ def main(argv, linux=None):
if not linux:
linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir,
- kunitconfig_path=cli_args.kunitconfig,
+ kunitconfig_paths=cli_args.kunitconfig,
kconfig_add=cli_args.kconfig_add,
arch=cli_args.arch,
cross_compile=cli_args.cross_compile,
@@ -457,7 +458,7 @@ def main(argv, linux=None):
elif cli_args.subcommand == 'build':
if not linux:
linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir,
- kunitconfig_path=cli_args.kunitconfig,
+ kunitconfig_paths=cli_args.kunitconfig,
kconfig_add=cli_args.kconfig_add,
arch=cli_args.arch,
cross_compile=cli_args.cross_compile,
@@ -476,7 +477,7 @@ def main(argv, linux=None):
elif cli_args.subcommand == 'exec':
if not linux:
linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir,
- kunitconfig_path=cli_args.kunitconfig,
+ kunitconfig_paths=cli_args.kunitconfig,
kconfig_add=cli_args.kconfig_add,
arch=cli_args.arch,
cross_compile=cli_args.cross_compile,
diff --git a/tools/testing/kunit/kunit_config.py b/tools/testing/kunit/kunit_config.py
index 89443400b17e..05b129030c6e 100644
--- a/tools/testing/kunit/kunit_config.py
+++ b/tools/testing/kunit/kunit_config.py
@@ -8,7 +8,7 @@
from dataclasses import dataclass
import re
-from typing import Dict, Iterable, Set
+from typing import Dict, Iterable, List, Set, Tuple
CONFIG_IS_NOT_SET_PATTERN = r'^# CONFIG_(\w+) is not set$'
CONFIG_PATTERN = r'^CONFIG_(\w+)=(\S+|".*")$'
@@ -64,6 +64,15 @@ class Kconfig:
def set_diff(self, other: 'Kconfig') -> Set[KconfigEntry]:
return set(self._as_entries()) - set(other._as_entries())
+ def differing_options(self, other: 'Kconfig') -> List[Tuple[KconfigEntry, KconfigEntry]]:
+ diff = [] # type: List[Tuple[KconfigEntry, KconfigEntry]]
+ for name, value in self._entries.items():
+ b = other._entries.get(name)
+ if b and value != b:
+ pair = (KconfigEntry(name, value), KconfigEntry(name, b))
+ diff.append(pair)
+ return diff
+
def merge_in_entries(self, other: 'Kconfig') -> None:
for name, value in other._entries.items():
self._entries[name] = value
diff --git a/tools/testing/kunit/kunit_kernel.py b/tools/testing/kunit/kunit_kernel.py
index 6d994bb24999..fc415ff7530e 100644
--- a/tools/testing/kunit/kunit_kernel.py
+++ b/tools/testing/kunit/kunit_kernel.py
@@ -176,6 +176,30 @@ def get_kunitconfig_path(build_dir: str) -> str:
def get_old_kunitconfig_path(build_dir: str) -> str:
return os.path.join(build_dir, OLD_KUNITCONFIG_PATH)
+def get_parsed_kunitconfig(build_dir: str,
+ kunitconfig_paths: Optional[List[str]]=None) -> kunit_config.Kconfig:
+ if not kunitconfig_paths:
+ path = get_kunitconfig_path(build_dir)
+ if not os.path.exists(path):
+ shutil.copyfile(DEFAULT_KUNITCONFIG_PATH, path)
+ return kunit_config.parse_file(path)
+
+ merged = kunit_config.Kconfig()
+
+ for path in kunitconfig_paths:
+ if os.path.isdir(path):
+ path = os.path.join(path, KUNITCONFIG_PATH)
+ if not os.path.exists(path):
+ raise ConfigError(f'Specified kunitconfig ({path}) does not exist')
+
+ partial = kunit_config.parse_file(path)
+ diff = merged.differing_options(partial)
+ if diff:
+ diff_str = '\n\n'.join(f'{a}\n vs from {path}\n{b}' for a, b in diff)
+ raise ConfigError(f'Multiple values specified for {len(diff)} options in kunitconfig:\n{diff_str}')
+ merged.merge_in_entries(partial)
+ return merged
+
def get_outfile_path(build_dir: str) -> str:
return os.path.join(build_dir, OUTFILE_PATH)
@@ -221,7 +245,7 @@ class LinuxSourceTree:
self,
build_dir: str,
load_config=True,
- kunitconfig_path='',
+ kunitconfig_paths: Optional[List[str]]=None,
kconfig_add: Optional[List[str]]=None,
arch=None,
cross_compile=None,
@@ -237,17 +261,7 @@ class LinuxSourceTree:
if not load_config:
return
- if kunitconfig_path:
- if os.path.isdir(kunitconfig_path):
- kunitconfig_path = os.path.join(kunitconfig_path, KUNITCONFIG_PATH)
- if not os.path.exists(kunitconfig_path):
- raise ConfigError(f'Specified kunitconfig ({kunitconfig_path}) does not exist')
- else:
- kunitconfig_path = get_kunitconfig_path(build_dir)
- if not os.path.exists(kunitconfig_path):
- shutil.copyfile(DEFAULT_KUNITCONFIG_PATH, kunitconfig_path)
-
- self._kconfig = kunit_config.parse_file(kunitconfig_path)
+ self._kconfig = get_parsed_kunitconfig(build_dir, kunitconfig_paths)
if kconfig_add:
kconfig = kunit_config.parse_from_string('\n'.join(kconfig_add))
self._kconfig.merge_in_entries(kconfig)
diff --git a/tools/testing/kunit/kunit_tool_test.py b/tools/testing/kunit/kunit_tool_test.py
index 3a8f638ff092..e21ae1331350 100755
--- a/tools/testing/kunit/kunit_tool_test.py
+++ b/tools/testing/kunit/kunit_tool_test.py
@@ -356,17 +356,46 @@ class LinuxSourceTreeTest(unittest.TestCase):
def test_invalid_kunitconfig(self):
with self.assertRaisesRegex(kunit_kernel.ConfigError, 'nonexistent.* does not exist'):
- kunit_kernel.LinuxSourceTree('', kunitconfig_path='/nonexistent_file')
+ kunit_kernel.LinuxSourceTree('', kunitconfig_paths=['/nonexistent_file'])
def test_valid_kunitconfig(self):
with tempfile.NamedTemporaryFile('wt') as kunitconfig:
- kunit_kernel.LinuxSourceTree('', kunitconfig_path=kunitconfig.name)
+ kunit_kernel.LinuxSourceTree('', kunitconfig_paths=[kunitconfig.name])
def test_dir_kunitconfig(self):
with tempfile.TemporaryDirectory('') as dir:
with open(os.path.join(dir, '.kunitconfig'), 'w'):
pass
- kunit_kernel.LinuxSourceTree('', kunitconfig_path=dir)
+ kunit_kernel.LinuxSourceTree('', kunitconfig_paths=[dir])
+
+ def test_multiple_kunitconfig(self):
+ want_kconfig = kunit_config.Kconfig()
+ want_kconfig.add_entry('KUNIT', 'y')
+ want_kconfig.add_entry('KUNIT_TEST', 'm')
+
+ with tempfile.TemporaryDirectory('') as dir:
+ other = os.path.join(dir, 'otherkunitconfig')
+ with open(os.path.join(dir, '.kunitconfig'), 'w') as f:
+ f.write('CONFIG_KUNIT=y')
+ with open(other, 'w') as f:
+ f.write('CONFIG_KUNIT_TEST=m')
+ pass
+
+ tree = kunit_kernel.LinuxSourceTree('', kunitconfig_paths=[dir, other])
+ self.assertFalse(want_kconfig.set_diff(tree._kconfig))
+
+
+ def test_multiple_kunitconfig_invalid(self):
+ with tempfile.TemporaryDirectory('') as dir:
+ other = os.path.join(dir, 'otherkunitconfig')
+ with open(os.path.join(dir, '.kunitconfig'), 'w') as f:
+ f.write('CONFIG_KUNIT=y')
+ with open(other, 'w') as f:
+ f.write('CONFIG_KUNIT=m')
+
+ with self.assertRaisesRegex(kunit_kernel.ConfigError, '(?s)Multiple values.*CONFIG_KUNIT'):
+ kunit_kernel.LinuxSourceTree('', kunitconfig_paths=[dir, other])
+
def test_kconfig_add(self):
want_kconfig = kunit_config.Kconfig()
@@ -637,7 +666,7 @@ class KUnitMainTest(unittest.TestCase):
kunit.main(['run', '--kunitconfig=mykunitconfig'])
# Just verify that we parsed and initialized it correctly here.
mock_linux_init.assert_called_once_with('.kunit',
- kunitconfig_path='mykunitconfig',
+ kunitconfig_paths=['mykunitconfig'],
kconfig_add=None,
arch='um',
cross_compile=None,
@@ -649,19 +678,32 @@ class KUnitMainTest(unittest.TestCase):
kunit.main(['config', '--kunitconfig=mykunitconfig'])
# Just verify that we parsed and initialized it correctly here.
mock_linux_init.assert_called_once_with('.kunit',
- kunitconfig_path='mykunitconfig',
+ kunitconfig_paths=['mykunitconfig'],
kconfig_add=None,
arch='um',
cross_compile=None,
qemu_config_path=None)
+ @mock.patch.object(kunit_kernel, 'LinuxSourceTree')
+ def test_run_multiple_kunitconfig(self, mock_linux_init):
+ mock_linux_init.return_value = self.linux_source_mock
+ kunit.main(['run', '--kunitconfig=mykunitconfig', '--kunitconfig=other'])
+ # Just verify that we parsed and initialized it correctly here.
+ mock_linux_init.assert_called_once_with('.kunit',
+ kunitconfig_paths=['mykunitconfig', 'other'],
+ kconfig_add=None,
+ arch='um',
+ cross_compile=None,
+ qemu_config_path=None)
+
+
@mock.patch.object(kunit_kernel, 'LinuxSourceTree')
def test_run_kconfig_add(self, mock_linux_init):
mock_linux_init.return_value = self.linux_source_mock
kunit.main(['run', '--kconfig_add=CONFIG_KASAN=y', '--kconfig_add=CONFIG_KCSAN=y'])
# Just verify that we parsed and initialized it correctly here.
mock_linux_init.assert_called_once_with('.kunit',
- kunitconfig_path=None,
+ kunitconfig_paths=None,
kconfig_add=['CONFIG_KASAN=y', 'CONFIG_KCSAN=y'],
arch='um',
cross_compile=None,
--
2.37.0.rc0.104.g0611611a94-goog
EFI still has two ways of exposing EFI variable to user space: the
original sysfs interface and the efivarfs pseudo-filesystem that
supersedes it, and which was introduced almost 10 years ago.
As a preparatory step towards refactoring the underlying infrastructure
shared between efivarfs and efi-pstore, I would like to finally get rid
of the sysfs interface which also uses that, but which is only enabled
on x86 and Itanium.
Cc: Matthew Garrett <mjg59(a)srcf.ucam.org>
Cc: Peter Jones <pjones(a)redhat.com>
Cc: Tony Luck <tony.luck(a)intel.com>
Cc: Kees Cook <keescook(a)chromium.org>
Cc: Thomas Gleixner <tglx(a)linutronix.de>
Cc: Ingo Molnar <mingo(a)redhat.com>
Cc: Borislav Petkov <bp(a)alien8.de>
Cc: Dave Hansen <dave.hansen(a)linux.intel.com>
Cc: linux-kselftest(a)vger.kernel.org
Ard Biesheuvel (2):
selftests/kexec: remove broken EFI_VARS secure boot fallback check
efi: remove deprecated 'efivars' sysfs interface
Documentation/x86/x86_64/uefi.rst | 2 +-
arch/arm/configs/milbeaut_m10v_defconfig | 1 -
arch/ia64/configs/bigsur_defconfig | 1 -
arch/ia64/configs/generic_defconfig | 1 -
arch/ia64/configs/gensparse_defconfig | 1 -
arch/ia64/configs/tiger_defconfig | 1 -
arch/ia64/configs/zx1_defconfig | 1 -
arch/x86/configs/i386_defconfig | 1 -
arch/x86/configs/x86_64_defconfig | 1 -
drivers/firmware/efi/Kconfig | 12 -
drivers/firmware/efi/Makefile | 1 -
drivers/firmware/efi/efivars.c | 671 --------------------
tools/testing/selftests/kexec/kexec_common_lib.sh | 36 +-
13 files changed, 3 insertions(+), 727 deletions(-)
delete mode 100644 drivers/firmware/efi/efivars.c
--
2.35.1
Hardware would directly write x2APIC ICR register instead of software
emulation in some circumstances, e.g when Intel IPI virtualization is
enabled. This behavior requires normal reserved bits checking to ensure
them input as zero, otherwise it will cause #GP. So we need mask out
those reserved bits from the data written to vICR register.
Remove Delivery Status bit emulation in test case as this flag
is invalid and not needed in x2APIC mode. KVM may ignore clearing
it during interrupt dispatch which will lead to fake test failure.
Opportunstically correct vector number for test sending IPI to
non-existent vCPUs.
Signed-off-by: Zeng Guang <guang.zeng(a)intel.com>
---
.../selftests/kvm/x86_64/xapic_state_test.c | 20 ++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/kvm/x86_64/xapic_state_test.c b/tools/testing/selftests/kvm/x86_64/xapic_state_test.c
index 0792334ba243..df916c6f53f9 100644
--- a/tools/testing/selftests/kvm/x86_64/xapic_state_test.c
+++ b/tools/testing/selftests/kvm/x86_64/xapic_state_test.c
@@ -70,13 +70,27 @@ static void ____test_icr(struct kvm_vm *vm, struct kvm_vcpu *vcpu, uint64_t val)
vcpu_ioctl(vm, vcpu->id, KVM_GET_LAPIC, &xapic);
icr = (u64)(*((u32 *)&xapic.regs[APIC_ICR])) |
(u64)(*((u32 *)&xapic.regs[APIC_ICR2])) << 32;
- if (!vcpu->is_x2apic)
+ if (!vcpu->is_x2apic) {
val &= (-1u | (0xffull << (32 + 24)));
- ASSERT_EQ(icr, val & ~APIC_ICR_BUSY);
+ ASSERT_EQ(icr, val & ~APIC_ICR_BUSY);
+ } else {
+ ASSERT_EQ(icr & ~APIC_ICR_BUSY, val & ~APIC_ICR_BUSY);
+ }
}
+#define X2APIC_RSVED_BITS_MASK (GENMASK_ULL(31,20) | \
+ GENMASK_ULL(17,16) | \
+ GENMASK_ULL(13,13))
+
static void __test_icr(struct kvm_vm *vm, struct kvm_vcpu *vcpu, uint64_t val)
{
+ if (vcpu->is_x2apic) {
+ /* Hardware writing vICR register requires reserved bits 31:20,
+ * 17:16 and 13 kept as zero to avoid #GP exception. Data value
+ * written to vICR should mask out those bits above.
+ */
+ val &= ~X2APIC_RSVED_BITS_MASK;
+ }
____test_icr(vm, vcpu, val | APIC_ICR_BUSY);
____test_icr(vm, vcpu, val & ~(u64)APIC_ICR_BUSY);
}
@@ -100,7 +114,7 @@ static void test_icr(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
icr = APIC_INT_ASSERT | 0xff;
for (i = vcpu->id + 1; i < 0xff; i++) {
for (j = 0; j < 8; j++)
- __test_icr(vm, vcpu, i << (32 + 24) | APIC_INT_ASSERT | (j << 8));
+ __test_icr(vm, vcpu, i << (32 + 24) | icr | (j << 8));
}
/* And again with a shorthand destination for all types of IPIs. */
--
2.27.0
There are several tests which depend on PCI, and hence need a bunch of
extra options to run under UML. This makes it awkward to give
configuration instructions (whether in documentation, or as part of a
.kunitconfig file), as two separate, incompatible sets of config options
are required for UML and "most other architectures".
For non-UML architectures, it's possible to add default kconfig options
via the qemu_config python files, but there's no equivalent for UML. Add
a new tools/testing/kunit/configs/arch_uml.config file containing extra
kconfig options to use on UML.
Signed-off-by: David Gow <davidgow(a)google.com>
---
It's really ugly to have to type:
--kconfig_add CONFIG_VIRTIO_UML=y
--kconfig_add CONFIG_UML_PCI_OVER_VIRTIO=y
when running many tests under UML, particularly since it isn't required
on other architectures.
This came up in discussion with Daniel this morning, and while the
ability to repeat the --kunitconfig flag would go some way to alleviate
this, having to add:
--kunitconfig ./tools/testing/kunit/config/uml_pci.kunitconfig
isn't all that much better.
So it seems like adding something by default would be nice.
This implementation is not perfect (in particular, there's no easy way
of _disabling_ these options now, though [1] probably will help). The
'arch_uml.config' filename can be bikeshedded, too.
Thoughts?
---
tools/testing/kunit/configs/arch_uml.config | 5 +++++
tools/testing/kunit/kunit_kernel.py | 11 ++++++++---
2 files changed, 13 insertions(+), 3 deletions(-)
create mode 100644 tools/testing/kunit/configs/arch_uml.config
diff --git a/tools/testing/kunit/configs/arch_uml.config b/tools/testing/kunit/configs/arch_uml.config
new file mode 100644
index 000000000000..e824ce43b05a
--- /dev/null
+++ b/tools/testing/kunit/configs/arch_uml.config
@@ -0,0 +1,5 @@
+# Config options which are added to UML builds by default
+
+# Enable virtio/pci, as a lot of tests require it.
+CONFIG_VIRTIO_UML=y
+CONFIG_UML_PCI_OVER_VIRTIO=y
diff --git a/tools/testing/kunit/kunit_kernel.py b/tools/testing/kunit/kunit_kernel.py
index 3539efaf99ba..05e7b1e188d7 100644
--- a/tools/testing/kunit/kunit_kernel.py
+++ b/tools/testing/kunit/kunit_kernel.py
@@ -26,6 +26,7 @@ KUNITCONFIG_PATH = '.kunitconfig'
OLD_KUNITCONFIG_PATH = 'last_used_kunitconfig'
DEFAULT_KUNITCONFIG_PATH = 'tools/testing/kunit/configs/default.config'
BROKEN_ALLCONFIG_PATH = 'tools/testing/kunit/configs/broken_on_uml.config'
+UML_KCONFIG_PATH = 'tools/testing/kunit/configs/arch_uml.config'
OUTFILE_PATH = 'test.log'
ABS_TOOL_PATH = os.path.abspath(os.path.dirname(__file__))
QEMU_CONFIGS_DIR = os.path.join(ABS_TOOL_PATH, 'qemu_configs')
@@ -53,7 +54,7 @@ class LinuxSourceTreeOperations:
except subprocess.CalledProcessError as e:
raise ConfigError(e.output.decode())
- def make_arch_qemuconfig(self, base_kunitconfig: kunit_config.Kconfig) -> None:
+ def make_arch_config(self, base_kunitconfig: kunit_config.Kconfig) -> None:
pass
def make_allyesconfig(self, build_dir: str, make_options) -> None:
@@ -109,7 +110,7 @@ class LinuxSourceTreeOperationsQemu(LinuxSourceTreeOperations):
self._kernel_command_line = qemu_arch_params.kernel_command_line + ' kunit_shutdown=reboot'
self._extra_qemu_params = qemu_arch_params.extra_qemu_params
- def make_arch_qemuconfig(self, base_kunitconfig: kunit_config.Kconfig) -> None:
+ def make_arch_config(self, base_kunitconfig: kunit_config.Kconfig) -> None:
kconfig = kunit_config.parse_from_string(self._kconfig)
base_kunitconfig.merge_in_entries(kconfig)
@@ -137,6 +138,10 @@ class LinuxSourceTreeOperationsUml(LinuxSourceTreeOperations):
def __init__(self, cross_compile=None):
super().__init__(linux_arch='um', cross_compile=cross_compile)
+ def make_arch_config(self, base_kunitconfig: kunit_config.Kconfig) -> None:
+ kconfig = kunit_config.parse_file(UML_KCONFIG_PATH)
+ base_kunitconfig.merge_in_entries(kconfig)
+
def make_allyesconfig(self, build_dir: str, make_options) -> None:
kunit_parser.print_with_timestamp(
'Enabling all CONFIGs for UML...')
@@ -313,7 +318,7 @@ class LinuxSourceTree:
return self.build_config(build_dir, make_options)
existing_kconfig = kunit_config.parse_file(kconfig_path)
- self._ops.make_arch_qemuconfig(self._kconfig)
+ self._ops.make_arch_config(self._kconfig)
if self._kconfig.is_subset_of(existing_kconfig) and not self._kunitconfig_changed(build_dir):
return True
print('Regenerating .config ...')
--
2.37.0.rc0.104.g0611611a94-goog
This patch series makes two changes to how KUnit test suites are stored
and executed:
- The .kunit_test_suites section is now used for tests in modules (in
lieu of a module_init funciton), as well as for built-in tests. The
module loader will now trigger test execution. This frees up the
module_init function for other uses.
- Instead of storing an array of arrays of suites, have the
kunit_test_suite() and kunit_test_suites() macros append to one global
(or per-module) list of test suites. This removes a needless layer of
indirection, and removes the need to NULL-terminate suite_sets.
The upshot of this is that it should now be possible to use the
kunit_test_suite() and kunit_test_suites() macros to register test
suites even from within modules which otherwise had module_init
functions. This was proving to be quite a common issue, resulting in
several modules calling into KUnit's private suite execution functions
to run their tests (often introducing incompatibilities with the KUnit
tooling).
This series also fixes the thunderbolt, nitro_enclaves, and
sdhci-of-aspeed tests to use kunit_test_suite() now that it works. This
is required, as otherwise the first two patches may break these tests
entirely.
Huge thanks to Jeremy Kerr, who designed and implemented the module
loader changes, and to Daniel Latypov for pushing the simplification of
the nested arrays in .kunit_test_suites.
I've tested this series both with builtin tests, and with modules on
x86_64, but there's always the possibility that there's something subtle
and nasty on another architecture, so please test!
Cheers,
-- David
Changes since v1:
https://lore.kernel.org/linux-kselftest/20220618090310.1174932-1-davidgow@g…
- Fix a compile issue when CONFIG_KUNIT=m (Thanks Christophe)
- No longer NULL-terminate suite_sets.
- Move the thunderbird Kconfig to the correct patch (Thanks Andra)
- Add all the Tested-by and Acked-by tags.
---
Daniel Latypov (1):
kunit: flatten kunit_suite*** to kunit_suite** in .kunit_test_suites
David Gow (3):
thunderbolt: test: Use kunit_test_suite() macro
nitro_enclaves: test: Use kunit_test_suite() macro
mmc: sdhci-of-aspeed: test: Use kunit_test_suite() macro
Jeremy Kerr (1):
kunit: unify module and builtin suite definitions
drivers/mmc/host/Kconfig | 5 +-
drivers/mmc/host/sdhci-of-aspeed-test.c | 8 +-
drivers/mmc/host/sdhci-of-aspeed.c | 27 ----
drivers/thunderbolt/Kconfig | 5 +-
drivers/thunderbolt/domain.c | 3 -
drivers/thunderbolt/tb.h | 8 -
drivers/thunderbolt/test.c | 12 +-
drivers/virt/nitro_enclaves/Kconfig | 5 +-
drivers/virt/nitro_enclaves/ne_misc_dev.c | 27 ----
.../virt/nitro_enclaves/ne_misc_dev_test.c | 5 +-
include/kunit/test.h | 60 ++------
include/linux/module.h | 5 +
kernel/module/main.c | 6 +
lib/kunit/executor.c | 115 ++++----------
lib/kunit/executor_test.c | 144 +++++-------------
lib/kunit/test.c | 54 ++++++-
16 files changed, 152 insertions(+), 337 deletions(-)
--
2.37.0.rc0.104.g0611611a94-goog
Hardware would directly write x2APIC ICR register instead of software
emulation in some circumstances, e.g when Intel IPI virtualization is
enabled. This behavior requires normal reserved bits checking to ensure
them input as zero, otherwise it will cause #GP. So we need mask out
those reserved bits from the data written to vICR register.
Remove Delivery Status bit emulation in test case as this flag
is invalid and not needed in x2APIC mode. KVM may ignore clearing
it during interrupt dispatch which will lead to fake test failure.
Opportunstically correct vector number for test sending IPI to
non-existent vCPUs.
Signed-off-by: Zeng Guang <guang.zeng(a)intel.com>
---
.../selftests/kvm/x86_64/xapic_state_test.c | 20 ++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/kvm/x86_64/xapic_state_test.c b/tools/testing/selftests/kvm/x86_64/xapic_state_test.c
index 0792334ba243..062d2e1adeb7 100644
--- a/tools/testing/selftests/kvm/x86_64/xapic_state_test.c
+++ b/tools/testing/selftests/kvm/x86_64/xapic_state_test.c
@@ -70,13 +70,27 @@ static void ____test_icr(struct kvm_vm *vm, struct kvm_vcpu *vcpu, uint64_t val)
vcpu_ioctl(vm, vcpu->id, KVM_GET_LAPIC, &xapic);
icr = (u64)(*((u32 *)&xapic.regs[APIC_ICR])) |
(u64)(*((u32 *)&xapic.regs[APIC_ICR2])) << 32;
- if (!vcpu->is_x2apic)
+ if (!vcpu->is_x2apic) {
val &= (-1u | (0xffull << (32 + 24)));
- ASSERT_EQ(icr, val & ~APIC_ICR_BUSY);
+ ASSERT_EQ(icr, val & ~APIC_ICR_BUSY);
+ } else {
+ ASSERT_EQ(icr, val);
+ }
}
+#define X2APIC_RSVED_BITS_MASK (GENMASK_ULL(31,20) | \
+ GENMASK_ULL(17,16) | \
+ GENMASK_ULL(13,13))
+
static void __test_icr(struct kvm_vm *vm, struct kvm_vcpu *vcpu, uint64_t val)
{
+ if (vcpu->is_x2apic) {
+ /* Hardware writing vICR register requires reserved bits 31:20,
+ * 17:16 and 13 kept as zero to avoid #GP exception. Data value
+ * written to vICR should mask out those bits above.
+ */
+ val &= ~X2APIC_RSVED_BITS_MASK;
+ }
____test_icr(vm, vcpu, val | APIC_ICR_BUSY);
____test_icr(vm, vcpu, val & ~(u64)APIC_ICR_BUSY);
}
@@ -100,7 +114,7 @@ static void test_icr(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
icr = APIC_INT_ASSERT | 0xff;
for (i = vcpu->id + 1; i < 0xff; i++) {
for (j = 0; j < 8; j++)
- __test_icr(vm, vcpu, i << (32 + 24) | APIC_INT_ASSERT | (j << 8));
+ __test_icr(vm, vcpu, i << (32 + 24) | icr | (j << 8));
}
/* And again with a shorthand destination for all types of IPIs. */
--
2.27.0
Dzień dobry,
jakiś czas temu zgłosiła się do nas firma, której strona internetowa nie pozycjonowała się wysoko w wyszukiwarce Google.
Na podstawie wykonanego przez nas audytu SEO zoptymalizowaliśmy treści na stronie pod kątem wcześniej opracowanych słów kluczowych. Nasz wewnętrzny system codziennie analizuje prawidłowe działanie witryny. Dzięki indywidualnej strategii, firma zdobywa coraz więcej Klientów.
Czy chcieliby Państwo zwiększyć liczbę osób odwiedzających stronę internetową firmy? Mógłbym przedstawić ofertę?
Pozdrawiam serdecznie,
Wiktor Zielonko
Add a colon in the "Optional" test usage message to ensure consistency
with the "Default" test usage message.
Signed-off-by: Gautam Menghani <gautammenghani201(a)gmail.com>
---
tools/testing/selftests/kselftest_deps.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/kselftest_deps.sh b/tools/testing/selftests/kselftest_deps.sh
index 00e60d6eb16b..708cb5429633 100755
--- a/tools/testing/selftests/kselftest_deps.sh
+++ b/tools/testing/selftests/kselftest_deps.sh
@@ -26,7 +26,7 @@ echo " main Makefile when optional -p is specified."
echo "- Prints pass/fail dependency check for each tests/sub-test."
echo "- Prints pass/fail targets and libraries."
echo "- Default: runs dependency checks on all tests."
-echo "- Optional test name can be specified to check dependencies for it."
+echo "- Optional: test name can be specified to check dependencies for it."
exit 1
}
--
2.34.1
Hi Linus,
Please pull the following Kselftest fixes update for Linux 5.19-rc4
This Kselftest fixes update for Linux 5.19-rc4 consists of compile
time fixes and run-time resources leaks.
-- Fix clang cross compilation
-- Fix resource leak when return error
-- fix compile error for dma_map_benchmark
-- Fix regression - make use of GUP_TEST_FILE macro
diff is attached.
thanks,
-- Shuah
----------------------------------------------------------------
The following changes since commit f2906aa863381afb0015a9eb7fefad885d4e5a56:
Linux 5.19-rc1 (2022-06-05 17:18:54 -0700)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest tags/linux-kselftest-fixes-5.19-rc4
for you to fetch changes up to 9b4d5c01eb234f66a15a746b1c73e10209edb199:
selftests: make use of GUP_TEST_FILE macro (2022-06-16 17:05:50 -0600)
----------------------------------------------------------------
linux-kselftest-fixes-5.19-rc4
This Kselftest fixes update for Linux 5.19-rc4 consists of compile
time fixes and run-time resources leaks.
-- Fix clang cross compilation
-- Fix resource leak when return error
-- fix compile error for dma_map_benchmark
-- Fix regression - make use of GUP_TEST_FILE macro
----------------------------------------------------------------
Ding Xiang (1):
selftests: vm: Fix resource leak when return error
Joel Savitz (1):
selftests: make use of GUP_TEST_FILE macro
Mark Brown (1):
selftests: Fix clang cross compilation
Yu Liao (1):
selftests dma: fix compile error for dma_map_benchmark
tools/testing/selftests/dma/Makefile | 1 +
tools/testing/selftests/dma/dma_map_benchmark.c | 2 +-
tools/testing/selftests/lib.mk | 25 +++++++++++++++++++++++--
tools/testing/selftests/vm/gup_test.c | 4 ++--
tools/testing/selftests/vm/ksm_tests.c | 2 ++
5 files changed, 29 insertions(+), 5 deletions(-)
----------------------------------------------------------------