# Execute Disable (NX) in Linux 2.6.16

## Sachankara

Hello,

I was wondering what settings are required to enable NX/Execute Disable on Linux 2.6.16 on an Intel Celeron M. Accordingly to Intel and /proc/cpuinfo, NX is supported, yet I cannot get it to work. Have the Linux developers simply not bothered to fix support for any other CPU than AMD 64/Intel Pentium M/Core Duo?

cat /proc/cpuinfo 

```
processor       : 0

vendor_id       : GenuineIntel

cpu family      : 6

model           : 13

model name      : Intel(R) Celeron(R) M processor         1.50GHz

stepping        : 8

cpu MHz         : 187.500

cache size      : 1024 KB

fdiv_bug        : no

hlt_bug         : no

f00f_bug        : no

coma_bug        : no

fpu             : yes

fpu_exception   : yes

cpuid level     : 2

wp              : yes

flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat clflush dts acpi mmx fxsr sse sse2 ss tm pbe nx

bogomips        : 3000.09
```

"dmesg | grep NX" and "grep NX /var/log/dmesg" returns nothing.

Would be interesting to see if anyone with a Celeron M have gotten it to work.

----------

## sternklang

Hi,

Include "noexec=on noexec32=on" in your kernel parameters in grub.conf -- actually, for a Celeron M just "noexec32=on" would work. This would be software emulation of the nx bit, since as far as I know the Celeron M doesn't have this feature built in.

----------

## Sachankara

Thanks, I'll try it in a minute. But why does Intel and /proc/cpuinfo claim that it has NX support if it really doesn't? False marketing?  :Wink: 

Edit: It did not work. The kernel devs deserve a kick in their a** for not making the NX detection better. /proc/cpuinfo should not list nx among the available flags unless the kernel supports it, because that just gives people like me false hope.

----------

## infirit

 *Sachankara wrote:*   

> Edit: It did not work. The kernel devs deserve a kick in their a** for not making the NX detection better. /proc/cpuinfo should not list nx among the available flags unless the kernel supports it, because that just gives people like me false hope.

 How did you come to the conlusion it was not working? Have you even tried to create an buffer overflow? I gues not.

Article with example code and his findings and the wikipedia entry on NX.

----------

## Sachankara

 *infirit wrote:*   

>  *Sachankara wrote:*   Edit: It did not work. The kernel devs deserve a kick in their a** for not making the NX detection better. /proc/cpuinfo should not list nx among the available flags unless the kernel supports it, because that just gives people like me false hope. How did you come to the conlusion it was not working? Have you even tried to create an buffer overflow? I gues not.
> 
> Article with example code and his findings and the wikipedia entry on NX.

 1. The kernel doesn't say anything about NX being enabled, as it should do accordingly to the kernel source code.

2. 

```
$ nano -w nx.c

void fun1()

{

   int m = 5;

   void (*p)();

   void fun2()

   {

      printf("fun2: %d\n", m);

      m = 10;

   }

   void fun3()

   {

      p();

   }

   p = fun2;

   fun3();

}

main()

{

   fun1();

}

$ gcc -c nx.c

nx.c: In function `fun1':

nx.c:16: varning: generating trampoline in object (requires executable stack)

$ gcc -o nx nx.o

$ execstack nx

X nx

$ ./nx

fun2: 5

$ execstack -c nx

$ execstack nx

- nx

$ ./nx

fun2: 5
```

There's no difference between the two execstack tests, so it would seem that it's not working on this Celeron M. The emulated stuff via PaX works though, but I'd like to use the native hardware support.

----------

## infirit

 *Sachankara wrote:*   

> 1. The kernel doesn't say anything about NX being enabled, as it should do accordingly to the kernel source code.

 I will check on my AMD64 system (64bit mode) if there is any mention of NX in the logs. I do not recall seeing it though while it do have the 2 noxec option passed in grub. I will also try your code and see if it generates a message in the log.

----------

## sternklang

On my amd64 system, your test program generates a segfault after execstack -c is run on it, so this is working on my system. Nonetheless, there's nothing in the dmesg output here to indicate it is working (other than the segfault I generated with your test program).

----------

## Sachankara

Accordingly to the kernel source code, NX support is enabled in arch/i386/mm/init.c . The requirements are that one has enabled 64 GiB support (PAE - Physical Address Extension on IA32) and has hardware support for NX. I've enabled 64 GiB support and my CPU has NX support, but it still doesn't seem to work.

A snippet from the code: 

```
void __init paging_init(void)

{

#ifdef CONFIG_X86_PAE

    set_nx();

    if (nx_enabled)

        printk("NX (Execute Disable) protection: active\n");

#endif

...
```

Also: 

```
/*

 * noexec = on|off

 *

 * Control non executable mappings.

 *

 * on      Enable

 * off     Disable

 */

void __init noexec_setup(const char *str)

{

    if (!strncmp(str, "on",2) && cpu_has_nx) {

        __supported_pte_mask |= _PAGE_NX;

        disable_nx = 0;

    } else if (!strncmp(str,"off",3)) {

        disable_nx = 1;

        __supported_pte_mask &= ~_PAGE_NX;

    }

}

int nx_enabled = 0;

#ifdef CONFIG_X86_PAE

static void __init set_nx(void)

{

    unsigned int v[4], l, h;

    if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) {

        cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]);

        if ((v[3] & (1 << 20)) && !disable_nx) {

            rdmsr(MSR_EFER, l, h);

            l |= EFER_NX;

            wrmsr(MSR_EFER, l, h);

            nx_enabled = 1;

            __supported_pte_mask |= _PAGE_NX;

        }

    }

}
```

So it sorts of seems that the kernel NX detection isn't working as it should, or there is something else going on. Guess I'll have to do some kernel hacking. :/

Of course, if I look at the code in arch/x86_64/mm/init.c , I cannot find anything which print messages concerning NX. Perhaps they've disabled the message for x86_64 simply because it's standard these days, but I've seen other's dmesg:s which print out the same thing as listed in arch/i386/mm/init.c ... Strange.

----------

## Sachankara

 *sternklang wrote:*   

> On my amd64 system, your test program generates a segfault after execstack -c is run on it, so this is working on my system. Nonetheless, there's nothing in the dmesg output here to indicate it is working (other than the segfault I generated with your test program).

 Well, that is what I thought. They've managed to enable it on x86_64 but not on IA32. I'll continue to look around some more.

----------

## infirit

 *Sachankara wrote:*   

>  *sternklang wrote:*   On my amd64 system, your test program generates a segfault after execstack -c is run on it, so this is working on my system. Nonetheless, there's nothing in the dmesg output here to indicate it is working (other than the segfault I generated with your test program). Well, that is what I thought. They've managed to enable it on x86_64 but not on IA32. I'll continue to look around some more.

 It does work for me on amd64 but there is no message in the log, weird   :Confused: 

----------

## sternklang

 *Sachankara wrote:*   

> They've managed to enable it on x86_64 but not on IA32. I'll continue to look around some more.

 

The original Celeron M did not support nx. Perhaps there's a specific "-march" you have to build with to get this feature.

----------

## Sachankara

 *sternklang wrote:*   

>  *Sachankara wrote:*   They've managed to enable it on x86_64 but not on IA32. I'll continue to look around some more. 
> 
> The original Celeron M did not support nx. Perhaps there's a specific "-march" you have to build with to get this feature.

 Well, the Celeron M370 does support NX, which can be confirmed by the fact that I got it running now with Linux 2.6.17.  :Smile: 

```
$ sudo dmesg | grep NX

NX (Execute Disable) protection: active

$ execstack -s nx

$ ./nx

fun2: 5

$ execstack -c nx

$ ./nx

Segmenteringsfel

```

I'll continue to try getting it to work with 2.6.16, because that's the kernel I use.

----------

