Merge tag 'pinctrl-v5.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw...
[linux-2.6-microblaze.git] / fs / userfaultfd.c
index 000b457..894cc28 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/security.h>
 #include <linux/hugetlb.h>
 
-int sysctl_unprivileged_userfaultfd __read_mostly = 1;
+int sysctl_unprivileged_userfaultfd __read_mostly;
 
 static struct kmem_cache *userfaultfd_ctx_cachep __read_mostly;
 
@@ -405,6 +405,13 @@ vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason)
 
        if (ctx->features & UFFD_FEATURE_SIGBUS)
                goto out;
+       if ((vmf->flags & FAULT_FLAG_USER) == 0 &&
+           ctx->flags & UFFD_USER_MODE_ONLY) {
+               printk_once(KERN_WARNING "uffd: Set unprivileged_userfaultfd "
+                       "sysctl knob to 1 if kernel faults must be handled "
+                       "without obtaining CAP_SYS_PTRACE capability\n");
+               goto out;
+       }
 
        /*
         * If it's already released don't get it. This avoids to loop
@@ -1959,16 +1966,23 @@ SYSCALL_DEFINE1(userfaultfd, int, flags)
        struct userfaultfd_ctx *ctx;
        int fd;
 
-       if (!sysctl_unprivileged_userfaultfd && !capable(CAP_SYS_PTRACE))
+       if (!sysctl_unprivileged_userfaultfd &&
+           (flags & UFFD_USER_MODE_ONLY) == 0 &&
+           !capable(CAP_SYS_PTRACE)) {
+               printk_once(KERN_WARNING "uffd: Set unprivileged_userfaultfd "
+                       "sysctl knob to 1 if kernel faults must be handled "
+                       "without obtaining CAP_SYS_PTRACE capability\n");
                return -EPERM;
+       }
 
        BUG_ON(!current->mm);
 
        /* Check the UFFD_* constants for consistency.  */
+       BUILD_BUG_ON(UFFD_USER_MODE_ONLY & UFFD_SHARED_FCNTL_FLAGS);
        BUILD_BUG_ON(UFFD_CLOEXEC != O_CLOEXEC);
        BUILD_BUG_ON(UFFD_NONBLOCK != O_NONBLOCK);
 
-       if (flags & ~UFFD_SHARED_FCNTL_FLAGS)
+       if (flags & ~(UFFD_SHARED_FCNTL_FLAGS | UFFD_USER_MODE_ONLY))
                return -EINVAL;
 
        ctx = kmem_cache_alloc(userfaultfd_ctx_cachep, GFP_KERNEL);