Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp1784605yba; Thu, 4 Apr 2019 19:01:26 -0700 (PDT) X-Google-Smtp-Source: APXvYqwr6s90t5fEO7ZRxnCUNhEF8AdPXQagUdw91InuWwreEAZe6TP78VMeudaMFIdyFuqCQQe8 X-Received: by 2002:aa7:9ab7:: with SMTP id x23mr4440759pfi.27.1554429686416; Thu, 04 Apr 2019 19:01:26 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1554429686; cv=none; d=google.com; s=arc-20160816; b=ryTpl65Cd3rWqTkBTvNebSwgItT9I4VA03ekI5kLrBmOUPvIWTIDkPZJ72MEutHZ+q 9I3qX4pfrzP5214BIiHpOF4DUK/7ZPmmd8r3IVqN1AKZ5PD11LvZ7AZ4x941vYKv+hdo e2LZSQ1k4aDRzUAmu7z5mcRzDHoJrrK5oV0NMem9Vd+i1UntLSclmNItlY8DGXHZ81t1 II3DyH/aWofuHKN1XS/r0JlBa1B8eLV96dPGuAY9VHucHgxTKuIGs3uNeG4NKA/KfqaI ZpZJooXIpWnqZrwWt++c4hN/6BQPIx0t9ZS6AWjypRMUzGLr8QkuMaDrKSD5TmZFwT3y zlBQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=ZCPoVm3c/aDatSPSEWIy/ABm05Z1o6QsVVRHRX6rMuA=; b=CsaBy4Zkc2/eZLLgcqwOfnsp1XV9gTp7064clRqIfpybBFRCLpR5+1y7x32j2V23da bZiE++p+2US+4npiOPQuiuZcRksYSJ4gDasq/Vz8mx9qv9oljXzfmiYA55lAiiCZ5IWV w3p3QTpJF8kLoS4BZ0Qvu4klgQaClTtrFzMV7VahmcKD3WpXvwQSg3VdM/QPb3eHynDm Qh70V6K+mP+G0mlcnVRbl/0DCKYrrrnzJN3kmbjfwZ+5QgOjQiaU8jXR1hPJ35Xu8M9i 5B6PNULQi6cBooRLGt0pZMEzm11XVQyvCj3ILbA6F3sj69A16meP5GnMF5mJWbnR99wS KIUw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@messagingengine.com header.s=fm2 header.b=fUIxs2Hn; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id u4si7876152pga.245.2019.04.04.19.01.10; Thu, 04 Apr 2019 19:01:26 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@messagingengine.com header.s=fm2 header.b=fUIxs2Hn; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730724AbfDECAU (ORCPT + 99 others); Thu, 4 Apr 2019 22:00:20 -0400 Received: from out1-smtp.messagingengine.com ([66.111.4.25]:57951 "EHLO out1-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727051AbfDECAT (ORCPT ); Thu, 4 Apr 2019 22:00:19 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailout.nyi.internal (Postfix) with ESMTP id AA40D24BF1; Thu, 4 Apr 2019 22:00:18 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute3.internal (MEProxy); Thu, 04 Apr 2019 22:00:18 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=ZCPoVm3c/aDatSPSEWIy/ABm05Z1o6QsVVRHRX6rMuA=; b=fUIxs2Hn taDA4meVA+92wKx+osRLZFMCrqLH0hZkP/IJ7xRFp0UF3QkOOIa+NyPd563Mzd3P e8ERDKps7zo4qKB/oYGmzxegTwQARfDYUk5RVDrbxyQui79/ReZc+NvaFxwFDEPr rBAfnTi/9XWe/Qb6W/HyqBZ7Nf1QHAcv3wK9NvIlzjyJ/e5EYW/29Zq59Ngiqm3V 6IUdYZqigtnqwavq3SMd98sCh6LOkDu+B7mdxQ/4B92bJLoyHtA8JC5k+cqU5zdS 5XzZRmtqEpKG+r6mfQueYXDKwpY/OgFWFw5NbKIZYbqihxT04gH9lhzAgAW+nZ9a G9+jkIqyVouXXw== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduuddrtdeigdehtdculddtuddrgedutddrtddtmd cutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdp uffrtefokffrpgfnqfghnecuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivg hnthhsucdlqddutddtmdenucfjughrpefhvffufffkofgjfhgggfestdekredtredttden ucfhrhhomhepfdfvohgsihhnucevrdcujfgrrhguihhnghdfuceothhosghinheskhgvrh hnvghlrdhorhhgqeenucfkphepuddvgedrudegledruddugedrkeeinecurfgrrhgrmhep mhgrihhlfhhrohhmpehtohgsihhnsehkvghrnhgvlhdrohhrghenucevlhhushhtvghruf hiiigvpedv X-ME-Proxy: Received: from eros.localdomain (124-149-114-86.dyn.iinet.net.au [124.149.114.86]) by mail.messagingengine.com (Postfix) with ESMTPA id 7DAF71031A; Thu, 4 Apr 2019 22:00:12 -0400 (EDT) From: "Tobin C. Harding" To: Shuah Khan Cc: "Tobin C. Harding" , Kees Cook , Jann Horn , Andy Shevchenko , Randy Dunlap , Rasmus Villemoes , Stephen Rothwell , Andy Lutomirski , Daniel Micay , Arnd Bergmann , Miguel Ojeda , "Gustavo A. R. Silva" , Greg Kroah-Hartman , Alexander Shishkin , kernel-hardening@lists.openwall.com, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 3/6] kselftest: Add test module framework header Date: Fri, 5 Apr 2019 12:58:56 +1100 Message-Id: <20190405015859.32755-4-tobin@kernel.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190405015859.32755-1-tobin@kernel.org> References: <20190405015859.32755-1-tobin@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org kselftest runs as a userspace process. Sometimes we need to test things from kernel space. One way of doing this is by creating a test module. Currently doing so requires developers to write a bunch of boiler plate in the module if kselftest is to be used to run the tests. This means we currently have a load of duplicate code to achieve these ends. If we have a uniform method for implementing test modules then we can reduce code duplication, ensure uniformity in the test framework, ease code maintenance, and reduce the work required to create tests. This all helps to encourage developers to write and run tests. Add a C header file that can be included in test modules. This provides a single point for common test functions/macros. Implement a few macros that make up the start of the test framework. Add documentation for new kselftest header to kselftest documentation. Acked-by: Kees Cook Signed-off-by: Tobin C. Harding --- Documentation/dev-tools/kselftest.rst | 94 +++++++++++++++++++++- tools/testing/selftests/kselftest_module.h | 48 +++++++++++ 2 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 tools/testing/selftests/kselftest_module.h diff --git a/Documentation/dev-tools/kselftest.rst b/Documentation/dev-tools/kselftest.rst index 7756f7a7c23b..c8c03388b9de 100644 --- a/Documentation/dev-tools/kselftest.rst +++ b/Documentation/dev-tools/kselftest.rst @@ -14,6 +14,10 @@ in safe mode with a limited scope. In limited mode, cpu-hotplug test is run on a single cpu as opposed to all hotplug capable cpus, and memory hotplug test is run on 2% of hotplug capable memory instead of 10%. +kselftest runs as a userspace process. Tests that can be written/run in +userspace may wish to use the `Test Harness`_. Tests that need to be +run in kernel space may wish to use a `Test Module`_. + Running the selftests (hotplug tests are run in limited mode) ============================================================= @@ -161,11 +165,97 @@ Contributing new tests (details) e.g: tools/testing/selftests/android/config +Test Module +=========== + +Kselftest tests the kernel from userspace. Sometimes things need +testing from within the kernel, one method of doing this is to create a +test module. We can tie the module into the kselftest framework by +using a shell script test runner. ``kselftest_module.sh`` is designed +to facilitate this process. There is also a header file provided to +assist writing kernel modules that are for use with kselftest: + +- ``tools/testing/kselftest/kselftest_module.h`` +- ``tools/testing/kselftest/kselftest_module.sh`` + +How to use +---------- + +Here we show the typical steps to create a test module and tie it into +kselftest. We use kselftests for lib/ as an example. + +1. Create the test module + +2. Create the test script that will run (load/unload) the module + e.g. ``tools/testing/selftests/lib/printf.sh`` + +3. Add line to config file e.g. ``tools/testing/selftests/lib/config`` + +4. Add test script to makefile e.g. ``tools/testing/selftests/lib/Makefile`` + +5. Verify it works: + +.. code-block:: sh + + # Assumes you have booted a fresh build of this kernel tree + cd /path/to/linux/tree + make kselftest-merge + make modules + sudo make modules_install + make TARGETS=lib kselftest + +Example Module +-------------- + +A bare bones test module might look like this: + +.. code-block:: c + + // SPDX-License-Identifier: GPL-2.0+ + + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include "../tools/testing/selftests/kselftest_module.h" + + KSTM_MODULE_GLOBALS(); + + /* + * Kernel module for testing the foobinator + */ + + static int __init test_function() + { + ... + } + + static void __init selftest(void) + { + KSTM_CHECK_ZERO(do_test_case("", 0)); + } + + KSTM_MODULE_LOADERS(test_foo); + MODULE_AUTHOR("John Developer "); + MODULE_LICENSE("GPL"); + +Example test script +------------------- + +.. code-block:: sh + + #!/bin/bash + # SPDX-License-Identifier: GPL-2.0+ + $(dirname $0)/../kselftest_module.sh "foo" test_foo + + Test Harness ============ -The kselftest_harness.h file contains useful helpers to build tests. The tests -from tools/testing/selftests/seccomp/seccomp_bpf.c can be used as example. +The kselftest_harness.h file contains useful helpers to build tests. The +test harness is for userspace testing, for kernel space testing see `Test +Module`_ above. + +The tests from tools/testing/selftests/seccomp/seccomp_bpf.c can be used as +example. Example ------- diff --git a/tools/testing/selftests/kselftest_module.h b/tools/testing/selftests/kselftest_module.h new file mode 100644 index 000000000000..e8eafaf0941a --- /dev/null +++ b/tools/testing/selftests/kselftest_module.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +#ifndef __KSELFTEST_MODULE_H +#define __KSELFTEST_MODULE_H + +#include + +/* + * Test framework for writing test modules to be loaded by kselftest. + * See Documentation/dev-tools/kselftest.rst for an example test module. + */ + +#define KSTM_MODULE_GLOBALS() \ +static unsigned int total_tests __initdata; \ +static unsigned int failed_tests __initdata + +#define KSTM_CHECK_ZERO(x) do { \ + total_tests++; \ + if (x) { \ + pr_warn("TC failed at %s:%d\n", __func__, __LINE__); \ + failed_tests++; \ + } \ +} while (0) + +static inline int kstm_report(unsigned int total_tests, unsigned int failed_tests) +{ + if (failed_tests == 0) + pr_info("all %u tests passed\n", total_tests); + else + pr_warn("failed %u out of %u tests\n", failed_tests, total_tests); + + return failed_tests ? -EINVAL : 0; +} + +#define KSTM_MODULE_LOADERS(__module) \ +static int __init __module##_init(void) \ +{ \ + pr_info("loaded.\n"); \ + selftest(); \ + return kstm_report(total_tests, failed_tests); \ +} \ +static void __exit __module##_exit(void) \ +{ \ + pr_info("unloaded.\n"); \ +} \ +module_init(__module##_init); \ +module_exit(__module##_exit) + +#endif /* __KSELFTEST_MODULE_H */ -- 2.21.0