All of lore.kernel.org
 help / color / mirror / Atom feed
From: Petr Pavlu <petr.pavlu@suse.com>
To: Daniel Gomez <da.gomez@kernel.org>
Cc: Luis Chamberlain <mcgrof@kernel.org>,
	Sami Tolvanen <samitolvanen@google.com>,
	Daniel Gomez <da.gomez@samsung.com>,
	linux-modules@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 1/2] module: Fix memory deallocation on error path in move_module()
Date: Thu, 12 Jun 2025 12:48:19 +0200	[thread overview]
Message-ID: <c7dbb33d-98b6-45da-be77-e86b9e6787ee@suse.com> (raw)
In-Reply-To: <ae967353-71fa-4438-a84b-8f7e2815f485@kernel.org>

On 6/10/25 8:51 PM, Daniel Gomez wrote:
> On 07/06/2025 18.16, Petr Pavlu wrote:
>> The function move_module() uses the variable t to track how many memory
>> types it has allocated and consequently how many should be freed if an
>> error occurs.
>>
>> The variable is initially set to 0 and is updated when a call to
>> module_memory_alloc() fails. However, move_module() can fail for other
>> reasons as well, in which case t remains set to 0 and no memory is freed.
> 
> Do you have a way to reproduce the leak?

I was only able to test it by directly inserting errors in
move_module().

> 
>>
>> Fix the problem by setting t to MOD_MEM_NUM_TYPES after all memory types
>> have been allocated. Additionally, make the deallocation loop more robust
>> by not relying on the mod_mem_type_t enum having a signed integer as its
>> underlying type.
>>
>> Fixes: c7ee8aebf6c0 ("module: add stop-grap sanity check on module memcpy()")
>> Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
>> ---
>>  kernel/module/main.c | 7 ++++---
>>  1 file changed, 4 insertions(+), 3 deletions(-)
>>
>> diff --git a/kernel/module/main.c b/kernel/module/main.c
>> index 08b59c37735e..322b38c0a782 100644
>> --- a/kernel/module/main.c
>> +++ b/kernel/module/main.c
>> @@ -2614,7 +2614,7 @@ static int find_module_sections(struct module *mod, struct load_info *info)
>>  static int move_module(struct module *mod, struct load_info *info)
>>  {
>>  	int i;
>> -	enum mod_mem_type t = 0;
>> +	enum mod_mem_type t;
>>  	int ret = -ENOMEM;
>>  	bool codetag_section_found = false;
>>  
>> @@ -2630,6 +2630,7 @@ static int move_module(struct module *mod, struct load_info *info)
>>  			goto out_err;
>>  		}
>>  	}
>> +	t = MOD_MEM_NUM_TYPES;
> 
> Why forcing to this? I think we want to loop from the last type found, in case
> move_module() fails after this point. Here's my suggestion:
> 
> diff --git a/kernel/module/main.c b/kernel/module/main.c
> index ada44860a868..c66881d2fb62 100644
> --- a/kernel/module/main.c
> +++ b/kernel/module/main.c
> @@ -2697,7 +2697,7 @@ static int find_module_sections(struct module *mod, struct load_info *info)
>  static int move_module(struct module *mod, struct load_info *info)
>  {
>         int i;
> -       enum mod_mem_type t;
> +       enum mod_mem_type t = MOD_TEXT;
>         int ret;
>         bool codetag_section_found = false;
> 
> @@ -2708,12 +2708,10 @@ static int move_module(struct module *mod, struct load_info *info)
>                 }
> 
>                 ret = module_memory_alloc(mod, type);
> -               if (ret) {
> -                       t = type;
> +               t = type;
> +               if (ret)
>                         goto out_err;
> -               }
>         }
> -       t = MOD_MEM_NUM_TYPES;
> 
>         /* Transfer each section which specifies SHF_ALLOC */
>         pr_debug("Final section addresses for %s:\n", mod->name)

This seems to be off by one. For instance, if the loop reaches the last
valid type in mod_mem_type, MOD_INIT_RODATA, and successfully allocates
its memory, the variable t gets set to MOD_INIT_RODATA. Subsequently, if
an error occurs later in move_module() and control is transferred to
out_err, the deallocation starts from t-1, and therefore MOD_INIT_RODATA
doesn't get freed.

If we want to always start from the last type found, the code would need
to be:

		[...]
		ret = module_memory_alloc(mod, type);
		if (ret)
			goto out_err;
		t = type + 1;
	}

I can adjust it in this way if it is preferred.

-- 
Thanks,
Petr

  reply	other threads:[~2025-06-12 10:48 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-07 16:16 [PATCH 0/2] module: Fix memory deallocation on error path in move_module() Petr Pavlu
2025-06-07 16:16 ` [PATCH 1/2] " Petr Pavlu
2025-06-08  7:25   ` Petr Pavlu
2025-06-09 22:12     ` Sami Tolvanen
2025-06-10 18:51   ` Daniel Gomez
2025-06-12 10:48     ` Petr Pavlu [this message]
2025-06-14 21:28       ` Daniel Gomez
2025-06-16 13:58         ` Petr Pavlu
2025-06-17  9:47           ` Daniel Gomez
2025-06-17 15:41             ` Petr Pavlu
2025-06-17 17:17               ` Daniel Gomez
2025-06-07 16:16 ` [PATCH 2/2] module: Avoid unnecessary return value initialization " Petr Pavlu
2025-06-09 22:13   ` Sami Tolvanen
2025-06-10 18:56   ` Daniel Gomez

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c7dbb33d-98b6-45da-be77-e86b9e6787ee@suse.com \
    --to=petr.pavlu@suse.com \
    --cc=da.gomez@kernel.org \
    --cc=da.gomez@samsung.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-modules@vger.kernel.org \
    --cc=mcgrof@kernel.org \
    --cc=samitolvanen@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.