This series contains three fixup patches for vm selftests. They
are independent. Please see the patches.
Patrick Wang (3):
selftests: vm: check numa_available() before operating
"merge_across_nodes" in ksm_tests
selftests: vm: add "test_hmm.sh" to TEST_FILES
selftests: vm: add the "settings" file with timeout variable
tools/testing/selftests/vm/Makefile | 1 +
tools/testing/selftests/vm/ksm_tests.c | 9 ++++++---
tools/testing/selftests/vm/settings | 1 +
3 files changed, 8 insertions(+), 3 deletions(-)
create mode 100644 tools/testing/selftests/vm/settings
--
2.25.1
Add the following new guidelines:
- Add instruction to use lib.mk
- Add instruction about how to use headers from kernel source
- Add instruction to add .gitignore file
- Add instruction about how to add new test in selftests/Makefile
- Add instruction about different build commands to test
Signed-off-by: Muhammad Usama Anjum <usama.anjum(a)collabora.com>
---
Following patch is fixing build of kselftest when separate output
direcotry is specified using kernel's top most Makefile. It should be
accepted first:
https://lore.kernel.org/lkml/20220223191016.1658728-1-usama.anjum@collabora…
---
Documentation/dev-tools/kselftest.rst | 46 ++++++++++++++++++++++++++-
1 file changed, 45 insertions(+), 1 deletion(-)
diff --git a/Documentation/dev-tools/kselftest.rst b/Documentation/dev-tools/kselftest.rst
index a833ecf12fbc1..637f83d1450dc 100644
--- a/Documentation/dev-tools/kselftest.rst
+++ b/Documentation/dev-tools/kselftest.rst
@@ -208,6 +208,13 @@ In general, the rules for selftests are
Contributing new tests (details)
================================
+ * Use lib.mk instead of writing Makefile from sratch. Specify flags and
+ binaries generation flags on need basis before including lib.mk. ::
+
+ CFLAGS = $(KHDR_INCLUDES)
+ TEST_GEN_PROGS := close_range_test
+ include ../lib.mk
+
* Use TEST_GEN_XXX if such binaries or files are generated during
compiling.
@@ -230,13 +237,50 @@ Contributing new tests (details)
* First use the headers inside the kernel source and/or git repo, and then the
system headers. Headers for the kernel release as opposed to headers
installed by the distro on the system should be the primary focus to be able
- to find regressions.
+ to find regressions. Use KHDR_INCLUDES in Makefile to include headers from
+ the kernel source.
* If a test needs specific kernel config options enabled, add a config file in
the test directory to enable them.
e.g: tools/testing/selftests/android/config
+ * Create a .gitignore file inside test directory and add all generated objects
+ in it.
+
+ * Add new test name in TARGETS in selftests/Makefile::
+
+ TARGETS += android
+
+ * All of the following build commands should be successful
+
+ - Same directory build of kselftests::
+
+ make kselftest-all
+ make kselftest-install
+ make kselftest-clean
+ make kselftest-gen_tar
+
+ - Build with absolute output directory path::
+
+ make kselftest-all O=/abs_build_path
+ make kselftest-install O=/abs_build_path
+ make kselftest-clean O=/abs_build_path
+ make kselftest-gen_tar O=/abs_build_path
+
+ - Build with relative output directory path::
+
+ make kselftest-all O=relative_path
+ make kselftest-install O=relative_path
+ make kselftest-clean O=relative_path
+ make kselftest-gen_tar O=relative_path
+
+ - Build from Makefile of selftests directly::
+
+ make -C tools/testing/selftests
+ make -C tools/testing/selftests O=/abs_build_path
+ make -C tools/testing/selftests O=relative_path
+
Test Module
===========
--
2.30.2
As suggested in [1], the kprobe_multi interface is to be fixed for 32-bit
architectures and compat, rather then disabled. As it turned out,
there are a couple of additional problems that are to be addressed:
- the absence of size overflow checks, leading to possible
out-of-bounds writes (addressed by the first patch; this one likely has
to be fixed in 5.18, where the version of the patch from [3]
may be preferrable, along with [4] to avoid applying the rest
of the series);
- the assumption that long has the same size as u64, which would make
cookies arrays size calculation incorrect on 32-bit architectures
(addressed by the second patch);
- the addrs array passing API, that is incompatible with compat and has
to be changed (addressed in the fourth patch): those are kernel
addresses and not user ones (as was incorrectly stated in [2]);
this change is only semantical for 64-bit user/kernelspace,
so it shouldn't impact ABI there, at least.
[1] https://lore.kernel.org/lkml/CAADnVQ+2gwhcMht4PuDnDOFKY68Wsq8QFz4Y69NBX_TLa…
[2] https://lore.kernel.org/lkml/20220510184155.GA8295@asgard.redhat.com/
[3] https://lore.kernel.org/lkml/20220516230455.GA25103@asgard.redhat.com/
[4] https://lore.kernel.org/lkml/20220506142148.GA24802@asgard.redhat.com/
v3:
- Rebased on top of bpf-next
- Removed unnecessary size/cookies_size assignments as suggested
by Yonghong Sond
v2: https://lore.kernel.org/lkml/20220516230441.GA22091@asgard.redhat.com/
- Fixed the isses reported by CI
v1: https://lore.kernel.org/lkml/20220516182657.GA28596@asgard.redhat.com/
Eugene Syromiatnikov (4):
bpf_trace: check size for overflow in bpf_kprobe_multi_link_attach
bpf_trace: support 32-bit kernels in bpf_kprobe_multi_link_attach
bpf_trace: handle compat in copy_user_syms
bpf_trace: pass array of u64 values in kprobe_multi.addrs
kernel/trace/bpf_trace.c | 67 ++++++++++++++++------
tools/lib/bpf/bpf.h | 2 +-
tools/lib/bpf/libbpf.c | 8 +--
tools/lib/bpf/libbpf.h | 2 +-
.../testing/selftests/bpf/prog_tests/bpf_cookie.c | 2 +-
.../selftests/bpf/prog_tests/kprobe_multi_test.c | 8 +--
6 files changed, 62 insertions(+), 27 deletions(-)
--
2.1.4
The ima_setup.sh is needed by test_progs test_ima. But the file is
missed if we build test_progs separately or installed bpf test to
another folder. This patch set fixed the issue in 2 different
scenarios.
Hangbin Liu (2):
selftests/bpf: Fix build error with ima_setup.sh
selftests/bpf: add missed ima_setup.sh in Makefile
tools/testing/selftests/bpf/Makefile | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
--
2.35.1
Hello.
While [1] seems to require additional work[2] due to changes
in the interface (and it has already been re-targeted for bpf-next),
I would like to ask to consider the following three patches, that fix
possible out-of-bounds write, properly disable the interface
for 32-bit compat user space, and prepare the libbpf interface change,
for the 5.18 release. Thank you.
[1] https://lore.kernel.org/lkml/cover.1652772731.git.esyr@redhat.com/
[2] https://lore.kernel.org/lkml/YoTXiAk1EpZ0rLKE@krava/i
v4:
- Added additional size checks for INT_MAX, as suggested by Yonghong
Song
- Added the third patch for the user space kprobe_multi.addrs type
change, split from the 4th bpf-next patch, as suggested by Yonghong
Song and Andrii Nakryiko
v3: https://lore.kernel.org/lkml/cover.1652876187.git.esyr@redhat.com/
- Split out patches for 5.18
- Removed superfluous size assignments after overflow_mul_check,
as suggested by Yonghong Song
v2: https://lore.kernel.org/lkml/20220516230441.GA22091@asgard.redhat.com/
- Fixed the isses reported by CI
v1: https://lore.kernel.org/lkml/20220516182657.GA28596@asgard.redhat.com/
Eugene Syromiatnikov (3):
bpf_trace: check size for overflow in bpf_kprobe_multi_link_attach
bpf_trace: bail out from bpf_kprobe_multi_link_attach when in compat
libbpf, selftests/bpf: pass array of u64 values in kprobe_multi.addrs
kernel/trace/bpf_trace.c | 15 +++++++++------
tools/lib/bpf/bpf.h | 2 +-
tools/lib/bpf/libbpf.c | 8 ++++----
tools/lib/bpf/libbpf.h | 2 +-
tools/testing/selftests/bpf/prog_tests/bpf_cookie.c | 2 +-
.../testing/selftests/bpf/prog_tests/kprobe_multi_test.c | 8 ++++----
6 files changed, 20 insertions(+), 17 deletions(-)
--
2.1.4
Currently, you cannot ovewrwrite what's in your kunitconfig via
--kconfig_add.
Nor can you override something in a qemu_config via either means.
This patch makes it so we have this level of priority
* --kconfig_add
* kunitconfig file (the default or the one from --kunitconfig)
* qemu_config
The rationale for this order is that the more "dynamic" sources of
kconfig options should take priority.
--kconfig_add is obviously the most dynamic.
And for kunitconfig, users probably tweak the file manually or specify
--kunitconfig more often than they delve into qemu_config python files.
And internally, we convert the kconfigs from a python list into a set or
dict fairly often. We should just use a dict internally.
We exposed the set transform in the past since we didn't define __eq__,
so also take the chance to shore up the kunit_kconfig.Kconfig interface.
Example
=======
Let's consider the unrealistic example where someone would want to
disable CONFIG_KUNIT.
I.e. they run
$ ./tools/testing/kunit/kunit.py config --kconfig_add=CONFIG_KUNIT=n
Before
------
We'd write the following
> # CONFIG_KUNIT is not set
> CONFIG_KUNIT_ALL_TESTS=y
> CONFIG_KUNIT_TEST=y
> CONFIG_KUNIT=y
> CONFIG_KUNIT_EXAMPLE_TEST=y
And we'd error out with
> ERROR:root:Not all Kconfig options selected in kunitconfig were in the generated .config.
> This is probably due to unsatisfied dependencies.
> Missing: # CONFIG_KUNIT is not set
After
-----
We'd write the following
> # CONFIG_KUNIT is not set
> CONFIG_KUNIT_TEST=y
> CONFIG_KUNIT_ALL_TESTS=y
> CONFIG_KUNIT_EXAMPLE_TEST=y
And we'd error out with
> ERROR:root:Not all Kconfig options selected in kunitconfig were in the generated .config.
> This is probably due to unsatisfied dependencies.
> Missing: CONFIG_KUNIT_EXAMPLE_TEST=y, CONFIG_KUNIT_TEST=y, CONFIG_KUNIT_ALL_TESTS=y
Signed-off-by: Daniel Latypov <dlatypov(a)google.com>
---
tools/testing/kunit/kunit_config.py | 49 +++++++++++++++-----------
tools/testing/kunit/kunit_kernel.py | 21 ++++++-----
tools/testing/kunit/kunit_tool_test.py | 45 ++++++++++-------------
3 files changed, 59 insertions(+), 56 deletions(-)
diff --git a/tools/testing/kunit/kunit_config.py b/tools/testing/kunit/kunit_config.py
index 75a8dc1683d4..89443400b17e 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 List, Set
+from typing import Dict, Iterable, Set
CONFIG_IS_NOT_SET_PATTERN = r'^# CONFIG_(\w+) is not set$'
CONFIG_PATTERN = r'^CONFIG_(\w+)=(\S+|".*")$'
@@ -32,35 +32,46 @@ class Kconfig:
"""Represents defconfig or .config specified using the Kconfig language."""
def __init__(self) -> None:
- self._entries = [] # type: List[KconfigEntry]
+ self._entries = {} # type: Dict[str, str]
- def entries(self) -> Set[KconfigEntry]:
- return set(self._entries)
+ def __eq__(self, other) -> bool:
+ if not isinstance(other, self.__class__):
+ return False
+ return self._entries == other._entries
- def add_entry(self, entry: KconfigEntry) -> None:
- self._entries.append(entry)
+ def __repr__(self) -> str:
+ return ','.join(str(e) for e in self._as_entries())
+
+
+ def _as_entries(self) -> Iterable[KconfigEntry]:
+ for name, value in self._entries.items():
+ yield KconfigEntry(name, value)
+
+ def add_entry(self, name: str, value: str) -> None:
+ self._entries[name] = value
def is_subset_of(self, other: 'Kconfig') -> bool:
- other_dict = {e.name: e.value for e in other.entries()}
- for a in self.entries():
- b = other_dict.get(a.name)
+ for name, value in self._entries.items():
+ b = other._entries.get(name)
if b is None:
- if a.value == 'n':
+ if value == 'n':
continue
return False
- if a.value != b:
+ if value != b:
return False
return True
+ def set_diff(self, other: 'Kconfig') -> Set[KconfigEntry]:
+ return set(self._as_entries()) - set(other._as_entries())
+
def merge_in_entries(self, other: 'Kconfig') -> None:
- if other.is_subset_of(self):
- return
- self._entries = list(self.entries().union(other.entries()))
+ for name, value in other._entries.items():
+ self._entries[name] = value
def write_to_file(self, path: str) -> None:
with open(path, 'a+') as f:
- for entry in self.entries():
- f.write(str(entry) + '\n')
+ for e in self._as_entries():
+ f.write(str(e) + '\n')
def parse_file(path: str) -> Kconfig:
with open(path, 'r') as f:
@@ -78,14 +89,12 @@ def parse_from_string(blob: str) -> Kconfig:
match = config_matcher.match(line)
if match:
- entry = KconfigEntry(match.group(1), match.group(2))
- kconfig.add_entry(entry)
+ kconfig.add_entry(match.group(1), match.group(2))
continue
empty_match = is_not_set_matcher.match(line)
if empty_match:
- entry = KconfigEntry(empty_match.group(1), 'n')
- kconfig.add_entry(entry)
+ kconfig.add_entry(empty_match.group(1), 'n')
continue
if line[0] == '#':
diff --git a/tools/testing/kunit/kunit_kernel.py b/tools/testing/kunit/kunit_kernel.py
index 3539efaf99ba..ebd2d91af710 100644
--- a/tools/testing/kunit/kunit_kernel.py
+++ b/tools/testing/kunit/kunit_kernel.py
@@ -53,8 +53,8 @@ class LinuxSourceTreeOperations:
except subprocess.CalledProcessError as e:
raise ConfigError(e.output.decode())
- def make_arch_qemuconfig(self, base_kunitconfig: kunit_config.Kconfig) -> None:
- pass
+ def make_arch_qemuconfig(self, base_kunitconfig: kunit_config.Kconfig) -> kunit_config.Kconfig:
+ return base_kunitconfig
def make_allyesconfig(self, build_dir: str, make_options) -> None:
raise ConfigError('Only the "um" arch is supported for alltests')
@@ -109,9 +109,10 @@ 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_qemuconfig(self, base_kunitconfig: kunit_config.Kconfig) -> kunit_config.Kconfig:
kconfig = kunit_config.parse_from_string(self._kconfig)
- base_kunitconfig.merge_in_entries(kconfig)
+ kconfig.merge_in_entries(base_kunitconfig)
+ return kconfig
def start(self, params: List[str], build_dir: str) -> subprocess.Popen:
kernel_path = os.path.join(build_dir, self._kernel_path)
@@ -265,9 +266,10 @@ class LinuxSourceTree:
def validate_config(self, build_dir: str) -> bool:
kconfig_path = get_kconfig_path(build_dir)
validated_kconfig = kunit_config.parse_file(kconfig_path)
- if self._kconfig.is_subset_of(validated_kconfig):
+ invalid = self._kconfig.set_diff(validated_kconfig)
+ if not invalid:
return True
- invalid = self._kconfig.entries() - validated_kconfig.entries()
+
message = 'Not all Kconfig options selected in kunitconfig were in the generated .config.\n' \
'This is probably due to unsatisfied dependencies.\n' \
'Missing: ' + ', '.join([str(e) for e in invalid])
@@ -282,7 +284,7 @@ class LinuxSourceTree:
if build_dir and not os.path.exists(build_dir):
os.mkdir(build_dir)
try:
- self._ops.make_arch_qemuconfig(self._kconfig)
+ self._kconfig = self._ops.make_arch_qemuconfig(self._kconfig)
self._kconfig.write_to_file(kconfig_path)
self._ops.make_olddefconfig(build_dir, make_options)
except ConfigError as e:
@@ -303,7 +305,7 @@ class LinuxSourceTree:
return True
old_kconfig = kunit_config.parse_file(old_path)
- return old_kconfig.entries() != self._kconfig.entries()
+ return old_kconfig != self._kconfig
def build_reconfig(self, build_dir: str, make_options) -> bool:
"""Creates a new .config if it is not a subset of the .kunitconfig."""
@@ -313,7 +315,8 @@ 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._kconfig = self._ops.make_arch_qemuconfig(self._kconfig)
+
if self._kconfig.is_subset_of(existing_kconfig) and not self._kunitconfig_changed(build_dir):
return True
print('Regenerating .config ...')
diff --git a/tools/testing/kunit/kunit_tool_test.py b/tools/testing/kunit/kunit_tool_test.py
index 25a2eb3bf114..3a8f638ff092 100755
--- a/tools/testing/kunit/kunit_tool_test.py
+++ b/tools/testing/kunit/kunit_tool_test.py
@@ -45,7 +45,7 @@ class KconfigTest(unittest.TestCase):
self.assertTrue(kconfig0.is_subset_of(kconfig0))
kconfig1 = kunit_config.Kconfig()
- kconfig1.add_entry(kunit_config.KconfigEntry('TEST', 'y'))
+ kconfig1.add_entry('TEST', 'y')
self.assertTrue(kconfig1.is_subset_of(kconfig1))
self.assertTrue(kconfig0.is_subset_of(kconfig1))
self.assertFalse(kconfig1.is_subset_of(kconfig0))
@@ -56,40 +56,28 @@ class KconfigTest(unittest.TestCase):
kconfig = kunit_config.parse_file(kconfig_path)
expected_kconfig = kunit_config.Kconfig()
- expected_kconfig.add_entry(
- kunit_config.KconfigEntry('UML', 'y'))
- expected_kconfig.add_entry(
- kunit_config.KconfigEntry('MMU', 'y'))
- expected_kconfig.add_entry(
- kunit_config.KconfigEntry('TEST', 'y'))
- expected_kconfig.add_entry(
- kunit_config.KconfigEntry('EXAMPLE_TEST', 'y'))
- expected_kconfig.add_entry(
- kunit_config.KconfigEntry('MK8', 'n'))
-
- self.assertEqual(kconfig.entries(), expected_kconfig.entries())
+ expected_kconfig.add_entry('UML', 'y')
+ expected_kconfig.add_entry('MMU', 'y')
+ expected_kconfig.add_entry('TEST', 'y')
+ expected_kconfig.add_entry('EXAMPLE_TEST', 'y')
+ expected_kconfig.add_entry('MK8', 'n')
+
+ self.assertEqual(kconfig, expected_kconfig)
def test_write_to_file(self):
kconfig_path = os.path.join(test_tmpdir, '.config')
expected_kconfig = kunit_config.Kconfig()
- expected_kconfig.add_entry(
- kunit_config.KconfigEntry('UML', 'y'))
- expected_kconfig.add_entry(
- kunit_config.KconfigEntry('MMU', 'y'))
- expected_kconfig.add_entry(
- kunit_config.KconfigEntry('TEST', 'y'))
- expected_kconfig.add_entry(
- kunit_config.KconfigEntry('EXAMPLE_TEST', 'y'))
- expected_kconfig.add_entry(
- kunit_config.KconfigEntry('MK8', 'n'))
+ expected_kconfig.add_entry('UML', 'y')
+ expected_kconfig.add_entry('MMU', 'y')
+ expected_kconfig.add_entry('TEST', 'y')
+ expected_kconfig.add_entry('EXAMPLE_TEST', 'y')
+ expected_kconfig.add_entry('MK8', 'n')
expected_kconfig.write_to_file(kconfig_path)
actual_kconfig = kunit_config.parse_file(kconfig_path)
-
- self.assertEqual(actual_kconfig.entries(),
- expected_kconfig.entries())
+ self.assertEqual(actual_kconfig, expected_kconfig)
class KUnitParserTest(unittest.TestCase):
@@ -381,8 +369,11 @@ class LinuxSourceTreeTest(unittest.TestCase):
kunit_kernel.LinuxSourceTree('', kunitconfig_path=dir)
def test_kconfig_add(self):
+ want_kconfig = kunit_config.Kconfig()
+ want_kconfig.add_entry('NOT_REAL', 'y')
+
tree = kunit_kernel.LinuxSourceTree('', kconfig_add=['CONFIG_NOT_REAL=y'])
- self.assertIn(kunit_config.KconfigEntry('NOT_REAL', 'y'), tree._kconfig.entries())
+ self.assertFalse(want_kconfig.set_diff(tree._kconfig))
def test_invalid_arch(self):
with self.assertRaisesRegex(kunit_kernel.ConfigError, 'not a valid arch, options are.*x86_64'):
base-commit: 1b11063d32d7e11366e48be64215ff517ce32217
--
2.36.1.124.g0e6072fb45-goog