|
@@ -352,8 +352,11 @@ fail:
|
|
|
return error;
|
|
return error;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-SYSCALL_DEFINE3(mprotect, unsigned long, start, size_t, len,
|
|
|
|
|
- unsigned long, prot)
|
|
|
|
|
|
|
+/*
|
|
|
|
|
+ * pkey==-1 when doing a legacy mprotect()
|
|
|
|
|
+ */
|
|
|
|
|
+static int do_mprotect_pkey(unsigned long start, size_t len,
|
|
|
|
|
+ unsigned long prot, int pkey)
|
|
|
{
|
|
{
|
|
|
unsigned long nstart, end, tmp, reqprot;
|
|
unsigned long nstart, end, tmp, reqprot;
|
|
|
struct vm_area_struct *vma, *prev;
|
|
struct vm_area_struct *vma, *prev;
|
|
@@ -361,6 +364,12 @@ SYSCALL_DEFINE3(mprotect, unsigned long, start, size_t, len,
|
|
|
const int grows = prot & (PROT_GROWSDOWN|PROT_GROWSUP);
|
|
const int grows = prot & (PROT_GROWSDOWN|PROT_GROWSUP);
|
|
|
const bool rier = (current->personality & READ_IMPLIES_EXEC) &&
|
|
const bool rier = (current->personality & READ_IMPLIES_EXEC) &&
|
|
|
(prot & PROT_READ);
|
|
(prot & PROT_READ);
|
|
|
|
|
+ /*
|
|
|
|
|
+ * A temporary safety check since we are not validating
|
|
|
|
|
+ * the pkey before we introduce the allocation code.
|
|
|
|
|
+ */
|
|
|
|
|
+ if (pkey != -1)
|
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
|
|
prot &= ~(PROT_GROWSDOWN|PROT_GROWSUP);
|
|
prot &= ~(PROT_GROWSDOWN|PROT_GROWSUP);
|
|
|
if (grows == (PROT_GROWSDOWN|PROT_GROWSUP)) /* can't be both */
|
|
if (grows == (PROT_GROWSDOWN|PROT_GROWSUP)) /* can't be both */
|
|
@@ -409,7 +418,7 @@ SYSCALL_DEFINE3(mprotect, unsigned long, start, size_t, len,
|
|
|
|
|
|
|
|
for (nstart = start ; ; ) {
|
|
for (nstart = start ; ; ) {
|
|
|
unsigned long newflags;
|
|
unsigned long newflags;
|
|
|
- int pkey = arch_override_mprotect_pkey(vma, prot, -1);
|
|
|
|
|
|
|
+ int new_vma_pkey;
|
|
|
|
|
|
|
|
/* Here we know that vma->vm_start <= nstart < vma->vm_end. */
|
|
/* Here we know that vma->vm_start <= nstart < vma->vm_end. */
|
|
|
|
|
|
|
@@ -417,7 +426,8 @@ SYSCALL_DEFINE3(mprotect, unsigned long, start, size_t, len,
|
|
|
if (rier && (vma->vm_flags & VM_MAYEXEC))
|
|
if (rier && (vma->vm_flags & VM_MAYEXEC))
|
|
|
prot |= PROT_EXEC;
|
|
prot |= PROT_EXEC;
|
|
|
|
|
|
|
|
- newflags = calc_vm_prot_bits(prot, pkey);
|
|
|
|
|
|
|
+ new_vma_pkey = arch_override_mprotect_pkey(vma, prot, pkey);
|
|
|
|
|
+ newflags = calc_vm_prot_bits(prot, new_vma_pkey);
|
|
|
newflags |= (vma->vm_flags & ~(VM_READ | VM_WRITE | VM_EXEC));
|
|
newflags |= (vma->vm_flags & ~(VM_READ | VM_WRITE | VM_EXEC));
|
|
|
|
|
|
|
|
/* newflags >> 4 shift VM_MAY% in place of VM_% */
|
|
/* newflags >> 4 shift VM_MAY% in place of VM_% */
|
|
@@ -454,3 +464,15 @@ out:
|
|
|
up_write(¤t->mm->mmap_sem);
|
|
up_write(¤t->mm->mmap_sem);
|
|
|
return error;
|
|
return error;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+SYSCALL_DEFINE3(mprotect, unsigned long, start, size_t, len,
|
|
|
|
|
+ unsigned long, prot)
|
|
|
|
|
+{
|
|
|
|
|
+ return do_mprotect_pkey(start, len, prot, -1);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+SYSCALL_DEFINE4(pkey_mprotect, unsigned long, start, size_t, len,
|
|
|
|
|
+ unsigned long, prot, int, pkey)
|
|
|
|
|
+{
|
|
|
|
|
+ return do_mprotect_pkey(start, len, prot, pkey);
|
|
|
|
|
+}
|