Skip to content

Commit

Permalink
mm: Allow architectures to define additional protection bits
Browse files Browse the repository at this point in the history
This patch allows architectures to define functions to deal with
additional protections bits for mmap() and mprotect().

arch_calc_vm_prot_bits() maps additonal protection bits to vm_flags
arch_vm_get_page_prot() maps additional vm_flags to the vma's vm_page_prot
arch_validate_prot() checks for valid values of the protection bits

Note: vm_get_page_prot() is now pretty ugly, but the generated code
should be identical for architectures that don't define additional
protection bits.

Signed-off-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
Acked-by: Andrew Morton <akpm@linux-foundation.org>
Acked-by: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
  • Loading branch information
Dave Kleikamp authored and ozbenh committed Jul 9, 2008
1 parent e5093ff commit b845f31
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 4 deletions.
29 changes: 28 additions & 1 deletion include/linux/mman.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,32 @@ static inline void vm_unacct_memory(long pages)
vm_acct_memory(-pages);
}

/*
* Allow architectures to handle additional protection bits
*/

#ifndef arch_calc_vm_prot_bits
#define arch_calc_vm_prot_bits(prot) 0
#endif

#ifndef arch_vm_get_page_prot
#define arch_vm_get_page_prot(vm_flags) __pgprot(0)
#endif

#ifndef arch_validate_prot
/*
* This is called from mprotect(). PROT_GROWSDOWN and PROT_GROWSUP have
* already been masked out.
*
* Returns true if the prot flags are valid
*/
static inline int arch_validate_prot(unsigned long prot)
{
return (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM)) == 0;
}
#define arch_validate_prot arch_validate_prot
#endif

/*
* Optimisation macro. It is equivalent to:
* (x & bit1) ? bit2 : 0
Expand All @@ -51,7 +77,8 @@ calc_vm_prot_bits(unsigned long prot)
{
return _calc_vm_trans(prot, PROT_READ, VM_READ ) |
_calc_vm_trans(prot, PROT_WRITE, VM_WRITE) |
_calc_vm_trans(prot, PROT_EXEC, VM_EXEC );
_calc_vm_trans(prot, PROT_EXEC, VM_EXEC) |
arch_calc_vm_prot_bits(prot);
}

/*
Expand Down
5 changes: 3 additions & 2 deletions mm/mmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,9 @@ pgprot_t protection_map[16] = {

pgprot_t vm_get_page_prot(unsigned long vm_flags)
{
return protection_map[vm_flags &
(VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)];
return __pgprot(pgprot_val(protection_map[vm_flags &
(VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)]) |
pgprot_val(arch_vm_get_page_prot(vm_flags)));
}
EXPORT_SYMBOL(vm_get_page_prot);

Expand Down
2 changes: 1 addition & 1 deletion mm/mprotect.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ sys_mprotect(unsigned long start, size_t len, unsigned long prot)
end = start + len;
if (end <= start)
return -ENOMEM;
if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM))
if (!arch_validate_prot(prot))
return -EINVAL;

reqprot = prot;
Expand Down

0 comments on commit b845f31

Please sign in to comment.