x86: Memory Protection Keys (v10)

Started by Dave Hansen on Feb 12, 2016 · 3 messages from 2 authors · Last reply Feb 16, 2016

Series

33 patches, 81 files

+1,426 −269

Subsystems (42)

Show 39 more

Maintainers (67)

Show 63 more
STALE3922d PENDING · 32 of 33 landed

Status: Pending, 32 of 33 landed.

open the first message on its own page

  1. [PATCH 27/33] mm, multi-arch: pass a protection key in to calc_vm_flag_bits()
    Related patches
Message details and related content
Memory Protection Keys for User pages is a CPU feature which will
first appear on Skylake Servers, but will also be supported on
future non-server parts (there is also a QEMU implementation).  It
provides a mechanism for enforcing page-based protections, but
without requiring modification of the page tables when an
application changes wishes to change permissions.

This set introduces supported limited to:
1. Allows "execute-only" memory
2. Enables KVM to run Protection-Key-enabled guests

This set contains the vast majority of of the code, with the
small but tricky explicit user interface parts left off.  We can
have a more focused review on those at a later time in a (much
smaller) follow-on series.

Changes from v9:
 * Added macros to allow some source-level backward compatability
   between the old-style get_user_pages*() calls taking tsk/mm and
   the new-style which assumes the current tsk/mm.
 * renamed the new gup variant to get_user_pages_remote() instead
   of get_user_pages_foreign()
 * rebased against 4.5-rc3

Changes from v8:
 * Reorganization of get_user_pages() patch with awesome feedback
   from Vlastimil Babka and suggestions from Jan Kara.
 * fix EXPORT_SYMBOL() and use get_current_user_page() in nommu.c

Changes from v7:
 * Fixed merge issue with cpu feature bitmap definitions
 * Fixed up some comments in get_user_pages() and smaps patches
   (thanks Vlastimil!)

Changes from v6:
 * fix up ??'s showing up in in smaps' VmFlags field
 * added execute-only support
 * removed all the new syscalls from this set.  We can discuss
   them in detail after this is merged.

203 more lines

[PATCH 27/33] mm, multi-arch: pass a protection key in to calc_vm_flag_bits()

Message details and related content
From: Dave Hansen <dave.hansen@linux.intel.com>

This plumbs a protection key through calc_vm_flag_bits().  We
could have done this in calc_vm_prot_bits(), but I did not feel
super strongly which way to go.  It was pretty arbitrary which
one to use.

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Cc: <redacted>
Cc: <redacted>
---

 b/arch/powerpc/include/asm/mman.h  |    5 +++--
 b/drivers/char/agp/frontend.c      |    2 +-
 b/drivers/staging/android/ashmem.c |    4 ++--
 b/include/linux/mman.h             |    6 +++---
 b/mm/mmap.c                        |    2 +-
 b/mm/mprotect.c                    |    2 +-
 b/mm/nommu.c                       |    2 +-
 7 files changed, 12 insertions(+), 11 deletions(-)

diff -puN arch/powerpc/include/asm/mman.h~pkeys-70-calc_vm_prot_bits arch/powerpc/include/asm/mman.h
--- a/arch/powerpc/include/asm/mman.h~pkeys-70-calc_vm_prot_bits	2016-02-12 10:44:25.996692997 -0800
+++ b/arch/powerpc/include/asm/mman.h	2016-02-12 10:44:26.009693591 -0800
@@ -18,11 +18,12 @@
  * This file is included by linux/mman.h, so we can't use cacl_vm_prot_bits()
  * here.  How important is the optimization?
  */
-static inline unsigned long arch_calc_vm_prot_bits(unsigned long prot)
+static inline unsigned long arch_calc_vm_prot_bits(unsigned long prot,
+		unsigned long pkey)
 {
 	return (prot & PROT_SAO) ? VM_SAO : 0;
 }
-#define arch_calc_vm_prot_bits(prot) arch_calc_vm_prot_bits(prot)
+#define arch_calc_vm_prot_bits(prot, pkey) arch_calc_vm_prot_bits(prot, pkey)
 
 static inline pgprot_t arch_vm_get_page_prot(unsigned long vm_flags)
 {
diff -puN drivers/char/agp/frontend.c~pkeys-70-calc_vm_prot_bits drivers/char/agp/frontend.c
--- a/drivers/char/agp/frontend.c~pkeys-70-calc_vm_prot_bits	2016-02-12 10:44:25.998693088 -0800
+++ b/drivers/char/agp/frontend.c	2016-02-12 10:44:26.009693591 -0800
@@ -156,7 +156,7 @@ static pgprot_t agp_convert_mmap_flags(i
 {
 	unsigned long prot_bits;
 
-	prot_bits = calc_vm_prot_bits(prot) | VM_SHARED;
+	prot_bits = calc_vm_prot_bits(prot, 0) | VM_SHARED;
 	return vm_get_page_prot(prot_bits);
 }
 
diff -puN drivers/staging/android/ashmem.c~pkeys-70-calc_vm_prot_bits drivers/staging/android/ashmem.c
--- a/drivers/staging/android/ashmem.c~pkeys-70-calc_vm_prot_bits	2016-02-12 10:44:25.999693134 -0800
+++ b/drivers/staging/android/ashmem.c	2016-02-12 10:44:26.010693636 -0800
@@ -372,8 +372,8 @@ static int ashmem_mmap(struct file *file
 	}
 
 	/* requested protection bits must match our allowed protection mask */
-	if (unlikely((vma->vm_flags & ~calc_vm_prot_bits(asma->prot_mask)) &
-		     calc_vm_prot_bits(PROT_MASK))) {
+	if (unlikely((vma->vm_flags & ~calc_vm_prot_bits(asma->prot_mask, 0)) &
+		     calc_vm_prot_bits(PROT_MASK, 0))) {
 		ret = -EPERM;
 		goto out;
 	}
diff -puN include/linux/mman.h~pkeys-70-calc_vm_prot_bits include/linux/mman.h
--- a/include/linux/mman.h~pkeys-70-calc_vm_prot_bits	2016-02-12 10:44:26.001693225 -0800
+++ b/include/linux/mman.h	2016-02-12 10:44:26.010693636 -0800
@@ -35,7 +35,7 @@ static inline void vm_unacct_memory(long
  */
 
 #ifndef arch_calc_vm_prot_bits
-#define arch_calc_vm_prot_bits(prot) 0
+#define arch_calc_vm_prot_bits(prot, pkey) 0
 #endif
 
 #ifndef arch_vm_get_page_prot
@@ -70,12 +70,12 @@ static inline int arch_validate_prot(uns
  * Combine the mmap "prot" argument into "vm_flags" used internally.
  */
 static inline unsigned long
-calc_vm_prot_bits(unsigned long prot)
+calc_vm_prot_bits(unsigned long prot, unsigned long pkey)
 {
 	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) |
-	       arch_calc_vm_prot_bits(prot);
+	       arch_calc_vm_prot_bits(prot, pkey);
 }
 
 /*
diff -puN mm/mmap.c~pkeys-70-calc_vm_prot_bits mm/mmap.c
--- a/mm/mmap.c~pkeys-70-calc_vm_prot_bits	2016-02-12 10:44:26.002693271 -0800
+++ b/mm/mmap.c	2016-02-12 10:44:26.011693682 -0800
@@ -1313,7 +1313,7 @@ unsigned long do_mmap(struct file *file,
 	 * to. we assume access permissions have been handled by the open
 	 * of the memory object, so we don't do any here.
 	 */
-	vm_flags |= calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags) |
+	vm_flags |= calc_vm_prot_bits(prot, 0) | calc_vm_flag_bits(flags) |
 			mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
 
 	if (flags & MAP_LOCKED)
diff -puN mm/mprotect.c~pkeys-70-calc_vm_prot_bits mm/mprotect.c
--- a/mm/mprotect.c~pkeys-70-calc_vm_prot_bits	2016-02-12 10:44:26.004693362 -0800
+++ b/mm/mprotect.c	2016-02-12 10:44:26.012693728 -0800
@@ -378,7 +378,7 @@ SYSCALL_DEFINE3(mprotect, unsigned long,
 	if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
 		prot |= PROT_EXEC;
 
-	vm_flags = calc_vm_prot_bits(prot);
+	vm_flags = calc_vm_prot_bits(prot, 0);
 
 	down_write(&current->mm->mmap_sem);
 
diff -puN mm/nommu.c~pkeys-70-calc_vm_prot_bits mm/nommu.c
--- a/mm/nommu.c~pkeys-70-calc_vm_prot_bits	2016-02-12 10:44:26.006693454 -0800
+++ b/mm/nommu.c	2016-02-12 10:44:26.012693728 -0800
@@ -1082,7 +1082,7 @@ static unsigned long determine_vm_flags(
 {
 	unsigned long vm_flags;
 
-	vm_flags = calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags);
+	vm_flags = calc_vm_prot_bits(prot, 0) | calc_vm_flag_bits(flags);
 	/* vm_flags |= mm->def_flags; */
 
 	if (!(capabilities & NOMMU_MAP_DIRECT)) {
_

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
Message details and related content
* Dave Hansen [off-list ref] wrote:
 81 files changed, 1393 insertions(+), 233 deletions(-)
The MIPS defconfig cross-build failed for me - log attached below.

Thanks,

	Ingo

===============>
  CC      security/keys/request_key_auth.o
In file included from /home/mingo/tip/arch/mips/include/asm/termios.h:12:0,
                 from /home/mingo/tip/include/uapi/linux/termios.h:5,
                 from /home/mingo/tip/include/linux/tty.h:6,
                 from /home/mingo/tip/kernel/signal.c:18:
/home/mingo/tip/kernel/signal.c: In function 'copy_siginfo_to_user':
/home/mingo/tip/include/uapi/asm-generic/siginfo.h:145:37: error: 'struct <anonymous>' has no member named '_pkey'
 #define si_pkey  _sifields._sigfault._pkey
                                     ^
/home/mingo/tip/arch/mips/include/asm/uaccess.h:441:15: note: in definition of macro '__put_user_nocheck'
  __typeof__(*(ptr)) __pu_val;     \
               ^
/home/mingo/tip/kernel/signal.c:2714:11: note: in expansion of macro '__put_user'
    err |= __put_user(from->si_pkey, &to->si_pkey);
           ^
/home/mingo/tip/kernel/signal.c:2714:42: note: in expansion of macro 'si_pkey'
    err |= __put_user(from->si_pkey, &to->si_pkey);
                                          ^
/home/mingo/tip/include/uapi/asm-generic/siginfo.h:145:37: error: 'const struct <anonymous>' has no member named '_pkey'
 #define si_pkey  _sifields._sigfault._pkey
                                     ^
/home/mingo/tip/arch/mips/include/asm/uaccess.h:444:14: note: in definition of macro '__put_user_nocheck'
  __pu_val = (x);       \
              ^
/home/mingo/tip/kernel/signal.c:2714:11: note: in expansion of macro '__put_user'
    err |= __put_user(from->si_pkey, &to->si_pkey);
           ^
/home/mingo/tip/kernel/signal.c:2714:28: note: in expansion of macro 'si_pkey'
    err |= __put_user(from->si_pkey, &to->si_pkey);
                            ^
/home/mingo/tip/include/uapi/asm-generic/siginfo.h:145:37: error: 'struct <anonymous>' has no member named '_pkey'
 #define si_pkey  _sifields._sigfault._pkey

587 more lines

Keyboard shortcuts
hback out one level
jnext message in thread / next series-diff position
kprevious message in thread / previous series-diff position
ldrill in
Escclose help / fold thread tree
?toggle this help