diff options
author | gber <gber@FreeBSD.org> | 2013-05-06 15:30:34 +0000 |
---|---|---|
committer | gber <gber@FreeBSD.org> | 2013-05-06 15:30:34 +0000 |
commit | 961ec795d088046f43bf59c8d94e736da9d88a25 (patch) | |
tree | 11664ec9eb962f4c9cf92813399d348fc8022a36 /sys/arm | |
parent | 03f9e64ed49fc13e4b91aa5db9fec92b06edcc22 (diff) | |
download | FreeBSD-src-961ec795d088046f43bf59c8d94e736da9d88a25.zip FreeBSD-src-961ec795d088046f43bf59c8d94e736da9d88a25.tar.gz |
Fix L2 PTE access permissions management.
Keep following access permissions:
APX AP Kernel User
1 01 R N
1 10 R R
0 01 R/W N
0 11 R/W R/W
Avoid using reserved in ARMv6 APX|AP settings:
- In case of unprivileged (user) access without permission to write,
the access permission bits were being set to reserved for ARMv6
(but valid for ARMv7) value of APX|AP = 111.
Fix-up faulting userland accesses properly:
- Wrong condition statement in pmap_fault_fixup() caused that
any genuine, unprivileged access was being fixed-up instead of
just skip doing anything and return. Staring from now we ensure
proper reaction for illicit user accesses.
L2_S_PROT_R and L2_S_PROT_U names might be misleading as they do not
reflect real permission levels. It will be clarified in following
patches (switch to AP[2:1] permissions model).
Obtained from: Semihalf
Diffstat (limited to 'sys/arm')
-rw-r--r-- | sys/arm/arm/pmap-v6.c | 15 | ||||
-rw-r--r-- | sys/arm/include/pmap.h | 2 |
2 files changed, 10 insertions, 7 deletions
diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c index 9d16509..b650329 100644 --- a/sys/arm/arm/pmap-v6.c +++ b/sys/arm/arm/pmap-v6.c @@ -983,6 +983,7 @@ pmap_set_prot(pt_entry_t *ptep, vm_prot_t prot, uint8_t user) if (!(prot & VM_PROT_EXECUTE)) *ptep |= L2_XN; + *ptep |= L2_APX; *ptep |= L2_S_PROT_R; if (user) @@ -990,6 +991,8 @@ pmap_set_prot(pt_entry_t *ptep, vm_prot_t prot, uint8_t user) if (prot & VM_PROT_WRITE) *ptep &= ~(L2_APX); + else if (user) + *ptep &= ~(L2_S_PROT_R); } /* @@ -1216,7 +1219,7 @@ pmap_fault_fixup(pmap_t pm, vm_offset_t va, vm_prot_t ftype, int user) /* * Catch a userland access to the vector page mapped at 0x0 */ - if (user && ((pte & L2_S_PROT_MASK) == L2_S_PROT_U)) + if (user && !(pte & L2_S_PROT_U)) goto out; if (va == vector_page) goto out; @@ -2649,7 +2652,10 @@ do_l2b_alloc: npte |= L2_TYPE_INV; } + npte |= L2_APX; npte |= L2_S_PROT_R; + if (user) + npte |= L2_S_PROT_U; if (prot & VM_PROT_WRITE) { npte &= ~(L2_APX); @@ -2657,11 +2663,8 @@ do_l2b_alloc: if (m != NULL && (m->oflags & VPO_UNMANAGED) == 0) vm_page_aflag_set(m, PGA_WRITEABLE); - } - - if (user) - npte |= L2_S_PROT_U; - + } else if (user) + npte &= ~(L2_S_PROT_R); if (!(prot & VM_PROT_EXECUTE) && m) npte |= L2_XN; diff --git a/sys/arm/include/pmap.h b/sys/arm/include/pmap.h index 7c8d073..1b35ab9 100644 --- a/sys/arm/include/pmap.h +++ b/sys/arm/include/pmap.h @@ -352,7 +352,7 @@ extern int pmap_needs_pte_sync; #elif (ARM_MMU_V6 + ARM_MMU_V7) != 0 #define L2_S_PROT_U (L2_AP0(2)) /* user access */ -#define L2_S_PROT_R (L2_APX|L2_AP0(1)) /* read access */ +#define L2_S_PROT_R (L2_AP0(1)) /* read access */ #define L2_S_PROT_MASK (L2_S_PROT_U|L2_S_PROT_R) #define L2_S_WRITABLE(pte) (!(pte & L2_APX)) |