Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b845f313 authored by Dave Kleikamp's avatar Dave Kleikamp Committed by Benjamin Herrenschmidt
Browse files

mm: Allow architectures to define additional protection bits



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: default avatarDave Kleikamp <shaggy@linux.vnet.ibm.com>
Acked-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Acked-by: default avatarHugh Dickins <hugh@veritas.com>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent e5093ff0
Loading
Loading
Loading
Loading
+28 −1
Original line number Diff line number Diff line
@@ -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
@@ -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);
}

/*
+3 −2
Original line number Diff line number Diff line
@@ -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);

+1 −1
Original line number Diff line number Diff line
@@ -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;