Re: [PATCH] Allow automatic kernel taint on unsigned module load to be disabled

From: Matthew Garrett
Date: Mon Aug 07 2017 - 01:31:07 EST


On Sun, Aug 6, 2017 at 9:47 PM, Rusty Russell <rusty@xxxxxxxxxxxxxxx> wrote:
> Matthew Garrett <mjg59@xxxxxxxxxx> writes:
>> And then you need an entire trusted userland, at which point you can
>> assert that the modules are trustworthy without having to validate
>> them so you don't need CONFIG_MODULE_SIG anyway.
>
> Yep. But your patch already gives userland that power, to silently load
> unsigned modules.

Only if sig_enforce isn't set.

>>> With your patch, you don't get tainting in the environment where you can
>>> verify.
>>
>> You don't anyway, do you? Loading has already failed before this point
>> if sig_enforce is set.
>
> No. You used to get a warning and a taint when you had a kernel
> configured to expect signatures and it didn't get one. You want to
> remove that warning, to silently accept unsigned modules.

I'm very confused here. If sig_enforce is set, the kernel will refuse
to load an unsigned module - it won't be tainted, modprobe will just
return an error. If sig_enforce is not set, any attacker in a position
to provide unsigned modules is also in a position to just subvert
modprobe, so you aren't in an environment where you can verify
anything. The taint is informational, not any form of security. You're
only able to securely verify module signatures in userland in very
constrainted setups.

>>> You'd be better adding a sysctl or equiv. to turn off force loading, and
>>> use that in your can-verify system.
>>
>> I'm not sure what you mean by "force loading" here - if sig_enforce is
>> set, you can't force load an unsigned module. If sig_enforce isn't
>> set, you'll taint regardless of whether or not you force.
>>
>> Wait. Hang on - are you confusing CONFIG_MODULE_SIG with CONFIG_MODVERSIONS?
>
> No, I mean stripping the signatures. (I thought modprobe could do this
> these days, but apparently not!)
>
> So, you're actually building the same kernel, but building two sets of
> modules: one without signatures, one with?
>
> And when deploying the one with signatures, you're setting sig_enforce.
> On the other, you don't want signatures because um, reasons? And you
> want to suppress the message?

No. A distribution may ship a kernel with signed modules. In some
configurations, the signatures are irrelevant - there's no mechanism
to verify that the correct kernel was loaded in the first place, so
for all you know the signature validation code has already been
removed at runtime. In that scenario you're fine with users loading
unsigned kernel modules and there's no benefit in tainting the kernel.
But the same kernel may be booted under circumstances where it *is*
possible to validate the kernel, and in those circumstances you want
to enforce module signatures and so sig_enforce is set.

Right now you have two choices:

1) unsigned modules taint the kernel if sig_enforce is false, unsigned
modules can't be loaded if sig_enforce is true (ie, CONFIG_MODULE_SIG
is set)
2) unsigned modules do not taint the kernel, unsigned modules can
always be loaded (ie, CONFIG_MODULE_SIG is unset)

What I want is:

3) unsigned modules do not taint the kernel if sig_enforce is false,
unsigned modules can't be loaded if sig_enforce is true

This is currently impossible to express, and as a result some
distributions ship with CONFIG_MODULE_SIG disabled in order to avoid
dealing with user questions about why loading locally built modules
now taints the kernel. Being able to build a single kernel that
satisfies more use cases seems like a win.

But maybe there's a cleaner way. How about adding a paramter like
sig_enforce (say taint_on_unsigned) and then adding a config parameter
equivalent to CONFIG_MODULE_SIG_FORCE? That way the default policy can
be set at build time, but can also be overridden by end users who
still want to be able to taint on unsigned module load.