stmmac: fix ptp init for gmac4
[cascardo/linux.git] / mm / mprotect.c
index abd9c82..bcdbe62 100644 (file)
 #include <linux/mmu_notifier.h>
 #include <linux/migrate.h>
 #include <linux/perf_event.h>
+#include <linux/pkeys.h>
 #include <linux/ksm.h>
 #include <linux/pkeys.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/cacheflush.h>
+#include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
 
 #include "internal.h"
@@ -304,6 +306,7 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
                           vma->vm_userfaultfd_ctx);
        if (*pprev) {
                vma = *pprev;
+               VM_WARN_ON((vma->vm_flags ^ newflags) & ~VM_SOFTDIRTY);
                goto success;
        }
 
@@ -327,7 +330,7 @@ success:
         * held in write mode.
         */
        vma->vm_flags = newflags;
-       dirty_accountable = vma_wants_writenotify(vma);
+       dirty_accountable = vma_wants_writenotify(vma, vma->vm_page_prot);
        vma_set_page_prot(vma);
 
        change_protection(vma, start, end, vma->vm_page_prot,
@@ -364,12 +367,6 @@ static int do_mprotect_pkey(unsigned long start, size_t len,
        const int grows = prot & (PROT_GROWSDOWN|PROT_GROWSUP);
        const bool rier = (current->personality & READ_IMPLIES_EXEC) &&
                                (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);
        if (grows == (PROT_GROWSDOWN|PROT_GROWSUP)) /* can't be both */
@@ -391,6 +388,14 @@ static int do_mprotect_pkey(unsigned long start, size_t len,
        if (down_write_killable(&current->mm->mmap_sem))
                return -EINTR;
 
+       /*
+        * If userspace did not allocate the pkey, do not let
+        * them use it here.
+        */
+       error = -EINVAL;
+       if ((pkey != -1) && !mm_pkey_is_allocated(current->mm, pkey))
+               goto out;
+
        vma = find_vma(current->mm, start);
        error = -ENOMEM;
        if (!vma)
@@ -485,3 +490,48 @@ SYSCALL_DEFINE4(pkey_mprotect, unsigned long, start, size_t, len,
 {
        return do_mprotect_pkey(start, len, prot, pkey);
 }
+
+SYSCALL_DEFINE2(pkey_alloc, unsigned long, flags, unsigned long, init_val)
+{
+       int pkey;
+       int ret;
+
+       /* No flags supported yet. */
+       if (flags)
+               return -EINVAL;
+       /* check for unsupported init values */
+       if (init_val & ~PKEY_ACCESS_MASK)
+               return -EINVAL;
+
+       down_write(&current->mm->mmap_sem);
+       pkey = mm_pkey_alloc(current->mm);
+
+       ret = -ENOSPC;
+       if (pkey == -1)
+               goto out;
+
+       ret = arch_set_user_pkey_access(current, pkey, init_val);
+       if (ret) {
+               mm_pkey_free(current->mm, pkey);
+               goto out;
+       }
+       ret = pkey;
+out:
+       up_write(&current->mm->mmap_sem);
+       return ret;
+}
+
+SYSCALL_DEFINE1(pkey_free, int, pkey)
+{
+       int ret;
+
+       down_write(&current->mm->mmap_sem);
+       ret = mm_pkey_free(current->mm, pkey);
+       up_write(&current->mm->mmap_sem);
+
+       /*
+        * We could provie warnings or errors if any VMA still
+        * has the pkey set here.
+        */
+       return ret;
+}