All of lore.kernel.org
 help / color / mirror / Atom feed
* [LTP] [PATCH v2] Add library support for /proc/sys/kernel/tainted
@ 2018-01-25 12:16 Michael Moese
  2018-01-25 12:26 ` Michael Moese
  2018-01-25 13:28 ` Cyril Hrubis
  0 siblings, 2 replies; 4+ messages in thread
From: Michael Moese @ 2018-01-25 12:16 UTC (permalink / raw)
  To: ltp

Someteimes, 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 <mmoese@suse.de>
---
 include/tst_taint.h | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/tst_taint.c     | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 210 insertions(+)
 create mode 100644 include/tst_taint.h
 create mode 100644 lib/tst_taint.c

diff --git a/include/tst_taint.h b/include/tst_taint.h
new file mode 100644
index 000000000..89162b44c
--- /dev/null
+++ b/include/tst_taint.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2018 Michael Moese <mmoese@suse.de>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/* 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..723a25c0e
--- /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 = tst_taint_read();
+	if ((taint & mask) != 0)
+		tst_res(TCONF, "Kernel is already tainted: %u", taint);
+
+	taint_mask = mask;
+}
+
+
+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);
+}
+
-- 
2.13.6


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [LTP] [PATCH v2] Add library support for /proc/sys/kernel/tainted
  2018-01-25 12:16 [LTP] [PATCH v2] Add library support for /proc/sys/kernel/tainted Michael Moese
@ 2018-01-25 12:26 ` Michael Moese
  2018-01-25 13:28 ` Cyril Hrubis
  1 sibling, 0 replies; 4+ messages in thread
From: Michael Moese @ 2018-01-25 12:26 UTC (permalink / raw)
  To: ltp

Hi,
I'm sorry I sent the wrong patch file. 
I will wait if you have other remarks, then re-send this.

> +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 = tst_taint_read();
> +	if ((taint & mask) != 0)
> +		tst_res(TCONF, "Kernel is already tainted: %u", taint);
> +
> +	taint_mask = mask;

This line above should go before the call to tst_taint_read()

Thx,
Michael
-- 
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [LTP] [PATCH v2] Add library support for /proc/sys/kernel/tainted
  2018-01-25 12:16 [LTP] [PATCH v2] Add library support for /proc/sys/kernel/tainted Michael Moese
  2018-01-25 12:26 ` Michael Moese
@ 2018-01-25 13:28 ` Cyril Hrubis
  2018-01-25 14:20   ` Michael Moese
  1 sibling, 1 reply; 4+ messages in thread
From: Cyril Hrubis @ 2018-01-25 13:28 UTC (permalink / raw)
  To: ltp

Hi!
> diff --git a/include/tst_taint.h b/include/tst_taint.h
> new file mode 100644
> index 000000000..89162b44c
> --- /dev/null
> +++ b/include/tst_taint.h
> @@ -0,0 +1,104 @@
> +/*
> + * Copyright (c) 2018 Michael Moese <mmoese@suse.de>
> + *
> + * 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 <http://www.gnu.org/licenses/>.
> + */
> +
> +/* 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)
          ^
	  Missing space, but that is very minor.
> + *		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.
> + */

API looks good, nice work.

> diff --git a/lib/tst_taint.c b/lib/tst_taint.c
> new file mode 100644
> index 000000000..723a25c0e
> --- /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;
> +	}

I would have probably put these into an array of structures indexed by
the position of the flag bit, but it's fine as it is as well.

> +	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 = tst_taint_read();
> +	if ((taint & mask) != 0)
> +		tst_res(TCONF, "Kernel is already tainted: %u", taint);
                          ^
			  I would argue this is TBROK rather than TCONF,
			  since the test is applicable just cannot be
			  run since kernel is tainted already.

			  TCONF means "test not applicable" usually due
			  to unsupported architecture, old kernel, etc.

> +	taint_mask = mask;
> +}
> +
> +
> +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);
> +}

Other than the minor things, this version looks good.

Can you please also add a paragraph 2.2.23 with the documentation to the
doc/test-writing-guidelines.txt (asciidoc formatted)?

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [LTP] [PATCH v2] Add library support for /proc/sys/kernel/tainted
  2018-01-25 13:28 ` Cyril Hrubis
@ 2018-01-25 14:20   ` Michael Moese
  0 siblings, 0 replies; 4+ messages in thread
From: Michael Moese @ 2018-01-25 14:20 UTC (permalink / raw)
  To: ltp

Hi,

On Thu, Jan 25, 2018 at 02:28:15PM +0100, Cyril Hrubis wrote:

> I would have probably put these into an array of structures indexed by
> the position of the flag bit, but it's fine as it is as well.

I considered this, but as I only have the bits, I would have to 
introduce a second parameter, to get it in a consecutive manner. 

I was thinking this would be shorter for now - if we don't like it I 
can change this anyway, later.

Thanks for the review

Michael
- 
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2018-01-25 14:20 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-25 12:16 [LTP] [PATCH v2] Add library support for /proc/sys/kernel/tainted Michael Moese
2018-01-25 12:26 ` Michael Moese
2018-01-25 13:28 ` Cyril Hrubis
2018-01-25 14:20   ` Michael Moese

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.