2006-12-14 09:50:00

by Franck Pommereau

[permalink] [raw]
Subject: Executability of the stack

Dear Linux developers,

I recently discovered that the Linux kernel on 32 bits x86 processors
reports the stack as being non-executable while it is actually
executable (because located in the same memory segment).

# grep maps /proc/self/maps
bfce8000-bfcfe000 rw-p bfce8000 00:00 0 [stack]

I think there is here a serious security concern has one could consider
to be protected against the execution of code injected on the stack (or
heap) while this is not the case.

Is there any reason for this situation? Is it possible to correct it?
Maybe it comes from sharing source code for 64 bits and 32 bits
architectures but if so, it should be possible (and highly desirable) to
treat 32 bits differently.

Best regards,
Franck Pommereau

-----------------------------------------------------------------------
Below is the output from the ver_linux script:
-----------------------------------------------------------------------
Linux pixie 2.6.17-10-386 #2 Tue Dec 5 22:26:18 UTC 2006 i686 GNU/Linux

Gnu C 4.1.2
Gnu make 3.81
binutils 2.17
util-linux 2.12r
mount 2.12r
module-init-tools 3.2.2
e2fsprogs 1.39
jfsutils 1.1.8
reiserfsprogs 3.6.19
reiser4progs 1.0.5
xfsprogs 2.8.10
pcmcia-cs 3.2.8
PPP 2.4.4
Linux C Library > libc.2.4
Dynamic linker (ldd) 2.4
Procps 3.2.7
Net-tools 1.60
Console-tools 0.2.3
Sh-utils 5.96
udev 093
Modules Loaded vmnet vmmon binfmt_misc rfcomm hidp l2cap ipv6
usbhid speedstep_centrino cpufreq_userspace cpufreq_stats freq_table
cpufreq_powersave cpufreq_ondemand cpufreq_conservative video tc1100_wmi
sbs sony_acpi pcc_acpi i2c_ec hotkey dock dev_acpi button battery
container ac asus_acpi deflate zlib_deflate twofish serpent aes blowfish
des sha256 sha1 crypto_null af_key af_packet dm_mod md_mod visor
usbserial parport_pc lp parport pcmcia sr_mod cdrom yenta_socket joydev
rsrc_nonstatic pcmcia_core nvidia snd_hda_intel snd_hda_codec tsdev
hci_usb sg snd_pcm_oss snd_mixer_oss bluetooth snd_pcm snd_timer evdev
tg3 serio_raw i2c_core intel_agp pcspkr psmouse snd soundcore
snd_page_alloc agpgart rtc shpchp pci_hotplug xt_tcpudp xt_state
iptable_filter ipt_MASQUERADE iptable_nat ip_nat ip_conntrack nfnetlink
ip_tables x_tables ext3 jbd ehci_hcd uhci_hcd usbcore ide_generic sd_mod
generic ata_piix libata scsi_mod thermal processor fan capability
commoncap vesafb fbcon tileblit font bitblit softcursor
-----------------------------------------------------------------------


2006-12-14 09:57:27

by Arjan van de Ven

[permalink] [raw]
Subject: Re: Executability of the stack

On Thu, 2006-12-14 at 10:26 +0100, Franck Pommereau wrote:
> Dear Linux developers,
>
> I recently discovered that the Linux kernel on 32 bits x86 processors
> reports the stack as being non-executable while it is actually
> executable (because located in the same memory segment).

this is not per se true, it depends on the capabilities of your 32 bit
x86 processor.


> # grep maps /proc/self/maps
> bfce8000-bfcfe000 rw-p bfce8000 00:00 0 [stack]

this shows that the *intent* is to have it non-executable.
Not all x86 processors can enforce this. All modern ones do.

> Is there any reason for this situation?

the alternative (showing effective permission) is equally confusing;
apps would see permissions they didn't set...

> Maybe it comes from sharing source code for 64 bits and 32 bits
> architectures but if so, it should be possible (and highly desirable) to
> treat 32 bits differently.

it's not a "32 bit" thing, it's an "older processors don't, newer ones
do" thing.

Can you paste your /proc/cpuinfo file here ? Maybe you have a processor
with the capability but just haven't enabled it (either in the bios or
in the kernel config)

Greetings,
Arjan van de Ven

2006-12-14 12:07:17

by Franck Pommereau

[permalink] [raw]
Subject: Re: Executability of the stack

>> # grep maps /proc/self/maps
>> bfce8000-bfcfe000 rw-p bfce8000 00:00 0 [stack]
>
> this shows that the *intent* is to have it non-executable.
> Not all x86 processors can enforce this. All modern ones do.

Mine is quite recent:

# cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 15
model name : Intel(R) Core(TM)2 CPU T7200 @ 2.00GHz
stepping : 6
cpu MHz : 1000.000
cache size : 4096 KB
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 10
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge
mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm
constant_tsc up pni monitor ds_cpl vmx est tm2 cx16 xtpr lahf_lm
bogomips : 3996.23

> the alternative (showing effective permission) is equally confusing;
> apps would see permissions they didn't set...

Indeed, both are confusing (the other way is having permission that you
do not see). But which one is the most dangerous from a security point
of view? For me it is believing that you're protected while you're not.

>> Maybe it comes from sharing source code for 64 bits and 32 bits
>> architectures but if so, it should be possible (and highly desirable) to
>> treat 32 bits differently.
>
> it's not a "32 bit" thing, it's an "older processors don't, newer ones
> do" thing.

I've read that 64 bit processors have an execute bit at the page level
while 32 bit ones do not (only at the segment level). I didn't know that
newer 31 bit CPUs did have this bit.

> Can you paste your /proc/cpuinfo file here ? Maybe you have a processor
> with the capability but just haven't enabled it (either in the bios or
> in the kernel config)

I'd be happy to know how to enable it.

Thanks for your help.
Franck

2006-12-14 12:19:11

by Arjan van de Ven

[permalink] [raw]
Subject: Re: Executability of the stack

On Thu, 2006-12-14 at 13:07 +0100, Franck Pommereau wrote:
> >> # grep maps /proc/self/maps
> >> bfce8000-bfcfe000 rw-p bfce8000 00:00 0 [stack]
> >
> > this shows that the *intent* is to have it non-executable.
> > Not all x86 processors can enforce this. All modern ones do.
>
> Mine is quite recent:

> mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm

the "nx" shows that if you configure your kernel correctly (enable PAE)
that you indeed have a non-executable capability, which will apply to
the stack (and afaik the heap too)

> > the alternative (showing effective permission) is equally confusing;
> > apps would see permissions they didn't set...
>
> Indeed, both are confusing (the other way is having permission that you
> do not see). But which one is the most dangerous from a security point
> of view? For me it is believing that you're protected while you're not.

it's debatable what the file means; the maps file shows software
permissions currently not hardware enforced permissions. The "problem"
is that if you show software permissions... it's harder to see the
kernels view (vma's etc). I don't think there's a perfect answer.

It gets even more complex if you have something like execshield in use;
where the stack and heap are non-executable, unless you get a "higher"
executable mapping. In that case, the appearance of such a higher
mapping would change the visual mapping of other mappings. Outright
confusing as well :)
>
> >> Maybe it comes from sharing source code for 64 bits and 32 bits
> >> architectures but if so, it should be possible (and highly desirable) to
> >> treat 32 bits differently.
> >
> > it's not a "32 bit" thing, it's an "older processors don't, newer ones
> > do" thing.
>
> I've read that 64 bit processors have an execute bit at the page level
> while 32 bit ones do not (only at the segment level). I didn't know that
> newer 31 bit CPUs did have this bit.

your cpu has this bit, you just didn't turn it on ;(

> > Can you paste your /proc/cpuinfo file here ? Maybe you have a processor
> > with the capability but just haven't enabled it (either in the bios or
> > in the kernel config)
>
> I'd be happy to know how to enable it.

enable
CONFIG_HIGHMEM64G=y

and you're all set.


Greetings,
Arjan van de Ven

--
if you want to mail me at work (you don't), use arjan (at) linux.intel.com
Test the interaction between Linux and your BIOS via http://www.linuxfirmwarekit.org

2006-12-14 12:36:28

by James Courtier-Dutton

[permalink] [raw]
Subject: Re: Executability of the stack

Arjan van de Ven wrote:
> On Thu, 2006-12-14 at 10:26 +0100, Franck Pommereau wrote:
>> Dear Linux developers,
>>
>> I recently discovered that the Linux kernel on 32 bits x86 processors
>> reports the stack as being non-executable while it is actually
>> executable (because located in the same memory segment).
>
> this is not per se true, it depends on the capabilities of your 32 bit
> x86 processor.
>
>
>> # grep maps /proc/self/maps
>> bfce8000-bfcfe000 rw-p bfce8000 00:00 0 [stack]
>
> this shows that the *intent* is to have it non-executable.
> Not all x86 processors can enforce this. All modern ones do.
>
>> Is there any reason for this situation?
>
> the alternative (showing effective permission) is equally confusing;
> apps would see permissions they didn't set...
>

Why not show both.
"intent" and "effective".

2006-12-14 14:58:23

by Franck Pommereau

[permalink] [raw]
Subject: Re: Executability of the stack

Arjan van de Ven wrote:
>> Why not show both.
>> "intent" and "effective".
>
> that would change the file format .. which is used by apps today already
> (including glibc)

So, what about having another file, say /proc/self/emaps (effective
maps) that would display how things are really set.

Currently, is there any solution to test for effective permission except
by trying to execute something on the stack (thus crashing the program
on a successful test...)?

Arjan van de Ven also wrote in other mails:
> the "nx" shows that if you configure your kernel correctly (enable
> PAE) that you indeed have a non-executable capability, which will
> apply to the stack (and afaik the heap too)
[...]
> enable
> CONFIG_HIGHMEM64G=y
> and you're all set
[...]
> btw in case you didn't realize this; your processor is also 64 it
> capable, just use any x86-64 distribution on it ;)

Thanks for the tips!

Franck

2006-12-14 15:17:45

by Theodore Ts'o

[permalink] [raw]
Subject: [PATCH] Clarify i386/Kconfig explanation of the HIGHMEM config options

> > I'd be happy to know how to enable it.
>
> CONFIG_HIGHMEM64G=y

This is not at all obvious from arch/i386/Kconfig. Maybe we should
fix this?

- Ted

Add an explanation that HIGHMEM64G is needed in order to get support
for the NX feature.

Remove an (incorrect) assertion that NOHIGHMEM is right for more
users, since most systems are coming with at least 1G of memory these
days, and even some laptops have up 4G of memory.

Finally, although the explanation of the 1G/3G split is correct, it is
not relevant to the NOHIGHMEM/HIGHMEM4G/HIGHMEM64G discussion, since
the each process will always see 3GB of virtual memory. It also might
be something else depending on the setting of CONFIG_VMSPLIT_*.

Signed-off-by: "Theodore Ts'o" <[email protected]>
---
arch/i386/Kconfig | 17 ++++++++---------
1 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index 8ff1c6f..4b8f156 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -457,22 +457,21 @@ config NOHIGHMEM
"high memory".

If you are compiling a kernel which will never run on a machine with
- more than 1 Gigabyte total physical RAM, answer "off" here (default
- choice and suitable for most users). This will result in a "3GB/1GB"
- split: 3GB are mapped so that each process sees a 3GB virtual memory
- space and the remaining part of the 4GB virtual memory space is used
- by the kernel to permanently map as much physical memory as
- possible.
+ more than 1 Gigabyte total physical RAM, answer "off" here.

If the machine has between 1 and 4 Gigabytes physical RAM, then
answer "4GB" here.

If more than 4 Gigabytes is used then answer "64GB" here. This
selection turns Intel PAE (Physical Address Extension) mode on.
- PAE implements 3-level paging on IA32 processors. PAE is fully
+ PAE implements 3-level paging on IA32 processors. PAE is fully
supported by Linux, PAE mode is implemented on all recent Intel
- processors (Pentium Pro and better). NOTE: If you say "64GB" here,
- then the kernel will not boot on CPUs that don't support PAE!
+ processors (Pentium Pro and better). PAE support is also needed
+ if you wish to enable NX support, to make your system more secure by
+ enabling non-executable stacks.
+
+ NOTE: If you say "64GB" here, then the kernel will not boot
+ on CPUs that don't support PAE!

The actual amount of total physical memory will either be
auto detected or can be forced by using a kernel command line option
--
1.4.1

2006-12-14 15:37:56

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH] Clarify i386/Kconfig explanation of the HIGHMEM config options

> + 1 Gigabyte or more total physical RAM, answer "off" here.
>

I don't think your proposed wording (1 gigabyte or more) versus (more
than 1 gigabyte) doesn't really change the sense of this.

If we want to be even more explicit about this, then if the CPU level
selected by the user is greater than Pentium-M (or whatever is was the
oldest CPU that didn't have NX support --- Arjan?) we shouldn't offer
this choice at all, and force CONFIG_HIGHMEM64G. We can give the user
a choice if CONFIG_EMBEDDED is enabled, but otherwise, if the CPU
level is new enough, I think we can safely make the argument that for
nearly all systems, they have enough memory and speed that perhaps we
should just simply always use HIGHMEM64G.

- Ted

2006-12-14 15:45:09

by jurriaan

[permalink] [raw]
Subject: Re: [PATCH] Clarify i386/Kconfig explanation of the HIGHMEM config options

From: Theodore Tso <[email protected]>
Date: Thu, Dec 14, 2006 at 10:17:45AM -0500
>
> Remove an (incorrect) assertion that NOHIGHMEM is right for more
> users, since most systems are coming with at least 1G of memory these
> days, and even some laptops have up 4G of memory.

Given this (on a system with 1G of memory, this option shouldn't be
used)

> If you are compiling a kernel which will never run on a machine with
> - more than 1 Gigabyte total physical RAM, answer "off" here (default
> - choice and suitable for most users). This will result in a "3GB/1GB"
> - split: 3GB are mapped so that each process sees a 3GB virtual memory
> - space and the remaining part of the 4GB virtual memory space is used
> - by the kernel to permanently map as much physical memory as
> - possible.
> + more than 1 Gigabyte total physical RAM, answer "off" here.

wouldn't

+ 1 Gigabyte or more total physical RAM, answer "off" here.

make clearer that even with 1G memory, you shouldn't use this option?
Since 1G is quite common, we should, IMHO, be clear about that case.

Kind regards,
Jurriaan
--
They also played a refreshing rendition of Justin's solo material,
Twilight Home and Ocean Rising, with Michael Dean wailing in the back
while going ballistic on the Djembe.
Pax Eternum on a NMA concert at Que Sera, Long Beach, in 2004
Debian (Unstable) GNU/Linux 2.6.19-rc5-mm1 2x4826 bogomips load 1.13
the Jack Vance Integral Edition: http://www.integralarchive.org

2006-12-14 15:52:10

by Arjan van de Ven

[permalink] [raw]
Subject: Re: [PATCH] Clarify i386/Kconfig explanation of the HIGHMEM config options

On Thu, 2006-12-14 at 10:17 -0500, Theodore Tso wrote:
> > > I'd be happy to know how to enable it.
> >
> > CONFIG_HIGHMEM64G=y
>
> This is not at all obvious from arch/i386/Kconfig. Maybe we should
> fix this?

looks better; maybe add how to look for "pae" and "nx" in
the /proc/cpuinfo flags line ?

--
if you want to mail me at work (you don't), use arjan (at) linux.intel.com
Test the interaction between Linux and your BIOS via http://www.linuxfirmwarekit.org

2006-12-14 16:06:32

by Arjan van de Ven

[permalink] [raw]
Subject: Re: [PATCH] Clarify i386/Kconfig explanation of the HIGHMEM config options

On Thu, 2006-12-14 at 10:37 -0500, Theodore Tso wrote:
> > + 1 Gigabyte or more total physical RAM, answer "off" here.
> >
>
> I don't think your proposed wording (1 gigabyte or more) versus (more
> than 1 gigabyte) doesn't really change the sense of this.
>
> If we want to be even more explicit about this, then if the CPU level
> selected by the user is greater than Pentium-M (or whatever is was the
> oldest CPU that didn't have NX support --- Arjan?)

later pentium M's do support PAE (for NX). Only the very first ones did
not. Celerons might not either.. but PPro and later generally have
pae...


--
if you want to mail me at work (you don't), use arjan (at) linux.intel.com
Test the interaction between Linux and your BIOS via http://www.linuxfirmwarekit.org

2006-12-14 16:11:32

by Avi Kivity

[permalink] [raw]
Subject: Re: [PATCH] Clarify i386/Kconfig explanation of the HIGHMEM config options

Theodore Tso wrote:
>> + 1 Gigabyte or more total physical RAM, answer "off" here.
>>
>>
>
> I don't think your proposed wording (1 gigabyte or more) versus (more
> than 1 gigabyte) doesn't really change the sense of this.
>
> If we want to be even more explicit about this, then if the CPU level
> selected by the user is greater than Pentium-M (or whatever is was the
> oldest CPU that didn't have NX support --- Arjan?) we shouldn't offer
> this choice at all, and force CONFIG_HIGHMEM64G. We can give the user
> a choice if CONFIG_EMBEDDED is enabled, but otherwise, if the CPU
> level is new enough, I think we can safely make the argument that for
> nearly all systems, they have enough memory and speed that perhaps we
> should just simply always use HIGHMEM64G.
>

CONFIG_HIGHMEM64G is not a good name for PAE, which is a feature that
enables both large physical memory and nx.

IMO we should have CONFIG_PAE, selected by either CONFIG_HIGHMEM64G or a
new CONFIG_NO_EXEC.



--
error compiling committee.c: too many arguments to function

2006-12-14 19:58:29

by Alistair John Strachan

[permalink] [raw]
Subject: Re: [PATCH] Clarify i386/Kconfig explanation of the HIGHMEM config options

On Thursday 14 December 2006 15:37, Theodore Tso wrote:
> > + 1 Gigabyte or more total physical RAM, answer "off" here.
>
> I don't think your proposed wording (1 gigabyte or more) versus (more
> than 1 gigabyte) doesn't really change the sense of this.

It does, because if you have exactly 1G of RAM, you should be using
CONFIG_HIGHMEM, otherwise you will only be able to see ~896M.

This is >1G versus >=1G, the latter is clearly more correct.

--
Cheers,
Alistair.

Final year Computer Science undergraduate.
1F2 55 South Clerk Street, Edinburgh, UK.

2006-12-15 17:01:16

by Bill Davidsen

[permalink] [raw]
Subject: Re: [PATCH] Clarify i386/Kconfig explanation of the HIGHMEM config options

[email protected] wrote:
> From: Theodore Tso <[email protected]>
> Date: Thu, Dec 14, 2006 at 10:17:45AM -0500
>> Remove an (incorrect) assertion that NOHIGHMEM is right for more
>> users, since most systems are coming with at least 1G of memory these
>> days, and even some laptops have up 4G of memory.
>
> Given this (on a system with 1G of memory, this option shouldn't be
> used)
>
>> If you are compiling a kernel which will never run on a machine with
>> - more than 1 Gigabyte total physical RAM, answer "off" here (default
>> - choice and suitable for most users). This will result in a "3GB/1GB"
>> - split: 3GB are mapped so that each process sees a 3GB virtual memory
>> - space and the remaining part of the 4GB virtual memory space is used
>> - by the kernel to permanently map as much physical memory as
>> - possible.
>> + more than 1 Gigabyte total physical RAM, answer "off" here.
>
> wouldn't
>
> + 1 Gigabyte or more total physical RAM, answer "off" here.
>
> make clearer that even with 1G memory, you shouldn't use this option?
> Since 1G is quite common, we should, IMHO, be clear about that case.

Actually, if you want it to be perfectly clear to people who don't keep
x86 spec sheets in the bathroom for spare time study, a redundant config
option for NX would be required. Then the logic would be:
PAE = MEM>4G || NX
as far as the actual build was concerned. Or you could reject NX in
config unless PAE was selected.

I don't think you will avoid confusion when you have two unrelated
reasons for enabling the same feature.

--
bill davidsen <[email protected]>
CTO TMR Associates, Inc
Doing interesting things with small computers since 1979