2009-10-21 15:03:24

by Eric Paris

[permalink] [raw]
Subject: request_module vs. modprobe blacklist (and security subsystem implications)

I recently added a new LSM hook into __request_module(),
security_kernel_module_request(). This new hook checks if a process
should have permission to trigger the loading of a kernel module. The
attack vector imagined was that some module (IPX for example) has a
vulnerability. An attack program (which doesn't have permission to load
the IPX module directly) might be able to get the networking stack to
try to autoload the module. Once loaded the attack program could then
use the larger surface area to exploit the kernel.

We have found that many users disable the IPv6 module by setting their
modprobe config to look like:

blacklist ipv6
install ipv6 /bin/true

The problem is that a number of programs (sendmail, procmail, sshd, and
more) have all been seen to do operations which tried to load the ipv6
module. These get into request_module(), hit the security hook, and are
obviously denied since the security system doesn't see a need for those
programs to be able to request a module be loaded.

What I really want is a way for the kernel to know that a module has
been disabled and to not even call the security hook. My thought would
be something like adding the ability to do

echo "ipv6 -l" > /proc/sys/kernel/modules_disabled

which would add "ipv6" to a list of strings. This list of strings could
be checked in request_module() and if the module was explicitly denied
autoloading ability we wouldn't make the call out to userspace (or the
security hook)

echo "ipv6 +l" > /proc/sys/kernel/modules_disabled

would reenable the ability of a module to be autoloaded.

cat /proc/sys/kernel/modules_disabled

would be a multiline output, first line would be the 0/1 state we know
today, rest of the lines would be the list of modules being denied
autoload.

What do others think? What's a better way to stop calling out to
userspace looking for the ipv6 module when userspace knows it's
disabled?

-Eric


2009-10-21 19:11:22

by Alan Jenkins

[permalink] [raw]
Subject: Re: request_module vs. modprobe blacklist (and security subsystem implications)

On 10/21/09, Eric Paris <[email protected]> wrote:
> I recently added a new LSM hook into __request_module(),
> security_kernel_module_request(). This new hook checks if a process
> should have permission to trigger the loading of a kernel module. The
> attack vector imagined was that some module (IPX for example) has a
> vulnerability. An attack program (which doesn't have permission to load
> the IPX module directly) might be able to get the networking stack to
> try to autoload the module. Once loaded the attack program could then
> use the larger surface area to exploit the kernel.
>
> We have found that many users disable the IPv6 module by setting their
> modprobe config to look like:
>
> blacklist ipv6
> install ipv6 /bin/true
>
> The problem is that a number of programs (sendmail, procmail, sshd, and
> more) have all been seen to do operations which tried to load the ipv6
> module. These get into request_module(), hit the security hook, and are
> obviously denied since the security system doesn't see a need for those
> programs to be able to request a module be loaded.
>
> What I really want is a way for the kernel to know that a module has
> been disabled and to not even call the security hook. My thought would
> be something like adding the ability to do
>
> echo "ipv6 -l" > /proc/sys/kernel/modules_disabled
>
> which would add "ipv6" to a list of strings. This list of strings could
> be checked in request_module() and if the module was explicitly denied
> autoloading ability we wouldn't make the call out to userspace (or the
> security hook)
>
> echo "ipv6 +l" > /proc/sys/kernel/modules_disabled
>
> would reenable the ability of a module to be autoloaded.
>
> cat /proc/sys/kernel/modules_disabled
>
> would be a multiline output, first line would be the 0/1 state we know
> today, rest of the lines would be the list of modules being denied
> autoload.
>
> What do others think? What's a better way to stop calling out to
> userspace looking for the ipv6 module when userspace knows it's
> disabled?
>
> -Eric

You don't explain why :-/. All I can see is that you want to correct
the error code from "permission denied" to "not supported". But
"permission denied" can often cover a variety of issues, no?

I don't see why a module blacklist implemented by extending
modules_disabled should return anything other than "permission
denied". If you disable modules completely, don't you get "permission
denied"?

And what would be the difference between "permission denied, you do
not have the right to load IPX", and "ipv6 is not supported due to a
policy decision by the system administrator"? I'd have thought
"permission denied" would suffice for either.

I'm sure I'm missing something important here :-).

Regards
Alan

2009-10-21 19:27:48

by Eric Paris

[permalink] [raw]
Subject: Re: request_module vs. modprobe blacklist (and security subsystem implications)

On Wed, 2009-10-21 at 20:11 +0100, Alan Jenkins wrote:
> On 10/21/09, Eric Paris <[email protected]> wrote:
> > I recently added a new LSM hook into __request_module(),
> > security_kernel_module_request(). This new hook checks if a process
> > should have permission to trigger the loading of a kernel module. The
> > attack vector imagined was that some module (IPX for example) has a
> > vulnerability. An attack program (which doesn't have permission to load
> > the IPX module directly) might be able to get the networking stack to
> > try to autoload the module. Once loaded the attack program could then
> > use the larger surface area to exploit the kernel.
> >
> > We have found that many users disable the IPv6 module by setting their
> > modprobe config to look like:
> >
> > blacklist ipv6
> > install ipv6 /bin/true
> >
> > The problem is that a number of programs (sendmail, procmail, sshd, and
> > more) have all been seen to do operations which tried to load the ipv6
> > module. These get into request_module(), hit the security hook, and are
> > obviously denied since the security system doesn't see a need for those
> > programs to be able to request a module be loaded.
> >
> > What I really want is a way for the kernel to know that a module has
> > been disabled and to not even call the security hook. My thought would
> > be something like adding the ability to do
> >
> > echo "ipv6 -l" > /proc/sys/kernel/modules_disabled
> >
> > which would add "ipv6" to a list of strings. This list of strings could
> > be checked in request_module() and if the module was explicitly denied
> > autoloading ability we wouldn't make the call out to userspace (or the
> > security hook)
> >
> > echo "ipv6 +l" > /proc/sys/kernel/modules_disabled
> >
> > would reenable the ability of a module to be autoloaded.
> >
> > cat /proc/sys/kernel/modules_disabled
> >
> > would be a multiline output, first line would be the 0/1 state we know
> > today, rest of the lines would be the list of modules being denied
> > autoload.
> >
> > What do others think? What's a better way to stop calling out to
> > userspace looking for the ipv6 module when userspace knows it's
> > disabled?
> >
> > -Eric
>
> You don't explain why :-/. All I can see is that you want to correct
> the error code from "permission denied" to "not supported". But
> "permission denied" can often cover a variety of issues, no?
>
> I don't see why a module blacklist implemented by extending
> modules_disabled should return anything other than "permission
> denied". If you disable modules completely, don't you get "permission
> denied"?
>
> And what would be the difference between "permission denied, you do
> not have the right to load IPX", and "ipv6 is not supported due to a
> policy decision by the system administrator"? I'd have thought
> "permission denied" would suffice for either.
>
> I'm sure I'm missing something important here :-)

Ah yes, not your fault though :) The problem is that SELinux reports
these denials and users get scared. We can (and now do) silence all of
these SELinux caused denials, but now we have no notification if a
malicious program tried to cause the auto loading of a module. What we
want is a way to inform users when their system is doing bad things,
like trying to load the IPX module, but not to cause these notifications
when SELinux is denying something that would have been effectively
"denied" by modprobe later when it called /bin/true instead of loading
the IPv6 module.

Basically I don't want to log a denial and put up a warning in front of
a user when the system administrator explicitly told modprobe to fail on
those.

Make a little more sense? I honestly don't care what the retval is, I
just care that I'm able to put up an SELinux message saying we stopped
something bad while not putting up lots of false positives...

2009-10-21 21:00:16

by Alan Jenkins

[permalink] [raw]
Subject: Re: request_module vs. modprobe blacklist (and security subsystem implications)

On 10/21/09, Eric Paris <[email protected]> wrote:
> On Wed, 2009-10-21 at 20:11 +0100, Alan Jenkins wrote:
>> On 10/21/09, Eric Paris <[email protected]> wrote:
>> > I recently added a new LSM hook into __request_module(),
>> > security_kernel_module_request(). This new hook checks if a process
>> > should have permission to trigger the loading of a kernel module. The
>> > attack vector imagined was that some module (IPX for example) has a
>> > vulnerability. An attack program (which doesn't have permission to load
>> > the IPX module directly) might be able to get the networking stack to
>> > try to autoload the module. Once loaded the attack program could then
>> > use the larger surface area to exploit the kernel.
>> >
>> > We have found that many users disable the IPv6 module by setting their
>> > modprobe config to look like:
>> >
>> > blacklist ipv6
>> > install ipv6 /bin/true
>> >
>> > The problem is that a number of programs (sendmail, procmail, sshd, and
>> > more) have all been seen to do operations which tried to load the ipv6
>> > module. These get into request_module(), hit the security hook, and are
>> > obviously denied since the security system doesn't see a need for those
>> > programs to be able to request a module be loaded.
>> >
>> > What I really want is a way for the kernel to know that a module has
>> > been disabled and to not even call the security hook. My thought would
>> > be something like adding the ability to do
>> >
>> > echo "ipv6 -l" > /proc/sys/kernel/modules_disabled
>> >
>> > which would add "ipv6" to a list of strings. This list of strings could
>> > be checked in request_module() and if the module was explicitly denied
>> > autoloading ability we wouldn't make the call out to userspace (or the
>> > security hook)
>> >
>> > echo "ipv6 +l" > /proc/sys/kernel/modules_disabled
>> >
>> > would reenable the ability of a module to be autoloaded.
>> >
>> > cat /proc/sys/kernel/modules_disabled
>> >
>> > would be a multiline output, first line would be the 0/1 state we know
>> > today, rest of the lines would be the list of modules being denied
>> > autoload.
>> >
>> > What do others think? What's a better way to stop calling out to
>> > userspace looking for the ipv6 module when userspace knows it's
>> > disabled?
>> >
>> > -Eric
>>
>> You don't explain why :-/. All I can see is that you want to correct
>> the error code from "permission denied" to "not supported". But
>> "permission denied" can often cover a variety of issues, no?
>>
>> I don't see why a module blacklist implemented by extending
>> modules_disabled should return anything other than "permission
>> denied". If you disable modules completely, don't you get "permission
>> denied"?
>>
>> And what would be the difference between "permission denied, you do
>> not have the right to load IPX", and "ipv6 is not supported due to a
>> policy decision by the system administrator"? I'd have thought
>> "permission denied" would suffice for either.
>>
>> I'm sure I'm missing something important here :-)
>
> Ah yes, not your fault though :) The problem is that SELinux reports
> these denials and users get scared. We can (and now do) silence all of
> these SELinux caused denials, but now we have no notification if a
> malicious program tried to cause the auto loading of a module. What we
> want is a way to inform users when their system is doing bad things,
> like trying to load the IPX module, but not to cause these notifications
> when SELinux is denying something that would have been effectively
> "denied" by modprobe later when it called /bin/true instead of loading
> the IPv6 module.
>
> Basically I don't want to log a denial and put up a warning in front of
> a user when the system administrator explicitly told modprobe to fail on
> those.
>
> Make a little more sense? I honestly don't care what the retval is, I
> just care that I'm able to put up an SELinux message saying we stopped
> something bad while not putting up lots of false positives...

Yes, that explains your position, thanks. I don't think I have any
real insight. It still intrigues me so I flailed around a bit, here
are my thoughts.

Maybe it's userspace' problem; any actual printk() messages should be
very non-scary, and then userspace gets to filter the messages (as
well as showing them in a shiny popup or whatever). The default
policy would be not to sound the alarm for the ipv6 module, since it
seems to be a bit special...

Or (handwave from position of extreme ignorance) you should have a
special SELinux rule with a high priority which matches the ipv6
module specifically, and is silent when it denies permission.

Or maybe it's better to ask why people disable ipv6. Isn't it
something to do with DNS performance? If that's the only common
reason, why isn't there an option for the DNS resolver? If there is
and people aren't using it, why do you think people would use your new
in-kernel module blacklist instead?

I suspect sysadmins probably aren't disabling ipv6 because it poses a
_local_ privilege escalation risk. If ipv6 is seen as slightly risky
_remotely_, perhaps it needs to be tamed so it e.g. requires
explicitly enabling on each network interface.

Alan

2009-10-22 00:48:08

by Andi Kleen

[permalink] [raw]
Subject: Re: request_module vs. modprobe blacklist (and security subsystem implications)

> The problem is that a number of programs (sendmail, procmail, sshd, and
> more) have all been seen to do operations which tried to load the ipv6
> module. These get into request_module(), hit the security hook, and are
> obviously denied since the security system doesn't see a need for those
> programs to be able to request a module be loaded.

What's the problem with being denied? After all the programs expect
this to error out

If you're worrying about the audit entries -- the obvious place
to fix that is somewhere in your security code. Don't make the rest
of the code uglier for this.

-Andi

2009-10-22 01:12:42

by Eric W. Biederman

[permalink] [raw]
Subject: Re: request_module vs. modprobe blacklist (and security subsystem implications)

Eric Paris <[email protected]> writes:

> I recently added a new LSM hook into __request_module(),
> security_kernel_module_request(). This new hook checks if a process
> should have permission to trigger the loading of a kernel module. The
> attack vector imagined was that some module (IPX for example) has a
> vulnerability. An attack program (which doesn't have permission to load
> the IPX module directly) might be able to get the networking stack to
> try to autoload the module. Once loaded the attack program could then
> use the larger surface area to exploit the kernel.
>
> We have found that many users disable the IPv6 module by setting their
> modprobe config to look like:
>
> blacklist ipv6
> install ipv6 /bin/true

They need to be using /proc/sys/net/ipv6/conf/*/disable_ipv6 instead.
As the above scenario keeps the bonding driver from loading.

Eric

2009-10-22 05:56:50

by Rusty Russell

[permalink] [raw]
Subject: Re: request_module vs. modprobe blacklist (and security subsystem implications)

On Thu, 22 Oct 2009 05:57:28 am Eric Paris wrote:
> Ah yes, not your fault though :) The problem is that SELinux reports
> these denials and users get scared. We can (and now do) silence all of
> these SELinux caused denials, but now we have no notification if a
> malicious program tried to cause the auto loading of a module.

Well, yes. I think you need to be more careful in your filtering.

If a userspace program tries some security exploit that has been closed, do
you want to warn about it? Because that seems to be the question here.

Why should ssh not load IPv6? Because noone should? Fine, but there's a
difference between "I expect it to do this but I won't let it" and "I don't
expect it to do this".

I think the question is bigger than modprobe.conf vs request_module.

Or am I confused?
Rusty.

2009-10-22 14:31:12

by Eric Paris

[permalink] [raw]
Subject: Re: request_module vs. modprobe blacklist (and security subsystem implications)

On Thu, 2009-10-22 at 16:26 +1030, Rusty Russell wrote:

I should start by making sure people are certainly they know what I'm
talking about (which I think thus far everyone does.) I am NOT talking
about a program which either calls modprobe directly or tries to
directly load a module. I'm talking about a program which does an
operation (say, try to create and IPv6 or IPX socket) which causes the
kernel to automatically launch modprobe in userspace to load that
module. Often times this is not a malicious action.

> On Thu, 22 Oct 2009 05:57:28 am Eric Paris wrote:
> > Ah yes, not your fault though :) The problem is that SELinux reports
> > these denials and users get scared. We can (and now do) silence all of
> > these SELinux caused denials, but now we have no notification if a
> > malicious program tried to cause the auto loading of a module.
>
> Well, yes. I think you need to be more careful in your filtering.

More careful filtering is somewhat possible. I can't stop the kernel
from reporting that SELinux blocked the kernel from autoloading a new
module, but I can send the module name with the denial message to
userspace and then have the desktop alert box stop showing denials which
modprobe config disabled, but it would be very brittle.

> If a userspace program tries some security exploit that has been closed, do
> you want to warn about it? Because that seems to be the question here.

I say yes. Knowing that malicious activity is taking place, even if it
didn't hurt anything is useful. I'd rather know that a script kiddie is
trying to attack me so I can deal with him rather than not realize until
after he is successful. But that's not quite the case here. If the
administrator explicitly disables a module (ok, IPv6 is the only
interesting one) the kernel still regularly upcalls to modprobe which
then does nothing. Wouldn't having a mechanism to stop the upcall and
delays be a good thing even without my SELinux complaint?

> Why should ssh not load IPv6? Because noone should? Fine, but there's a
> difference between "I expect it to do this but I won't let it" and "I don't
> expect it to do this".

In this case it's because the admin decided not to allow it. In this
case it is 'I expect it to do this, and I know that later it would fail,
so I don't want to complain that it is failing now.' I want a way to
move the failure up, and to allow and admin to stop with the useless
userspace callouts to modprobe.

I want a way to make the kernel not upcall at all, if I have that I can
make SELinux do whatever I want. If I don't have that, all I can do is
some post failure fragile userspace filtering.

2009-10-23 09:16:37

by Rusty Russell

[permalink] [raw]
Subject: Re: request_module vs. modprobe blacklist (and security subsystem implications)

On Fri, 23 Oct 2009 01:00:22 am Eric Paris wrote:
> > If a userspace program tries some security exploit that has been closed, do
> > you want to warn about it? Because that seems to be the question here.
>
> I say yes. Knowing that malicious activity is taking place, even if it
> didn't hurt anything is useful.

Hi Eric,

Your proposal is troubling for three reasons:

1) You would disable logging for things you actually want logged.
2) What *actually* happens when ssh tries to load ipv6 is that
"modprobe net-pf-10" gets called.
3) Containing modprobe behavior in one set of config files is really nice.

> > Why should ssh not load IPv6? Because noone should? Fine, but there's a
> > difference between "I expect it to do this but I won't let it" and "I don't
> > expect it to do this".
>
> In this case it's because the admin decided not to allow it. In this
> case it is 'I expect it to do this, and I know that later it would fail,
> so I don't want to complain that it is failing now.' I want a way to
> move the failure up, and to allow and admin to stop with the useless
> userspace callouts to modprobe.

No. I anticipate that in the future you will want to do some fairly
sophisticated filtering. That does not belong in the kernel unless there
are performance concerns, and I don't think there are here.

There are all kinds of things that can be administratively prohibited, and
it would be nice if my security tools would Just Work with that: I don't think
pushing all the different restrictions into the kernel for SELinux's sake
is the way forward.

> I want a way to make the kernel not upcall at all, if I have that I can
> make SELinux do whatever I want. If I don't have that, all I can do is
> some post failure fragile userspace filtering.

If the kernel is better at filtering than userspace, that is an SELinux
problem that you should address.

Cheers,
Rusty.

2009-10-23 14:24:15

by Eric Paris

[permalink] [raw]
Subject: Re: request_module vs. modprobe blacklist (and security subsystem implications)

On Fri, 2009-10-23 at 19:46 +1030, Rusty Russell wrote:
> On Fri, 23 Oct 2009 01:00:22 am Eric Paris wrote:
> > > If a userspace program tries some security exploit that has been closed, do
> > > you want to warn about it? Because that seems to be the question here.
> >
> > I say yes. Knowing that malicious activity is taking place, even if it
> > didn't hurt anything is useful.
>
> Hi Eric,
>
> Your proposal is troubling for three reasons:
>
> 1) You would disable logging for things you actually want logged.

I would?

> 2) What *actually* happens when ssh tries to load ipv6 is that
> "modprobe net-pf-10" gets called.
> 3) Containing modprobe behavior in one set of config files is really nice.

It is it also means that we, somewhat regularly call userspace
needlessly and there is nothing an admin can do to stop it.

But it appears you disagree that fixing that problem is worth it, and I
don't feel strongly enough to keep arguing :)

-Eric

2009-10-23 14:59:52

by Rusty Russell

[permalink] [raw]
Subject: Re: request_module vs. modprobe blacklist (and security subsystem implications)

On Sat, 24 Oct 2009 12:53:50 am Eric Paris wrote:
> On Fri, 2009-10-23 at 19:46 +1030, Rusty Russell wrote:
> > On Fri, 23 Oct 2009 01:00:22 am Eric Paris wrote:
> > > > If a userspace program tries some security exploit that has been closed, do
> > > > you want to warn about it? Because that seems to be the question here.
> > >
> > > I say yes. Knowing that malicious activity is taking place, even if it
> > > didn't hurt anything is useful.
> >
> > Hi Eric,
> >
> > Your proposal is troubling for three reasons:
> >
> > 1) You would disable logging for things you actually want logged.
>
> I would?

Yep, admin disables loading of ipx to prevent hole. Now, you no longer get
logging notification.

> > 2) What *actually* happens when ssh tries to load ipv6 is that
> > "modprobe net-pf-10" gets called.
> > 3) Containing modprobe behavior in one set of config files is really nice.
>
> It is it also means that we, somewhat regularly call userspace
> needlessly and there is nothing an admin can do to stop it.

Yes, but that's nothing to do with SELinux; we exec modprobe for no effect.
Yet I've yet to see a report that this is a performance issue. These brains
are in userspace for a reason.

> But it appears you disagree that fixing that problem is worth it, and I
> don't feel strongly enough to keep arguing :)

But we have learnt something, at least!

Cheers,
Rusty.