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
This is v5 of Syscall User Dispatch. It has some big changes in
comparison to v4.
First of all, it allows the vdso trampoline code for architectures that
support it. This is exposed through an arch hook. It also addresses
the concern about what happens when a bad selector is provided, instead
of SIGSEGV, we fail with SIGSYS, which is more debug-able.
Another major change is that it is now based on top of Gleixner's common
syscall entry work, and is supposed to only be used by that code.
Therefore, the entry symbol is not exported outside of kernel/entry/ code.
The biggest change in this version is the attempt to avoid using one of
the final TIF flags on x86 32 bit, without increasing the size of that
variable to 64 bit. My expectation is that, with this work, plus the
removal of TIF_IA32, TIF_X32 and TIF_FORCE_TF, we might be able to avoid
changing this field to 64 bits at all. Instead, this follows the
suggestion by Andy to have a generic TIF flag for SECCOMP and this
mechanism, and use another field to decide which one is enabled. The
code for this is not complex, so it seems like a viable approach.
Finally, this version adds some documentation to the feature.
Kees, I dropped your reviewed-by on patch 5, given the amount of
changes.
Thanks,
Previous submissions are archived at:
RFC/v1: https://lkml.org/lkml/2020/7/8/96
v2: https://lkml.org/lkml/2020/7/9/17
v3: https://lkml.org/lkml/2020/7/12/4
v4: https://lwn.net/ml/linux-kernel/20200712044516.2347844-1-krisman@collabora.…
Gabriel Krisman Bertazi (9):
kernel: Support TIF_SYSCALL_INTERCEPT flag
kernel: entry: Support TIF_SYSCAL_INTERCEPT on common entry code
x86: vdso: Expose sigreturn address on vdso to the kernel
signal: Expose SYS_USER_DISPATCH si_code type
kernel: Implement selective syscall userspace redirection
kernel: entry: Support Syscall User Dispatch for common syscall entry
x86: Enable Syscall User Dispatch
selftests: Add kselftest for syscall user dispatch
doc: Document Syscall User Dispatch
.../admin-guide/syscall-user-dispatch.rst | 87 ++++++
arch/Kconfig | 21 ++
arch/x86/Kconfig | 1 +
arch/x86/entry/vdso/vdso2c.c | 2 +
arch/x86/entry/vdso/vdso32/sigreturn.S | 2 +
arch/x86/entry/vdso/vma.c | 15 +
arch/x86/include/asm/elf.h | 1 +
arch/x86/include/asm/thread_info.h | 4 +-
arch/x86/include/asm/vdso.h | 2 +
arch/x86/kernel/signal_compat.c | 2 +-
fs/exec.c | 8 +
include/linux/entry-common.h | 6 +-
include/linux/sched.h | 8 +-
include/linux/seccomp.h | 20 +-
include/linux/syscall_intercept.h | 71 +++++
include/linux/syscall_user_dispatch.h | 29 ++
include/uapi/asm-generic/siginfo.h | 3 +-
include/uapi/linux/prctl.h | 5 +
kernel/entry/Makefile | 1 +
kernel/entry/common.c | 32 +-
kernel/entry/common.h | 15 +
kernel/entry/syscall_user_dispatch.c | 101 ++++++
kernel/fork.c | 10 +-
kernel/seccomp.c | 7 +-
kernel/sys.c | 5 +
tools/testing/selftests/Makefile | 1 +
.../syscall_user_dispatch/.gitignore | 2 +
.../selftests/syscall_user_dispatch/Makefile | 9 +
.../selftests/syscall_user_dispatch/config | 1 +
.../syscall_user_dispatch.c | 292 ++++++++++++++++++
30 files changed, 744 insertions(+), 19 deletions(-)
create mode 100644 Documentation/admin-guide/syscall-user-dispatch.rst
create mode 100644 include/linux/syscall_intercept.h
create mode 100644 include/linux/syscall_user_dispatch.h
create mode 100644 kernel/entry/common.h
create mode 100644 kernel/entry/syscall_user_dispatch.c
create mode 100644 tools/testing/selftests/syscall_user_dispatch/.gitignore
create mode 100644 tools/testing/selftests/syscall_user_dispatch/Makefile
create mode 100644 tools/testing/selftests/syscall_user_dispatch/config
create mode 100644 tools/testing/selftests/syscall_user_dispatch/syscall_user_dispatch.c
--
2.28.0
This makes sure that simple SCM_RIGHTS fd passing works as expected, to
avoid any future regressions. This is mostly code from Michael Kerrisk's
examples on how to set up and perform fd passing with SCM_RIGHTS. Add
a test script and wire it up to the selftests.
Signed-off-by: Kees Cook <keescook(a)chromium.org>
---
FYI, this also relicenses Michael's code (with his permission) from
GPL3+ to GPL2+, who is on CC to publicly confirm. :) Thank you Michael!
---
tools/testing/selftests/Makefile | 1 +
tools/testing/selftests/socket/.gitignore | 4 +
tools/testing/selftests/socket/Makefile | 11 ++
tools/testing/selftests/socket/hello.txt | 1 +
tools/testing/selftests/socket/scm_rights.h | 40 +++++
.../selftests/socket/scm_rights_recv.c | 168 ++++++++++++++++++
.../selftests/socket/scm_rights_send.c | 144 +++++++++++++++
.../selftests/socket/simple_scm_rights.sh | 30 ++++
tools/testing/selftests/socket/unix_sockets.c | 88 +++++++++
tools/testing/selftests/socket/unix_sockets.h | 23 +++
10 files changed, 510 insertions(+)
create mode 100644 tools/testing/selftests/socket/.gitignore
create mode 100644 tools/testing/selftests/socket/Makefile
create mode 100644 tools/testing/selftests/socket/hello.txt
create mode 100644 tools/testing/selftests/socket/scm_rights.h
create mode 100644 tools/testing/selftests/socket/scm_rights_recv.c
create mode 100644 tools/testing/selftests/socket/scm_rights_send.c
create mode 100755 tools/testing/selftests/socket/simple_scm_rights.sh
create mode 100644 tools/testing/selftests/socket/unix_sockets.c
create mode 100644 tools/testing/selftests/socket/unix_sockets.h
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index e03bc15ce731..97e155596660 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -51,6 +51,7 @@ TARGETS += rtc
TARGETS += seccomp
TARGETS += sigaltstack
TARGETS += size
+TARGETS += socket
TARGETS += sparc64
TARGETS += splice
TARGETS += static_keys
diff --git a/tools/testing/selftests/socket/.gitignore b/tools/testing/selftests/socket/.gitignore
new file mode 100644
index 000000000000..bc9a892956b0
--- /dev/null
+++ b/tools/testing/selftests/socket/.gitignore
@@ -0,0 +1,4 @@
+unix_sockets.o
+scm_rights_send
+scm_rights_recv
+scm_rights
diff --git a/tools/testing/selftests/socket/Makefile b/tools/testing/selftests/socket/Makefile
new file mode 100644
index 000000000000..3eb7ef0db997
--- /dev/null
+++ b/tools/testing/selftests/socket/Makefile
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0+
+TEST_PROGS := simple_scm_rights.sh
+TEST_GEN_PROGS_EXTENDED := scm_rights_send scm_rights_recv
+
+include ../lib.mk
+
+$(OUTPUT)/unix_sockets.o: unix_sockets.h
+$(OUTPUT)/scm_rights_recv: $(OUTPUT)/unix_sockets.o scm_rights.h
+$(OUTPUT)/scm_rights_send: $(OUTPUT)/unix_sockets.o scm_rights.h
+
+EXTRA_CLEAN += $(OUTPUT)/unix_sockets.o $(OUTPUT)/scm_rights
diff --git a/tools/testing/selftests/socket/hello.txt b/tools/testing/selftests/socket/hello.txt
new file mode 100644
index 000000000000..e965047ad7c5
--- /dev/null
+++ b/tools/testing/selftests/socket/hello.txt
@@ -0,0 +1 @@
+Hello
diff --git a/tools/testing/selftests/socket/scm_rights.h b/tools/testing/selftests/socket/scm_rights.h
new file mode 100644
index 000000000000..4501a46bf1be
--- /dev/null
+++ b/tools/testing/selftests/socket/scm_rights.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * scm_rights.h
+ *
+ * Copyright (C) Michael Kerrisk, 2020.
+ *
+ * Header file used by scm_rights_send.c and scm_rights_recv.c.
+ */
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include "unix_sockets.h"
+
+#define SOCK_PATH "scm_rights"
+
+#define errExit(fmt, ...) do { \
+ fprintf(stderr, fmt, ## __VA_ARGS__); \
+ fprintf(stderr, ": %s\n", strerror(errno)); \
+ exit(EXIT_FAILURE); \
+ } while (0)
+
+#define fatal(str) errExit("%s\n", str)
+
+#define usageErr(fmt, ...) do { \
+ fprintf(stderr, "Usage: "); \
+ fprintf(stderr, fmt, ## __VA_ARGS__); \
+ exit(EXIT_FAILURE); \
+ } while (0)
+
+static bool debugging;
+
+#define debug(fmt, ...) do { \
+ if (debugging) \
+ fprintf(stderr, fmt, ## __VA_ARGS__); \
+ } while (0)
diff --git a/tools/testing/selftests/socket/scm_rights_recv.c b/tools/testing/selftests/socket/scm_rights_recv.c
new file mode 100644
index 000000000000..4c916e43c319
--- /dev/null
+++ b/tools/testing/selftests/socket/scm_rights_recv.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * scm_rights_recv.c
+ *
+ * Copyright (C) Michael Kerrisk, 2020.
+ *
+ * Used in conjunction with scm_rights_send.c to demonstrate passing of
+ * file descriptors via a UNIX domain socket.
+ *
+ * This program receives a file descriptor sent to a UNIX domain socket.
+ *
+ * Usage is as shown in the usageErr() call below.
+ *
+ * File descriptors can be exchanged over stream or datagram sockets. This
+ * program uses stream sockets by default; the "-d" command-line option
+ * specifies that datagram sockets should be used instead.
+ *
+ * This program is Linux-specific.
+ */
+#include "scm_rights.h"
+
+#define BUF_SIZE 100
+
+int
+main(int argc, char *argv[])
+{
+ int data, lfd, sfd, fd, opt;
+ ssize_t nr;
+ bool useDatagramSocket;
+ struct msghdr msgh;
+ struct iovec iov;
+
+ /* Allocate a char array of suitable size to hold the ancillary data.
+ * However, since this buffer is in reality a 'struct cmsghdr', use a
+ * union to ensure that it is aligned as required for that structure.
+ * Alternatively, we could allocate the buffer using malloc(), which
+ * returns a buffer that satisfies the strictest alignment
+ * requirements of any type
+ */
+
+ union {
+ char buf[CMSG_SPACE(sizeof(int))];
+ /* Space large enough to hold an 'int' */
+ struct cmsghdr align;
+ } controlMsg;
+ struct cmsghdr *cmsgp; /* Pointer used to iterate through
+ * headers in ancillary data
+ */
+
+ /* Parse command-line options */
+
+ useDatagramSocket = false;
+
+ while ((opt = getopt(argc, argv, "dD")) != -1) {
+ switch (opt) {
+ case 'd':
+ useDatagramSocket = true;
+ break;
+
+ default:
+ usageErr("%s [-dD]\n"
+ " -D enable debugging\n"
+ " -d use datagram socket\n", argv[0]);
+ }
+ }
+
+ /* Create socket bound to a well-known address. In the case where
+ * we are using stream sockets, also make the socket a listening
+ * socket and accept a connection on the socket.
+ */
+
+ if (remove(SOCK_PATH) == -1 && errno != ENOENT)
+ errExit("remove-%s", SOCK_PATH);
+
+ if (useDatagramSocket) {
+ sfd = unixBind(SOCK_PATH, SOCK_DGRAM);
+ if (sfd == -1)
+ errExit("unixBind");
+
+ } else {
+ lfd = unixBind(SOCK_PATH, SOCK_STREAM);
+ if (lfd == -1)
+ errExit("unixBind");
+
+ if (listen(lfd, 5) == -1)
+ errExit("listen");
+
+ sfd = accept(lfd, NULL, NULL);
+ if (sfd == -1)
+ errExit("accept");
+ }
+
+ /* The 'msg_name' field can be set to point to a buffer where the
+ * kernel will place the address of the peer socket. However, we don't
+ * need the address of the peer, so we set this field to NULL.
+ */
+
+ msgh.msg_name = NULL;
+ msgh.msg_namelen = 0;
+
+ /* Set fields of 'msgh' to point to buffer used to receive the (real)
+ * data read by recvmsg()
+ */
+
+ msgh.msg_iov = &iov;
+ msgh.msg_iovlen = 1;
+ iov.iov_base = &data;
+ iov.iov_len = sizeof(int);
+
+ /* Set 'msgh' fields to describe the ancillary data buffer */
+
+ msgh.msg_control = controlMsg.buf;
+ msgh.msg_controllen = sizeof(controlMsg.buf);
+
+ /* Receive real plus ancillary data */
+
+ nr = recvmsg(sfd, &msgh, 0);
+ if (nr == -1)
+ errExit("recvmsg");
+ debug("recvmsg() returned %ld\n", (long) nr);
+
+ if (nr > 0)
+ debug("Received data = %d\n", data);
+
+ /* Get the address of the first 'cmsghdr' in the received
+ * ancillary data
+ */
+
+ cmsgp = CMSG_FIRSTHDR(&msgh);
+
+ /* Check the validity of the 'cmsghdr' */
+
+ if (cmsgp == NULL || cmsgp->cmsg_len != CMSG_LEN(sizeof(int)))
+ fatal("bad cmsg header / message length");
+ if (cmsgp->cmsg_level != SOL_SOCKET)
+ fatal("cmsg_level != SOL_SOCKET");
+ if (cmsgp->cmsg_type != SCM_RIGHTS)
+ fatal("cmsg_type != SCM_RIGHTS");
+
+ /* The data area of the 'cmsghdr' is an 'int' (a file descriptor);
+ * copy that integer to a local variable. (The received file descriptor
+ * is typically a different file descriptor number than was used in the
+ * sending process.)
+ */
+
+ memcpy(&fd, CMSG_DATA(cmsgp), sizeof(int));
+ debug("Received FD %d\n", fd);
+
+ /* Having obtained the file descriptor, read the file's contents and
+ * print them on standard output
+ */
+
+ for (;;) {
+ char buf[BUF_SIZE];
+ ssize_t numRead;
+
+ numRead = read(fd, buf, BUF_SIZE);
+ if (numRead == -1)
+ errExit("read");
+
+ if (numRead == 0)
+ break;
+
+ write(STDOUT_FILENO, buf, numRead);
+ }
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tools/testing/selftests/socket/scm_rights_send.c b/tools/testing/selftests/socket/scm_rights_send.c
new file mode 100644
index 000000000000..c5718d10a80d
--- /dev/null
+++ b/tools/testing/selftests/socket/scm_rights_send.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * scm_rights_send.c
+ *
+ * Copyright (C) Michael Kerrisk, 2020.
+ *
+ * Used in conjunction with scm_rights_recv.c to demonstrate passing of
+ * file descriptors via a UNIX domain socket.
+ *
+ * This program sends a file descriptor to a UNIX domain socket.
+ *
+ * Usage is as shown in the usageErr() call below.
+ *
+ * File descriptors can be exchanged over stream or datagram sockets. This
+ * program uses stream sockets by default; the "-d" command-line option
+ * specifies that datagram sockets should be used instead.
+ *
+ * This program is Linux-specific.
+ */
+#include "scm_rights.h"
+
+int
+main(int argc, char *argv[])
+{
+ int data, sfd, opt, fd;
+ ssize_t ns;
+ bool useDatagramSocket;
+ struct msghdr msgh;
+ struct iovec iov;
+
+ /* Allocate a char array of suitable size to hold the ancillary data.
+ * However, since this buffer is in reality a 'struct cmsghdr', use a
+ * union to ensure that it is aligned as required for that structure.
+ * Alternatively, we could allocate the buffer using malloc(), which
+ * returns a buffer that satisfies the strictest alignment
+ * requirements of any type.
+ */
+
+ union {
+ char buf[CMSG_SPACE(sizeof(int))];
+ /* Space large enough to hold an 'int' */
+ struct cmsghdr align;
+ } controlMsg;
+ struct cmsghdr *cmsgp; /* Pointer used to iterate through
+ * headers in ancillary data
+ */
+
+ /* Parse command-line options */
+
+ useDatagramSocket = false;
+
+ while ((opt = getopt(argc, argv, "dD")) != -1) {
+ switch (opt) {
+ case 'd':
+ useDatagramSocket = true;
+ break;
+ case 'D':
+ debugging = true;
+ break;
+ default:
+ usageErr("%s [-dD] file\n"
+ " -D enable debugging\n"
+ " -d use datagram socket\n", argv[0]);
+ }
+ }
+
+ if (argc != optind + 1)
+ usageErr("%s [-dD] file\n", argv[0]);
+
+ /* Open the file named on the command line */
+
+ fd = open(argv[optind], O_RDONLY);
+ if (fd == -1)
+ errExit("open");
+
+ /* The 'msg_name' field can be used to specify the address of the
+ * destination socket when sending a datagram. However, we do not
+ * need to use this field because we use connect() below, which sets
+ * a default outgoing address for datagrams.
+ */
+
+ msgh.msg_name = NULL;
+ msgh.msg_namelen = 0;
+
+ /* On Linux, we must transmit at least 1 byte of real data in
+ * order to send ancillary data
+ */
+
+ msgh.msg_iov = &iov;
+ msgh.msg_iovlen = 1;
+ iov.iov_base = &data;
+ iov.iov_len = sizeof(int);
+ data = 12345;
+ debug("Sending data = %d\n", data);
+
+ /* Set 'msgh' fields to describe the ancillary data buffer */
+
+ msgh.msg_control = controlMsg.buf;
+ msgh.msg_controllen = sizeof(controlMsg.buf);
+
+ /* The control message buffer must be zero-initialized in order
+ * for the CMSG_NXTHDR() macro to work correctly. Although we
+ * don't need to use CMSG_NXTHDR() in this example (because
+ * there is only one block of ancillary data), we show this
+ * step to demonstrate best practice
+ */
+
+ memset(controlMsg.buf, 0, sizeof(controlMsg.buf));
+
+ /* Set message header to describe the ancillary data that
+ * we want to send
+ */
+
+ cmsgp = CMSG_FIRSTHDR(&msgh);
+ cmsgp->cmsg_len = CMSG_LEN(sizeof(int));
+ cmsgp->cmsg_level = SOL_SOCKET;
+ cmsgp->cmsg_type = SCM_RIGHTS;
+ memcpy(CMSG_DATA(cmsgp), &fd, sizeof(int));
+
+ /* Connect to the peer socket */
+
+ sfd = unixConnect(SOCK_PATH, useDatagramSocket ? SOCK_DGRAM : SOCK_STREAM);
+ if (sfd == -1)
+ errExit("unixConnect");
+
+ debug("Sending FD %d\n", fd);
+
+ /* Send real plus ancillary data */
+
+ ns = sendmsg(sfd, &msgh, 0);
+ if (ns == -1)
+ errExit("sendmsg");
+
+ debug("sendmsg() returned %ld\n", (long) ns);
+
+ /* Once the file descriptor has been sent, it is no longer necessary
+ * to keep it open in the sending process
+ */
+
+ if (close(fd) == -1)
+ errExit("close");
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tools/testing/selftests/socket/simple_scm_rights.sh b/tools/testing/selftests/socket/simple_scm_rights.sh
new file mode 100755
index 000000000000..31ea0fc1bb6d
--- /dev/null
+++ b/tools/testing/selftests/socket/simple_scm_rights.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0+
+set -e
+
+ret=0
+hello=$(cat hello.txt)
+
+rm -f scm_rights
+(sleep 0.1; ./scm_rights_send hello.txt) &
+out=$(./scm_rights_recv)
+
+if [ "$hello" != "$out" ] ; then
+ echo "FAIL: SCM_RIGHTS fd contents mismatch"
+ ret=1
+else
+ echo "ok: SOCK_STREAM"
+fi
+
+rm -f scm_rights
+(sleep 0.1; ./scm_rights_send -d hello.txt) &
+out=$(./scm_rights_recv -d)
+
+if [ "$hello" != "$out" ] ; then
+ echo "FAIL: SCM_RIGHTS fd contents mismatch"
+ ret=1
+else
+ echo "ok: SOCK_DGRAM"
+fi
+
+exit $ret
diff --git a/tools/testing/selftests/socket/unix_sockets.c b/tools/testing/selftests/socket/unix_sockets.c
new file mode 100644
index 000000000000..a7678fad1a16
--- /dev/null
+++ b/tools/testing/selftests/socket/unix_sockets.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * unix_sockets.c
+ *
+ * Copyright (C) Michael Kerrisk, 2020.
+ *
+ * A package of useful routines for UNIX domain sockets.
+ */
+#include "unix_sockets.h" /* Declares functions defined here */
+
+/* Build a UNIX domain socket address structure for 'path', returning
+ * it in 'addr'. Returns -1 on success, or 0 on error.
+ */
+
+int
+unixBuildAddress(const char *path, struct sockaddr_un *addr)
+{
+ if (addr == NULL || path == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset(addr, 0, sizeof(struct sockaddr_un));
+ addr->sun_family = AF_UNIX;
+ if (strlen(path) < sizeof(addr->sun_path)) {
+ strncpy(addr->sun_path, path, sizeof(addr->sun_path) - 1);
+ return 0;
+ } else {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+}
+
+/* Create a UNIX domain socket of type 'type' and connect it
+ * to the remote address specified by the 'path'.
+ * Return the socket descriptor on success, or -1 on error
+ */
+
+int
+unixConnect(const char *path, int type)
+{
+ int sd, savedErrno;
+ struct sockaddr_un addr;
+
+ if (unixBuildAddress(path, &addr) == -1)
+ return -1;
+
+ sd = socket(AF_UNIX, type, 0);
+ if (sd == -1)
+ return -1;
+
+ if (connect(sd, (struct sockaddr *) &addr,
+ sizeof(struct sockaddr_un)) == -1) {
+ savedErrno = errno;
+ close(sd); /* Might change 'errno' */
+ errno = savedErrno;
+ return -1;
+ }
+
+ return sd;
+}
+
+/* Create a UNIX domain socket and bind it to 'path'.
+ * Return the socket descriptor on success, or -1 on error.
+ */
+
+int
+unixBind(const char *path, int type)
+{
+ int sd, savedErrno;
+ struct sockaddr_un addr;
+
+ if (unixBuildAddress(path, &addr) == -1)
+ return -1;
+
+ sd = socket(AF_UNIX, type, 0);
+ if (sd == -1)
+ return -1;
+
+ if (bind(sd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un)) == -1) {
+ savedErrno = errno;
+ close(sd); /* Might change 'errno' */
+ errno = savedErrno;
+ return -1;
+ }
+
+ return sd;
+}
diff --git a/tools/testing/selftests/socket/unix_sockets.h b/tools/testing/selftests/socket/unix_sockets.h
new file mode 100644
index 000000000000..e03a5aecd10c
--- /dev/null
+++ b/tools/testing/selftests/socket/unix_sockets.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * unix_sockets.h
+ *
+ * Copyright (C) Michael Kerrisk, 2020.
+ *
+ * Header file for unix_sockets.c.
+ */
+#ifndef UNIX_SOCKETS_H
+#define UNIX_SOCKETS_H /* Prevent accidental double inclusion */
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+int unixBuildAddress(const char *path, struct sockaddr_un *addr);
+
+int unixConnect(const char *path, int type);
+
+int unixBind(const char *path, int type);
+
+#endif
--
2.25.1
--
Kees Cook
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
The following 4 tests in timers can take longer than the default 45
seconds that added in commit 852c8cbf34d3 ("selftests/kselftest/runner.sh:
Add 45 second timeout per test") to run:
* nsleep-lat - 2m7.350s
* set-timer-lat - 2m0.66s
* inconsistency-check - 1m45.074s
* raw_skew - 2m0.013s
Thus they will be marked as failed with the current 45s setting:
not ok 3 selftests: timers: nsleep-lat # TIMEOUT
not ok 4 selftests: timers: set-timer-lat # TIMEOUT
not ok 6 selftests: timers: inconsistency-check # TIMEOUT
not ok 7 selftests: timers: raw_skew # TIMEOUT
Disable the timeout setting for timers can make these tests finish
properly:
ok 3 selftests: timers: nsleep-lat
ok 4 selftests: timers: set-timer-lat
ok 6 selftests: timers: inconsistency-check
ok 7 selftests: timers: raw_skew
https://bugs.launchpad.net/bugs/1864626
Fixes: 852c8cbf34d3 ("selftests/kselftest/runner.sh: Add 45 second timeout per test")
Signed-off-by: Po-Hsu Lin <po-hsu.lin(a)canonical.com>
---
tools/testing/selftests/timers/Makefile | 1 +
tools/testing/selftests/timers/settings | 1 +
2 files changed, 2 insertions(+)
create mode 100644 tools/testing/selftests/timers/settings
diff --git a/tools/testing/selftests/timers/Makefile b/tools/testing/selftests/timers/Makefile
index 7656c7c..0e73a16 100644
--- a/tools/testing/selftests/timers/Makefile
+++ b/tools/testing/selftests/timers/Makefile
@@ -13,6 +13,7 @@ DESTRUCTIVE_TESTS = alarmtimer-suspend valid-adjtimex adjtick change_skew \
TEST_GEN_PROGS_EXTENDED = $(DESTRUCTIVE_TESTS)
+TEST_FILES := settings
include ../lib.mk
diff --git a/tools/testing/selftests/timers/settings b/tools/testing/selftests/timers/settings
new file mode 100644
index 0000000..e7b9417
--- /dev/null
+++ b/tools/testing/selftests/timers/settings
@@ -0,0 +1 @@
+timeout=0
--
2.7.4