From patchwork Fri Mar 9 12:44:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Moese X-Patchwork-Id: 883602 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.linux.it (client-ip=213.254.12.146; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.de Received: from picard.linux.it (picard.linux.it [213.254.12.146]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zyRsY3rmZz9sWr for ; Fri, 9 Mar 2018 23:44:33 +1100 (AEDT) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id 046343E757A for ; Fri, 9 Mar 2018 13:44:31 +0100 (CET) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-4.smtp.seeweb.it (in-4.smtp.seeweb.it [217.194.8.4]) by picard.linux.it (Postfix) with ESMTP id 6A6333E748C for ; Fri, 9 Mar 2018 13:44:21 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by in-4.smtp.seeweb.it (Postfix) with ESMTPS id 80AE51001529 for ; Fri, 9 Mar 2018 13:44:20 +0100 (CET) Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id F130EACCD for ; Fri, 9 Mar 2018 12:44:19 +0000 (UTC) From: Michael Moese To: ltp@lists.linux.it Date: Fri, 9 Mar 2018 13:44:16 +0100 Message-Id: <20180309124418.30271-2-mmoese@suse.de> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180309124418.30271-1-mmoese@suse.de> References: <20180309124418.30271-1-mmoese@suse.de> X-Virus-Scanned: clamav-milter 0.99.2 at in-4.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=-0.0 required=7.0 tests=SPF_PASS, T_RP_MATCHES_RCVD autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-4.smtp.seeweb.it Subject: [LTP] [PATCH v6 1/3] Add library support for /proc/sys/kernel/tainted X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.18 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" Sometimes, it is important to detect if the kernel has issued a warning, died, or is tainted in another way. Linux provides this information in /proc/sys/kernel/tainted in the form of a bitfield. This patch provides library functions for testcases to detect, if it has tainted the kernel. The following functions will be introduced: - int tst_taint_init(unsigned int mask) check if the flags supplied as mask are supported by the running kernel, and if so, if they are not yet set. - int tst_taint_check() check if one or more of the bits specified in the mask provided to tst_taint_init() before are set. Returns 0 if those flags are not set, or the bitmask of set flags These can be used in the following way: First, during testcase setup: void setup(void) { ... tst_taint_init(TST_TAINT_W | TST_TAINT_D); } Second, check if the test triggered a bug: void run(void) { ... . test code here ... if (tst_taint_check() != 0) tst_res(TFAIL, "kernel has issues"); else tst_res(TPASS, "kernel seems to be fine"); } Signed-off-by: Michael Moese --- doc/test-writing-guidelines.txt | 42 ++++++++++++++++ include/tst_taint.h | 104 +++++++++++++++++++++++++++++++++++++++ lib/tst_taint.c | 106 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 252 insertions(+) create mode 100644 include/tst_taint.h create mode 100644 lib/tst_taint.c diff --git a/doc/test-writing-guidelines.txt b/doc/test-writing-guidelines.txt index 4c60cd66b..5082a07be 100644 --- a/doc/test-writing-guidelines.txt +++ b/doc/test-writing-guidelines.txt @@ -1320,6 +1320,48 @@ common.h:9: FAIL: check failed test.c:8: INFO: do_action(arg) failed ------------------------------------------------------------------------------- +2.2.24 Tainted kernels +^^^^^^^^^^^^^^^^^^^^^^ + +If you need to detect, if a testcase triggers a kernel warning, bug or oops, +the following can be used to detect TAINT_W or TAINT_D: + +[source,c] +------------------------------------------------------------------------------- +#include "tst_test.h" +#include "tst_taint.h" + +void setup(void) +{ + ... + tst_taint_init(TST_TAINT_W | TST_TAINT_D); + ... +} +... +void run(void) +{ + ... + if (tst_taint_check() == 0) + tst_res(TPASS, "kernel is not tainted"); + else + tst_res(TFAIL, "kernel is tainted"); +} +------------------------------------------------------------------------------- + +You have to call tst_taint_init() with non-zero flags first, preferably during +setup(). The function will generate a TCONF if the requested flags are not +fully supported on the running kernel, and TBROK if either a zero mask was +supplied or if the kernel is already tainted before executing the test. + +Then you can call tst_taint_check() during run(), which returns 0 or the +tainted flags set in /proc/sys/kernel/tainted as specified earlier. + +Depending on your kernel version, not all tainted-flags will be supported. + +For reference to tainted kernels, see kernel documentation: +Documentation/admin-guide/tainted-kernels.rst or +https://www.kernel.org/doc/html/latest/admin-guide/tainted-kernels.html + 2.3 Writing a testcase in shell ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/include/tst_taint.h b/include/tst_taint.h new file mode 100644 index 000000000..1039e2ddc --- /dev/null +++ b/include/tst_taint.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2018 Michael Moese + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Usage example + * + * ... + * #include "tst_test.h" + * #include "tst_taint.h" + * .. + * void setup(void) + * { + * ... + * tst_taint_init(TST_TAINT_W | TST_TAINT_D)); + * ... + * } + * + * void run(void) + * { + * ... + * . test code here + * ... + * if (tst_taint_check() != 0) + * tst_res(TFAIL, "kernel has issues"); + * else + * tst_res(TPASS, "kernel seems to be fine"); + * } + * + * + * + * The above code checks, if the kernel issued a warning (TST_TAINT_W) + * or even died (TST_TAINT_D) during test execution. + * If these are set after running a test case, we most likely + * triggered a kernel bug. + */ + +#ifndef TST_TAINTED_H__ +#define TST_TAINTED_H__ + +/* + * This are all 17 flags that are present in kernel 4.15 + * see kernel/panic.c in kernel sources + * + * Not all of them are valid in all kernel versions. + */ +#define TST_TAINT_G (1 << 0) /* a module with non-GPL license loaded */ +#define TST_TAINT_F (1 << 1) /* a module was force-loaded */ +#define TST_TAINT_S (1 << 2) /* SMP with Non-SMP kernel */ +#define TST_TAINT_R (1 << 3) /* module force unloaded */ +#define TST_TAINT_M (1 << 4) /* machine check error occurred */ +#define TST_TAINT_B (1 << 5) /* page-release function found bad page */ +#define TST_TAINT_U (1 << 6) /* user requested taint flag */ +#define TST_TAINT_D (1 << 7) /* kernel died recently - OOPS or BUG */ +#define TST_TAINT_A (1 << 8) /* ACPI table has been overwritten */ +#define TST_TAINT_W (1 << 9) /* a warning has been issued by kernel */ +#define TST_TAINT_C (1 << 10) /* driver from drivers/staging was loaded */ +#define TST_TAINT_I (1 << 11) /* working around BIOS/Firmware bug */ +#define TST_TAINT_O (1 << 12) /* out of tree module loaded */ +#define TST_TAINT_E (1 << 13) /* unsigned module was loaded */ +#define TST_TAINT_L (1 << 14) /* A soft lock-up has previously occurred */ +#define TST_TAINT_K (1 << 15) /* kernel has been live-patched */ +#define TST_TAINT_X (1 << 16) /* auxiliary taint, for distro's use */ + +/* + * Initialize and prepare support for checking tainted kernel. + * + * supply the mask of TAINT-flags you want to check, for example + * (TST_TAINT_W | TST_TAINT_D) when you want to check if the kernel issued + * a warning or even reported it died. + * + * This function tests if the requested flags are supported on the + * locally running kernel. In case the tainted-flags are already set by + * the kernel, there is no reason to continue and TCONF is generated. + * + * The mask must not be zero. + */ +void tst_taint_init(unsigned int mask); + + +/* + * check if the tainted flags handed to tst_taint_init() are still not set + * during or after running the test. + * Calling this function is only allowed after tst_taint_init() was called, + * otherwise TBROK will be generated. + * + * returns 0 or a bitmask of the flags that currently tainted the kernel. + */ +unsigned int tst_taint_check(void); + + +#endif /* TST_TAINTED_H__ */ diff --git a/lib/tst_taint.c b/lib/tst_taint.c new file mode 100644 index 000000000..8d7a37b47 --- /dev/null +++ b/lib/tst_taint.c @@ -0,0 +1,106 @@ +#define TST_NO_DEFAULT_MAIN + +#include "tst_test.h" +#include "tst_taint.h" +#include "tst_safe_stdio.h" + +#define TAINT_FILE "/proc/sys/kernel/tainted" + +static unsigned int taint_mask = -1; + +static unsigned int tst_taint_read(void) +{ + unsigned int val; + + if (taint_mask == (unsigned int) -1) + tst_brk(TBROK, "need to call tst_taint_init() first"); + + SAFE_FILE_SCANF(TAINT_FILE, "%u", &val); + + return val; +} + +static int tst_taint_check_kver(unsigned int mask) +{ + int r1; + int r2; + int r3 = 0; + + if (mask & TST_TAINT_X) { + r1 = 4; + r2 = 15; + } else if (mask & TST_TAINT_K) { + r1 = 4; + r2 = 0; + } else if (mask & TST_TAINT_L) { + r1 = 3; + r2 = 17; + } else if (mask & TST_TAINT_E) { + r1 = 3; + r2 = 15; + } else if (mask & TST_TAINT_O) { + r1 = 3; + r2 = 2; + } else if (mask & TST_TAINT_I) { + r1 = 2; + r2 = 6; + r3 = 35; + } else if (mask & TST_TAINT_C) { + r1 = 2; + r2 = 6; + r3 = 28; + } else if (mask & TST_TAINT_W) { + r1 = 2; + r2 = 6; + r3 = 26; + } else if (mask & TST_TAINT_A) { + r1 = 2; + r2 = 6; + r3 = 25; + } else if (mask & TST_TAINT_D) { + r1 = 2; + r2 = 6; + r3 = 23; + } else if (mask & TST_TAINT_U) { + r1 = 2; + r2 = 6; + r3 = 21; + } else { + r1 = 2; + r2 = 6; + r3 = 16; + } + + return tst_kvercmp(r1, r2, r3); +} + +void tst_taint_init(unsigned int mask) +{ + unsigned int taint = -1; + + if (mask == 0) + tst_brk(TBROK, "mask is not allowed to be 0"); + + if (tst_taint_check_kver(mask) < 0) + tst_res(TCONF, "Kernel is too old for requested mask"); + + taint_mask = mask; + + taint = tst_taint_read(); + if ((taint & mask) != 0) + tst_brk(TBROK, "Kernel is already tainted: %u", taint); +} + + +unsigned int tst_taint_check(void) +{ + unsigned int taint = -1; + + if (taint_mask == (unsigned int) -1) + tst_brk(TBROK, "need to call tst_taint_init() first"); + + taint = tst_taint_read(); + + return (taint & taint_mask); +} + From patchwork Fri Mar 9 12:44:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Moese X-Patchwork-Id: 883599 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.linux.it (client-ip=213.254.12.146; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.de Received: from picard.linux.it (picard.linux.it [213.254.12.146]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zyRsP1d6fz9sXK for ; Fri, 9 Mar 2018 23:44:24 +1100 (AEDT) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id 041E53E749B for ; Fri, 9 Mar 2018 13:44:22 +0100 (CET) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-2.smtp.seeweb.it (in-2.smtp.seeweb.it [IPv6:2001:4b78:1:20::2]) by picard.linux.it (Postfix) with ESMTP id F3A3B3E71AB for ; Fri, 9 Mar 2018 13:44:20 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by in-2.smtp.seeweb.it (Postfix) with ESMTPS id 9FD5E60222F for ; Fri, 9 Mar 2018 13:44:20 +0100 (CET) Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 0DF79AD38 for ; Fri, 9 Mar 2018 12:44:20 +0000 (UTC) From: Michael Moese To: ltp@lists.linux.it Date: Fri, 9 Mar 2018 13:44:17 +0100 Message-Id: <20180309124418.30271-3-mmoese@suse.de> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180309124418.30271-1-mmoese@suse.de> References: <20180309124418.30271-1-mmoese@suse.de> X-Virus-Scanned: clamav-milter 0.99.2 at in-2.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=-0.0 required=7.0 tests=SPF_PASS, T_RP_MATCHES_RCVD autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-2.smtp.seeweb.it Subject: [LTP] [PATCH v6 2/3] Add a library wrapper for sigaction() X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.18 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" In a multithreaded program, using signal() results in unspecified behavior. In this case, sigaction() has to be used to install a signal handler. Therefore, SAFE_SIGACTION() is added. Signed-off-by: Michael Moese --- include/tst_safe_macros.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/include/tst_safe_macros.h b/include/tst_safe_macros.h index 06bff13c7..bf12e0719 100644 --- a/include/tst_safe_macros.h +++ b/include/tst_safe_macros.h @@ -397,6 +397,26 @@ static inline sighandler_t safe_signal(const char *file, const int lineno, #define SAFE_SIGNAL(signum, handler) \ safe_signal(__FILE__, __LINE__, (signum), (handler)) + + +static inline int safe_sigaction(const char *file, const int lineno, + int signum, const struct sigaction *act, + struct sigaction *oldact) +{ + int rval; + + rval = sigaction(signum, act, oldact); + + if (rval == -1) { + tst_brk_(file, lineno, TBROK | TERRNO, + "sigaction(%d, %p, %p) failed", signum, act, oldact); + } + + return rval; +} +#define SAFE_SIGACTION(signum, act, oldact) \ + safe_sigaction(__FILE__, __LINE__, (signum), (act), (oldact)) + #define SAFE_EXECLP(file, arg, ...) do { \ execlp((file), (arg), ##__VA_ARGS__); \ tst_brk_(__FILE__, __LINE__, TBROK | TERRNO, \ From patchwork Fri Mar 9 12:44:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Moese X-Patchwork-Id: 883601 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.linux.it (client-ip=213.254.12.146; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.de Received: from picard.linux.it (picard.linux.it [213.254.12.146]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zyRsV3bHfz9sWr for ; Fri, 9 Mar 2018 23:44:30 +1100 (AEDT) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id DC5D33E7502 for ; Fri, 9 Mar 2018 13:44:27 +0100 (CET) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-2.smtp.seeweb.it (in-2.smtp.seeweb.it [IPv6:2001:4b78:1:20::2]) by picard.linux.it (Postfix) with ESMTP id 52ABB3E748B for ; Fri, 9 Mar 2018 13:44:21 +0100 (CET) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by in-2.smtp.seeweb.it (Postfix) with ESMTPS id 8AEB7602224 for ; Fri, 9 Mar 2018 13:44:20 +0100 (CET) Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 11E0CAD6A for ; Fri, 9 Mar 2018 12:44:20 +0000 (UTC) From: Michael Moese To: ltp@lists.linux.it Date: Fri, 9 Mar 2018 13:44:18 +0100 Message-Id: <20180309124418.30271-4-mmoese@suse.de> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180309124418.30271-1-mmoese@suse.de> References: <20180309124418.30271-1-mmoese@suse.de> X-Virus-Scanned: clamav-milter 0.99.2 at in-2.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=-0.0 required=7.0 tests=SPF_PASS, T_RP_MATCHES_RCVD autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-2.smtp.seeweb.it Subject: [LTP] [PATCH v6 3/3] Add regression test for CVE-2017-17053 X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.18 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" This patch adds a regression test for CVE-2017-17053, based on the reproducer in the message of this commit: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ccd5b3235180eef3cfec337df1c8554ab151b5cc Be warned, if the running kernel is vulnerable to this CVE, it will die in most cases. Signed-off-by: Michael Moese --- runtest/cve | 1 + testcases/cve/.gitignore | 1 + testcases/cve/Makefile | 2 + testcases/cve/cve-2017-17053.c | 166 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 170 insertions(+) create mode 100644 testcases/cve/cve-2017-17053.c diff --git a/runtest/cve b/runtest/cve index 0c385c670..8c68ab496 100644 --- a/runtest/cve +++ b/runtest/cve @@ -30,3 +30,4 @@ cve-2017-17807 request_key04 cve-2017-1000364 stack_clash cve-2017-5754 meltdown cve-2017-17052 cve-2017-17052 +cve-2017-17053 cve-2017-17053 diff --git a/testcases/cve/.gitignore b/testcases/cve/.gitignore index c878069f1..c1ac83e3a 100644 --- a/testcases/cve/.gitignore +++ b/testcases/cve/.gitignore @@ -12,3 +12,4 @@ cve-2017-5669 meltdown stack_clash cve-2017-17052 +cve-2017-17053 diff --git a/testcases/cve/Makefile b/testcases/cve/Makefile index 86100dbf2..3a05dd4fe 100644 --- a/testcases/cve/Makefile +++ b/testcases/cve/Makefile @@ -37,6 +37,8 @@ meltdown: CFLAGS += -msse2 endif cve-2017-17052: CFLAGS += -pthread +cve-2017-17053: CFLAGS += -pthread + cve-2015-3290: CFLAGS += -pthread include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/cve/cve-2017-17053.c b/testcases/cve/cve-2017-17053.c new file mode 100644 index 000000000..523ee53c3 --- /dev/null +++ b/testcases/cve/cve-2017-17053.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2018 Michael Moese + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/* Regression test for CVE-2017-17053, original reproducer can be found + * here: + * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ccd5b3235180eef3cfec337df1c8554ab151b5cc + * + * Be careful! This test may crash your kernel! + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tst_test.h" +#include "tst_taint.h" +#include "lapi/syscalls.h" + +#define EXEC_USEC 5000000 + +/* this is basically identical to SAFE_PTHREAD_CREATE(), but is tolerating the + * call to fail whenn the error is EAGAIN or EWOULDBLOCK */ +static void try_pthread_create(pthread_t *thread_id, const pthread_attr_t *attr, + void *(*thread_fn)(void *), void *arg) +{ + int rval; + + rval = pthread_create(thread_id, attr, thread_fn, arg); + + if (rval && rval != EAGAIN && rval != EWOULDBLOCK) + tst_brk(TBROK, "pthread_create(%p,%p,%p,%p) failed: %s", + thread_id, attr, thread_fn, arg, tst_strerrno(rval)); +} + +/* this is basically identical to SAFE_FORK(), but is tolerating the + * call to fail whenn the error is EAGAIN or EWOULDBLOCK */ +static int try_fork(void) +{ + pid_t pid; + + tst_flush(); + + pid = fork(); + if (pid < 0 && errno != EAGAIN && errno == EWOULDBLOCK) + tst_brk(TBROK | TERRNO, "fork() failed"); + + return pid; +} + + + +struct shm_data { + volatile sig_atomic_t do_exit; + volatile sig_atomic_t segfaulted; +}; +static struct shm_data *shm; + +static void handler(int sig) +{ + (void)sig; + + shm->segfaulted = 1; + shm->do_exit = 1; +} + +static void install_sighandler(void) +{ + struct sigaction sa; + + sa.sa_flags = SA_SIGINFO; + sigemptyset(&sa.sa_mask); + sa.sa_handler = handler; + + SAFE_SIGACTION(SIGSEGV, &sa, NULL); +} + +static void setup(void) +{ + tst_taint_init(TST_TAINT_W | TST_TAINT_D); + + shm = SAFE_MMAP(NULL, sizeof(struct shm_data), + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, -1, 0); +} + +static void cleanup(void) +{ + SAFE_MUNMAP(shm, sizeof(struct shm_data)); +} + +static void *fork_thread(void *arg) +{ + try_fork(); + return arg; +} + +void run_test(void) +{ + struct user_desc desc = { .entry_number = 8191 }; + + install_sighandler(); + syscall(__NR_modify_ldt, 1, &desc, sizeof(desc)); + + for (;;) { + if (shm->do_exit) + exit(0); + + if (try_fork() == 0) { + pthread_t t; + + srand(getpid()); + try_pthread_create(&t, NULL, fork_thread, NULL); + usleep(rand() % 10000); + syscall(__NR_exit_group, 0); + } + } +} + +void run(void) +{ + int status; + pid_t pid; + + shm->do_exit = 0; + shm->segfaulted = 0; + + pid = SAFE_FORK(); + if (pid == 0) { + run_test(); + } else { + usleep(EXEC_USEC); + shm->do_exit = 1; + } + + SAFE_WAIT(&status); + + if (WIFEXITED(status) && shm->segfaulted == 0 && tst_taint_check() == 0) + tst_res(TPASS, "kernel survived"); + else + tst_res(TFAIL, "kernel is vulnerable"); +} + +static struct tst_test test = { + .forks_child = 1, + .setup = setup, + .cleanup = cleanup, + .test_all = run, +};