| From 39680f50ae54cbbb6e72ac38b8329dd3eb9105f4 Mon Sep 17 00:00:00 2001 |
| From: Linus Torvalds <torvalds@linux-foundation.org> |
| Date: Tue, 1 Mar 2016 11:56:22 -0800 |
| Subject: userfaultfd: don't block on the last VM updates at exit time |
| |
| From: Linus Torvalds <torvalds@linux-foundation.org> |
| |
| commit 39680f50ae54cbbb6e72ac38b8329dd3eb9105f4 upstream. |
| |
| The exit path will do some final updates to the VM of an exiting process |
| to inform others of the fact that the process is going away. |
| |
| That happens, for example, for robust futex state cleanup, but also if |
| the parent has asked for a TID update when the process exits (we clear |
| the child tid field in user space). |
| |
| However, at the time we do those final VM accesses, we've already |
| stopped accepting signals, so the usual "stop waiting for userfaults on |
| signal" code in fs/userfaultfd.c no longer works, and the process can |
| become an unkillable zombie waiting for something that will never |
| happen. |
| |
| To solve this, just make handle_userfault() abort any user fault |
| handling if we're already in the exit path past the signal handling |
| state being dead (marked by PF_EXITING). |
| |
| This VM special case is pretty ugly, and it is possible that we should |
| look at finalizing signals later (or move the VM final accesses |
| earlier). But in the meantime this is a fairly minimally intrusive fix. |
| |
| Reported-and-tested-by: Dmitry Vyukov <dvyukov@google.com> |
| Acked-by: Andrea Arcangeli <aarcange@redhat.com> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Cc: Sedat Dilek <sedat.dilek@gmail.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/userfaultfd.c | 6 ++++++ |
| 1 file changed, 6 insertions(+) |
| |
| --- a/fs/userfaultfd.c |
| +++ b/fs/userfaultfd.c |
| @@ -287,6 +287,12 @@ int handle_userfault(struct vm_area_stru |
| goto out; |
| |
| /* |
| + * We don't do userfault handling for the final child pid update. |
| + */ |
| + if (current->flags & PF_EXITING) |
| + goto out; |
| + |
| + /* |
| * Check that we can return VM_FAULT_RETRY. |
| * |
| * NOTE: it should become possible to return VM_FAULT_RETRY |