A question about PROT_NONE on ARM and ARM26

Jamie Lokier
2004-06-30T02:44:44Z

Hi folks,

I'm doing a survey of the different architectural implementations of
PROT_* flags for mmap() and mprotect(). I'm looking at linux-2.6.5.

The ARM and ARM26 implementations are very similar to plain x86: read
implies exec, exec implies read and write implies read.

But I see a potential bug with PROT_NONE. I'm not sure if it's real,
so could you please confirm?

In include/asm-arm26/pgtable.h, I see this (reindented for mail):

#define PAGE_NONE \
__pgprot(_PAGE_PRESENT | _PAGE_CLEAN | _PAGE_READONLY | _PAGE_NOT_USER)
#define PAGE_READONLY \
__pgprot(_PAGE_PRESENT | _PAGE_CLEAN | _PAGE_READONLY )

In include/asm-arm/pgtable.h, I see this (reindented for mail):

#define _L_PTE_DEFAULT \
L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_CACHEABLE | L_PTE_BUFFERABLE
#define _L_PTE_READ \
L_PTE_USER | L_PTE_EXEC
#define PAGE_NONE \
__pgprot(_L_PTE_DEFAULT)
#define PAGE_READONLY
__pgprot(_L_PTE_DEFAULT | _L_PTE_READ)

Apparently the difference between PAGE_NONE and PAGE_READONLY, in each
case, is that PAGE_NONE is not readable from userspace but _is_
readable from kernel space.

Therefore all user accesses to a PROT_NONE page will cause a fault.

My question is: if the _kernel_ reads a PROT_NONE page, will it fault?
It looks likely to me.

This means that calling write() with a PROT_NONE region would succeed,
wouldn't it?

If so, this is a bug. A minor bug, perhaps, but nonetheless I wish to
document it.

I don't know if you would be able to rearrange the pte bits so that a
PROT_NONE page is not accessible to the kernel either. E.g. on i386
this is done by making PROT_NONE not set the hardware's present bit
but a different bit, and "pte_present()" tests both of those bits to
test the virtual present bit.

Thanks,
-- Jamie