summaryrefslogtreecommitdiff
path: root/arch/um/kernel
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2021-01-13 22:08:03 +0100
committerRichard Weinberger <richard@nod.at>2021-02-12 21:32:04 +0100
commita7d48886cacf8b426e0079bca9639d2657cf2d38 (patch)
treeba45b820c900f3bd2f93a37d78bb77be3f93a106 /arch/um/kernel
parent47da29763ec9a153b9b685bff9db659e4e09e494 (diff)
um: defer killing userspace on page table update failures
In some cases we can get to fix_range_common() with mmap_sem held, and in others we get there without it being held. For example, we get there with it held from sys_mprotect(), and without it held from fork_handler(). Avoid any issues in this and simply defer killing the task until it runs the next time. Do it on the mm so that another task that shares the same mm can't continue running afterwards. Cc: stable@vger.kernel.org Fixes: 468f65976a8d ("um: Fix hung task in fix_range_common()") Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'arch/um/kernel')
-rw-r--r--arch/um/kernel/tlb.c7
1 files changed, 3 insertions, 4 deletions
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index 89468da6bf88..5be1b0da9f3b 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -352,12 +352,11 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
/* This is not an else because ret is modified above */
if (ret) {
+ struct mm_id *mm_idp = &current->mm->context.id;
+
printk(KERN_ERR "fix_range_common: failed, killing current "
"process: %d\n", task_tgid_vnr(current));
- /* We are under mmap_lock, release it such that current can terminate */
- mmap_write_unlock(current->mm);
- force_sig(SIGKILL);
- do_signal(&current->thread.regs);
+ mm_idp->kill = 1;
}
}