2006-10-05 18:59:50

by Michael Büsch

[permalink] [raw]
Subject: Really good idea to allow mmap(0, FIXED)?

Hi,

This question has already been discussed here in the past, but
we did not come to a good result. So I want to ask the question again:

Is is really a good idea to allow processes to remap something
to address 0?
I say no, because this can potentially be used to turn rather harmless
kernel bugs into a security vulnerability.

Let's say we have some kernel NULL pointer dereference bug somewhere,
that's rather harmless, if it happens in process context and
does not leak any resources on segfaulting the triggering app.
So the worst thing that happens is a crashing app. Yeah, this bug must
be fixed. But my point is that this bug can probably be used to
manipulate the way the kernel works or even to inject code into
the kernel from userspace.

Attached to this mail is an example. The kernel module represents
the actual "kernel-bug". Its whole purpose in this example is to
introduce a user-triggerable NULL pointer dereference.
Please stop typing now, if you are typing something like
"If you can load a kernel module, you have access to the kernel anyway".
This is different. We always _had_ and most likely _have_ NULL pointer
dereference bugs in the kernel.

The example programm injects a magic value 0xB15B00B2 into the
kernel, which is printk'ed on success.

In my opinion, this should be forbidden by disallowing mmapping
to address 0. A NULL pointer dereference is such a common bug, that
it is worth protecting against.
Besides that, I currently don't see a valid reason to mmap address 0.

Comments?

--
Greetings Michael.


Attachments:
(No filename) (1.51 kB)
knulltest.tar.gz (1.41 kB)
Download all attachments

2006-10-05 19:50:48

by linux-os (Dick Johnson)

[permalink] [raw]
Subject: Re: Really good idea to allow mmap(0, FIXED)?


On Thu, 5 Oct 2006, Michael Buesch wrote:

> Hi,
>
> This question has already been discussed here in the past, but
> we did not come to a good result. So I want to ask the question again:

Meaning that you didn't get the result you wanted.

> Is is really a good idea to allow processes to remap something
> to address 0?

Of course you must be able to remap the physical address 0 (offset
zero in the whole machine), and if your 'hint' to mmap() in
user code is a 0, it can (it's allowed) to return a pointer
initialized to zero --and it's your fault if it's incompatible
with some 'C' runtime libraries.

It is a perfectly good address and the fact that malloc() returns
(void *)0 upon failure, does not qualify it as king or some other
ruler. In fact, mmap() returns (void *)-1 upon failure.

> I say no, because this can potentially be used to turn rather harmless
> kernel bugs into a security vulnerability.
>

Can't. The kernel doesn't check for NULL for user access, it
simply traps if the address is bad. That's why we have copy/to/from_user()
for user-mode access.

> Let's say we have some kernel NULL pointer dereference bug somewhere,
> that's rather harmless, if it happens in process context and
> does not leak any resources on segfaulting the triggering app.
> So the worst thing that happens is a crashing app. Yeah, this bug must
> be fixed. But my point is that this bug can probably be used to
> manipulate the way the kernel works or even to inject code into
> the kernel from userspace.
>

Can't.

> Attached to this mail is an example. The kernel module represents
> the actual "kernel-bug". Its whole purpose in this example is to
> introduce a user-triggerable NULL pointer dereference.
> Please stop typing now, if you are typing something like
> "If you can load a kernel module, you have access to the kernel anyway".
> This is different. We always _had_ and most likely _have_ NULL pointer
> dereference bugs in the kernel.
>
> The example programm injects a magic value 0xB15B00B2 into the
> kernel, which is printk'ed on success.

Well this shows nothing interesting.

>
> In my opinion, this should be forbidden by disallowing mmapping
> to address 0. A NULL pointer dereference is such a common bug, that
> it is worth protecting against.
> Besides that, I currently don't see a valid reason to mmap address 0.
>

That's where the real-mode BIOS table is. Who says that I can't
look at any piece of physical memory I want. It's my machine.

The whole concept of a NULL pointer is simply an artifact of
incorrect engineering.

> Comments?
>
> --
> Greetings Michael.
>

Cheers,
Dick Johnson
Penguin : Linux version 2.6.16.24 on an i686 machine (5592.72 BogoMips).
New book: http://www.AbominableFirebug.com/
_


****************************************************************
The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to [email protected] - and destroy all copies of this information, including any attachments, without reading or disclosing them.

Thank you.

2006-10-05 21:32:14

by Alan

[permalink] [raw]
Subject: Re: Really good idea to allow mmap(0, FIXED)?

Ar Iau, 2006-10-05 am 20:59 +0200, ysgrifennodd Michael Buesch:
> Is is really a good idea to allow processes to remap something
> to address 0?

It is very useful indeed. Consider for example dosemu.

> Besides that, I currently don't see a valid reason to mmap address 0.
>
> Comments?

User zero is not neccessarily mapped at kernel zero so your argument
isn't portable either.


2006-10-05 23:56:03

by David Wagner

[permalink] [raw]
Subject: Re: Really good idea to allow mmap(0, FIXED)?

Michael Buesch wrote:
>Is is really a good idea to allow processes to remap something
>to address 0?
>I say no, because this can potentially be used to turn rather harmless
>kernel bugs into a security vulnerability.

Let me see if I understand. If the kernel does this somewhere:

struct s *foo;
foo->x->y = 0;

and if there is some way that userland code can cause this to be
executed with 'foo' set to a NULL pointer, then user-land code can
do this:

mmap(0, 4096, PROT_READ|PROT_EXEC|PROT_WRITE,
MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
struct s *bar = 0;
bar->x = ... whatever ...;

An attacker could execute this user-land code and then invoke the
kernel in a way that causes the above kernel statement to be executed
with foo==NULL. The result will effectively be as though the kernel
executed the statement '*whatever = 0;', where 'whatever' can be
completely controlled by the attacker.

In other words, the consequences of the buggy kernel code listed above
is that an attacker can choose any location in memory (of his choice,
including code that is within kernel space) and set it to zero.

If this is correct so far, this sounds pretty dangerous. For instance,
the above hypothetical scenario would be enough to allow an attacker
to set his euid to zero by overwriting the euid field in the process
structure maintained by the kernel. That would mean that a NULL pointer
bug in the kernel might allow an attacker to gain root. That would
mean that every NULL pointer dereference bug is potentially security
critical. If so, we'd better be pretty darn careful to make sure we've
eliminated all NULL pointer bugs in the kernel.

Is this right? Have I correctly understood the issue?

2006-10-06 04:34:15

by Jeremy Fitzhardinge

[permalink] [raw]
Subject: Re: Really good idea to allow mmap(0, FIXED)?

David Wagner wrote:
> Is this right? Have I correctly understood the issue?

More or less, though a simpler example would be something like:

if (thing->uid == 0)
do_magic();

and if "thing" happens to be in userspace (NULL or otherwise) then the
user can control this test. So the answer is that the kernel shouldn't
be looking at uninitialized pointers.

J

2006-10-06 05:40:21

by Jan Engelhardt

[permalink] [raw]
Subject: Re: Really good idea to allow mmap(0, FIXED)?


>>Is is really a good idea to allow processes to remap something
>>to address 0?
>>I say no, because this can potentially be used to turn rather harmless
>>kernel bugs into a security vulnerability.
>
>Let me see if I understand. If the kernel does this somewhere:
[...]

For reference, please see http://lkml.org/lkml/2006/2/22/90


-`J'
--

2006-10-06 07:25:20

by Arjan van de Ven

[permalink] [raw]
Subject: Re: Really good idea to allow mmap(0, FIXED)?

On Thu, 2006-10-05 at 23:55 +0000, David Wagner wrote:
> Michael Buesch wrote:
> >Is is really a good idea to allow processes to remap something
> >to address 0?
> >I say no, because this can potentially be used to turn rather harmless
> >kernel bugs into a security vulnerability.
>
> Let me see if I understand. If the kernel does this somewhere:
>
> struct s *foo;
> foo->x->y = 0;
>
> and if there is some way that userland code can cause this to be
> executed with 'foo' set to a NULL pointer, then user-land code can
> do this:
>
> mmap(0, 4096, PROT_READ|PROT_EXEC|PROT_WRITE,
> MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
> struct s *bar = 0;

the question isn't if it's a good idea to allow mmap(0) but to allow
mmap PROT_WRITE | PROT_EXEC !


2006-10-06 10:36:37

by Mikael Pettersson

[permalink] [raw]
Subject: Re: Really good idea to allow mmap(0, FIXED)?

Arjan van de Ven writes:
> > mmap(0, 4096, PROT_READ|PROT_EXEC|PROT_WRITE,
> > MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
> > struct s *bar = 0;
>
> the question isn't if it's a good idea to allow mmap(0) but to allow
> mmap PROT_WRITE | PROT_EXEC !

It is if you want JITs, code loaders, virtualisation engines, etc
to continue working.

2006-10-06 11:20:14

by Arjan van de Ven

[permalink] [raw]
Subject: Re: Really good idea to allow mmap(0, FIXED)?

On Fri, 2006-10-06 at 12:36 +0200, Mikael Pettersson wrote:
> Arjan van de Ven writes:
> > > mmap(0, 4096, PROT_READ|PROT_EXEC|PROT_WRITE,
> > > MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
> > > struct s *bar = 0;
> >
> > the question isn't if it's a good idea to allow mmap(0) but to allow
> > mmap PROT_WRITE | PROT_EXEC !
>
> It is if you want JITs, code loaders, virtualisation engines, etc
> to continue working.

yeah I know we can't forbid it point blank
(having said that, on architectures where I and D cache aren't coherent
(and there are many, including ia64), most of these are buggy anyway;
the sane ones actually do an mprotect between writing and executing, so
that the kernel can take care of the cache coherency properly)

--
if you want to mail me at work (you don't), use arjan (at) linux.intel.com

2006-10-06 14:41:19

by Michael Büsch

[permalink] [raw]
Subject: Re: Really good idea to allow mmap(0, FIXED)?

On Thursday 05 October 2006 21:50, linux-os (Dick Johnson) wrote:
> Of course you must be able to remap the physical address 0 (offset
> zero in the whole machine), and if your 'hint' to mmap() in
> user code is a 0, it can (it's allowed) to return a pointer
> initialized to zero --and it's your fault if it's incompatible
> with some 'C' runtime libraries.
>
> It is a perfectly good address and the fact that malloc() returns
> (void *)0 upon failure, does not qualify it as king or some other
> ruler. In fact, mmap() returns (void *)-1 upon failure.

You are explainint something that is _completely_ unrelated to the
issue I am describing.

> > I say no, because this can potentially be used to turn rather harmless
> > kernel bugs into a security vulnerability.
> >
>
> Can't. The kernel doesn't check for NULL for user access, it
> simply traps if the address is bad. That's why we have copy/to/from_user()
> for user-mode access.

See my example.

> > Let's say we have some kernel NULL pointer dereference bug somewhere,
> > that's rather harmless, if it happens in process context and
> > does not leak any resources on segfaulting the triggering app.
> > So the worst thing that happens is a crashing app. Yeah, this bug must
> > be fixed. But my point is that this bug can probably be used to
> > manipulate the way the kernel works or even to inject code into
> > the kernel from userspace.
> >
>
> Can't.

See my example. It _does_ inject a userspace controlled value into
the kernel.

> > Attached to this mail is an example. The kernel module represents
> > the actual "kernel-bug". Its whole purpose in this example is to
> > introduce a user-triggerable NULL pointer dereference.
> > Please stop typing now, if you are typing something like
> > "If you can load a kernel module, you have access to the kernel anyway".
> > This is different. We always _had_ and most likely _have_ NULL pointer
> > dereference bugs in the kernel.
> >
> > The example programm injects a magic value 0xB15B00B2 into the
> > kernel, which is printk'ed on success.
>
> Well this shows nothing interesting.

It _does_. What if the pointer was a function pointer and the
kernel executed it? Eh? It would continue to execute userspace
controlled code.

> >
> > In my opinion, this should be forbidden by disallowing mmapping
> > to address 0. A NULL pointer dereference is such a common bug, that
> > it is worth protecting against.
> > Besides that, I currently don't see a valid reason to mmap address 0.
> >
>
> That's where the real-mode BIOS table is. Who says that I can't
> look at any piece of physical memory I want. It's my machine.

Doing it in the kernel and not from unprivileged user processes
would be a good idea for this anyway...

> The whole concept of a NULL pointer is simply an artifact of
> incorrect engineering.

I do _NOT_ complain about the NULL pointer. You simply did not get
my point.

--
Greetings Michael.

2006-10-06 14:44:47

by Michael Büsch

[permalink] [raw]
Subject: Re: Really good idea to allow mmap(0, FIXED)?

On Thursday 05 October 2006 23:58, Alan Cox wrote:
> Ar Iau, 2006-10-05 am 20:59 +0200, ysgrifennodd Michael Buesch:
> > Is is really a good idea to allow processes to remap something
> > to address 0?
>
> It is very useful indeed. Consider for example dosemu.

Ok, good point.

> > Besides that, I currently don't see a valid reason to mmap address 0.
> >
> > Comments?
>
> User zero is not neccessarily mapped at kernel zero so your argument
> isn't portable either.

Eh, so what about the following.
We _have_ arches which map user zero to kernel zero. What about
specialcasing that on a per-arch case. So remapping user zero to
something else in kernel.

--
Greetings Michael.

2006-10-06 14:56:08

by Michael Büsch

[permalink] [raw]
Subject: Re: Really good idea to allow mmap(0, FIXED)?

Ok, some people have good points against special casing
address 0 here. That's fine.
But: I think, if we don't protect from remapping address 0,
we should _really_ take NULL pointer dereference bugs more serious.
Every NULL pointer dereference bug should be checked for the
possibility of unprivileged users controlling the kernel.
I think currently NULL pointer dereferece bugs are not seen as
a security vulnerability by most people. In future we
should look at the bugs more closely and check if this is a
security vulnerability or just a "crash my app" bug.


On Thursday 05 October 2006 20:59, Michael Buesch wrote:
> Hi,
>
> This question has already been discussed here in the past, but
> we did not come to a good result. So I want to ask the question again:
>
> Is is really a good idea to allow processes to remap something
> to address 0?
> I say no, because this can potentially be used to turn rather harmless
> kernel bugs into a security vulnerability.
>
> Let's say we have some kernel NULL pointer dereference bug somewhere,
> that's rather harmless, if it happens in process context and
> does not leak any resources on segfaulting the triggering app.
> So the worst thing that happens is a crashing app. Yeah, this bug must
> be fixed. But my point is that this bug can probably be used to
> manipulate the way the kernel works or even to inject code into
> the kernel from userspace.
>
> Attached to this mail is an example. The kernel module represents
> the actual "kernel-bug". Its whole purpose in this example is to
> introduce a user-triggerable NULL pointer dereference.
> Please stop typing now, if you are typing something like
> "If you can load a kernel module, you have access to the kernel anyway".
> This is different. We always _had_ and most likely _have_ NULL pointer
> dereference bugs in the kernel.
>
> The example programm injects a magic value 0xB15B00B2 into the
> kernel, which is printk'ed on success.
>
> In my opinion, this should be forbidden by disallowing mmapping
> to address 0. A NULL pointer dereference is such a common bug, that
> it is worth protecting against.
> Besides that, I currently don't see a valid reason to mmap address 0.
>
> Comments?
>

--
Greetings Michael.

2006-10-06 19:43:11

by David Wagner

[permalink] [raw]
Subject: Re: Really good idea to allow mmap(0, FIXED)?

Arjan van de Ven wrote:
>> Let me see if I understand. If the kernel does this somewhere:
>>
>> struct s *foo;
>> foo->x->y = 0;
>>
>> and if there is some way that userland code can cause this to be
>> executed with 'foo' set to a NULL pointer, then user-land code can
>> do this:
>>
>> mmap(0, 4096, PROT_READ|PROT_EXEC|PROT_WRITE,
>> MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
>> struct s *bar = 0;
>
>the question isn't if it's a good idea to allow mmap(0) but to allow
>mmap PROT_WRITE | PROT_EXEC !

Oops. Please ignore the PROT_EXEC. That is completely irrelevant.
I'm sorry I included it; the inclusion of PROT_EXEC was a mistake.
Delete PROT_EXEC, then re-read my email -- everything else in there is
still valid.

The security exploit I explained didn't involve executing anything
from the mmap'ed page; the kernel reads an address from this page,
and then dereferences it. Even without PROT_EXEC, it sounds like a
user-triggerable NULL pointer dereference in the kernel can create a
local root exploit (at least in some cases).

2006-10-06 19:47:51

by David Wagner

[permalink] [raw]
Subject: Re: Really good idea to allow mmap(0, FIXED)?

Jan Engelhardt wrote:
>For reference, please see http://lkml.org/lkml/2006/2/22/90

Thanks. Ok, I've read that. That was helpful. But I think this risk
is more serious than was realized in that thread from February.

The February thread you mention talked about the security consequences of
calling (dereferencing) a function pointer that is NULL. The security
consequences are indeed bad. However, that thread only discussed the
security consequences of NULL pointer bugs involving function pointers,
and there was no indication in that thread that other types of NULL
pointer bugs had any security relevance.

But now it seems, as I described in my email, that all NULL pointer bugs
(whether function pointers or not) have the potential to create security
vulnerabilities. Every NULL pointer bug has to be viewed with suspicion,
until it has been confirmed that it cannot be exploited. This sounds more
serious than was realized back in February.

Right? Or am I missing something important again?

2006-10-07 11:23:14

by Pavel Machek

[permalink] [raw]
Subject: Re: Really good idea to allow mmap(0, FIXED)?

Hi!
>
> > > Besides that, I currently don't see a valid reason to mmap address 0.
> > >
> > > Comments?
> >
> > User zero is not neccessarily mapped at kernel zero so your argument
> > isn't portable either.
>
> Eh, so what about the following.
> We _have_ arches which map user zero to kernel zero. What about
> specialcasing that on a per-arch case. So remapping user zero to
> something else in kernel.

Just add some magic constant on architectures you care about... make
user 0 start at 4mb in kernel... and you get your security hardened
kernel w/o breaking dosemu. All you need is to create a patch :-)


--
Thanks for all the (sleeping) penguins.

2006-10-08 00:21:59

by Jeremy Fitzhardinge

[permalink] [raw]
Subject: Re: Really good idea to allow mmap(0, FIXED)?

David Wagner wrote:
> Oops. Please ignore the PROT_EXEC. That is completely irrelevant.
> I'm sorry I included it; the inclusion of PROT_EXEC was a mistake.
> Delete PROT_EXEC, then re-read my email -- everything else in there is
> still valid.
>
Though (*something_ops->thingy)() becomes a lot more interesting if
something_ops or ->thingy is NULL...

J

2006-10-08 02:03:22

by David Wagner

[permalink] [raw]
Subject: Re: Really good idea to allow mmap(0, FIXED)?

Jeremy Fitzhardinge wrote:
>David Wagner wrote:
>> Oops. Please ignore the PROT_EXEC. That is completely irrelevant.
>
>Though (*something_ops->thingy)() becomes a lot more interesting if
>something_ops or ->thingy is NULL...

If something_ops is NULL, catastrophic consequences ensue either way.
It's just as bad even if address 0 isn't mmap'ed with PROT_EXEC. For
example, suppose that .thingy is at offset 0x14 (say) and something_ops
is NULL. Then (*something_ops->thingy)() reads 4 bytes from address
0x14, treats what the 4 bytes read as an address, and transfers control
to that address. (On a 32-bit x86.) Since the latter address is under
the attacker's control, this means that the kernel has just transferred
control to an address of the attacker's choosing -- not good.

As you say, if something_ops->thingy is NULL, then mmap'ing address 0
with PROT_EXEC allows evil consequences.

2006-10-08 19:18:46

by Michael Büsch

[permalink] [raw]
Subject: Re: Really good idea to allow mmap(0, FIXED)?

On Sunday 08 October 2006 02:22, Jeremy Fitzhardinge wrote:
> Though (*something_ops->thingy)() becomes a lot more interesting if
> something_ops or ->thingy is NULL...

It's always very critical if a userspace program can modify some
data in the kernel. Be it function pointers or plain data.
Also consider something like:

if (task->uid == 0)
allow_access_to_time_machine();
else
return -EPERM;

Now if "task" may be a NULL pointer (due to a bug) it
can be exploited.

PS: Please don't drop me from the CC list ;)

--
Greetings Michael.