[LTP] [PATCH] Add library support for /proc/sys/kernel/tainted

Cyril Hrubis chrubis@suse.cz
Wed Jan 24 14:13:13 CET 2018


Hi!
>  include/tst_taint.h | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  lib/tst_taint.c     |  52 ++++++++++++++++++++++++++
>  2 files changed, 156 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..34e69c2f5
> --- /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)
> + * {
> + *	if (!tst_taint_supported())
> + *		tst_brk(TCONF, "Kernel does not support tainted flags");

I think that we should check here if the kernel was tainted before the
test here and issue TBROK.

And also I would like to have the API tailored for the most common case
as well. So what about something as adding tst_check_taint(unsigned mask)
to be called from the test setup that would:

* check if kernel is new enough, otherwise do TCONF

* check if all flags in the mask are not set, otherwise do TBROK

> + * }
> + *
> + * void run(void)
> + * {
> + *	...
> + *	. test code here
> + *	...
> + *	if(tst_taint_check(TST_TAINT_W | TST_TAINT_D))
> + *		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). If these are set durin execution of 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 */
> +
> +/*
> + * check if kernel is recent enough to support the tainted-flags that
> + * allow us to check if the kernel issued a warning or died.
> + * This _must_ be called before calling other functions!
> + *
> + * returns 1 if supported, 0 otherwise
> + */
> +int tst_taint_supported(void);
> +
> +
> +/*
> + * read /proc/sys/kernel/tainted and check if at least one of the
> + * bits specified in mask is set.
> + * mask is required to be > 0. Use tst_taint_read() in order to check
> + * for absence of any tainted flags.
> + *
> + * returns 1 if at least one bit of mask is set in
> + * /proc/sys/kernel/tainted, 0 otherwise.
> + * (unsigned int) -1 is returned if mask is zero or tst_taint_supported
> + * was not called before
> + */
> +int tst_taint_check_mask(unsigned int mask);
> +
> +
> +/*
> + * read /proc/sys/kernel/tainted and return the value
> + */
> +unsigned int tst_taint_read(void);
> +
> +#endif /* TST_TAINTED_H__ */
> diff --git a/lib/tst_taint.c b/lib/tst_taint.c
> new file mode 100644
> index 000000000..de9093976
> --- /dev/null
> +++ b/lib/tst_taint.c
> @@ -0,0 +1,52 @@
> +#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 int taint_supported = -1;
> +
> +int tst_taint_supported(void)
> +{
> +	if (tst_kvercmp(2, 6, 26) < 0) {
> +		tst_res(TINFO, "Kernel version prior to 2.6.26 detected.\n");
> +		tst_res(TINFO, "please check kernel output manually\n");

Actually we skip the test if kernel is too old, so the second tst_res()
message does to make much sense.

> +		taint_supported = 0;
> +	} else
> +		taint_supported = 1;
> +
> +	return taint_supported;
> +}
> +
> +unsigned int tst_taint_read(void)
> +{
> +	unsigned int val;
> +
> +	if (taint_supported == -1) {
> +		tst_brk(TCONF, "call tst_taint_supported() before tst_taint_read()");
                         ^
			 This is definitelly TBROK == test broken, since
			 we are calling functions out of order.

> +		return (unsigned int) -1;

Actually we will never got here, so we may as well remove the return
here.

> +	}
> +	SAFE_FILE_SCANF(TAINT_FILE, "%u", &val);
> +
> +	return val;
> +}
> +
> +int tst_taint_check_mask(unsigned int mask)
> +{
> +	unsigned int taint;
> +
> +	taint = tst_taint_read();
> +	if (taint == (unsigned int) -1)
> +		return -1;

Here as well no need to check the return value against -1 since
tst_taint_read() will exit anyways.

> +	if (mask == 0) {
> +		tst_brk(TCONF, "mask is not allowed to be 0");
> +		return  -1;
> +	}

This should be done before we attempt to read the the tainted file, also
no need for the return, tst_brk() will exit the test.

> +	if ((taint & mask) != 0)
> +		return 1;
> +
> +	return 0;
> +}
> -- 
> 2.13.6
> 
> 
> -- 
> Mailing list info: https://lists.linux.it/listinfo/ltp

-- 
Cyril Hrubis
chrubis@suse.cz


More information about the ltp mailing list