[PATCH 0/3] module: make structure definitions always visible

2 views
Skip to first unread message

Thomas Weißschuh

unread,
Jun 12, 2025, 10:54:13 AM6/12/25
to Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Daniel Gomez, Brendan Higgins, David Gow, Rae Moar, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com, Thomas Weißschuh
Code using IS_ENABLED(CONFIG_MODULES) as a C expression may need access
to the module structure definitions to compile.
Make sure these structure definitions are always visible.

Signed-off-by: Thomas Weißschuh <thomas.w...@linutronix.de>
---
Thomas Weißschuh (3):
module: move 'struct module_use' to internal.h
module: make structure definitions always visible
kunit: test: Drop CONFIG_MODULE ifdeffery

include/linux/module.h | 30 ++++++++++++------------------
kernel/module/internal.h | 7 +++++++
lib/kunit/test.c | 8 --------
3 files changed, 19 insertions(+), 26 deletions(-)
---
base-commit: 19272b37aa4f83ca52bdf9c16d5d81bdd1354494
change-id: 20250611-kunit-ifdef-modules-0fefd13ae153

Best regards,
--
Thomas Weißschuh <thomas.w...@linutronix.de>

Thomas Weißschuh

unread,
Jun 12, 2025, 10:54:14 AM6/12/25
to Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Daniel Gomez, Brendan Higgins, David Gow, Rae Moar, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com, Thomas Weißschuh
The struct was moved to the public header file in
commit c8e21ced08b3 ("module: fix kdb's illicit use of struct module_use.").
Back then the structure was used outside of the module core.
Nowadays this is not true anymore, so the structure can be made internal.

Signed-off-by: Thomas Weißschuh <thomas.w...@linutronix.de>
---
include/linux/module.h | 7 -------
kernel/module/internal.h | 7 +++++++
2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/linux/module.h b/include/linux/module.h
index 92e1420fccdffc9de9f49da9061546cc1e0c89d1..52f7b0487a2733c56e2531a434887e56e1bf45b2 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -313,13 +313,6 @@ void *__symbol_get_gpl(const char *symbol);
__used __section(".no_trim_symbol") = __stringify(x); \
(typeof(&x))(__symbol_get(__stringify(x))); })

-/* modules using other modules: kdb wants to see this. */
-struct module_use {
- struct list_head source_list;
- struct list_head target_list;
- struct module *source, *target;
-};
-
enum module_state {
MODULE_STATE_LIVE, /* Normal state. */
MODULE_STATE_COMING, /* Full formed, running module_init. */
diff --git a/kernel/module/internal.h b/kernel/module/internal.h
index 8d74b0a21c82b5360977a29736eca78ee6b6be3e..1c2e0b0dc52e72d5ecd2f1b310ce535364b3f33b 100644
--- a/kernel/module/internal.h
+++ b/kernel/module/internal.h
@@ -109,6 +109,13 @@ struct find_symbol_arg {
enum mod_license license;
};

+/* modules using other modules */
+struct module_use {
+ struct list_head source_list;
+ struct list_head target_list;
+ struct module *source, *target;
+};
+
int mod_verify_sig(const void *mod, struct load_info *info);
int try_to_force_load(struct module *mod, const char *reason);
bool find_symbol(struct find_symbol_arg *fsa);

--
2.49.0

Thomas Weißschuh

unread,
Jun 12, 2025, 10:54:15 AM6/12/25
to Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Daniel Gomez, Brendan Higgins, David Gow, Rae Moar, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com, Thomas Weißschuh
The function stubs exposed by module.h allow the code to compile properly
without the ifdeffery. The generated object code stays the same, as the
compiler can optimize away all the dead code.
As the code is still typechecked developer errors can be detected faster.

Signed-off-by: Thomas Weißschuh <thomas.w...@linutronix.de>
---
lib/kunit/test.c | 8 --------
1 file changed, 8 deletions(-)

diff --git a/lib/kunit/test.c b/lib/kunit/test.c
index 146d1b48a0965e8aaddb6162928f408bbb542645..019b2ac9c8469021542b610278f8842e100d57ad 100644
--- a/lib/kunit/test.c
+++ b/lib/kunit/test.c
@@ -759,7 +759,6 @@ void __kunit_test_suites_exit(struct kunit_suite **suites, int num_suites)
}
EXPORT_SYMBOL_GPL(__kunit_test_suites_exit);

-#ifdef CONFIG_MODULES
static void kunit_module_init(struct module *mod)
{
struct kunit_suite_set suite_set, filtered_set;
@@ -847,7 +846,6 @@ static struct notifier_block kunit_mod_nb = {
.notifier_call = kunit_module_notify,
.priority = 0,
};
-#endif

KUNIT_DEFINE_ACTION_WRAPPER(kfree_action_wrapper, kfree, const void *)

@@ -938,20 +936,14 @@ static int __init kunit_init(void)
kunit_debugfs_init();

kunit_bus_init();
-#ifdef CONFIG_MODULES
return register_module_notifier(&kunit_mod_nb);
-#else
- return 0;
-#endif
}
late_initcall(kunit_init);

static void __exit kunit_exit(void)
{
memset(&kunit_hooks, 0, sizeof(kunit_hooks));
-#ifdef CONFIG_MODULES
unregister_module_notifier(&kunit_mod_nb);
-#endif

kunit_bus_shutdown();


--
2.49.0

Thomas Weißschuh

unread,
Jun 12, 2025, 10:54:15 AM6/12/25
to Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Daniel Gomez, Brendan Higgins, David Gow, Rae Moar, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com, Thomas Weißschuh
To write code that works with both CONFIG_MODULES=y and CONFIG_MODULES=n
it is convenient to use "if (IS_ENABLED(CONFIG_MODULES))" over raw #ifdef.
The code will still fully typechecked but the unreachable parts are
discarded by the compiler. This prevents accidental breakage when a certain
kconfig combination was not specifically tested by the developer.
This pattern is already supported to some extend by module.h defining
empty stub functions if CONFIG_MODULES=n.
However some users of module.h work on the structured defined by module.h.

Therefore these structure definitions need to be visible, too.

Many structure members are still gated by specific configuration settings.
The assumption for those is that the code using them will be gated behind
the same configuration setting anyways.

Signed-off-by: Thomas Weißschuh <thomas.w...@linutronix.de>
---
include/linux/module.h | 23 ++++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/include/linux/module.h b/include/linux/module.h
index 52f7b0487a2733c56e2531a434887e56e1bf45b2..7f783e71636542b99db3dd869a9387d14992df45 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -302,17 +302,6 @@ static typeof(name) __mod_device_table__##type##__##name \

struct notifier_block;

-#ifdef CONFIG_MODULES
-
-extern int modules_disabled; /* for sysctl */
-/* Get/put a kernel symbol (calls must be symmetric) */
-void *__symbol_get(const char *symbol);
-void *__symbol_get_gpl(const char *symbol);
-#define symbol_get(x) ({ \
- static const char __notrim[] \
- __used __section(".no_trim_symbol") = __stringify(x); \
- (typeof(&x))(__symbol_get(__stringify(x))); })
-
enum module_state {
MODULE_STATE_LIVE, /* Normal state. */
MODULE_STATE_COMING, /* Full formed, running module_init. */
@@ -598,6 +587,18 @@ struct module {
struct _ddebug_info dyndbg_info;
#endif
} ____cacheline_aligned __randomize_layout;
+
+#ifdef CONFIG_MODULES
+
+extern int modules_disabled; /* for sysctl */
+/* Get/put a kernel symbol (calls must be symmetric) */
+void *__symbol_get(const char *symbol);
+void *__symbol_get_gpl(const char *symbol);
+#define symbol_get(x) ({ \
+ static const char __notrim[] \
+ __used __section(".no_trim_symbol") = __stringify(x); \
+ (typeof(&x))(__symbol_get(__stringify(x))); })
+
#ifndef MODULE_ARCH_INIT
#define MODULE_ARCH_INIT {}
#endif

--
2.49.0

Petr Pavlu

unread,
Jun 17, 2025, 3:38:35 AM6/17/25
to Thomas Weißschuh, Luis Chamberlain, Sami Tolvanen, Daniel Gomez, Brendan Higgins, David Gow, Rae Moar, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com
On 6/12/25 4:53 PM, Thomas Weißschuh wrote:
> The struct was moved to the public header file in
> commit c8e21ced08b3 ("module: fix kdb's illicit use of struct module_use.").
> Back then the structure was used outside of the module core.
> Nowadays this is not true anymore, so the structure can be made internal.
>
> Signed-off-by: Thomas Weißschuh <thomas.w...@linutronix.de>

Reviewed-by: Petr Pavlu <petr....@suse.com>

--
Thanks,
Petr

Petr Pavlu

unread,
Jun 17, 2025, 3:44:54 AM6/17/25
to Thomas Weißschuh, Luis Chamberlain, Sami Tolvanen, Daniel Gomez, Brendan Higgins, David Gow, Rae Moar, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com
On 6/12/25 4:53 PM, Thomas Weißschuh wrote:
> The function stubs exposed by module.h allow the code to compile properly
> without the ifdeffery. The generated object code stays the same, as the
> compiler can optimize away all the dead code.
> As the code is still typechecked developer errors can be detected faster.
>
> Signed-off-by: Thomas Weißschuh <thomas.w...@linutronix.de>

I'm worried that patches #2 and #3 make the code harder to understand
because they hide what is compiled and when.

Normally, '#ifdef CONFIG_XYZ' or IS_ENABLED(CONFIG_XYZ) directly
surrounds functionality that should be conditional. This makes it clear
what is used and when.

The patches obscure whether, for instance, kunit_module_notify() in
lib/kunit/test.c is actually used and present in the resulting binary
behind several steps. Understanding its usage requires tracing the code
from kunit_module_notify() to the definition of kunit_mod_nb, then to
the register_module_notifier() call, and finally depends on an ifdef in
another file, include/linux/module.h.

Is this really better? Are there places where this pattern is already
used? Does it actually help in practice, considering that CONFIG_MODULES
is enabled in most cases?

--
Thanks,
Petr

Thomas Weißschuh

unread,
Jun 17, 2025, 4:39:50 AM6/17/25
to Petr Pavlu, Luis Chamberlain, Sami Tolvanen, Daniel Gomez, Brendan Higgins, David Gow, Rae Moar, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com
On Tue, Jun 17, 2025 at 09:44:49AM +0200, Petr Pavlu wrote:
> On 6/12/25 4:53 PM, Thomas Weißschuh wrote:
> > The function stubs exposed by module.h allow the code to compile properly
> > without the ifdeffery. The generated object code stays the same, as the
> > compiler can optimize away all the dead code.
> > As the code is still typechecked developer errors can be detected faster.
> >
> > Signed-off-by: Thomas Weißschuh <thomas.w...@linutronix.de>
>
> I'm worried that patches #2 and #3 make the code harder to understand
> because they hide what is compiled and when.
>
> Normally, '#ifdef CONFIG_XYZ' or IS_ENABLED(CONFIG_XYZ) directly
> surrounds functionality that should be conditional. This makes it clear
> what is used and when.

#ifdef is discouraged in C files and IS_ENABLED(CONFIG_MODULES) does not work
(here) without patch #2.

> The patches obscure whether, for instance, kunit_module_notify() in
> lib/kunit/test.c is actually used and present in the resulting binary
> behind several steps. Understanding its usage requires tracing the code
> from kunit_module_notify() to the definition of kunit_mod_nb, then to
> the register_module_notifier() call, and finally depends on an ifdef in
> another file, include/linux/module.h.

I agree that it is not completely clear what will end up in the binary.
On the other hand we can program the happy path and the compiler will take care
of all the corner cases.
We could add an "if (IS_ENABLED(CONFIG_MODULES))" which does not really change
anything but would be clearer to read.

> Is this really better? Are there places where this pattern is already
> used? Does it actually help in practice, considering that CONFIG_MODULES
> is enabled in most cases?

This came up for me when refactoring some KUnit internal code.
I used "kunit.py run" (which uses CONFIG_MODULES=n) to test my changes.
But some callers of changed functions were not updated and this wasn't reported.

The stub functions are a standard pattern and already implemented by module.h.
I have not found a header which hides structure definitions.

Documentation/process/coding-style.rst:

21) Conditional Compilation
---------------------------

Wherever possible, don't use preprocessor conditionals (#if, #ifdef) in .c
files; doing so makes code harder to read and logic harder to follow. Instead,
use such conditionals in a header file defining functions for use in those .c
files, providing no-op stub versions in the #else case, and then call those
functions unconditionally from .c files. The compiler will avoid generating
any code for the stub calls, producing identical results, but the logic will
remain easy to follow.

I should add the documentation reference to patch #2.

Petr Pavlu

unread,
Jun 17, 2025, 11:07:37 AM6/17/25
to Thomas Weißschuh, Luis Chamberlain, Sami Tolvanen, Daniel Gomez, Brendan Higgins, David Gow, Rae Moar, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com
I see.

>
> The stub functions are a standard pattern and already implemented by module.h.

Stub functions are ok, I have no concerns about that pattern.

> I have not found a header which hides structure definitions.

It seems you're right. I think that makes patch #2 acceptable, it is
consistent with other kernel code.

>
> Documentation/process/coding-style.rst:
>
> 21) Conditional Compilation
> ---------------------------
>
> Wherever possible, don't use preprocessor conditionals (#if, #ifdef) in .c
> files; doing so makes code harder to read and logic harder to follow. Instead,
> use such conditionals in a header file defining functions for use in those .c
> files, providing no-op stub versions in the #else case, and then call those
> functions unconditionally from .c files. The compiler will avoid generating
> any code for the stub calls, producing identical results, but the logic will
> remain easy to follow.
>
> I should add the documentation reference to patch #2.

This part discusses stub functions. I feel patch #3 stretches the
intention of the coding style described here. As discussed, the patch
somewhat hides when the functions are actually used, which might not be
desirable, but I'll leave it to the kunit folks to decide what they
prefer.

--
Thanks,
Petr

Daniel Gomez

unread,
Jun 19, 2025, 12:27:24 PM6/19/25
to Thomas Weißschuh, Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Daniel Gomez, Brendan Higgins, David Gow, Rae Moar, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com
On 12/06/2025 16.53, Thomas WeiÃschuh wrote:
> The struct was moved to the public header file in
> commit c8e21ced08b3 ("module: fix kdb's illicit use of struct module_use.").
> Back then the structure was used outside of the module core.
> Nowadays this is not true anymore, so the structure can be made internal.
>
> Signed-off-by: Thomas Weißschuh <thomas.w...@linutronix.de>

Reviewed-by: Daniel Gomez <da.g...@samsung.com>

David Gow

unread,
Jun 20, 2025, 5:52:13 AM6/20/25
to Thomas Weißschuh, Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Daniel Gomez, Brendan Higgins, Rae Moar, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com
On Thu, 12 Jun 2025 at 22:54, Thomas Weißschuh
<thomas.w...@linutronix.de> wrote:
>
> The function stubs exposed by module.h allow the code to compile properly
> without the ifdeffery. The generated object code stays the same, as the
> compiler can optimize away all the dead code.
> As the code is still typechecked developer errors can be detected faster.
>
> Signed-off-by: Thomas Weißschuh <thomas.w...@linutronix.de>
> ---

Acked-by: David Gow <davi...@google.com>

Cheers,
-- David

Daniel Gomez

unread,
Jul 7, 2025, 3:11:14 PM7/7/25
to Thomas Weißschuh, Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Daniel Gomez, Brendan Higgins, David Gow, Rae Moar, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com
On 12/06/2025 16.53, Thomas WeiÃschuh wrote:
> To write code that works with both CONFIG_MODULES=y and CONFIG_MODULES=n
> it is convenient to use "if (IS_ENABLED(CONFIG_MODULES))" over raw #ifdef.
> The code will still fully typechecked but the unreachable parts are
> discarded by the compiler. This prevents accidental breakage when a certain
> kconfig combination was not specifically tested by the developer.
> This pattern is already supported to some extend by module.h defining
> empty stub functions if CONFIG_MODULES=n.
> However some users of module.h work on the structured defined by module.h.
>
> Therefore these structure definitions need to be visible, too.

We are missing here which structures are needed. + we are making more things
visible than what we actually need.

>
> Many structure members are still gated by specific configuration settings.
> The assumption for those is that the code using them will be gated behind
> the same configuration setting anyways.

I think code and kconfig need to reflect the actual dependencies. For example,
if CONFIG_LIVEPATCH depends on CONFIG_MODULES, we need to specify that in
Kconfig with depends on, as well as keep the code gated by these 2 configs with
ifdef/IS_ENABLED.
The patch exposes data structures that are not needed. + breaks the
config dependencies.

For example, before this patch:

#ifdef CONFIG_MODULES

{...}

struct mod_tree_node {

{...}

struct module_memory {
void *base;
bool is_rox;
unsigned int size;

#ifdef CONFIG_MODULES_TREE_LOOKUP
struct mod_tree_node mtn;
#endif
};

{...}
#endif /* CONFIG_MODULES */

After the patch, mod_tree_node is not needed externally. And the mtn field
in module_memory is exposed only under MODULES_TREE_LOOKUP and not MODULES
+ MODULES_TREE_LOOKUP.

I general, I see the issues I mentioned with LIVEPATCH, mod_tree_node, macros,
and LOOKUP.

> #define MODULE_ARCH_INIT {}
> #endif
>

Petr Pavlu

unread,
Jul 8, 2025, 5:32:13 AM7/8/25
to Daniel Gomez, Thomas Weißschuh, Luis Chamberlain, Sami Tolvanen, Daniel Gomez, Brendan Higgins, David Gow, Rae Moar, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com
I think the idea is that having unnecessary structures in header files
isn't particularly harmful, as they won't affect the resulting binary.
On the other hand, they can help with type checking of conditional code
as shown by patch #3.

This is different compared to "extern int modules_disabled;" and
"void *__symbol_get(const char *symbol);" which the patch correctly
still protects by '#ifdef CONFIG_MODULES'. Not hiding them could result
in successful compilation but an error only at link time.

--
Thanks,
Petr

Petr Pavlu

unread,
Jul 8, 2025, 5:39:45 AM7/8/25
to Thomas Weißschuh, Luis Chamberlain, Sami Tolvanen, Daniel Gomez, Brendan Higgins, David Gow, Rae Moar, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com
On 6/12/25 4:53 PM, Thomas Weißschuh wrote:
Nit: I suggest keeping MODULE_ARCH_INIT in its current position,
immediately after the 'struct module' declaration, because the macro is
directly tied to that structure.

--
Thanks,
Petr

Thomas Weißschuh

unread,
Jul 11, 2025, 2:29:10 AM7/11/25
to Daniel Gomez, Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Daniel Gomez, Brendan Higgins, David Gow, Rae Moar, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com
On Mon, Jul 07, 2025 at 09:11:05PM +0200, Daniel Gomez wrote:
> On 12/06/2025 16.53, Thomas WeiÃschuh wrote:
> > To write code that works with both CONFIG_MODULES=y and CONFIG_MODULES=n
> > it is convenient to use "if (IS_ENABLED(CONFIG_MODULES))" over raw #ifdef.
> > The code will still fully typechecked but the unreachable parts are
> > discarded by the compiler. This prevents accidental breakage when a certain
> > kconfig combination was not specifically tested by the developer.
> > This pattern is already supported to some extend by module.h defining
> > empty stub functions if CONFIG_MODULES=n.
> > However some users of module.h work on the structured defined by module.h.
> >
> > Therefore these structure definitions need to be visible, too.
>
> We are missing here which structures are needed. + we are making more things
> visible than what we actually need.
>
> >
> > Many structure members are still gated by specific configuration settings.
> > The assumption for those is that the code using them will be gated behind
> > the same configuration setting anyways.
>
> I think code and kconfig need to reflect the actual dependencies. For example,
> if CONFIG_LIVEPATCH depends on CONFIG_MODULES, we need to specify that in
> Kconfig with depends on, as well as keep the code gated by these 2 configs with
> ifdef/IS_ENABLED.

If CONFIG_LIVEPATCH depends on CONFIG_MODULES in kconfig then
IS_ENABLED(CONFIG_LIVEPATCH) will depend on CONFIG_MODULES automatically.
There is no need for another explicit IS_ENABLED(CONFIG_MODULES).
If we want to expose 'struct module' to !CONFIG_MODULES code, all it's
effective member types also need to be included.
With my patch these member types are actually still implictly gated behind
CONFIG_MODULES as they depend on it through kconfig.

>
> For example, before this patch:
>
> #ifdef CONFIG_MODULES
>
> {...}
>
> struct mod_tree_node {
>
> {...}
>
> struct module_memory {
> void *base;
> bool is_rox;
> unsigned int size;
>
> #ifdef CONFIG_MODULES_TREE_LOOKUP
> struct mod_tree_node mtn;
> #endif
> };
>
> {...}
> #endif /* CONFIG_MODULES */
>
> After the patch, mod_tree_node is not needed externally.

Can you explain what you mean with "not needed externally"?
'struct mod_tree_node' is only ever used by core module code.
It is only public because it is embedded in the public 'struct module'

> And the mtn field
> in module_memory is exposed only under MODULES_TREE_LOOKUP and not MODULES
> + MODULES_TREE_LOOKUP.

As mentioned above, MODULES_TREE_LOOKUP && !MODULES can never happen.

Daniel Gomez

unread,
Jul 11, 2025, 9:24:35 AM7/11/25
to Thomas Weißschuh, Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Daniel Gomez, Brendan Higgins, David Gow, Rae Moar, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com
On 11/07/2025 08.29, Thomas WeiÃschuh wrote:
> On Mon, Jul 07, 2025 at 09:11:05PM +0200, Daniel Gomez wrote:
>> On 12/06/2025 16.53, Thomas WeiÃschuh wrote:
>>> To write code that works with both CONFIG_MODULES=y and CONFIG_MODULES=n
>>> it is convenient to use "if (IS_ENABLED(CONFIG_MODULES))" over raw #ifdef.
>>> The code will still fully typechecked but the unreachable parts are
>>> discarded by the compiler. This prevents accidental breakage when a certain
>>> kconfig combination was not specifically tested by the developer.
>>> This pattern is already supported to some extend by module.h defining
>>> empty stub functions if CONFIG_MODULES=n.
>>> However some users of module.h work on the structured defined by module.h.
>>>
>>> Therefore these structure definitions need to be visible, too.
>>
>> We are missing here which structures are needed. + we are making more things
>> visible than what we actually need.
>>
>>>
>>> Many structure members are still gated by specific configuration settings.
>>> The assumption for those is that the code using them will be gated behind
>>> the same configuration setting anyways.
>>
>> I think code and kconfig need to reflect the actual dependencies. For example,
>> if CONFIG_LIVEPATCH depends on CONFIG_MODULES, we need to specify that in
>> Kconfig with depends on, as well as keep the code gated by these 2 configs with
>> ifdef/IS_ENABLED.
>
> If CONFIG_LIVEPATCH depends on CONFIG_MODULES in kconfig then
> IS_ENABLED(CONFIG_LIVEPATCH) will depend on CONFIG_MODULES automatically.
> There is no need for another explicit IS_ENABLED(CONFIG_MODULES).

This makes sense to me. My assessment before to reflect in code what we have in
kconfig does not scale. Thanks.

>
>>>
>>> Signed-off-by: Thomas Weißschuh <thomas.w...@linutronix.de>
>>> ---
>>> include/linux/module.h | 23 ++++++++++++-----------
>>> 1 file changed, 12 insertions(+), 11 deletions(-)

{...}

>>
>> After the patch, mod_tree_node is not needed externally.
>
> Can you explain what you mean with "not needed externally"?
> 'struct mod_tree_node' is only ever used by core module code.
> It is only public because it is embedded in the public 'struct module'

But only when MODULES_TREE_LOOKUP is enabled. Now, all kernels (regardless of
that config) will define mod_tree_node data structure.

However, Petr already stated that is harmless to do so. I was trying here to
not be useless.

With that, changes look good to me:

Reviewed-by: Daniel Gomez <da.g...@samsung.com>

Daniel Gomez

unread,
Jul 11, 2025, 9:25:21 AM7/11/25
to Thomas Weißschuh, Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Daniel Gomez, Brendan Higgins, David Gow, Rae Moar, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com
On 12/06/2025 16.53, Thomas WeiÃschuh wrote:
> The function stubs exposed by module.h allow the code to compile properly
> without the ifdeffery. The generated object code stays the same, as the
> compiler can optimize away all the dead code.
> As the code is still typechecked developer errors can be detected faster.
>
> Signed-off-by: Thomas Weißschuh <thomas.w...@linutronix.de>

Reviewed-by: Daniel Gomez <da.g...@samsung.com>

Thomas Weißschuh

unread,
Jul 11, 2025, 9:31:44 AM7/11/25
to Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Daniel Gomez, Brendan Higgins, David Gow, Rae Moar, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com, Thomas Weißschuh
Code using IS_ENABLED(CONFIG_MODULES) as a C expression may need access
to the module structure definitions to compile.
Make sure these structure definitions are always visible.

This will conflict with commit 6bb37af62634 ("module: Move modprobe_path
and modules_disabled ctl_tables into the module subsys") from the sysctl
tree, but the resolution is trivial.

Signed-off-by: Thomas Weißschuh <thomas.w...@linutronix.de>
---
Changes in v2:
- Pick up tags from v1
- Keep MODULE_ARCH_INIT and 'struct module' definitions together
- Link to v1: https://lore.kernel.org/r/20250612-kunit-ifdef-mo...@linutronix.de

---
Thomas Weißschuh (3):
module: move 'struct module_use' to internal.h
module: make structure definitions always visible
kunit: test: Drop CONFIG_MODULE ifdeffery

include/linux/module.h | 29 +++++++++++------------------
kernel/module/internal.h | 7 +++++++
lib/kunit/test.c | 8 --------
3 files changed, 18 insertions(+), 26 deletions(-)

Thomas Weißschuh

unread,
Jul 11, 2025, 9:31:44 AM7/11/25
to Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Daniel Gomez, Brendan Higgins, David Gow, Rae Moar, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com, Thomas Weißschuh
The struct was moved to the public header file in commit c8e21ced08b3
("module: fix kdb's illicit use of struct module_use.").
Back then the structure was used outside of the module core.
Nowadays this is not true anymore, so the structure can be made internal.

Signed-off-by: Thomas Weißschuh <thomas.w...@linutronix.de>
Reviewed-by: Daniel Gomez <da.g...@samsung.com>
Reviewed-by: Petr Pavlu <petr....@suse.com>
---
include/linux/module.h | 7 -------
kernel/module/internal.h | 7 +++++++
2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/linux/module.h b/include/linux/module.h
index 92e1420fccdffc9de9f49da9061546cc1e0c89d1..52f7b0487a2733c56e2531a434887e56e1bf45b2 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -313,13 +313,6 @@ void *__symbol_get_gpl(const char *symbol);
__used __section(".no_trim_symbol") = __stringify(x); \
(typeof(&x))(__symbol_get(__stringify(x))); })

-/* modules using other modules: kdb wants to see this. */
-struct module_use {
- struct list_head source_list;
- struct list_head target_list;
- struct module *source, *target;
-};
-
enum module_state {
MODULE_STATE_LIVE, /* Normal state. */
MODULE_STATE_COMING, /* Full formed, running module_init. */
diff --git a/kernel/module/internal.h b/kernel/module/internal.h
index 8d74b0a21c82b5360977a29736eca78ee6b6be3e..1c2e0b0dc52e72d5ecd2f1b310ce535364b3f33b 100644
--- a/kernel/module/internal.h
+++ b/kernel/module/internal.h
@@ -109,6 +109,13 @@ struct find_symbol_arg {
enum mod_license license;
};

+/* modules using other modules */
+struct module_use {
+ struct list_head source_list;
+ struct list_head target_list;
+ struct module *source, *target;
+};
+
int mod_verify_sig(const void *mod, struct load_info *info);
int try_to_force_load(struct module *mod, const char *reason);
bool find_symbol(struct find_symbol_arg *fsa);

--
2.50.0

Thomas Weißschuh

unread,
Jul 11, 2025, 9:31:45 AM7/11/25
to Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Daniel Gomez, Brendan Higgins, David Gow, Rae Moar, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com, Thomas Weißschuh
To write code that works with both CONFIG_MODULES=y and CONFIG_MODULES=n
it is convenient to use "if (IS_ENABLED(CONFIG_MODULES))" over raw #ifdef.
The code will still fully typechecked but the unreachable parts are
discarded by the compiler. This prevents accidental breakage when a certain
kconfig combination was not specifically tested by the developer.
This pattern is already supported to some extend by module.h defining
empty stub functions if CONFIG_MODULES=n.
However some users of module.h work on the structured defined by module.h.

Therefore these structure definitions need to be visible, too.

Many structure members are still gated by specific configuration settings.
The assumption for those is that the code using them will be gated behind
the same configuration setting anyways.

Signed-off-by: Thomas Weißschuh <thomas.w...@linutronix.de>
Reviewed-by: Daniel Gomez <da.g...@samsung.com>
---
include/linux/module.h | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/include/linux/module.h b/include/linux/module.h
index 52f7b0487a2733c56e2531a434887e56e1bf45b2..2f330e60a7420a144abeed6d357ac93c39a705e9 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -302,17 +302,6 @@ static typeof(name) __mod_device_table__##type##__##name \

struct notifier_block;

-#ifdef CONFIG_MODULES
-
-extern int modules_disabled; /* for sysctl */
-/* Get/put a kernel symbol (calls must be symmetric) */
-void *__symbol_get(const char *symbol);
-void *__symbol_get_gpl(const char *symbol);
-#define symbol_get(x) ({ \
- static const char __notrim[] \
- __used __section(".no_trim_symbol") = __stringify(x); \
- (typeof(&x))(__symbol_get(__stringify(x))); })
-
enum module_state {
MODULE_STATE_LIVE, /* Normal state. */
MODULE_STATE_COMING, /* Full formed, running module_init. */
@@ -602,6 +591,17 @@ struct module {
#define MODULE_ARCH_INIT {}
#endif

+#ifdef CONFIG_MODULES
+
+extern int modules_disabled; /* for sysctl */
+/* Get/put a kernel symbol (calls must be symmetric) */
+void *__symbol_get(const char *symbol);
+void *__symbol_get_gpl(const char *symbol);
+#define symbol_get(x) ({ \
+ static const char __notrim[] \
+ __used __section(".no_trim_symbol") = __stringify(x); \
+ (typeof(&x))(__symbol_get(__stringify(x))); })
+
#ifndef HAVE_ARCH_KALLSYMS_SYMBOL_VALUE
static inline unsigned long kallsyms_symbol_value(const Elf_Sym *sym)
{

--
2.50.0

Thomas Weißschuh

unread,
Jul 11, 2025, 9:31:46 AM7/11/25
to Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Daniel Gomez, Brendan Higgins, David Gow, Rae Moar, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com, Thomas Weißschuh
The function stubs exposed by module.h allow the code to compile properly
without the ifdeffery. The generated object code stays the same, as the
compiler can optimize away all the dead code.
As the code is still typechecked developer errors can be detected faster.

Signed-off-by: Thomas Weißschuh <thomas.w...@linutronix.de>
Acked-by: David Gow <davi...@google.com>
Reviewed-by: Daniel Gomez <da.g...@samsung.com>
---
2.50.0

Daniel Gomez

unread,
Jul 11, 2025, 9:39:08 AM7/11/25
to Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Brendan Higgins, David Gow, Rae Moar, Thomas Weißschuh, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com

On Fri, 11 Jul 2025 15:31:35 +0200, Thomas Weißschuh wrote:
> Code using IS_ENABLED(CONFIG_MODULES) as a C expression may need access
> to the module structure definitions to compile.
> Make sure these structure definitions are always visible.
>
> This will conflict with commit 6bb37af62634 ("module: Move modprobe_path
> and modules_disabled ctl_tables into the module subsys") from the sysctl
> tree, but the resolution is trivial.
>
> [...]

Applied, thanks!

[1/3] module: move 'struct module_use' to internal.h
commit: bb02f22eaabc4d878577e2b8c46ed7b6be5f5459
[2/3] module: make structure definitions always visible
commit: 02281b559cd1fdfdc8f7eb05bbbe3ab7b35246f0
[3/3] kunit: test: Drop CONFIG_MODULE ifdeffery
commit: dffcba8acea3a80b3478750ac32f17bd5345b68e

Best regards,
--
Daniel Gomez <da.g...@samsung.com>

Thomas Weißschuh

unread,
Jul 11, 2025, 9:51:45 AM7/11/25
to Daniel Gomez, Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Brendan Higgins, David Gow, Rae Moar, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com
Thanks!

FYI If you apply a patch you need to add yourself to the Signed-off-by chain.
And Link tags are nice. For example:

b4 shazam --add-my-sob --add-link

Daniel Gomez

unread,
Jul 11, 2025, 10:06:29 AM7/11/25
to Thomas Weißschuh, Daniel Gomez, Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Brendan Higgins, David Gow, Rae Moar, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com
You're correct. I had a lapse there. Branch updated. Thanks!

[1/3] module: move 'struct module_use' to internal.h
commit: 6633d3a45a8c075193304d12ba10a1771d1dbf10
[2/3] module: make structure definitions always visible
commit: a55842991352a8b512f40d1424b65c911ffbf6fa
[3/3] kunit: test: Drop CONFIG_MODULE ifdeffery
commit: 699657e8e50ae967ae26f704f6fbfa598fcb0cef
Reply all
Reply to author
Forward
0 new messages