[PATCH 0/2] scsi: target+fcoe: replace -EEXIST with -EBUSY in module_init() paths

Daniel Gomez posted 2 patches 1 month, 2 weeks ago
drivers/scsi/fcoe/fcoe_transport.c | 2 +-
drivers/target/target_core_hba.c   | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
[PATCH 0/2] scsi: target+fcoe: replace -EEXIST with -EBUSY in module_init() paths
Posted by Daniel Gomez 1 month, 2 weeks ago
The error code -EEXIST is reserved by the kernel module loader to
indicate that a module with the same name is already loaded. When a
module's init function returns -EEXIST, kmod interprets this as "module
already loaded" and reports success instead of failure [1].

The kernel module loader will include a safety net that provides -EEXIST
to -EBUSY with a warning [2], and a documentation patch has been sent to
prevent future occurrences [3].

These affected code paths were identified using a static analysis tool
[4] that traces -EEXIST returns to module_init(). The tool was developed
with AI assistance and all findings were manually validated.

Link: https://lore.kernel.org/all/aKEVQhJpRdiZSliu@orbyte.nwl.cc/ [1]
Link: https://lore.kernel.org/all/20251013-module-warn-ret-v1-0-ab65b41af01f@intel.com/ [2]
Link: https://lore.kernel.org/all/20251218-dev-module-init-eexists-modules-docs-v1-0-361569aa782a@samsung.com/ [3]
Link: https://gitlab.com/-/snippets/4913469 [4]

Signed-off-by: Daniel Gomez <da.gomez@samsung.com>
---
Daniel Gomez (2):
      target: replace -EEXIST with -EBUSY
      scsi: fcoe: replace -EEXIST with -EBUSY

 drivers/scsi/fcoe/fcoe_transport.c | 2 +-
 drivers/target/target_core_hba.c   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
---
base-commit: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
change-id: 20251218-dev-module-init-eexists-linux-scsi-4e91a16f7bdd

Best regards,
--  
Daniel Gomez <da.gomez@samsung.com>
Re: [PATCH 0/2] scsi: target+fcoe: replace -EEXIST with -EBUSY in module_init() paths
Posted by James Bottomley 1 month, 2 weeks ago
On Sat, 2025-12-20 at 04:37 +0100, Daniel Gomez wrote:
> The error code -EEXIST is reserved by the kernel module loader to
> indicate that a module with the same name is already loaded. When a
> module's init function returns -EEXIST, kmod interprets this as
> "module already loaded" and reports success instead of failure [1].

That reference doesn't sufficiently explain why this error code should
be unique to modules.  EEXIST is used all over the kernel to indicate
that something being attempted has already happened or does already
exist and that seems perfectly logical .... please explain why you're
trying to push it back to being a single use case for modules alone.

Regards,

James
Re: [PATCH 0/2] scsi: target+fcoe: replace -EEXIST with -EBUSY in module_init() paths
Posted by Daniel Gomez 1 month, 2 weeks ago
On 20/12/2025 05.27, James Bottomley wrote:
> On Sat, 2025-12-20 at 04:37 +0100, Daniel Gomez wrote:
>> The error code -EEXIST is reserved by the kernel module loader to
>> indicate that a module with the same name is already loaded. When a
>> module's init function returns -EEXIST, kmod interprets this as
>> "module already loaded" and reports success instead of failure [1].
> 
> That reference doesn't sufficiently explain why this error code should
> be unique to modules.

It's unique only to the module initialization. You can find how it's used in the
kernel module code at module_patient_check_exists() in kernel/module/main.c [1].

In addition, init_module(2) man pages indicates this:

man 2 init_module | grep EEXIST
       EEXIST A module with this name is already loaded.

So, a module that is already loaded will be detected by the kernel module loader
and the EEXIST error will be returned. This will be detected by kmod as success
[2]. I think this functionality was added very early on in kmod by commit
5f35147 "libkmod-module: probe: add flag to stop loading on already loaded" [3].
Prior to that, module-init-tools had the same behavior [4]. Even in modutils
[5], we had back then in insmod/insmod.c:2088:

		case EEXIST:
			if (dolock) {
				/*
				 * Assume that we were just invoked
				 * simultaneous with another insmod
				 * and return success.
				 */
				exit_status = 0;
				goto out;
			}
			error("a module named %s already exists", m_name);
			goto out;

Link: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/module/main.c?h=v6.19-rc1#n3206 [1]
Link: https://github.com/kmod-project/kmod/blob/v34.2/libkmod/libkmod-module.c#L1088 [2]
Link: https://github.com/kmod-project/kmod/commit/5f3514731ef82084c1a24b15445e0f1352681a19 [3]
Link: https://git.kernel.org/pub/scm/utils/kernel/module-init-tools/module-init-tools.git/tree/modprobe.c#n1797 [4]
Link: https://cdn.kernel.org/pub/linux/utils/kernel/modutils/v2.4/modutils-2.4.27.tar.gz [5]

> EEXIST is used all over the kernel to indicate
> that something being attempted has already happened or does already
> exist and that seems perfectly logical .... please explain why you're

That is correct but not all are conflicts within the
module_init()/init_module(2) path. I have detected 40+ cases where this error
is returned and another 20+ where error is returned but in upper layers of
the module itself, not propagated back to userspace. So far, I've only sent just
a few + docs:

https://lore.kernel.org/all/20251220-dev-module-init-eexists-dm-devel-v1-1-90ed00444ea0@samsung.com 
https://lore.kernel.org/all/20251220-dev-module-init-eexists-keyring-v1-1-a2f23248c300@samsung.com
https://lore.kernel.org/all/20251220-dev-module-init-eexists-linux-acpi-v1-1-af59b1a0e217@samsung.com
https://lore.kernel.org/all/20251218-dev-module-init-eexists-modules-docs-v1-0-361569aa782a@samsung.com

> trying to push it back to being a single use case for modules alone.
> 
> Regards,
> 
> James
> 
> 
>
Re: [PATCH 0/2] scsi: target+fcoe: replace -EEXIST with -EBUSY in module_init() paths
Posted by James Bottomley 1 month, 2 weeks ago
On Sun, 2025-12-21 at 04:30 +0100, Daniel Gomez wrote:
> On 20/12/2025 05.27, James Bottomley wrote:
> > On Sat, 2025-12-20 at 04:37 +0100, Daniel Gomez wrote:
> > > The error code -EEXIST is reserved by the kernel module loader to
> > > indicate that a module with the same name is already loaded. When
> > > a module's init function returns -EEXIST, kmod interprets this as
> > > "module already loaded" and reports success instead of failure
> > > [1].
> > 
> > That reference doesn't sufficiently explain why this error code
> > should be unique to modules.
> 
> It's unique only to the module initialization. You can find how it's
> used in the kernel module code at module_patient_check_exists() in
> kernel/module/main.c [1].
> 
> In addition, init_module(2) man pages indicates this:
> 
> man 2 init_module | grep EEXIST
>        EEXIST A module with this name is already loaded.
> 
> So, a module that is already loaded will be detected by the kernel
> module loader and the EEXIST error will be returned. This will be
> detected by kmod as success [2]. I think this functionality was added
> very early on in kmod by commit 5f35147 "libkmod-module: probe: add
> flag to stop loading on already loaded" [3]. Prior to that, module-
> init-tools had the same behavior [4]. Even in
> modutils [5], we had back then in insmod/insmod.c:2088:
> 
> 		case EEXIST:
> 			if (dolock) {
> 				/*
> 				 * Assume that we were just invoked
> 				 * simultaneous with another insmod
> 				 * and return success.
> 				 */
> 				exit_status = 0;
> 				goto out;
> 			}
> 			error("a module named %s already exists",
> m_name);
> 			goto out;
> 
> Link:
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/module/main.c?h=v6.19-rc1#n3206
>  [1]
> Link:
> https://github.com/kmod-project/kmod/blob/v34.2/libkmod/libkmod-module.c#L1088
>  [2]
> Link:
> https://github.com/kmod-project/kmod/commit/5f3514731ef82084c1a24b15445e0f1352681a19
>  [3]
> Link:
> https://git.kernel.org/pub/scm/utils/kernel/module-init-tools/module-init-tools.git/tree/modprobe.c#n1797
>  [4]
> Link:
> https://cdn.kernel.org/pub/linux/utils/kernel/modutils/v2.4/modutils-2.4.27.tar.gz
>  [5]
> 
> > EEXIST is used all over the kernel to indicate
> > that something being attempted has already happened or does already
> > exist and that seems perfectly logical .... please explain why
> > you're
> 
> That is correct but not all are conflicts within the
> module_init()/init_module(2) path. I have detected 40+ cases where
> this error is returned and another 20+ where error is returned but in
> upper layers of the module itself, not propagated back to userspace.
> So far, I've only sent just a few + docs:
> 
> https://lore.kernel.org/all/20251220-dev-module-init-eexists-dm-devel-v1-1-90ed00444ea0@samsung.com
>  
> https://lore.kernel.org/all/20251220-dev-module-init-eexists-keyring-v1-1-a2f23248c300@samsung.com
> https://lore.kernel.org/all/20251220-dev-module-init-eexists-linux-acpi-v1-1-af59b1a0e217@samsung.com
> https://lore.kernel.org/all/20251218-dev-module-init-eexists-modules-docs-v1-0-361569aa782a@samsung.com

None of that answers the why question:  Given that EEXIST is used all
over the kernel, for what appear to be fairly legitimate cases, why
would we suddenly want it to become only for modules?  I get that we
can, as you propose patches above, but why should we bother?  It seems
to be a useful error code outside the module use case, so why the need
to restrict it to being only for modules?

Regards,

James
Re: [PATCH 0/2] scsi: target+fcoe: replace -EEXIST with -EBUSY in module_init() paths
Posted by Daniel Gomez 1 month, 2 weeks ago
On 21/12/2025 05.02, James Bottomley wrote:
> On Sun, 2025-12-21 at 04:30 +0100, Daniel Gomez wrote:
>> On 20/12/2025 05.27, James Bottomley wrote:
>>> On Sat, 2025-12-20 at 04:37 +0100, Daniel Gomez wrote:
> None of that answers the why question:  Given that EEXIST is used all
> over the kernel, for what appear to be fairly legitimate cases, why
> would we suddenly want it to become only for modules?  I get that we
> can, as you propose patches above, but why should we bother?  It seems
> to be a useful error code outside the module use case, so why the need
> to restrict it to being only for modules?

Because both the module loader and module_init() return through the same
(f)init_module() syscall path, we need to ensure consistency in what we report
back to userspace. The init_module(2) man page documents EEXIST as "a module
with this name is already loaded." When module_init() returns EEXIST for
a different reason, userspace tools following the documented behavior will
misinterpret it. We can't use the same error code for different meanings and
expect the caller to differentiate.