Table of mmap PROT_* implementations by architecture

From: Jamie Lokier
Date: Wed Jun 30 2004 - 22:40:31 EST


>From a study of Linux 2.6.5 source code, and some patches.
This is based on studying the source, not running tests, so there
may be errors.

This table shows expected page protections, for different values of
PROT_READ, PROT_WRITE and PROT_EXEC passed to mmap() and mprotect().

(As noted in a recent mail from me, real behaviour isn't quite this
simple. Reading from a write-only page will *sometimes* raise a
signal, and sometimes not, possibly dependent on background paging
decisions. Therefore some of these entries should say "!w!" instead
of "rwx", and "!w-" instead of "rw-". Perhaps there are other
combinations too, depending on architecture-specific fault handlers).


======================+========================================================
Requested PROT flags | --- R-- -W- RW- --X R-X -WX RWX
======================+========================================================
alpha | --- r-- rw- rw- --x r-x rwx rwx
----------------------+--------------------------------------------------------
arm | --- r-x rwx rwx r-x r-x rwx rwx
----------------------+--------------------------------------------------------
cris | --- r-x rwx rwx r-x r-x rwx rwx
----------------------+--------------------------------------------------------
h8300 | No MMU
----------------------+--------------------------------------------------------
i386 (plain) | --- r-x rwx rwx r-x r-x rwx rwx
i386 (PaX) | --- r-- rw- rw- r-x r-x rw-(2) rw-(2)
i386 (exec-shield) | --- r--(3) rw-(3) rw-(3) r-x r-x rwx rwx
i386 (NX) | --- r-- rw- rw- r-x r-x rwx rwx
----------------------+--------------------------------------------------------
ia64 | --- r-- rw- rw- --x(1) r-x rwx rwx
----------------------+--------------------------------------------------------
m68k (motorola) | --- r-x rwx rwx r-x r-x rwx rwx
m68k (sun3) | r-x r-x rwx rwx r-x r-x rwx rwx
m68k (no mmu) | No MMU
----------------------+--------------------------------------------------------
mips | --- r-x rwx rwx r-x r-x rwx rwx
mips64 | --- r-x rwx rwx r-x r-x rwx rwx
mips (PaX) (4) | --- r-x rwx rwx r-x r-x rwx rwx
mips64 (PaX) (4) | --- r-x rwx rwx r-x r-x rwx rwx
----------------------+--------------------------------------------------------
parisc | --- r-- -w- rw- r-x r-x rwx rwx
parisc (PaX) | --- r-- -w- rw- r-x r-x rw-(2) rw-(2)
----------------------+--------------------------------------------------------
ppc | ---(1) r-x rwx(5) rwx r-x(5) r-x rwx(5) rwx
ppc64 | ---(1) r-x rwx(5) rwx r-x(5) r-x rwx(5) rwx
ppc (PaX) | ---(1) r-- rw- rw- r-x r-x rw-(2) rw-(2)
ppc64 (PaX for 2.6) | ---(1) r-- rw- rw- r-x r-x rw-(2) rw-(2)
----------------------+--------------------------------------------------------
s390 | --- r-x rwx rwx r-x r-x rwx rwx
----------------------+--------------------------------------------------------
sh | --- r-x rwx rwx r-x r-x rwx rwx
sh (no mmu) | No MMU
----------------------+--------------------------------------------------------
sparc (sun4) | --- r-x rwx rwx r-x r-x rwx rwx
sparc (sun4c) | --- r-x rwx rwx r-x r-x rwx rwx
sparc (SRMMU) | ---(1) r-x(6) rwx(6) rwx(6) r-x r-x rwx rwx
sparc64 | --- r-x rwx rwx r-x r-x rwx rwx
sparc (Pax+SRMMU) | ---(1) r-- rw- rw- r-x r-x rw-(2) rw-(2)
sparc64 (Pax) | --- r-- rw- rw- r-x r-x rw-(2) rw-(2)
----------------------+--------------------------------------------------------
um (user mode) | ---(7) r-x rwx rwx r-x r-x rwx rwx
----------------------+--------------------------------------------------------
v850 | No MMU
----------------------+--------------------------------------------------------
x86_64 (AMD NX) | --- r-- rw- rw- r-x r-x rwx rwx
x86_64 (Intel no-NX) | --- r-x rwx rwx r-x r-x rwx rwx
x86_64 (Intel NX) | --- r-- rw- rw- r-x r-x rwx rwx
x86_64 (PaX NX) | --- r-- rw- rw- r-x r-x rw-(2) rw-(2)
x86_64 (PaX no-NX) (4)| --- r-x rwx rwx r-x r-x rwx rwx
----------------------+--------------------------------------------------------

(1) - In kernel, maybe these pages are readable using "write()"?
In each case that is labelled, I'm not sure from reading the code.
(Pages are always readable using ptrace(), that's ok, but write()
and other kernel reads shouldn't be able to read PROT_NONE pages).

(2) - The PaX security patch simulates fine-grained exec permission.
PaX also disallows ALL writable+executable pages as a matter of
policy: PROT_WRITE|PROT_EXEC does not make the mapping executable
and mprotect() cannot change this. This feature can be switched
off for marked executables, or globally.

(3) - The Exec-Shield patch, when the CPU doesn't support the NX capability
or when it's not a recent enough patch, uses segmentation to
*approximate* fine-grained exec permission. If this is so, code
which detects that one PROT_EXEC page isn't executable cannot
assume that all non-PROT_EXEC pages aren't executable.

(4) - PaX is available for MIPS, but doesn't really disable execute
permissions. On x86-64, PaX assumes the AMD64 architecture with NX
capability (quite rightly) and so fails to disable execute permissions
on Intel IA32e chips without NX.

(5) - The PPC code looks like it "ought to" not allow exec in these cases,
but other comments indicate that the _PAGE_EXEC flag is ignored anyway.

(6) - The code says SRMMU can implement no-exec, but it's not implemented.

(7) - On User Mode Linux, PROT_NONE may depend on underlying architecture.
Otherwise, read and exec are always synonymous and write implies read,
regardless of the underlying architecture.


Enjoy,
-- Jamie
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/