]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - fs/userfaultfd.c
mm/cgroup: avoid panic when init with low memory
[mirror_ubuntu-artful-kernel.git] / fs / userfaultfd.c
index 3c421d06a18e6ee1a7fde0d09030c9f7306cb989..dd48052e086f6de4092abde32c36a86125e4584d 100644 (file)
@@ -14,7 +14,8 @@
 
 #include <linux/list.h>
 #include <linux/hashtable.h>
-#include <linux/sched.h>
+#include <linux/sched/signal.h>
+#include <linux/sched/mm.h>
 #include <linux/mm.h>
 #include <linux/poll.h>
 #include <linux/slab.h>
@@ -489,7 +490,7 @@ int handle_userfault(struct vm_fault *vmf, unsigned long reason)
                         * in such case.
                         */
                        down_read(&mm->mmap_sem);
-                       ret = 0;
+                       ret = VM_FAULT_NOPAGE;
                }
        }
 
@@ -526,10 +527,11 @@ out:
        return ret;
 }
 
-static int userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx,
-                                            struct userfaultfd_wait_queue *ewq)
+static void userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx,
+                                             struct userfaultfd_wait_queue *ewq)
 {
-       int ret = 0;
+       if (WARN_ON_ONCE(current->flags & PF_EXITING))
+               goto out;
 
        ewq->ctx = ctx;
        init_waitqueue_entry(&ewq->wq, current);
@@ -546,7 +548,6 @@ static int userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx,
                        break;
                if (ACCESS_ONCE(ctx->released) ||
                    fatal_signal_pending(current)) {
-                       ret = -1;
                        __remove_wait_queue(&ctx->event_wqh, &ewq->wq);
                        break;
                }
@@ -565,9 +566,8 @@ static int userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx,
         * ctx may go away after this if the userfault pseudo fd is
         * already released.
         */
-
+out:
        userfaultfd_ctx_put(ctx);
-       return ret;
 }
 
 static void userfaultfd_event_complete(struct userfaultfd_ctx *ctx,
@@ -625,7 +625,7 @@ int dup_userfaultfd(struct vm_area_struct *vma, struct list_head *fcs)
        return 0;
 }
 
-static int dup_fctx(struct userfaultfd_fork_ctx *fctx)
+static void dup_fctx(struct userfaultfd_fork_ctx *fctx)
 {
        struct userfaultfd_ctx *ctx = fctx->orig;
        struct userfaultfd_wait_queue ewq;
@@ -635,17 +635,15 @@ static int dup_fctx(struct userfaultfd_fork_ctx *fctx)
        ewq.msg.event = UFFD_EVENT_FORK;
        ewq.msg.arg.reserved.reserved1 = (unsigned long)fctx->new;
 
-       return userfaultfd_event_wait_completion(ctx, &ewq);
+       userfaultfd_event_wait_completion(ctx, &ewq);
 }
 
 void dup_userfaultfd_complete(struct list_head *fcs)
 {
-       int ret = 0;
        struct userfaultfd_fork_ctx *fctx, *n;
 
        list_for_each_entry_safe(fctx, n, fcs, list) {
-               if (!ret)
-                       ret = dup_fctx(fctx);
+               dup_fctx(fctx);
                list_del(&fctx->list);
                kfree(fctx);
        }
@@ -774,34 +772,6 @@ void userfaultfd_unmap_complete(struct mm_struct *mm, struct list_head *uf)
        }
 }
 
-void userfaultfd_exit(struct mm_struct *mm)
-{
-       struct vm_area_struct *vma = mm->mmap;
-
-       /*
-        * We can do the vma walk without locking because the caller
-        * (exit_mm) knows it now has exclusive access
-        */
-       while (vma) {
-               struct userfaultfd_ctx *ctx = vma->vm_userfaultfd_ctx.ctx;
-
-               if (ctx && (ctx->features & UFFD_FEATURE_EVENT_EXIT)) {
-                       struct userfaultfd_wait_queue ewq;
-
-                       userfaultfd_ctx_get(ctx);
-
-                       msg_init(&ewq.msg);
-                       ewq.msg.event = UFFD_EVENT_EXIT;
-
-                       userfaultfd_event_wait_completion(ctx, &ewq);
-
-                       ctx->features &= ~UFFD_FEATURE_EVENT_EXIT;
-               }
-
-               vma = vma->vm_next;
-       }
-}
-
 static int userfaultfd_release(struct inode *inode, struct file *file)
 {
        struct userfaultfd_ctx *ctx = file->private_data;