diff options
-rw-r--r-- | include/linux/mman.h | 29 | ||||
-rw-r--r-- | mm/mmap.c | 5 | ||||
-rw-r--r-- | mm/mprotect.c | 2 |
3 files changed, 32 insertions, 4 deletions
diff --git a/include/linux/mman.h b/include/linux/mman.h index dab8892e6ff1..30d1073bac3b 100644 --- a/include/linux/mman.h +++ b/include/linux/mman.h | |||
@@ -34,6 +34,32 @@ static inline void vm_unacct_memory(long pages) | |||
34 | } | 34 | } |
35 | 35 | ||
36 | /* | 36 | /* |
37 | * Allow architectures to handle additional protection bits | ||
38 | */ | ||
39 | |||
40 | #ifndef arch_calc_vm_prot_bits | ||
41 | #define arch_calc_vm_prot_bits(prot) 0 | ||
42 | #endif | ||
43 | |||
44 | #ifndef arch_vm_get_page_prot | ||
45 | #define arch_vm_get_page_prot(vm_flags) __pgprot(0) | ||
46 | #endif | ||
47 | |||
48 | #ifndef arch_validate_prot | ||
49 | /* | ||
50 | * This is called from mprotect(). PROT_GROWSDOWN and PROT_GROWSUP have | ||
51 | * already been masked out. | ||
52 | * | ||
53 | * Returns true if the prot flags are valid | ||
54 | */ | ||
55 | static inline int arch_validate_prot(unsigned long prot) | ||
56 | { | ||
57 | return (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM)) == 0; | ||
58 | } | ||
59 | #define arch_validate_prot arch_validate_prot | ||
60 | #endif | ||
61 | |||
62 | /* | ||
37 | * Optimisation macro. It is equivalent to: | 63 | * Optimisation macro. It is equivalent to: |
38 | * (x & bit1) ? bit2 : 0 | 64 | * (x & bit1) ? bit2 : 0 |
39 | * but this version is faster. | 65 | * but this version is faster. |
@@ -51,7 +77,8 @@ calc_vm_prot_bits(unsigned long prot) | |||
51 | { | 77 | { |
52 | return _calc_vm_trans(prot, PROT_READ, VM_READ ) | | 78 | return _calc_vm_trans(prot, PROT_READ, VM_READ ) | |
53 | _calc_vm_trans(prot, PROT_WRITE, VM_WRITE) | | 79 | _calc_vm_trans(prot, PROT_WRITE, VM_WRITE) | |
54 | _calc_vm_trans(prot, PROT_EXEC, VM_EXEC ); | 80 | _calc_vm_trans(prot, PROT_EXEC, VM_EXEC) | |
81 | arch_calc_vm_prot_bits(prot); | ||
55 | } | 82 | } |
56 | 83 | ||
57 | /* | 84 | /* |
@@ -72,8 +72,9 @@ pgprot_t protection_map[16] = { | |||
72 | 72 | ||
73 | pgprot_t vm_get_page_prot(unsigned long vm_flags) | 73 | pgprot_t vm_get_page_prot(unsigned long vm_flags) |
74 | { | 74 | { |
75 | return protection_map[vm_flags & | 75 | return __pgprot(pgprot_val(protection_map[vm_flags & |
76 | (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)]; | 76 | (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)]) | |
77 | pgprot_val(arch_vm_get_page_prot(vm_flags))); | ||
77 | } | 78 | } |
78 | EXPORT_SYMBOL(vm_get_page_prot); | 79 | EXPORT_SYMBOL(vm_get_page_prot); |
79 | 80 | ||
diff --git a/mm/mprotect.c b/mm/mprotect.c index a5bf31c27375..ecfaa5844b5f 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c | |||
@@ -239,7 +239,7 @@ sys_mprotect(unsigned long start, size_t len, unsigned long prot) | |||
239 | end = start + len; | 239 | end = start + len; |
240 | if (end <= start) | 240 | if (end <= start) |
241 | return -ENOMEM; | 241 | return -ENOMEM; |
242 | if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM)) | 242 | if (!arch_validate_prot(prot)) |
243 | return -EINVAL; | 243 | return -EINVAL; |
244 | 244 | ||
245 | reqprot = prot; | 245 | reqprot = prot; |