Re: [PATCH v4] module: Extend module_blacklist parameter to built-in modules

Petr Pavlu <[email protected]>
Newsgroups org.kernel.vger.linux-arch,org.kernel.vger.linux-kernel,org.kernel.vger.linux-modules
Message-ID <[email protected]>
On 7/13/26 2:13 PM, Aaron Tomlin wrote:
> On Mon, Jul 13, 2026 at 10:32:14AM +0200, Arnd Bergmann wrote:
>> On Sat, Jul 11, 2026, at 01:13, Aaron Tomlin wrote:
>>> On Fri, Jul 10, 2026 at 05:59:59PM +0200, Arnd Bergmann wrote:
>>>> On Wed, Jul 8, 2026, at 04:00, Aaron Tomlin wrote:
>>>>> Currently, the "module_blacklist=" command-line parameter only applies
>>>>> to loadable modules. If a module is built-in, the parameter is silently
>>>>> ignored. This patch extends the blacklisting functionality to built-in
>>>>> modules by intercepting their initialisation routines during early boot.
>>>>
>>>> Andrew already asked you to provide more background on what you need
>>>> this part for. Do you have a specific driver you need to disable?
>>>>
>>>> Can't you do the same thing using initcall_blacklist?
>>>
>>> The primary motivation for this patch is to provide consistent
>>> administrative control.
>>
>> Ok, it sounds like you don't actually need it then.
>>
>>> Regarding your suggestion to use initcall_blacklist=, while it is certainly
>>> a capable mechanism, it is fundamentally considered a debugging facility
>>> intended for developers.
>>
>> I don't see much of a difference here, it's clearly still only a
>> debugging tool to me, not a general administrative interface: turning
>> off a random built-in driver likely causes undefined behavior later
>> if there are any other drivers (built-in or loaded) that depend on it.
>>
>> Overall I don't think it's worth the added complexity.
> 
> Hi Arnd,
> 
> I appreciate your candour, but I must respectfully disagree with the
> assessment that this is merely a debugging tool with no practical
> necessity.
> 
> The requirement stems from large-scale infrastructure management and
> configuration consistency. System administrators rely on standard
> provisioning scripts across diverse hardware. If a distribution arbitrarily
> alters a kernel configuration, changing a module from loadable (=m) to
> built-in (=y), the administrator's module_blacklist= directive is suddenly
> and silently ignored. This creates a severe policy enforcement gap.

Note that a gap will still exist if the administrator previously
blacklisted a specific loadable module using the blacklist command in
/etc/modprobe.d/ instead of the module_blacklist kernel parameter.

> 
> Regarding the distinction between initcall_blacklist= and
> module_blacklist=, the difference lies entirely in ABI stability.
> To use initcall_blacklist= requires the administrator to know the exact
> internal C function name of the initialisation routine (e.g.,
> foo_driver_init). This is an internal kernel implementation detail, subject
> to change without notice, and entirely undocumented for users. Conversely,
> the module name is a stable, well-known, and documented user-facing
> identifier. Providing a stable interface for administrative policy is the
> very definition of a general administrative tool, rather than a developer
> debugging facility.
> For example, consider CVE-2021-43267. A system administrator can now use
> module_blacklist=tipc which would cover both built-in and loadable module
> configurations.
> 
> To address your concern regarding undefined behaviour, disabling a built-in
> driver carries the exact same dependency risks as preventing a loadable
> module from loading via the traditional blacklist. In both scenarios,
> dependent drivers will naturally fail to probe or initialise. System
> administrators who apply denylists are already expected to understand the
> hardware and software dependencies of the modules they are explicitly
> disabling.

The dependency risk is somewhat greater with built-in modules. Consider
two modules, A and B. Module A exports fun_a() that is used by module B.
fun_a() depends on state initialized in A's init function.

If both modules are loadable, then B can be inserted only after A has
been loaded successfully, that is, A is not blacklisted and its init
function completes successfully.

If A is built-in and blacklisted, nothing prevents B from calling
fun_a() and potentially encountering an undefined state.

That said, it seems the same problem can already occur today if A is
built-in and fails to initialize, since do_initcall_level() doesn't
check the return value from do_one_initcall().

> 
> I understand your hesitation regarding added complexity. However, with the
> fast-path optimisation suggested by Sami (which bypassing the scan entirely
> if the parameter is unused), the overhead is essentially zero. I believe
> bridging the logical gap between how we treat =m and =y modules is well
> worth that minimal footprint.

I see the point from a consistency perspective.

-- 
Cheers,
Petr
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.