lkml.org 
[lkml]   [2010]   [Feb]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH] tracehook: add some self tests
Date
At the moment, we stress test the asm/syscall.h functions.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
---
arch/Kconfig | 2 +
kernel/Makefile | 1 +
kernel/tracehooktest.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++
lib/Kconfig.debug | 15 +++++
4 files changed, 152 insertions(+), 0 deletions(-)
create mode 100644 kernel/tracehooktest.c

diff --git a/arch/Kconfig b/arch/Kconfig
index 7f418bb..9c2add3 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -105,6 +105,8 @@ config HAVE_KRETPROBES
# TIF_NOTIFY_RESUME calls tracehook_notify_resume()
# signal delivery calls tracehook_signal_handler()
#
+# See CONFIG_TRACEHOOK_SELF_TEST for some test code to help.
+#
config HAVE_ARCH_TRACEHOOK
bool

diff --git a/kernel/Makefile b/kernel/Makefile
index d7c13d2..5b5e4e4 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_FREEZER) += power/
obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
obj-$(CONFIG_KEXEC) += kexec.o
obj-$(CONFIG_BACKTRACE_SELF_TEST) += backtracetest.o
+obj-$(CONFIG_TRACEHOOK_SELF_TEST) += tracehooktest.o
obj-$(CONFIG_COMPAT) += compat.o
obj-$(CONFIG_CGROUPS) += cgroup.o
obj-$(CONFIG_CGROUP_FREEZER) += cgroup_freezer.o
diff --git a/kernel/tracehooktest.c b/kernel/tracehooktest.c
new file mode 100644
index 0000000..3a7d491
--- /dev/null
+++ b/kernel/tracehooktest.c
@@ -0,0 +1,134 @@
+/*
+ * Self tests for the misc pieces of the tracehook code.
+ *
+ * Copyright 2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/ptrace.h>
+
+#include <asm/syscall.h>
+
+static int __init syscall_test(void)
+{
+ struct pt_regs _regs, *regs = &_regs;
+ long _args[8];
+ long *args = _args + 1;
+ long *sys_args[6], *sa;
+ unsigned int i, n, s;
+
+ /*
+ * First find each system register in pt_regs. We have to assume
+ * syscall_set_arguments() works with very basic arguments.
+ */
+ pr_info("TEST: asm/syscall.h: arg offsets: { ");
+
+ for (s = 0; s < 6; ++s)
+ args[s] = s;
+ memset(regs, 0xad, sizeof(*regs));
+ syscall_set_arguments(NULL, regs, 0, 6, args);
+
+ for (s = 0; s < 6; ++s) {
+ for (sa = (long *)regs; sa < (long *)(regs + 1); ++sa)
+ if (memcmp(&s, sa, sizeof(s)) == 0)
+ break;
+ if (sa == (long *)(regs + 1)) {
+ pr_cont(" FAIL (couldn't locate sys arg %u)\n", s);
+ return 1;
+ }
+ sys_args[s] = sa;
+ pr_cont("%li ", (unsigned long)sa - (unsigned long)regs);
+ }
+ pr_cont("}: PASS\n");
+
+ /* Make sure syscall_get_arguments() works with basic args */
+ pr_info("TEST: asm/syscall.h: basic syscall_get_arguments(): ");
+ memset(regs, 0xad, sizeof(*regs));
+ for (s = 0; s < 6; ++s)
+ *sys_args[s] = s;
+ syscall_get_arguments(NULL, regs, 0, 6, args);
+ for (s = 0; s < 6; ++s)
+ if (args[s] != s) {
+ pr_cont("FAIL with arg %i (%li)\n", s, args[s]);
+ return 1;
+ }
+ pr_cont("PASS\n");
+
+ /* Now brute force all values of i/n */
+ pr_info("TEST: asm/syscall.h: all i/n get/set combos: ");
+ for (i = 0; i < 6; ++i) {
+ for (n = 0; n < 7 - i; ++n) {
+
+ /* Seed for syscall_get_arguments() test */
+ for (s = 0; s < 6; ++s)
+ *sys_args[s] = -(s + 1);
+ memset(_args, 0, sizeof(_args));
+ syscall_get_arguments(NULL, regs, i, n, args);
+
+ /* Check canaries */
+ if (_args[0] != 0 || _args[7] != 0)
+ goto abort_i_n_get_tests;
+
+ /* Check all system argument values */
+ for (s = i; s < i + n; ++s)
+ if (*sys_args[s] != args[s - i])
+ goto abort_i_n_get_tests;
+
+ /* Check all unused slots */
+ for (s = i + n; s < 7; ++s)
+ if (args[s] != 0)
+ goto abort_i_n_get_tests;
+
+ /* Seed for syscall_set_arguments() test */
+ for (s = 0; s < 6; ++s)
+ args[s] = -(s + 1);
+ memset(regs, 0, sizeof(*regs));
+ syscall_set_arguments(NULL, regs, i, n, args);
+
+ /* Check the entire register set */
+ for (sa = (long *)regs; sa < (long *)(regs + 1); ++sa) {
+ if (*sa == 0)
+ continue;
+ /* Only some args should be set */
+ for (s = i; s < i + n; ++s)
+ if (sa == sys_args[s])
+ break;
+ if (s == i + n)
+ goto abort_i_n_set_tests;
+ }
+
+ /* Check the valid system argument values */
+ for (s = i; s < i + n; ++s)
+ if (*sys_args[s] != -(s + 1 - i))
+ goto abort_i_n_set_tests;
+ }
+ }
+ pr_cont("PASS\n");
+
+ return 0;
+
+ abort_i_n_get_tests:
+ pr_cont("FAIL (get @ i=%u n=%u)\n", i, n);
+ return 1;
+ abort_i_n_set_tests:
+ pr_cont("FAIL (set @ i=%u n=%u)\n", i, n);
+ return 1;
+}
+
+static int __init tracehooktest_init(void)
+{
+ return syscall_test();
+}
+module_init(tracehooktest_init);
+
+static void __exit tracehooktest_exit(void)
+{
+ /* stub to unload */
+}
+module_exit(tracehooktest_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>");
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 139fdbc..34b6793 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -788,6 +788,21 @@ config BACKTRACE_SELF_TEST

Say N if you are unsure.

+config TRACEHOOK_SELF_TEST
+ tristate "Self test for the tracehook code"
+ depends on HAVE_ARCH_TRACEHOOK
+ default n
+ help
+ This option provides a kernel module that can be used to test
+ the kernel stack tracehook code. This option is not useful
+ for distributions or general kernels, but only for kernel
+ developers working on architecture code.
+
+ Say N if you are unsure.
+
+ Choose M here to compile this code as a module. The module will
+ be called tracehooktest.
+
config DEBUG_BLOCK_EXT_DEVT
bool "Force extended block device numbers and spread them"
depends on DEBUG_KERNEL
--
1.7.0


\
 
 \ /
  Last update: 2010-02-15 07:19    [W:2.341 / U:0.008 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site