diff mbox series

[v5] module: Add CONFIG_MODULE_DISABLE_INIT_FREE option

Message ID 20231013062711.28852-1-quic_jiangenj@quicinc.com (mailing list archive)
State New, archived
Headers show
Series [v5] module: Add CONFIG_MODULE_DISABLE_INIT_FREE option | expand

Commit Message

Joey Jiao Oct. 13, 2023, 6:27 a.m. UTC
Syzkaller uses the _RET_IP_ (also known as pc) to decode covered
file/function/line, and it employs pc ^ hash(prev_pc) (referred to as
signal) to indicate covered edge. If the pc for the same file/line
keeps changing across reboots, syzkaller will report incorrect coverage
data. Additionally, even if kaslr can be disabled, we cannot get the
same covered edge for module because both pc and prev_pc have changed,
thus altering pc ^ hash(prev_pc).

To facilitate syzkaller coverage, it is crucial for both the core kernel
and modules to maintain at the same addresses across reboots.

So, the following steps are necessary:
- In userspace:
  1) To maintain an uninterrupted loading sequence, it is recommended to
execute modprobe commands by loading one module at a time, to avoid any
interference from the scheduler.
  2) Avoid unloading any module during fuzzing.
- In kernel:
  1) Disable CONFIG_RANDOMIZE_BASE to load the core kernel at the same
address consistently.
  2) To ensure deterministic module loading at the same address, enabling
CONFIG_MODULE_DISABLE_INIT_FREE prevents the asynchronous freeing of init
sections. Without this option, there is a possibility that the next module
could be loaded into previous freed init pages of a previous loaded module.

It is important to note that this option is intended for fuzzing tests only
and should not be set as the default configuration in production builds.

Signed-off-by: Joey Jiao <quic_jiangenj@quicinc.com>
---
 kernel/module/Kconfig | 13 +++++++++++++
 kernel/module/main.c  |  3 ++-
 2 files changed, 15 insertions(+), 1 deletion(-)

Comments

Luis Chamberlain Oct. 13, 2023, 6:58 p.m. UTC | #1
Joey,

Thanks for working hard on expanding on the commit log to try to
describe the rationale for this. I'd like review from the linux-hardening
folks and at least one syzkaller developer.

On Fri, Oct 13, 2023 at 11:57:11AM +0530, Joey Jiao wrote:
> Syzkaller uses the _RET_IP_ (also known as pc) to decode covered
> file/function/line,

OK but that seems immediately limited as your Kconfig confirms to
!CONFIG_RANDOMIZE_BASE and even for things like kaslr.

> and it employs pc ^ hash(prev_pc) (referred to as
> signal) to indicate covered edge. If the pc for the same file/line
> keeps changing across reboots, syzkaller will report incorrect coverage
> data.

Yeah that seems pretty limiting. Why not use something like the
effort being put forward to map symbols a bit more accurately to
file / lines as with what Alessandro Carminati is doing for
scripts/link-vmlinux.sh to kallsyms. Although that effort helps
tracers differentiate duplicate symbols it would seem to also help
fuzzers too even if CONFIG_RANDOMIZE_BASE or kaslr are enabled.

[0] https://lore.kernel.org/all/ZSVkRkf3DNyxb7Vw@oracle.com/T/#m465130eb6cdd16a4c187206c69cf6a17960f90a9

> Additionally, even if kaslr can be disabled, we cannot get the
> same covered edge for module because both pc and prev_pc have changed,
> thus altering pc ^ hash(prev_pc).
> 
> To facilitate syzkaller coverage, it is crucial for both the core kernel
> and modules to maintain at the same addresses across reboots.

The problem I see with this, is that, even if it does help, the argument
being put forward here is that the below recipe is completley
deterministic and it's not obviously clear to me that it truly is.

> So, the following steps are necessary:
> - In userspace:
>   1) To maintain an uninterrupted loading sequence, it is recommended to
> execute modprobe commands by loading one module at a time, to avoid any
> interference from the scheduler.
>   2) Avoid unloading any module during fuzzing.
> - In kernel:
>   1) Disable CONFIG_RANDOMIZE_BASE to load the core kernel at the same
> address consistently.
>   2) To ensure deterministic module loading at the same address, enabling
> CONFIG_MODULE_DISABLE_INIT_FREE prevents the asynchronous freeing of init
> sections. Without this option, there is a possibility that the next module
> could be loaded into previous freed init pages of a previous loaded module.

Is this well documented somewhere as a requirement for kernels running
syzkaller?

Because clearly CONFIG_MODULE_DISABLE_INIT_FREE is showing that the
above recipe was *not* deterministic and that there were holes in it.
Who's to say this completes the determinism?

Now, if the justificaiton is that it helps current *state of the art*
fuzzing mapping... that's different and then this could just be
temporary until a more accurate deterministic mechanism is considered.

> It is important to note that this option is intended for fuzzing tests only
> and should not be set as the default configuration in production builds.

  Luis

> 
> Signed-off-by: Joey Jiao <quic_jiangenj@quicinc.com>
> ---
>  kernel/module/Kconfig | 13 +++++++++++++
>  kernel/module/main.c  |  3 ++-
>  2 files changed, 15 insertions(+), 1 deletion(-)
> 
> diff --git a/kernel/module/Kconfig b/kernel/module/Kconfig
> index 33a2e991f608..d0df0b5997b0 100644
> --- a/kernel/module/Kconfig
> +++ b/kernel/module/Kconfig
> @@ -389,4 +389,17 @@ config MODULES_TREE_LOOKUP
>  	def_bool y
>  	depends on PERF_EVENTS || TRACING || CFI_CLANG
>  
> +config MODULE_DISABLE_INIT_FREE
> +	bool "Disable freeing of init sections"
> +	default n
> +	depends on !RANDOMIZE_BASE
> +	help
> +	  By default, the kernel frees init sections after module is fully
> +	  loaded.
> +
> +	  Enabling MODULE_DISABLE_INIT_FREE allows users to prevent the freeing
> +	  of init sections. It is particularly helpful for syzkaller fuzzing,
> +	  ensuring that the module consistently loads at the same address
> +	  across reboots.

But that seems false, I don't see proof to that yet. Helping it be more
acurrate, maybe. If the docs for syzkaller clearly spell these
requirements out then maybe this is valuable upstream for now, but
in the meantime the assumption above is just a bit too large for me
to accept to be true.

> +
>  endif # MODULES
> diff --git a/kernel/module/main.c b/kernel/module/main.c
> index 98fedfdb8db5..d226df3a6cf6 100644
> --- a/kernel/module/main.c
> +++ b/kernel/module/main.c
> @@ -2593,7 +2593,8 @@ static noinline int do_init_module(struct module *mod)
>  	 * be cleaned up needs to sync with the queued work - ie
>  	 * rcu_barrier()
>  	 */
> -	if (llist_add(&freeinit->node, &init_free_list))
> +	if (!IS_ENABLED(CONFIG_MODULE_DISABLE_INIT_FREE) &&
> +	    llist_add(&freeinit->node, &init_free_list))
>  		schedule_work(&init_free_wq);
>  
>  	mutex_unlock(&module_mutex);
> -- 
> 2.42.0
>
Dan Carpenter Oct. 27, 2023, noon UTC | #2
Hi Joey,

kernel test robot noticed the following build warnings:

https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Joey-Jiao/module-Add-CONFIG_MODULE_DISABLE_INIT_FREE-option/20231017-115509
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git modules-next
patch link:    https://lore.kernel.org/r/20231013062711.28852-1-quic_jiangenj%40quicinc.com
patch subject: [PATCH v5] module: Add CONFIG_MODULE_DISABLE_INIT_FREE option
config: x86_64-randconfig-161-20231026 (https://download.01.org/0day-ci/archive/20231027/202310271751.28pKVu4K-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-12) 11.3.0
reproduce: (https://download.01.org/0day-ci/archive/20231027/202310271751.28pKVu4K-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
| Closes: https://lore.kernel.org/r/202310271751.28pKVu4K-lkp@intel.com/

smatch warnings:
kernel/module/main.c:2608 do_init_module() warn: possible memory leak of 'freeinit'

vim +/freeinit +2608 kernel/module/main.c

c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2517  
c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2518  	freeinit = kmalloc(sizeof(*freeinit), GFP_KERNEL);
c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2519  	if (!freeinit) {
c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2520  		ret = -ENOMEM;
c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2521  		goto fail;
c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2522  	}
ac3b4328392344 kernel/module/main.c Song Liu         2023-02-06  2523  	freeinit->init_text = mod->mem[MOD_INIT_TEXT].base;
ac3b4328392344 kernel/module/main.c Song Liu         2023-02-06  2524  	freeinit->init_data = mod->mem[MOD_INIT_DATA].base;
ac3b4328392344 kernel/module/main.c Song Liu         2023-02-06  2525  	freeinit->init_rodata = mod->mem[MOD_INIT_RODATA].base;
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2526  
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2527  	do_mod_ctors(mod);
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2528  	/* Start the module */
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2529  	if (mod->init != NULL)
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2530  		ret = do_one_initcall(mod->init);
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2531  	if (ret < 0) {
c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2532  		goto fail_free_freeinit;
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2533  	}
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2534  	if (ret > 0) {
bddb12b32f90c5 kernel/module.c      Andrew Morton    2013-11-12  2535  		pr_warn("%s: '%s'->init suspiciously returned %d, it should "
bddb12b32f90c5 kernel/module.c      Andrew Morton    2013-11-12  2536  			"follow 0/-E convention\n"
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2537  			"%s: loading module anyway...\n",
bddb12b32f90c5 kernel/module.c      Andrew Morton    2013-11-12  2538  			__func__, mod->name, ret, __func__);
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2539  		dump_stack();
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2540  	}
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2541  
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2542  	/* Now it's a first class citizen! */
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2543  	mod->state = MODULE_STATE_LIVE;
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2544  	blocking_notifier_call_chain(&module_notify_list,
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2545  				     MODULE_STATE_LIVE, mod);
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2546  
38dc717e97153e kernel/module.c      Jessica Yu       2020-11-27  2547  	/* Delay uevent until module has finished its init routine */
38dc717e97153e kernel/module.c      Jessica Yu       2020-11-27  2548  	kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD);
38dc717e97153e kernel/module.c      Jessica Yu       2020-11-27  2549  
774a1221e862b3 kernel/module.c      Tejun Heo        2013-01-15  2550  	/*
774a1221e862b3 kernel/module.c      Tejun Heo        2013-01-15  2551  	 * We need to finish all async code before the module init sequence
67d6212afda218 kernel/module.c      Igor Pylypiv     2022-01-27  2552  	 * is done. This has potential to deadlock if synchronous module
67d6212afda218 kernel/module.c      Igor Pylypiv     2022-01-27  2553  	 * loading is requested from async (which is not allowed!).
774a1221e862b3 kernel/module.c      Tejun Heo        2013-01-15  2554  	 *
67d6212afda218 kernel/module.c      Igor Pylypiv     2022-01-27  2555  	 * See commit 0fdff3ec6d87 ("async, kmod: warn on synchronous
67d6212afda218 kernel/module.c      Igor Pylypiv     2022-01-27  2556  	 * request_module() from async workers") for more details.
774a1221e862b3 kernel/module.c      Tejun Heo        2013-01-15  2557  	 */
67d6212afda218 kernel/module.c      Igor Pylypiv     2022-01-27  2558  	if (!mod->async_probe_requested)
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2559  		async_synchronize_full();
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2560  
ac3b4328392344 kernel/module/main.c Song Liu         2023-02-06  2561  	ftrace_free_mem(mod, mod->mem[MOD_INIT_TEXT].base,
ac3b4328392344 kernel/module/main.c Song Liu         2023-02-06  2562  			mod->mem[MOD_INIT_TEXT].base + mod->mem[MOD_INIT_TEXT].size);
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2563  	mutex_lock(&module_mutex);
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2564  	/* Drop initial reference. */
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2565  	module_put(mod);
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2566  	trim_init_extable(mod);
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2567  #ifdef CONFIG_KALLSYMS
8244062ef1e545 kernel/module.c      Rusty Russell    2016-02-03  2568  	/* Switch to core kallsyms now init is done: kallsyms may be walking! */
8244062ef1e545 kernel/module.c      Rusty Russell    2016-02-03  2569  	rcu_assign_pointer(mod->kallsyms, &mod->core_kallsyms);
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2570  #endif
444d13ff10fb13 kernel/module.c      Jessica Yu       2016-07-27  2571  	module_enable_ro(mod, true);
93c2e105f6bcee kernel/module.c      Peter Zijlstra   2015-05-27  2572  	mod_tree_remove_init(mod);
d453cded05ee21 kernel/module.c      Rusty Russell    2015-01-20  2573  	module_arch_freeing_init(mod);
ac3b4328392344 kernel/module/main.c Song Liu         2023-02-06  2574  	for_class_mod_mem_type(type, init) {
ac3b4328392344 kernel/module/main.c Song Liu         2023-02-06  2575  		mod->mem[type].base = NULL;
ac3b4328392344 kernel/module/main.c Song Liu         2023-02-06  2576  		mod->mem[type].size = 0;
ac3b4328392344 kernel/module/main.c Song Liu         2023-02-06  2577  	}
df3e764d8e5cd4 kernel/module/main.c Luis Chamberlain 2023-03-28  2578  
607c543f939d8c kernel/module.c      Andrii Nakryiko  2020-11-20  2579  #ifdef CONFIG_DEBUG_INFO_BTF_MODULES
607c543f939d8c kernel/module.c      Andrii Nakryiko  2020-11-20  2580  	/* .BTF is not SHF_ALLOC and will get removed, so sanitize pointer */
607c543f939d8c kernel/module.c      Andrii Nakryiko  2020-11-20  2581  	mod->btf_data = NULL;
607c543f939d8c kernel/module.c      Andrii Nakryiko  2020-11-20  2582  #endif
c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2583  	/*
c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2584  	 * We want to free module_init, but be aware that kallsyms may be
0be964be0d4508 kernel/module.c      Peter Zijlstra   2015-05-27  2585  	 * walking this with preempt disabled.  In all the failure paths, we
cb2f55369d3a9e kernel/module.c      Paul E. McKenney 2018-11-06  2586  	 * call synchronize_rcu(), but we don't want to slow down the success
1a7b7d9220819a kernel/module.c      Rick Edgecombe   2019-04-25  2587  	 * path. module_memfree() cannot be called in an interrupt, so do the
1a7b7d9220819a kernel/module.c      Rick Edgecombe   2019-04-25  2588  	 * work and call synchronize_rcu() in a work queue.
1a7b7d9220819a kernel/module.c      Rick Edgecombe   2019-04-25  2589  	 *
ae646f0b9ca135 kernel/module.c      Jeffrey Hugo     2018-05-11  2590  	 * Note that module_alloc() on most architectures creates W+X page
ae646f0b9ca135 kernel/module.c      Jeffrey Hugo     2018-05-11  2591  	 * mappings which won't be cleaned up until do_free_init() runs.  Any
ae646f0b9ca135 kernel/module.c      Jeffrey Hugo     2018-05-11  2592  	 * code such as mark_rodata_ro() which depends on those mappings to
ae646f0b9ca135 kernel/module.c      Jeffrey Hugo     2018-05-11  2593  	 * be cleaned up needs to sync with the queued work - ie
cb2f55369d3a9e kernel/module.c      Paul E. McKenney 2018-11-06  2594  	 * rcu_barrier()
c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2595  	 */
36022a47582048 kernel/module/main.c Joey Jiao        2023-10-13  2596  	if (!IS_ENABLED(CONFIG_MODULE_DISABLE_INIT_FREE) &&
36022a47582048 kernel/module/main.c Joey Jiao        2023-10-13  2597  	    llist_add(&freeinit->node, &init_free_list))

Let's not allocate freeinit if CONFIG_MODULE_DISABLE_INIT_FREE is not
enabled.

1a7b7d9220819a kernel/module.c      Rick Edgecombe   2019-04-25  2598  		schedule_work(&init_free_wq);
1a7b7d9220819a kernel/module.c      Rick Edgecombe   2019-04-25  2599  
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2600  	mutex_unlock(&module_mutex);
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2601  	wake_up_all(&module_wq);
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2602  
df3e764d8e5cd4 kernel/module/main.c Luis Chamberlain 2023-03-28  2603  	mod_stat_add_long(text_size, &total_text_size);
df3e764d8e5cd4 kernel/module/main.c Luis Chamberlain 2023-03-28  2604  	mod_stat_add_long(total_size, &total_mod_size);
df3e764d8e5cd4 kernel/module/main.c Luis Chamberlain 2023-03-28  2605  
df3e764d8e5cd4 kernel/module/main.c Luis Chamberlain 2023-03-28  2606  	mod_stat_inc(&modcount);
df3e764d8e5cd4 kernel/module/main.c Luis Chamberlain 2023-03-28  2607  
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16 @2608  	return 0;
c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2609  
c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2610  fail_free_freeinit:
c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2611  	kfree(freeinit);
c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2612  fail:
c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2613  	/* Try to protect us from buggy refcounters. */
c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2614  	mod->state = MODULE_STATE_GOING;
cb2f55369d3a9e kernel/module.c      Paul E. McKenney 2018-11-06  2615  	synchronize_rcu();
c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2616  	module_put(mod);
c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2617  	blocking_notifier_call_chain(&module_notify_list,
c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2618  				     MODULE_STATE_GOING, mod);
7e545d6eca20ce kernel/module.c      Jessica Yu       2016-03-16  2619  	klp_module_going(mod);
7dcd182bec271a kernel/module.c      Jessica Yu       2016-02-16  2620  	ftrace_release_mod(mod);
c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2621  	free_module(mod);
c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2622  	wake_up_all(&module_wq);
df3e764d8e5cd4 kernel/module/main.c Luis Chamberlain 2023-03-28  2623  
c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2624  	return ret;
34e1169d996ab1 kernel/module.c      Kees Cook        2012-10-16  2625  }
Dan Carpenter Oct. 27, 2023, 12:27 p.m. UTC | #3
On Fri, Oct 27, 2023 at 03:00:00PM +0300, Dan Carpenter wrote:
> 607c543f939d8c kernel/module.c      Andrii Nakryiko  2020-11-20  2579  #ifdef CONFIG_DEBUG_INFO_BTF_MODULES
> 607c543f939d8c kernel/module.c      Andrii Nakryiko  2020-11-20  2580  	/* .BTF is not SHF_ALLOC and will get removed, so sanitize pointer */
> 607c543f939d8c kernel/module.c      Andrii Nakryiko  2020-11-20  2581  	mod->btf_data = NULL;
> 607c543f939d8c kernel/module.c      Andrii Nakryiko  2020-11-20  2582  #endif
> c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2583  	/*
> c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2584  	 * We want to free module_init, but be aware that kallsyms may be
> 0be964be0d4508 kernel/module.c      Peter Zijlstra   2015-05-27  2585  	 * walking this with preempt disabled.  In all the failure paths, we
> cb2f55369d3a9e kernel/module.c      Paul E. McKenney 2018-11-06  2586  	 * call synchronize_rcu(), but we don't want to slow down the success
> 1a7b7d9220819a kernel/module.c      Rick Edgecombe   2019-04-25  2587  	 * path. module_memfree() cannot be called in an interrupt, so do the
> 1a7b7d9220819a kernel/module.c      Rick Edgecombe   2019-04-25  2588  	 * work and call synchronize_rcu() in a work queue.
> 1a7b7d9220819a kernel/module.c      Rick Edgecombe   2019-04-25  2589  	 *
> ae646f0b9ca135 kernel/module.c      Jeffrey Hugo     2018-05-11  2590  	 * Note that module_alloc() on most architectures creates W+X page
> ae646f0b9ca135 kernel/module.c      Jeffrey Hugo     2018-05-11  2591  	 * mappings which won't be cleaned up until do_free_init() runs.  Any
> ae646f0b9ca135 kernel/module.c      Jeffrey Hugo     2018-05-11  2592  	 * code such as mark_rodata_ro() which depends on those mappings to
> ae646f0b9ca135 kernel/module.c      Jeffrey Hugo     2018-05-11  2593  	 * be cleaned up needs to sync with the queued work - ie
> cb2f55369d3a9e kernel/module.c      Paul E. McKenney 2018-11-06  2594  	 * rcu_barrier()
> c749637909eea5 kernel/module.c      Rusty Russell    2015-01-20  2595  	 */
> 36022a47582048 kernel/module/main.c Joey Jiao        2023-10-13  2596  	if (!IS_ENABLED(CONFIG_MODULE_DISABLE_INIT_FREE) &&
> 36022a47582048 kernel/module/main.c Joey Jiao        2023-10-13  2597  	    llist_add(&freeinit->node, &init_free_list))
> 
> Let's not allocate freeinit if CONFIG_MODULE_DISABLE_INIT_FREE is not
> enabled.

Wait.  It's the other way around actually.  freeinit isn't used if
CONFIG_MODULE_DISABLE_INIT_FREE is enabled.

regards,
dan carpenter
diff mbox series

Patch

diff --git a/kernel/module/Kconfig b/kernel/module/Kconfig
index 33a2e991f608..d0df0b5997b0 100644
--- a/kernel/module/Kconfig
+++ b/kernel/module/Kconfig
@@ -389,4 +389,17 @@  config MODULES_TREE_LOOKUP
 	def_bool y
 	depends on PERF_EVENTS || TRACING || CFI_CLANG
 
+config MODULE_DISABLE_INIT_FREE
+	bool "Disable freeing of init sections"
+	default n
+	depends on !RANDOMIZE_BASE
+	help
+	  By default, the kernel frees init sections after module is fully
+	  loaded.
+
+	  Enabling MODULE_DISABLE_INIT_FREE allows users to prevent the freeing
+	  of init sections. It is particularly helpful for syzkaller fuzzing,
+	  ensuring that the module consistently loads at the same address
+	  across reboots.
+
 endif # MODULES
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 98fedfdb8db5..d226df3a6cf6 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -2593,7 +2593,8 @@  static noinline int do_init_module(struct module *mod)
 	 * be cleaned up needs to sync with the queued work - ie
 	 * rcu_barrier()
 	 */
-	if (llist_add(&freeinit->node, &init_free_list))
+	if (!IS_ENABLED(CONFIG_MODULE_DISABLE_INIT_FREE) &&
+	    llist_add(&freeinit->node, &init_free_list))
 		schedule_work(&init_free_wq);
 
 	mutex_unlock(&module_mutex);