Execute Disable Bit in Intel Core 2 Duo processor

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
Hi,
It seems that Intel's Execute Disable Bit functionality can
help prevent certain classes of malicious buffer overflow
attacks by allowing the processor to classify areas in memory
by where application code can execute and where it cannot.

But, isn't it a normal functionality present in almost many
of the processors that have memory classification as
Read Only Memory and Read/Write Memory areas ?

What is so special with 'Execute Disable Bit' option and
why is it hightlighted so explicity in the Intel Core 2 Duo
processors ? Any ideas ?

Thx in advans,
Karthik Balaguru

Re: Execute Disable Bit in Intel Core 2 Duo processor
Quoted text here. Click to load it

No. You can write to a data segment, but you shouldn't be allowed to
execute code out of that segment.

Quoted text here. Click to load it

For one thing, it stops code been executed in data only segments.

For example, if you can place your stack/local variables into
non-executable memory, you can stop code placed on the stack by a
buffer overflow exploit from actually been executed.

Simon.

--
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980's technology to a 21st century world

Re: Execute Disable Bit in Intel Core 2 Duo processor
Quoted text here. Click to load it

I don't remember the date, but this was a *Big Fsking Deal*
back around 1985 in the Microsoft world.  As best as I can
remember, Microsoft decreed that in the future, code and data
would be separate and there would be no more .com files.
This, of course, would break a large percentage of the existent
programs and caused much gnashing of teeth.  It also meant
the most trivial dos assembly program would grow by about
30 lines to add all the segment setup stuff.

Someone might remember the Dr. Dobbs Journal article on the
subject...

Re: Execute Disable Bit in Intel Core 2 Duo processor
Quoted text here. Click to load it

I actually remember some of this (vaguely), but from the viewpoint of
the late 80's/early 90's.

[Some background for anyone who never experienced this: On the 8086 a
segment is 64Kbytes in size. In the DOS days, Microsoft had various
segmented memory models (small, medium, compact, large, IIRC), which
allowed various combinations of code size and data size as well as the
.COM format which put everything in one 64K segment.

Because accessing code or data across segments required more code to be
generated, you chose the smallest memory model which you could get away
with in order to try and fit your code and/or data into a 64K segment.

For example, you could have a model which allowed 64K of code, but allowed
a larger than 64K data size. (But don't ask me to remember which memory
model it was. :-))]

IIRC, Microsoft _strongly_ encouraged you to move to one of the segmented
memory models, but the .COM format was still supported in the language and
linker tools of that timeframe (at least in the versions I remember using)
if you wanted to use it.

BTW, my choice of the word segment above was badly chosen in light of
it's existing use in the x86. I was thinking more along the lines of
a range of pages.

Simon.

--
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980's technology to a 21st century world

Re: Execute Disable Bit in Intel Core 2 Duo processor

Quoted text here. Click to load it

Compact.

FWIW:

    Model    Data    Code
    
    Tiny         near
    Small    near    near
    Medium   near    far
    Compact  far     near
    Large    far     far
    Huge     huge    huge

near = single segment, far = multiple segments without normalisation
(pointer arithmetic only affects the offset), huge = multiple segments
with normalisation.


Re: Execute Disable Bit in Intel Core 2 Duo processor
Quoted text here. Click to load it

Looks like a mnemonic for Double Norwich Court Bob Major!



Re: Execute Disable Bit in Intel Core 2 Duo processor



Quoted text here. Click to load it

Memory model just meant the type of pointers by default. It was not a
limitation for accessible code and data spaces per se.

VLV





Re: Execute Disable Bit in Intel Core 2 Duo processor
Quoted text here. Click to load it

Thanks. (It's been a _long_ time since I had to care about this :-) ).

Simon.

--
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980's technology to a 21st century world

Re: Execute Disable Bit in Intel Core 2 Duo processor
On Dec 8, 10:55A0%pm, Simon Clubley <clubley@remove_me.eisner.decus.org-
Earth.UFP> wrote:
Quoted text here. Click to load it

Thx for the response. Interesting :-)
But, Does only Intel Core 2 Duo processors have this feature ?
Is it so complicated to design that other processors do not
have this feature ?
I think, filesystems give us the control to allow
a person to either Read/Write/Execute. So, it can be locked
via filesystem method also. Any thoughts ?

Thx in advans,
Karthik Balaguru

Re: Execute Disable Bit in Intel Core 2 Duo processor
Quoted text here. Click to load it


Lots of processors have "executable" as a memory attribute.  "Not
executable" was added to x86 back in about 2004 (IIRC AMD added it
first with the 64 bit extensions, and Intel followed soon thereafter),
and has been standard on almost all x86s shipped in the last few
years.  "Not executable" and "executable" are really the same thing,
thing but since the default always was "executable" for x86, it was
logical to add the inverse condition, and then any OS's that didn't
set NX would continue to work unchanged.

FWIW, the canonical three memory attributes are read, write and
execute, and the various combinations thereof (not all processors
support all combinations, and some possible combinations - write only,
for example, don't make a lot of practical sense).

Nor is this really that new a concept to x86.  Even the 286 had, in
protected mode, a hard separation between code and data segments (code
segments were readable, but could never be writeable - if you wanted
to write into a code segment, you have to create an aliasing writable
data segment, and then write to that).  In fact, the now standard
technique of writing code into a stack segment via a buffer overflow
does not work in protected mode Win16 or 16 bit OS/2 (you can still
get the buffer overflow and munge the stack, but the stack segment is
a type of data segment and is not executable, so you can't run the
code).

Segments in 32 bit mode still provide that protection, but since the
flat model creates only a couple of segments, that are, in fact,
aliasing the same linear addresses, the protection is ineffective.
Note that even on 32 bit x86, in flat model, if you attempted to write
to memory using the code selector, the CPU would trap.  64 bit mode
greatly reduces functionality of segments.


Quoted text here. Click to load it


File system protections are a completely different subject, and have
essentially nothing to do with memory attributes (with some obvious
exceptions - for instance, one would assume that a sane OS would mark
memory pages assigned to a memory mapped file as not-writable if the
mapped file was read-only, or would avoid marking memory pages
executable if they didn92%t come from a program file with permission to
run).

Re: Execute Disable Bit in Intel Core 2 Duo processor
On Tue, 8 Dec 2009 14:11:54 -0800 (PST), " snipped-for-privacy@yahoo.com"

Quoted text here. Click to load it


It is strange that it took so long for the x86 architecture to have a
usable execution prevention, since such features have been common in
minicomputers since the 1970's.

Quoted text here. Click to load it

At least the program loader needs to write into the code segment
(initial loading and possible fixups). Typically this is done in the
kernel mode and memory area is mapped as data.

Quoted text here. Click to load it

This overlapping is a (possibly stupid) design made by the OS and
linker designer. Using smaller segments than 4 GiB and using separate
segment base address would allow protecting the code segment and
data+stack segment from each other.
 


Re: Execute Disable Bit in Intel Core 2 Duo processor
Quoted text here. Click to load it


It's not quite that easy if you want to have a flat address space
encompassing both your code and data - and there are very definite
advantages to that.  You *can* create a code segment with a limit
value that prevents code from executing above a certain address, and
then mark all the corresponding pages read-only (thus the pages below
the limit are at most execute/read, and the pages above the limit are
read/write).  The problem is that this conflicts with the very common
OS design of having both OS and application segments (segment !3D% x86
hardware segment) in the address space, but separate.  It would
perhaps have been reasonable to end up with four areas in the address
space - OS code, OS data, application code and application data (with
both code areas below the CS limit), at the expense of additional
fragmentation of the address space.

Re: Execute Disable Bit in Intel Core 2 Duo processor
On Wed, 9 Dec 2009 14:04:13 -0800 (PST), " snipped-for-privacy@yahoo.com"

Quoted text here. Click to load it

Such as ?

On a PDP-11 with separate I/D support, on a subroutine call I
preferred loosing the ability of using the (more or less useless)
R0-R5 as the parameter passing register (i.e. in-line parameters) and
be forced to use the PC as the only parameter passing register (i.e.
stack based parameter passing) when using separate I/D (64 KiB Code
and 64 KiB data space :-).

Of course, this was the days of core memory.

The situation might be different with some Harvard architecture
processors (such as PIC), in which the instruction space is in Flash
and the non-volatile data space is in RAM.

Quoted text here. Click to load it

While I fully understand the need for 32 or even 64 bit data/stack
address space for handling large data arrays, with current modular
software design methods, a 64 KiB address space should be enough,
provided that the "far" calls can be used easily.

My guess is that the reason of full code space is the frustration with
128/256/512 byte branch restrictions in most older platforms. With
current programming practices, there shouldn't be much need for
branches +/-32KiB, but instead a "far" call shouldn't be a problem.
 
Quoted text here. Click to load it

The more or less standard practice with 32 bit OS since the 1970's has
been 2 GiB for user data space and 2 GiB for kernel code/data.

Unfortunately, this has caused quite careless use of the virtual
space, since for example in Windows NT, it is quite hard to find at
least 100 MiB continuous address space for file mapping into virtual
address space.


Re: Execute Disable Bit in Intel Core 2 Duo processor

Quoted text here. Click to load it

Linux/x86 typically uses 3GiB for user-space with the top 1GiB reserved
for kernel mode.


Re: Execute Disable Bit in Intel Core 2 Duo processor

Quoted text here. Click to load it

In practice, the last part doesn't always happen. On Linux, execute
permission only affects whether you can execve() a file; lack of execute
permission doesn't prevent you from mmap()ing a file PROT_EXEC (however,
this will fail (with EPERM) if the file is on a filesytem mounted with the
noexec attribute).

Also, the lack of write-only pages on x86 means that PROT_WRITE must be
treated as PROT_READ|PROT_WRITE, which means that the file must have been
open()ed O_RDWR, not O_WRONLY. In turn, this can cause problems for
mmap()ing certain devices, which can't tell if you requested read access
because you actually want to read from the device or simply to keep mmap()
happy.


Re: Execute Disable Bit in Intel Core 2 Duo processor

Quoted text here. Click to load it

Beware the references to "segments" in replies. As well as being a
generic term it is used specifically by Intel and AMD. Intel's 32-bit
x86 architecture defines a code segment as well as a number of data
segments. The code segment is used implicitly for instruction fetches.
This cannot be overridden so there is a guarantee that instructions
are fetched from the code segment.

As with other segments the code segment has a base address and a limit
so can provide security. According to AMD, however, designers of
popular operating systems (you can guess what these might be) failed
to make use of the code segment restrictions and made code and data
segments overlap. As a consequence when AMD designed the 64-bit x86
architecture they simplified the design and got rid of most of the
segment functionality. The 64-bit modes mandate the overlap of code
and most data segments.

The older OS designs and the new 64-bit modes, therefore, had no
protection against being told to execute code in data areas. How to
fix it? An execute disable bit was needed. Segmentation was deprecated
so the new bit was added in the paging structures. Execution can
therefore be prohibited on a per-page basis.

Quoted text here. Click to load it

They do make a fuss about a single bit don't they. In a sense it is a
fix to a problem that didn't need to exist. Each code segment could
have been prevented from overlapping with data but it wasn't. As much
to the point, operating systems could have been more secure but they
weren't. For example, why should execution of any unprivileged code
whether it's in a buffer or not be able to subvert a system? Or why
should a buffer overflow be able to overwrite privileged code or data?
Neither should be possible.

Due to issues such as buffer overflow attacks the execute disable bit
has gained a marked presence in the mind of many. This single bit
definition has become a big selling point for CPUs from both AMD and
Intel. Check the Intel processor manuals for full details. I think
they are easier to read than AMDs.

By the way, I've never found a simple list of which processors support
the bit. The official answer is to use the cpuid instruction to test
for its presence.

James

Re: Execute Disable Bit in Intel Core 2 Duo processor
On Wed, 9 Dec 2009 09:17:09 -0800 (PST), James Harris

Quoted text here. Click to load it

Thanks for this explanation.  I'm intimately familiar with the P2,
having done chipset testing for Intel.  But I have not kept up.  I had
written a reply, yesterday, but hadn't posted it hoping for an
informed reply.  In that post, I had _guessed_ that the only place I
could imagine adding such a "new" feature, beyond what is already
available in the GDT and LDT, was the paging system that mediates
between linear and physical addressing.  You've confirmed my hunch.

Quoted text here. Click to load it

Agreed!

Quoted text here. Click to load it

That's been my experience, as well.

Quoted text here. Click to load it

Thanks very much for taking a moment.  I learned something about some
of the newer processors.

Jon

Re: Execute Disable Bit in Intel Core 2 Duo processor
Quoted text here. Click to load it


In general it cannot.  Injecting code into applications is quite
enough to do damage.

Re: Execute Disable Bit in Intel Core 2 Duo processor

Quoted text here. Click to load it

A large part of the problem was that Windows was designed for 8086 and
Unix was designed for systems with page-level protection. The 80386 didn't
include page-level execute permission on the assumption that software
would use segments, but Unix assumes a flat address space (e.g. the
pointers returned by mmap() and passed to munmap() can be either code or
data).

Quoted text here. Click to load it

In general, it can't. On both Windows NT and Unix, a buffer overflow can
only subvert that process; however, that still means that an attacker can
run code under the account in question.

Windows 95/98/ME had problems due to the bottom 1MiB of physical memory
needing to be writable by all applications, so that legacy real-mode 8086
applications worked.

OTOH, "classic" Macs  (i.e. prior to the Unix-based OSX) didn't have *any*
memory protection, yet buffer overflows were relatively uncommon, mostly
due to the use of objective-C rather than C/C++.

Linux/x86 has supported a non-executable stack since before the NX bit
was added, by making the code segment shorter than the data segment (the
stack is at the top of the user-mode address space), but this doesn't work
for the heap (which is at the bottom of the address space). However, a
non-executable stack caused problems for code which uses trampolines
(this was quite common for objective-C code), and for some emulators, so
many distributions disabled this feature.

Various compiler features can guard against buffer overflows, but they
either have a memory penalty (inserting guard pages between stack frames)
or a performance penalty (inserting canary words which are checked before
restoring the saved PC from the stack).


Site Timeline