diff mbox series

[2/2] module: Show the last unloaded module's taint flag(s)

Message ID 20220627164052.2416485-2-atomlin@redhat.com (mailing list archive)
State New, archived
Headers show
Series [1/2] module: Modify module_flags() to accept show_state argument | expand

Commit Message

Aaron Tomlin June 27, 2022, 4:40 p.m. UTC
For diagnostic purposes, this patch, in addition to keeping a record/or
track of the last known unloaded module, we now will include the
module's taint flag(s) too e.g: " [last unloaded: fpga_mgr_mod(OE)]"

Signed-off-by: Aaron Tomlin <atomlin@redhat.com>
---
 kernel/module/main.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

Comments

Christophe Leroy June 28, 2022, 5:54 a.m. UTC | #1
Le 27/06/2022 à 18:40, Aaron Tomlin a écrit :
> For diagnostic purposes, this patch, in addition to keeping a record/or
> track of the last known unloaded module, we now will include the
> module's taint flag(s) too e.g: " [last unloaded: fpga_mgr_mod(OE)]"
> 
> Signed-off-by: Aaron Tomlin <atomlin@redhat.com>
> ---
>   kernel/module/main.c | 10 ++++++++--
>   1 file changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/kernel/module/main.c b/kernel/module/main.c
> index dcb83cf18d84..0ca6fd38b903 100644
> --- a/kernel/module/main.c
> +++ b/kernel/module/main.c
> @@ -524,7 +524,12 @@ static struct module_attribute modinfo_##field = {                    \
>   MODINFO_ATTR(version);
>   MODINFO_ATTR(srcversion);
>   
> -static char last_unloaded_module[MODULE_NAME_LEN+1];
> +/*
> + * Maximum number of characters written by module_flags()
> + * without a module's state information.
> + */
> +#define LAST_UNLOADED_MODULE_NAME_LEN (MODULE_NAME_LEN + MODULE_FLAGS_BUF_SIZE - 2 + 1)
> +static char last_unloaded_module[LAST_UNLOADED_MODULE_NAME_LEN];
>   
>   #ifdef CONFIG_MODULE_UNLOAD
>   
> @@ -694,6 +699,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
>   {
>   	struct module *mod;
>   	char name[MODULE_NAME_LEN];
> +	char buf[LAST_UNLOADED_MODULE_NAME_LEN];
>   	int ret, forced = 0;
>   
>   	if (!capable(CAP_SYS_MODULE) || modules_disabled)
> @@ -753,8 +759,8 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
>   
>   	async_synchronize_full();
>   
> -	/* Store the name of the last unloaded module for diagnostic purposes */
>   	strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module));
> +	strcat(last_unloaded_module, module_flags(mod, buf, false));

You replace a bounded string copy by an unbounded strict contat.

Should you use strlcat() instead ?

>   
>   	free_module(mod);
>   	/* someone could wait for the module in add_unformed_module() */
Aaron Tomlin June 28, 2022, 7:47 a.m. UTC | #2
On Tue 2022-06-28 05:54 +0000, Christophe Leroy wrote:
> > -	/* Store the name of the last unloaded module for diagnostic purposes */
> >   	strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module));
> > +	strcat(last_unloaded_module, module_flags(mod, buf, false));
> 
> You replace a bounded string copy by an unbounded strict contat.
> 
> Should you use strlcat() instead ?

Hi Christophe,

Why? If I understand correctly, both the destination and source string are
NULL-terminated (see module_flags()). So, strcat() should be sufficient.


Kind regards,
Christophe Leroy June 28, 2022, 8:16 a.m. UTC | #3
Le 28/06/2022 à 09:47, Aaron Tomlin a écrit :
> On Tue 2022-06-28 05:54 +0000, Christophe Leroy wrote:
>>> -	/* Store the name of the last unloaded module for diagnostic purposes */
>>>    	strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module));
>>> +	strcat(last_unloaded_module, module_flags(mod, buf, false));
>>
>> You replace a bounded string copy by an unbounded strict contat.
>>
>> Should you use strlcat() instead ?
> 
> Hi Christophe,
> 
> Why? If I understand correctly, both the destination and source string are
> NULL-terminated (see module_flags()). So, strcat() should be sufficient.
> 

Are you sure you will never ever end up with a string longer than the 
length of last_unloaded_module ?
Aaron Tomlin June 28, 2022, 8:23 a.m. UTC | #4
On Tue 2022-06-28 08:16 +0000, Christophe Leroy wrote:
> Are you sure you will never ever end up with a string longer than the 
> length of last_unloaded_module ?

If I am not mistaken, the length of 'last_unloaded_module' has been
increased to accommodate for: the maximum module name, total module flag
count, '(', ')' and '\0'.


Kind regards,
Aaron Tomlin July 3, 2022, 2:22 p.m. UTC | #5
On Tue 2022-06-28 08:47 +0100, Aaron Tomlin wrote:
> On Tue 2022-06-28 05:54 +0000, Christophe Leroy wrote:
> > > -	/* Store the name of the last unloaded module for diagnostic purposes */
> > >   	strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module));
> > > +	strcat(last_unloaded_module, module_flags(mod, buf, false));
> > 
> > You replace a bounded string copy by an unbounded strict contat.
> > 
> > Should you use strlcat() instead ?
> 
> Hi Christophe,
> 
> Why? If I understand correctly, both the destination and source string are
> NULL-terminated (see module_flags()). So, strcat() should be sufficient.

Hi Luis,

Any thoughts on this? As far as I can tell, the destination string cannot
be overwritten; albeit, I can use the safer option if you prefer.


Kind regards,
Luis Chamberlain July 6, 2022, 11:33 p.m. UTC | #6
On Sun, Jul 03, 2022 at 03:22:18PM +0100, Aaron Tomlin wrote:
> On Tue 2022-06-28 08:47 +0100, Aaron Tomlin wrote:
> > On Tue 2022-06-28 05:54 +0000, Christophe Leroy wrote:
> > > > -	/* Store the name of the last unloaded module for diagnostic purposes */
> > > >   	strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module));
> > > > +	strcat(last_unloaded_module, module_flags(mod, buf, false));
> > > 
> > > You replace a bounded string copy by an unbounded strict contat.
> > > 
> > > Should you use strlcat() instead ?
> > 
> > Hi Christophe,
> > 
> > Why? If I understand correctly, both the destination and source string are
> > NULL-terminated (see module_flags()). So, strcat() should be sufficient.
> 
> Hi Luis,
> 
> Any thoughts on this? As far as I can tell, the destination string cannot
> be overwritten; albeit, I can use the safer option if you prefer.

Yeah I don't like this as-is, it makes it not so easy to follow, I'll
reply in my review of your patch now.

  Luis
Luis Chamberlain July 6, 2022, 11:37 p.m. UTC | #7
On Mon, Jun 27, 2022 at 05:40:52PM +0100, Aaron Tomlin wrote:
> For diagnostic purposes, this patch, in addition to keeping a record/or
> track of the last known unloaded module, we now will include the
> module's taint flag(s) too e.g: " [last unloaded: fpga_mgr_mod(OE)]"
> 
> Signed-off-by: Aaron Tomlin <atomlin@redhat.com>
> ---
>  kernel/module/main.c | 10 ++++++++--
>  1 file changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/kernel/module/main.c b/kernel/module/main.c
> index dcb83cf18d84..0ca6fd38b903 100644
> --- a/kernel/module/main.c
> +++ b/kernel/module/main.c
> @@ -524,7 +524,12 @@ static struct module_attribute modinfo_##field = {                    \
>  MODINFO_ATTR(version);
>  MODINFO_ATTR(srcversion);
>  
> -static char last_unloaded_module[MODULE_NAME_LEN+1];
> +/*
> + * Maximum number of characters written by module_flags()
> + * without a module's state information.
> + */
> +#define LAST_UNLOADED_MODULE_NAME_LEN (MODULE_NAME_LEN + MODULE_FLAGS_BUF_SIZE - 2 + 1)
> +static char last_unloaded_module[LAST_UNLOADED_MODULE_NAME_LEN];

First of all this then confuses a reader easily as one would expect
last_unloaded_module always just has the module. Second, "module flags"
really throws a user off, as one would expect a module flag is some sort
of parameter, but in reality these are just taint flags.

So I'd much prefer we split the taint flags out to its own buffer and
dump the data to it alone.

The first patch seems sensible.

  Luis

>  #ifdef CONFIG_MODULE_UNLOAD
>  
> @@ -694,6 +699,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
>  {
>  	struct module *mod;
>  	char name[MODULE_NAME_LEN];
> +	char buf[LAST_UNLOADED_MODULE_NAME_LEN];
>  	int ret, forced = 0;
>  
>  	if (!capable(CAP_SYS_MODULE) || modules_disabled)
> @@ -753,8 +759,8 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
>  
>  	async_synchronize_full();
>  
> -	/* Store the name of the last unloaded module for diagnostic purposes */
>  	strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module));
> +	strcat(last_unloaded_module, module_flags(mod, buf, false));
>  
>  	free_module(mod);
>  	/* someone could wait for the module in add_unformed_module() */
> -- 
> 2.34.3
>
diff mbox series

Patch

diff --git a/kernel/module/main.c b/kernel/module/main.c
index dcb83cf18d84..0ca6fd38b903 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -524,7 +524,12 @@  static struct module_attribute modinfo_##field = {                    \
 MODINFO_ATTR(version);
 MODINFO_ATTR(srcversion);
 
-static char last_unloaded_module[MODULE_NAME_LEN+1];
+/*
+ * Maximum number of characters written by module_flags()
+ * without a module's state information.
+ */
+#define LAST_UNLOADED_MODULE_NAME_LEN (MODULE_NAME_LEN + MODULE_FLAGS_BUF_SIZE - 2 + 1)
+static char last_unloaded_module[LAST_UNLOADED_MODULE_NAME_LEN];
 
 #ifdef CONFIG_MODULE_UNLOAD
 
@@ -694,6 +699,7 @@  SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
 {
 	struct module *mod;
 	char name[MODULE_NAME_LEN];
+	char buf[LAST_UNLOADED_MODULE_NAME_LEN];
 	int ret, forced = 0;
 
 	if (!capable(CAP_SYS_MODULE) || modules_disabled)
@@ -753,8 +759,8 @@  SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
 
 	async_synchronize_full();
 
-	/* Store the name of the last unloaded module for diagnostic purposes */
 	strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module));
+	strcat(last_unloaded_module, module_flags(mod, buf, false));
 
 	free_module(mod);
 	/* someone could wait for the module in add_unformed_module() */