Red Hat Bugzilla – Bug 161487
noexec=off does not clear the EFER bit
Last modified: 2012-06-20 12:12:07 EDT
From Bugzilla Helper:
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20040913 Firefox/0.10
Description of problem:
This is with regards to the NX bit (a.k.a. Execute Disable).
By default NX is enabled and bit 11 of EFER is set.
To disable this, you need to use "noexec=off" in the boot command line. The expected result is that the bit in the EFER is cleared. However, it remains set.
Version-Release number of selected component (if applicable):
Steps to Reproduce:
1. Use noexec=off in the boot command line
2. Once you're up, read the EFER register for all cpu's in the system.
3. Check the 11th bit. It should be clear. But you'll see that it's still set.
Actual Results: I see that the NX bit in EFER shows that NX is still enabled.
Expected Results: The 11th bit should be clear.
The routines involved are in arch/i386/mm/init.c and arch/i386/kernel/setup.c.
The first file is the key file. The second one is merely relevant to the discussion.
The following display shows the sequence of events. paging_init() executes first. It calls set_nx() because PAE is enabled. At this time, the kernel has not seen the noexec option. Therefore, he concludes that NX should be enabled. He sets the 11th bit of EFER. Back to paging_init(). It finds that nx_enabled is true and prints out the kernel message. Later, the kernel processes the noexec option and executes noexec_setup(). He sets disable_nx to true (which contradicts nx_enabled because this flag is also true). Then clears the exec_shield flag, which affects application program behavior enough such that you think everything went fine. At any rate, there is no code to update EFER at this point. Therefore the 11th bit of EFER is still true (that NX is enabled).
Jun 23 01:08:49 ernie kernel: set_nx. 0 MASHLEY. 1
Jun 23 01:08:49 ernie kernel: NX enabled. 1 MASHLEY. ffffffffffffffff 0 -2147483648
Jun 23 01:08:50 ernie kernel: noexec_setup OFF. 1 MASHLEY. 1
The following is further demonstration of the problem. I added code in noexec_setup() in the else portion of the IF statement. I clear the EFER bit. Furthermore, I modify parse_cmdline_early() to call noexec_setup(). This last change reflects what the base kernel does. Yes, this will result in two calls to noexec_setup() but I'm trying to demonstrate the problem. The following is the result. paging_init() finds that nx_enabled is false. And that is correct. Note that this change affects the EFER bit of only the boot cpu. The other cpu's will still have the wrong EFER settings. But like I said, this is not a fix. I'm just showing the problem.
Jun 23 01:16:22 ernie kernel: noexec_setup OFF. 1 MASHLEY. 0
Jun 23 01:16:22 ernie kernel: NX disabled. 0 MASHLEY. 7fffffffffffffff 0 0
Jun 23 01:16:23 ernie kernel: noexec_setup OFF. 1 MASHLEY. 0
So now, when I run a driver after the fact, to read the EFER bit, I find that the boot cpu has its EFER settings correct (11th bit is clear). The rest of the cpu's still have bad EFER's. Ideally, the EFER's on all cpu's (hyperthreading and multi-coring issues included) should be correct.
I will attach the two source files to show you where I put my printk's.
Created attachment 115886 [details]
Look for "MASHLEY". correlate these lines to what I showed in my description of
Created attachment 115887 [details]
Look for "MASHLEY". Correlate these lines to what I wrote to describe the
Thank you for submitting this issue for consideration in Red Hat Enterprise Linux. The release for which you requested us to review is now End of Life.
Please See https://access.redhat.com/support/policy/updates/errata/
If you would like Red Hat to re-consider your feature request for an active release, please re-open the request via appropriate support channels and provide additional supporting details about the importance of this issue.