linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3] taint/module: Clean up global and module taint flags handling
@ 2016-09-21 11:47 Petr Mladek
  2016-09-21 12:07 ` Josh Poimboeuf
  2016-09-23  4:48 ` Jessica Yu
  0 siblings, 2 replies; 10+ messages in thread
From: Petr Mladek @ 2016-09-21 11:47 UTC (permalink / raw)
  To: Rusty Russell
  Cc: Andrew Morton, Jiri Kosina, Josh Poimboeuf, Jessica Yu,
	live-patching, linux-kernel, Petr Mladek

The commit 66cc69e34e86a231 ("Fix: module signature vs tracepoints:
add new TAINT_UNSIGNED_MODULE") updated module_taint_flags() to
potentially print one more character. But it did not increase the
size of the corresponding buffers in m_show() and print_modules().

We have recently done the same mistake when adding a taint flag
for livepatching, see
https://lkml.kernel.org/g/cfba2c823bb984690b73572aaae1db596b54a082.1472137475.git.jpoimboe@redhat.com

Also struct module uses an incompatible type for mod-taints flags.
It survived from the commit 2bc2d61a9638dab670d ("[PATCH] list module
taint flags in Oops/panic"). There was used "int" for the global taint
flags at these times. But only the global tain flags was later changed
to "unsigned long" by the commit 25ddbb18aae33ad2 ("Make the taint
flags reliable").

This patch defines TAINT_FLAGS_COUNT that can be used to create
arrays and buffers of the right size. Note that we could not use
enum because the taint flag indexes are used also in assembly code.

Then it reworks the table that describes the taint flags. The TAINT_*
numbers can be used as the index. Instead, we add information
if the taint flag is also shown per-module.

Finally, it uses "unsigned long", bit operations, and the updated
taint_flags table also for mod->taints.

It is not optimal because only few taint flags can be printed by
module_taint_flags(). But better be on the safe side. IMHO, it is
not worth the optimization and this is a good compromise.

Signed-off-by: Petr Mladek <pmladek@suse.com>
---
Changes against v2:

  + fixed a typo in a comment

  + rebased on top of for-next branch from git/jikos/livepatching.git
    that has the commit commit 2992ef29ae01af9983 ("livepatch/module:
     make TAINT_LIVEPATCH module-specific").


Changes against v1:

  + reverted the change to enums because it broke asm code

  + instead, forced the size of the taint_flags table;
    used taint numbers as the index; used the table also
    in module.c

  + fixed the type of mod->taints


 include/linux/kernel.h |  9 +++++++++
 include/linux/module.h |  2 +-
 kernel/module.c        | 33 +++++++++++++------------------
 kernel/panic.c         | 53 ++++++++++++++++++++++++--------------------------
 4 files changed, 48 insertions(+), 49 deletions(-)

diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index d96a6118d26a..2e2b9477c5b8 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -509,6 +509,15 @@ extern enum system_states {
 #define TAINT_UNSIGNED_MODULE		13
 #define TAINT_SOFTLOCKUP		14
 #define TAINT_LIVEPATCH			15
+#define TAINT_FLAGS_COUNT		16
+
+struct taint_flag {
+	char true;	/* character printed when tainted */
+	char false;	/* character printed when not tainted */
+	bool module;	/* also show as a per-module taint flag */
+};
+
+extern const struct taint_flag taint_flags[TAINT_FLAGS_COUNT];
 
 extern const char hex_asc[];
 #define hex_asc_lo(x)	hex_asc[((x) & 0x0f)]
diff --git a/include/linux/module.h b/include/linux/module.h
index 0c3207d26ac0..f6ee569c62bb 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -399,7 +399,7 @@ struct module {
 	/* Arch-specific module values */
 	struct mod_arch_specific arch;
 
-	unsigned int taints;	/* same bits as kernel:tainted */
+	unsigned long taints;	/* same bits as kernel:taint_flags */
 
 #ifdef CONFIG_GENERIC_BUG
 	/* Support for BUG */
diff --git a/kernel/module.c b/kernel/module.c
index f57dd63186e6..a4acd8f403ae 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -330,7 +330,7 @@ static inline void add_taint_module(struct module *mod, unsigned flag,
 				    enum lockdep_ok lockdep_ok)
 {
 	add_taint(flag, lockdep_ok);
-	mod->taints |= (1U << flag);
+	set_bit(flag, &mod->taints);
 }
 
 /*
@@ -1138,24 +1138,13 @@ static inline int module_unload_init(struct module *mod)
 static size_t module_flags_taint(struct module *mod, char *buf)
 {
 	size_t l = 0;
+	int i;
+
+	for (i = 0; i < TAINT_FLAGS_COUNT; i++) {
+		if (taint_flags[i].module && test_bit(i, &mod->taints))
+			buf[l++] = taint_flags[i].true;
+	}
 
-	if (mod->taints & (1 << TAINT_PROPRIETARY_MODULE))
-		buf[l++] = 'P';
-	if (mod->taints & (1 << TAINT_OOT_MODULE))
-		buf[l++] = 'O';
-	if (mod->taints & (1 << TAINT_FORCED_MODULE))
-		buf[l++] = 'F';
-	if (mod->taints & (1 << TAINT_CRAP))
-		buf[l++] = 'C';
-	if (mod->taints & (1 << TAINT_UNSIGNED_MODULE))
-		buf[l++] = 'E';
-	if (mod->taints & (1 << TAINT_LIVEPATCH))
-		buf[l++] = 'K';
-	/*
-	 * TAINT_FORCED_RMMOD: could be added.
-	 * TAINT_CPU_OUT_OF_SPEC, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't
-	 * apply to modules.
-	 */
 	return l;
 }
 
@@ -4041,6 +4030,10 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
 }
 #endif /* CONFIG_KALLSYMS */
 
+/* Maximum number of characters written by module_flags() */
+#define MODULE_FLAGS_BUF_SIZE (TAINT_FLAGS_COUNT + 4)
+
+/* Keep in sync with MODULE_FLAGS_BUF_SIZE !!! */
 static char *module_flags(struct module *mod, char *buf)
 {
 	int bx = 0;
@@ -4085,7 +4078,7 @@ static void m_stop(struct seq_file *m, void *p)
 static int m_show(struct seq_file *m, void *p)
 {
 	struct module *mod = list_entry(p, struct module, list);
-	char buf[8];
+	char buf[MODULE_FLAGS_BUF_SIZE];
 
 	/* We always ignore unformed modules. */
 	if (mod->state == MODULE_STATE_UNFORMED)
@@ -4256,7 +4249,7 @@ EXPORT_SYMBOL_GPL(__module_text_address);
 void print_modules(void)
 {
 	struct module *mod;
-	char buf[8];
+	char buf[MODULE_FLAGS_BUF_SIZE];
 
 	printk(KERN_DEFAULT "Modules linked in:");
 	/* Most callers should already have preempt disabled, but make sure */
diff --git a/kernel/panic.c b/kernel/panic.c
index ca8cea1ef673..f51bda2acdeb 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -265,30 +265,27 @@ void panic(const char *fmt, ...)
 
 EXPORT_SYMBOL(panic);
 
-
-struct tnt {
-	u8	bit;
-	char	true;
-	char	false;
-};
-
-static const struct tnt tnts[] = {
-	{ TAINT_PROPRIETARY_MODULE,	'P', 'G' },
-	{ TAINT_FORCED_MODULE,		'F', ' ' },
-	{ TAINT_CPU_OUT_OF_SPEC,	'S', ' ' },
-	{ TAINT_FORCED_RMMOD,		'R', ' ' },
-	{ TAINT_MACHINE_CHECK,		'M', ' ' },
-	{ TAINT_BAD_PAGE,		'B', ' ' },
-	{ TAINT_USER,			'U', ' ' },
-	{ TAINT_DIE,			'D', ' ' },
-	{ TAINT_OVERRIDDEN_ACPI_TABLE,	'A', ' ' },
-	{ TAINT_WARN,			'W', ' ' },
-	{ TAINT_CRAP,			'C', ' ' },
-	{ TAINT_FIRMWARE_WORKAROUND,	'I', ' ' },
-	{ TAINT_OOT_MODULE,		'O', ' ' },
-	{ TAINT_UNSIGNED_MODULE,	'E', ' ' },
-	{ TAINT_SOFTLOCKUP,		'L', ' ' },
-	{ TAINT_LIVEPATCH,		'K', ' ' },
+/*
+ * TAINT_FORCED_RMMOD could be a per-module flag but the module
+ * is being removed anyway.
+ */
+const struct taint_flag taint_flags[TAINT_FLAGS_COUNT] = {
+	{ 'P', 'G', true },	/* TAINT_PROPRIETARY_MODULE */
+	{ 'F', ' ', true },	/* TAINT_FORCED_MODULE */
+	{ 'S', ' ', false },	/* TAINT_CPU_OUT_OF_SPEC */
+	{ 'R', ' ', false },	/* TAINT_FORCED_RMMOD */
+	{ 'M', ' ', false },	/* TAINT_MACHINE_CHECK */
+	{ 'B', ' ', false },	/* TAINT_BAD_PAGE */
+	{ 'U', ' ', false },	/* TAINT_USER */
+	{ 'D', ' ', false },	/* TAINT_DIE */
+	{ 'A', ' ', false },	/* TAINT_OVERRIDDEN_ACPI_TABLE */
+	{ 'W', ' ', false },	/* TAINT_WARN */
+	{ 'C', ' ', true },	/* TAINT_CRAP */
+	{ 'I', ' ', false },	/* TAINT_FIRMWARE_WORKAROUND */
+	{ 'O', ' ', true },	/* TAINT_OOT_MODULE */
+	{ 'E', ' ', true },	/* TAINT_UNSIGNED_MODULE */
+	{ 'L', ' ', false },	/* TAINT_SOFTLOCKUP */
+	{ 'K', ' ', true },	/* TAINT_LIVEPATCH */
 };
 
 /**
@@ -315,16 +312,16 @@ static const struct tnt tnts[] = {
  */
 const char *print_tainted(void)
 {
-	static char buf[ARRAY_SIZE(tnts) + sizeof("Tainted: ")];
+	static char buf[TAINT_FLAGS_COUNT + sizeof("Tainted: ")];
 
 	if (tainted_mask) {
 		char *s;
 		int i;
 
 		s = buf + sprintf(buf, "Tainted: ");
-		for (i = 0; i < ARRAY_SIZE(tnts); i++) {
-			const struct tnt *t = &tnts[i];
-			*s++ = test_bit(t->bit, &tainted_mask) ?
+		for (i = 0; i < TAINT_FLAGS_COUNT; i++) {
+			const struct taint_flag *t = &taint_flags[i];
+			*s++ = test_bit(i, &tainted_mask) ?
 					t->true : t->false;
 		}
 		*s = 0;
-- 
1.8.5.6

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

* Re: [PATCH v3] taint/module: Clean up global and module taint flags handling
  2016-09-21 11:47 [PATCH v3] taint/module: Clean up global and module taint flags handling Petr Mladek
@ 2016-09-21 12:07 ` Josh Poimboeuf
  2016-09-23  4:48 ` Jessica Yu
  1 sibling, 0 replies; 10+ messages in thread
From: Josh Poimboeuf @ 2016-09-21 12:07 UTC (permalink / raw)
  To: Petr Mladek
  Cc: Rusty Russell, Andrew Morton, Jiri Kosina, Jessica Yu,
	live-patching, linux-kernel

On Wed, Sep 21, 2016 at 01:47:22PM +0200, Petr Mladek wrote:
> The commit 66cc69e34e86a231 ("Fix: module signature vs tracepoints:
> add new TAINT_UNSIGNED_MODULE") updated module_taint_flags() to
> potentially print one more character. But it did not increase the
> size of the corresponding buffers in m_show() and print_modules().
> 
> We have recently done the same mistake when adding a taint flag
> for livepatching, see
> https://lkml.kernel.org/g/cfba2c823bb984690b73572aaae1db596b54a082.1472137475.git.jpoimboe@redhat.com

No objections to the patch itself, but this link didn't work for me.

Replacing the 'g' with 'r' fixed it:

  https://lkml.kernel.org/r/cfba2c823bb984690b73572aaae1db596b54a082.1472137475.git.jpoimboe@redhat.com

Or, even better, I think Jiri doesn't rebase his livepatching 'for-next'
branch, so maybe just use the commit id:

  2992ef29ae01 ("livepatch/module: make TAINT_LIVEPATCH module-specific")

-- 
Josh

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

* Re: taint/module: Clean up global and module taint flags handling
  2016-09-21 11:47 [PATCH v3] taint/module: Clean up global and module taint flags handling Petr Mladek
  2016-09-21 12:07 ` Josh Poimboeuf
@ 2016-09-23  4:48 ` Jessica Yu
  2016-09-23 12:45   ` Jiri Kosina
  2016-10-07  7:57   ` Jiri Kosina
  1 sibling, 2 replies; 10+ messages in thread
From: Jessica Yu @ 2016-09-23  4:48 UTC (permalink / raw)
  To: Petr Mladek
  Cc: Rusty Russell, Andrew Morton, Jiri Kosina, Josh Poimboeuf,
	live-patching, linux-kernel

+++ Petr Mladek [21/09/16 13:47 +0200]:
>The commit 66cc69e34e86a231 ("Fix: module signature vs tracepoints:
>add new TAINT_UNSIGNED_MODULE") updated module_taint_flags() to
>potentially print one more character. But it did not increase the
>size of the corresponding buffers in m_show() and print_modules().
>
>We have recently done the same mistake when adding a taint flag
>for livepatching, see
>https://lkml.kernel.org/g/cfba2c823bb984690b73572aaae1db596b54a082.1472137475.git.jpoimboe@redhat.com
>
>Also struct module uses an incompatible type for mod-taints flags.
>It survived from the commit 2bc2d61a9638dab670d ("[PATCH] list module
>taint flags in Oops/panic"). There was used "int" for the global taint
>flags at these times. But only the global tain flags was later changed
>to "unsigned long" by the commit 25ddbb18aae33ad2 ("Make the taint
>flags reliable").
>
>This patch defines TAINT_FLAGS_COUNT that can be used to create
>arrays and buffers of the right size. Note that we could not use
>enum because the taint flag indexes are used also in assembly code.
>
>Then it reworks the table that describes the taint flags. The TAINT_*
>numbers can be used as the index. Instead, we add information
>if the taint flag is also shown per-module.
>
>Finally, it uses "unsigned long", bit operations, and the updated
>taint_flags table also for mod->taints.
>
>It is not optimal because only few taint flags can be printed by
>module_taint_flags(). But better be on the safe side. IMHO, it is
>not worth the optimization and this is a good compromise.
>
>Signed-off-by: Petr Mladek <pmladek@suse.com>
>---
>Changes against v2:
>
>  + fixed a typo in a comment
>
>  + rebased on top of for-next branch from git/jikos/livepatching.git
>    that has the commit commit 2992ef29ae01af9983 ("livepatch/module:
>     make TAINT_LIVEPATCH module-specific").

Reviewed-by: Jessica Yu <jeyu@redhat.com>

Hm, quick question, which tree would this patch go to? Though the
cleanup is for modules, there is an indirect cross-tree dependency
(taint_flag.module needs to be true for TAINT_LIVEPATCH for Josh's
patch to still work as intended). The least complicated thing to do
would be to just take this through the livepatch tree (with Rusty's
approval :-)), no?

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

* Re: taint/module: Clean up global and module taint flags handling
  2016-09-23  4:48 ` Jessica Yu
@ 2016-09-23 12:45   ` Jiri Kosina
  2016-10-07  7:57   ` Jiri Kosina
  1 sibling, 0 replies; 10+ messages in thread
From: Jiri Kosina @ 2016-09-23 12:45 UTC (permalink / raw)
  To: Jessica Yu
  Cc: Petr Mladek, Rusty Russell, Andrew Morton, Josh Poimboeuf,
	live-patching, linux-kernel

On Fri, 23 Sep 2016, Jessica Yu wrote:

> Hm, quick question, which tree would this patch go to? Though the 
> cleanup is for modules, there is an indirect cross-tree dependency 
> (taint_flag.module needs to be true for TAINT_LIVEPATCH for Josh's patch 
> to still work as intended). The least complicated thing to do would be 
> to just take this through the livepatch tree (with Rusty's approval 
> :-)), no?

That'd be my preference, given there would be an Ack from Rusty coming.

Thanks,

-- 
Jiri Kosina
SUSE Labs

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

* Re: taint/module: Clean up global and module taint flags handling
  2016-09-23  4:48 ` Jessica Yu
  2016-09-23 12:45   ` Jiri Kosina
@ 2016-10-07  7:57   ` Jiri Kosina
  2016-10-26  1:07     ` Rusty Russell
  1 sibling, 1 reply; 10+ messages in thread
From: Jiri Kosina @ 2016-10-07  7:57 UTC (permalink / raw)
  To: Jessica Yu
  Cc: Petr Mladek, Rusty Russell, Andrew Morton, Josh Poimboeuf,
	live-patching, linux-kernel

On Fri, 23 Sep 2016, Jessica Yu wrote:

> Hm, quick question, which tree would this patch go to? Though the
> cleanup is for modules, there is an indirect cross-tree dependency
> (taint_flag.module needs to be true for TAINT_LIVEPATCH for Josh's
> patch to still work as intended). The least complicated thing to do
> would be to just take this through the livepatch tree (with Rusty's
> approval :-)), no?

I don't want to be sneaking this behind Rusty's back, but he hasn't 
reposnded so far.

It's not vitally super-crucial to have this present in this very pull 
request, so I am currently putting this on hold wrt. the upcoming merge 
window pull request, and we'll then proceeed afterwards once Rusty 
expressess his (n)ack. If this doesn't happen during the coming weeks, 
I'll pick this up myself.

Thanks,

-- 
Jiri Kosina
SUSE Labs

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

* Re: taint/module: Clean up global and module taint flags handling
  2016-10-07  7:57   ` Jiri Kosina
@ 2016-10-26  1:07     ` Rusty Russell
  2016-10-26  8:17       ` Jiri Kosina
  0 siblings, 1 reply; 10+ messages in thread
From: Rusty Russell @ 2016-10-26  1:07 UTC (permalink / raw)
  To: Jiri Kosina, Jessica Yu
  Cc: Petr Mladek, Andrew Morton, Josh Poimboeuf, live-patching, linux-kernel

Jiri Kosina <jikos@kernel.org> writes:
> On Fri, 23 Sep 2016, Jessica Yu wrote:
>
>> Hm, quick question, which tree would this patch go to? Though the
>> cleanup is for modules, there is an indirect cross-tree dependency
>> (taint_flag.module needs to be true for TAINT_LIVEPATCH for Josh's
>> patch to still work as intended). The least complicated thing to do
>> would be to just take this through the livepatch tree (with Rusty's
>> approval :-)), no?
>
> I don't want to be sneaking this behind Rusty's back, but he hasn't 
> reposnded so far.

I finally side-stepped this by appointing Jessica maintainer, thus her
Reviewed-by is sufficient for the module tree.

Lazy, huh?

Sorry for the delay,
Rusty.

> It's not vitally super-crucial to have this present in this very pull 
> request, so I am currently putting this on hold wrt. the upcoming merge 
> window pull request, and we'll then proceeed afterwards once Rusty 
> expressess his (n)ack. If this doesn't happen during the coming weeks, 
> I'll pick this up myself.
>
> Thanks,
>
> -- 
> Jiri Kosina
> SUSE Labs

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

* Re: taint/module: Clean up global and module taint flags handling
  2016-10-26  1:07     ` Rusty Russell
@ 2016-10-26  8:17       ` Jiri Kosina
  2016-10-26 23:14         ` Jessica Yu
  0 siblings, 1 reply; 10+ messages in thread
From: Jiri Kosina @ 2016-10-26  8:17 UTC (permalink / raw)
  To: Rusty Russell
  Cc: Jessica Yu, Petr Mladek, Andrew Morton, Josh Poimboeuf,
	live-patching, linux-kernel

On Wed, 26 Oct 2016, Rusty Russell wrote:

> >> Hm, quick question, which tree would this patch go to? Though the
> >> cleanup is for modules, there is an indirect cross-tree dependency
> >> (taint_flag.module needs to be true for TAINT_LIVEPATCH for Josh's
> >> patch to still work as intended). The least complicated thing to do
> >> would be to just take this through the livepatch tree (with Rusty's
> >> approval :-)), no?
> >
> > I don't want to be sneaking this behind Rusty's back, but he hasn't 
> > reposnded so far.
> 
> I finally side-stepped this by appointing Jessica maintainer, thus her
> Reviewed-by is sufficient for the module tree.

Awesome! :)

> Lazy, huh?

Laziness has always been the main power behind all the progress of the 
mankind :P

Jessica, do you want me to take the patch through livepatching tree still, 
or would you route it yourself now?

Thanks,

-- 
Jiri Kosina
SUSE Labs

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

* Re: taint/module: Clean up global and module taint flags handling
  2016-10-26  8:17       ` Jiri Kosina
@ 2016-10-26 23:14         ` Jessica Yu
  0 siblings, 0 replies; 10+ messages in thread
From: Jessica Yu @ 2016-10-26 23:14 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: Rusty Russell, Petr Mladek, Andrew Morton, Josh Poimboeuf,
	live-patching, linux-kernel

+++ Jiri Kosina [26/10/16 10:17 +0200]:
>On Wed, 26 Oct 2016, Rusty Russell wrote:
>
>> >> Hm, quick question, which tree would this patch go to? Though the
>> >> cleanup is for modules, there is an indirect cross-tree dependency
>> >> (taint_flag.module needs to be true for TAINT_LIVEPATCH for Josh's
>> >> patch to still work as intended). The least complicated thing to do
>> >> would be to just take this through the livepatch tree (with Rusty's
>> >> approval :-)), no?
>> >
>> > I don't want to be sneaking this behind Rusty's back, but he hasn't
>> > reposnded so far.
>>
>> I finally side-stepped this by appointing Jessica maintainer, thus her
>> Reviewed-by is sufficient for the module tree.
>
>Awesome! :)
>
>> Lazy, huh?
>
>Laziness has always been the main power behind all the progress of the
>mankind :P
>
>Jessica, do you want me to take the patch through livepatching tree still,
>or would you route it yourself now?

Hi Jiri,

Once I'm done fumbling with maintainership logistics, I will take this
patch through my tree. :-)

Thanks,
Jessica

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

* Re: taint/module: Clean up global and module taint flags handling
  2016-09-13 20:36 ` Jessica Yu
@ 2016-09-14 15:45   ` Petr Mladek
  0 siblings, 0 replies; 10+ messages in thread
From: Petr Mladek @ 2016-09-14 15:45 UTC (permalink / raw)
  To: Jessica Yu
  Cc: Rusty Russell, Andrew Morton, Jiri Kosina, Josh Poimboeuf,
	live-patching, linux-kernel

On Tue 2016-09-13 16:36:09, Jessica Yu wrote:
> +++ Petr Mladek [12/09/16 16:13 +0200]:
> >The commit 66cc69e34e86a231 ("Fix: module signature vs tracepoints:
> >add new TAINT_UNSIGNED_MODULE") updated module_taint_flags() to
> >potentially print one more character. But it did not increase the
> >size of the corresponding buffers in m_show() and print_modules().
> >
> >We have recently done the same mistake when adding a taint flag
> >for livepatching, see
> >https://lkml.kernel.org/g/cfba2c823bb984690b73572aaae1db596b54a082.1472137475.git.jpoimboe@redhat.com
> >
> >Also struct module uses an incompatible type for mod-taints flags.
> >It survived from the commit 2bc2d61a9638dab670d ("[PATCH] list module
> >taint flags in Oops/panic"). There was used "int" for the global taint
> >flags at these times. But only the global tain flags was later changed
> >to "unsigned long" by the commit 25ddbb18aae33ad2 ("Make the taint
> >flags reliable").
> >
> >This patch defines TAINT_FLAGS_COUNT that can be used to create
> >arrays and buffers of the right size. Note that we could not use
> >enum because the taint flag indexes are used also in assembly code.
> >
> >Then it reworks the table that describes the taint flags. The TAINT_*
> >numbers can be used as the index. Instead, we add information
> >if the taint flag is also shown per-module.
> >
> >Finally, it uses "unsigned long", bit operations, and the updated
> >taint_flags table also for mod->taints.
> >
> >It is not optimal because only few taint flags can be printed by
> >module_taint_flags(). But better be on the safe side. IMHO, it is
> >not worth the optimization and this is a good compromise.
> >
> >Signed-off-by: Petr Mladek <pmladek@suse.com>
> >---
> >
> >Changes against v1:
> >
> > + reverted the change to enums because it broke asm code
> >
> > + instead, forced the size of the taint_flags table;
> >   used taint numbers as the index; used the table also
> >   in module.c
> >
> > + fixed the type of mod->taints
> >
> >
> >include/linux/kernel.h |  9 +++++++++
> >include/linux/module.h |  2 +-
> >kernel/module.c        | 31 +++++++++++++----------------
> >kernel/panic.c         | 53 ++++++++++++++++++++++++--------------------------
> >4 files changed, 48 insertions(+), 47 deletions(-)
> >
> >diff --git a/include/linux/kernel.h b/include/linux/kernel.h
> >index d96a6118d26a..33e88ff3af40 100644
> >--- a/include/linux/kernel.h
> >+++ b/include/linux/kernel.h
> >@@ -509,6 +509,15 @@ extern enum system_states {
> >#define TAINT_UNSIGNED_MODULE		13
> >#define TAINT_SOFTLOCKUP		14
> >#define TAINT_LIVEPATCH			15
> >+#define TAINT_FLAGS_COUNT		16
> >+
> >+struct taint_flag {
> >+	char true;	/* character printed when tained */
> >+	char false;	/* character printed when not tained */
> 
> s/tained/tainted

Great catch!
 
> >diff --git a/kernel/panic.c b/kernel/panic.c
> >index ca8cea1ef673..36d4fa264b2c 100644
> >--- a/kernel/panic.c
> >+++ b/kernel/panic.c
> >+/*
> >+ * TAINT_FORCED_RMMOD could be a per-module flag but the module
> >+ * is being removed anyway.
> >+ */
> >+const struct taint_flag taint_flags[TAINT_FLAGS_COUNT] = {
> >+	{ 'P', 'G', true },	/* TAINT_PROPRIETARY_MODULE */
> >+	{ 'F', ' ', true },	/* TAINT_FORCED_MODULE */
> >+	{ 'S', ' ', false },	/* TAINT_CPU_OUT_OF_SPEC */
> >+	{ 'R', ' ', false },	/* TAINT_FORCED_RMMOD */
> >+	{ 'M', ' ', false },	/* TAINT_MACHINE_CHECK */
> >+	{ 'B', ' ', false },	/* TAINT_BAD_PAGE */
> >+	{ 'U', ' ', false },	/* TAINT_USER */
> >+	{ 'D', ' ', false },	/* TAINT_DIE */
> >+	{ 'A', ' ', false },	/* TAINT_OVERRIDDEN_ACPI_TABLE */
> >+	{ 'W', ' ', false },	/* TAINT_WARN */
> >+	{ 'C', ' ', true },	/* TAINT_CRAP */
> >+	{ 'I', ' ', false },	/* TAINT_FIRMWARE_WORKAROUND */
> >+	{ 'O', ' ', true },	/* TAINT_OOT_MODULE */
> >+	{ 'E', ' ', true },	/* TAINT_UNSIGNED_MODULE */
> >+	{ 'L', ' ', false },	/* TAINT_SOFTLOCKUP */
> >+	{ 'K', ' ', false },	/* TAINT_LIVEPATCH */
> 
> This should be true here, right? TAINT_LIVEPATCH has been made a
> module-specific taint by commit 2992ef29ae ("livepatch/module: make
> TAINT_LIVEPATCH module-specific").

I was not sure whose maintainer tree would be used. So, I rather based
this on the Linus' stable tree. If it will go via the Jikos' livepatch
I could rebase it on top of the commit 2992ef29ae ("livepatch/module: make
TAINT_LIVEPATCH module-specific").

> I think the rest looks fine, thanks for working on the cleanups.

Thanks for review.

Best Regards,
Petr

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

* Re: taint/module: Clean up global and module taint flags handling
  2016-09-12 14:13 [PATCH v2] " Petr Mladek
@ 2016-09-13 20:36 ` Jessica Yu
  2016-09-14 15:45   ` Petr Mladek
  0 siblings, 1 reply; 10+ messages in thread
From: Jessica Yu @ 2016-09-13 20:36 UTC (permalink / raw)
  To: Petr Mladek
  Cc: Rusty Russell, Andrew Morton, Jiri Kosina, Josh Poimboeuf,
	live-patching, linux-kernel

+++ Petr Mladek [12/09/16 16:13 +0200]:
>The commit 66cc69e34e86a231 ("Fix: module signature vs tracepoints:
>add new TAINT_UNSIGNED_MODULE") updated module_taint_flags() to
>potentially print one more character. But it did not increase the
>size of the corresponding buffers in m_show() and print_modules().
>
>We have recently done the same mistake when adding a taint flag
>for livepatching, see
>https://lkml.kernel.org/g/cfba2c823bb984690b73572aaae1db596b54a082.1472137475.git.jpoimboe@redhat.com
>
>Also struct module uses an incompatible type for mod-taints flags.
>It survived from the commit 2bc2d61a9638dab670d ("[PATCH] list module
>taint flags in Oops/panic"). There was used "int" for the global taint
>flags at these times. But only the global tain flags was later changed
>to "unsigned long" by the commit 25ddbb18aae33ad2 ("Make the taint
>flags reliable").
>
>This patch defines TAINT_FLAGS_COUNT that can be used to create
>arrays and buffers of the right size. Note that we could not use
>enum because the taint flag indexes are used also in assembly code.
>
>Then it reworks the table that describes the taint flags. The TAINT_*
>numbers can be used as the index. Instead, we add information
>if the taint flag is also shown per-module.
>
>Finally, it uses "unsigned long", bit operations, and the updated
>taint_flags table also for mod->taints.
>
>It is not optimal because only few taint flags can be printed by
>module_taint_flags(). But better be on the safe side. IMHO, it is
>not worth the optimization and this is a good compromise.
>
>Signed-off-by: Petr Mladek <pmladek@suse.com>
>---
>
>Changes against v1:
>
>  + reverted the change to enums because it broke asm code
>
>  + instead, forced the size of the taint_flags table;
>    used taint numbers as the index; used the table also
>    in module.c
>
>  + fixed the type of mod->taints
>
>
> include/linux/kernel.h |  9 +++++++++
> include/linux/module.h |  2 +-
> kernel/module.c        | 31 +++++++++++++----------------
> kernel/panic.c         | 53 ++++++++++++++++++++++++--------------------------
> 4 files changed, 48 insertions(+), 47 deletions(-)
>
>diff --git a/include/linux/kernel.h b/include/linux/kernel.h
>index d96a6118d26a..33e88ff3af40 100644
>--- a/include/linux/kernel.h
>+++ b/include/linux/kernel.h
>@@ -509,6 +509,15 @@ extern enum system_states {
> #define TAINT_UNSIGNED_MODULE		13
> #define TAINT_SOFTLOCKUP		14
> #define TAINT_LIVEPATCH			15
>+#define TAINT_FLAGS_COUNT		16
>+
>+struct taint_flag {
>+	char true;	/* character printed when tained */
>+	char false;	/* character printed when not tained */

s/tained/tainted

>+	bool module;	/* also show as a per-module taint flag */
>+};
>+
>+extern const struct taint_flag taint_flags[TAINT_FLAGS_COUNT];
>
> extern const char hex_asc[];
> #define hex_asc_lo(x)	hex_asc[((x) & 0x0f)]
>diff --git a/include/linux/module.h b/include/linux/module.h
>index 0c3207d26ac0..f6ee569c62bb 100644
>--- a/include/linux/module.h
>+++ b/include/linux/module.h
>@@ -399,7 +399,7 @@ struct module {
> 	/* Arch-specific module values */
> 	struct mod_arch_specific arch;
>
>-	unsigned int taints;	/* same bits as kernel:tainted */
>+	unsigned long taints;	/* same bits as kernel:taint_flags */
>
> #ifdef CONFIG_GENERIC_BUG
> 	/* Support for BUG */
>diff --git a/kernel/module.c b/kernel/module.c
>index 529efae9f481..303e03e08b51 100644
>--- a/kernel/module.c
>+++ b/kernel/module.c
>@@ -330,7 +330,7 @@ static inline void add_taint_module(struct module *mod, unsigned flag,
> 				    enum lockdep_ok lockdep_ok)
> {
> 	add_taint(flag, lockdep_ok);
>-	mod->taints |= (1U << flag);
>+	set_bit(flag, &mod->taints);
> }
>
> /*
>@@ -1138,22 +1138,13 @@ static inline int module_unload_init(struct module *mod)
> static size_t module_flags_taint(struct module *mod, char *buf)
> {
> 	size_t l = 0;
>+	int i;
>+
>+	for (i = 0; i < TAINT_FLAGS_COUNT; i++) {
>+		if (taint_flags[i].module && test_bit(i, &mod->taints))
>+			buf[l++] = taint_flags[i].true;
>+	}
>
>-	if (mod->taints & (1 << TAINT_PROPRIETARY_MODULE))
>-		buf[l++] = 'P';
>-	if (mod->taints & (1 << TAINT_OOT_MODULE))
>-		buf[l++] = 'O';
>-	if (mod->taints & (1 << TAINT_FORCED_MODULE))
>-		buf[l++] = 'F';
>-	if (mod->taints & (1 << TAINT_CRAP))
>-		buf[l++] = 'C';
>-	if (mod->taints & (1 << TAINT_UNSIGNED_MODULE))
>-		buf[l++] = 'E';
>-	/*
>-	 * TAINT_FORCED_RMMOD: could be added.
>-	 * TAINT_CPU_OUT_OF_SPEC, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't
>-	 * apply to modules.
>-	 */
> 	return l;
> }
>
>@@ -4036,6 +4027,10 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
> }
> #endif /* CONFIG_KALLSYMS */
>
>+/* Maximum number of characters written by module_flags() */
>+#define MODULE_FLAGS_BUF_SIZE (TAINT_FLAGS_COUNT + 4)
>+
>+/* Keep in sync with MODULE_FLAGS_BUF_SIZE !!! */
> static char *module_flags(struct module *mod, char *buf)
> {
> 	int bx = 0;
>@@ -4080,7 +4075,7 @@ static void m_stop(struct seq_file *m, void *p)
> static int m_show(struct seq_file *m, void *p)
> {
> 	struct module *mod = list_entry(p, struct module, list);
>-	char buf[8];
>+	char buf[MODULE_FLAGS_BUF_SIZE];
>
> 	/* We always ignore unformed modules. */
> 	if (mod->state == MODULE_STATE_UNFORMED)
>@@ -4251,7 +4246,7 @@ EXPORT_SYMBOL_GPL(__module_text_address);
> void print_modules(void)
> {
> 	struct module *mod;
>-	char buf[8];
>+	char buf[MODULE_FLAGS_BUF_SIZE];
>
> 	printk(KERN_DEFAULT "Modules linked in:");
> 	/* Most callers should already have preempt disabled, but make sure */
>diff --git a/kernel/panic.c b/kernel/panic.c
>index ca8cea1ef673..36d4fa264b2c 100644
>--- a/kernel/panic.c
>+++ b/kernel/panic.c
>@@ -265,30 +265,27 @@ void panic(const char *fmt, ...)
>
> EXPORT_SYMBOL(panic);
>
>-
>-struct tnt {
>-	u8	bit;
>-	char	true;
>-	char	false;
>-};
>-
>-static const struct tnt tnts[] = {
>-	{ TAINT_PROPRIETARY_MODULE,	'P', 'G' },
>-	{ TAINT_FORCED_MODULE,		'F', ' ' },
>-	{ TAINT_CPU_OUT_OF_SPEC,	'S', ' ' },
>-	{ TAINT_FORCED_RMMOD,		'R', ' ' },
>-	{ TAINT_MACHINE_CHECK,		'M', ' ' },
>-	{ TAINT_BAD_PAGE,		'B', ' ' },
>-	{ TAINT_USER,			'U', ' ' },
>-	{ TAINT_DIE,			'D', ' ' },
>-	{ TAINT_OVERRIDDEN_ACPI_TABLE,	'A', ' ' },
>-	{ TAINT_WARN,			'W', ' ' },
>-	{ TAINT_CRAP,			'C', ' ' },
>-	{ TAINT_FIRMWARE_WORKAROUND,	'I', ' ' },
>-	{ TAINT_OOT_MODULE,		'O', ' ' },
>-	{ TAINT_UNSIGNED_MODULE,	'E', ' ' },
>-	{ TAINT_SOFTLOCKUP,		'L', ' ' },
>-	{ TAINT_LIVEPATCH,		'K', ' ' },
>+/*
>+ * TAINT_FORCED_RMMOD could be a per-module flag but the module
>+ * is being removed anyway.
>+ */
>+const struct taint_flag taint_flags[TAINT_FLAGS_COUNT] = {
>+	{ 'P', 'G', true },	/* TAINT_PROPRIETARY_MODULE */
>+	{ 'F', ' ', true },	/* TAINT_FORCED_MODULE */
>+	{ 'S', ' ', false },	/* TAINT_CPU_OUT_OF_SPEC */
>+	{ 'R', ' ', false },	/* TAINT_FORCED_RMMOD */
>+	{ 'M', ' ', false },	/* TAINT_MACHINE_CHECK */
>+	{ 'B', ' ', false },	/* TAINT_BAD_PAGE */
>+	{ 'U', ' ', false },	/* TAINT_USER */
>+	{ 'D', ' ', false },	/* TAINT_DIE */
>+	{ 'A', ' ', false },	/* TAINT_OVERRIDDEN_ACPI_TABLE */
>+	{ 'W', ' ', false },	/* TAINT_WARN */
>+	{ 'C', ' ', true },	/* TAINT_CRAP */
>+	{ 'I', ' ', false },	/* TAINT_FIRMWARE_WORKAROUND */
>+	{ 'O', ' ', true },	/* TAINT_OOT_MODULE */
>+	{ 'E', ' ', true },	/* TAINT_UNSIGNED_MODULE */
>+	{ 'L', ' ', false },	/* TAINT_SOFTLOCKUP */
>+	{ 'K', ' ', false },	/* TAINT_LIVEPATCH */

This should be true here, right? TAINT_LIVEPATCH has been made a
module-specific taint by commit 2992ef29ae ("livepatch/module: make
TAINT_LIVEPATCH module-specific").

I think the rest looks fine, thanks for working on the cleanups.

Jessica

> };
>
> /**
>@@ -315,16 +312,16 @@ static const struct tnt tnts[] = {
>  */
> const char *print_tainted(void)
> {
>-	static char buf[ARRAY_SIZE(tnts) + sizeof("Tainted: ")];
>+	static char buf[TAINT_FLAGS_COUNT + sizeof("Tainted: ")];
>
> 	if (tainted_mask) {
> 		char *s;
> 		int i;
>
> 		s = buf + sprintf(buf, "Tainted: ");
>-		for (i = 0; i < ARRAY_SIZE(tnts); i++) {
>-			const struct tnt *t = &tnts[i];
>-			*s++ = test_bit(t->bit, &tainted_mask) ?
>+		for (i = 0; i < TAINT_FLAGS_COUNT; i++) {
>+			const struct taint_flag *t = &taint_flags[i];
>+			*s++ = test_bit(i, &tainted_mask) ?
> 					t->true : t->false;
> 		}
> 		*s = 0;
>-- 
>1.8.5.6
>

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

end of thread, other threads:[~2016-10-26 23:14 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-21 11:47 [PATCH v3] taint/module: Clean up global and module taint flags handling Petr Mladek
2016-09-21 12:07 ` Josh Poimboeuf
2016-09-23  4:48 ` Jessica Yu
2016-09-23 12:45   ` Jiri Kosina
2016-10-07  7:57   ` Jiri Kosina
2016-10-26  1:07     ` Rusty Russell
2016-10-26  8:17       ` Jiri Kosina
2016-10-26 23:14         ` Jessica Yu
  -- strict thread matches above, loose matches on Subject: below --
2016-09-12 14:13 [PATCH v2] " Petr Mladek
2016-09-13 20:36 ` Jessica Yu
2016-09-14 15:45   ` Petr Mladek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).