aboutsummaryrefslogtreecommitdiff
path: root/arch/um/os-Linux
diff options
context:
space:
mode:
authorGravatar Johannes Berg <johannes.berg@intel.com> 2021-01-13 22:08:03 +0100
committerGravatar Richard Weinberger <richard@nod.at> 2021-02-12 21:32:04 +0100
commita7d48886cacf8b426e0079bca9639d2657cf2d38 (patch)
treeba45b820c900f3bd2f93a37d78bb77be3f93a106 /arch/um/os-Linux
parentum: mm: check more comprehensively for stub changes (diff)
downloadlinux-a7d48886cacf8b426e0079bca9639d2657cf2d38.tar.gz
linux-a7d48886cacf8b426e0079bca9639d2657cf2d38.tar.bz2
linux-a7d48886cacf8b426e0079bca9639d2657cf2d38.zip
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/os-Linux')
-rw-r--r--arch/um/os-Linux/skas/process.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index ed4bbffe8d7a..d910e25c273e 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -300,6 +300,7 @@ static int userspace_tramp(void *stack)
}
int userspace_pid[NR_CPUS];
+int kill_userspace_mm[NR_CPUS];
/**
* start_userspace() - prepare a new userspace process
@@ -393,6 +394,8 @@ void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
interrupt_end();
while (1) {
+ if (kill_userspace_mm[0])
+ fatal_sigsegv();
/*
* This can legitimately fail if the process loads a
@@ -714,4 +717,5 @@ void reboot_skas(void)
void __switch_mm(struct mm_id *mm_idp)
{
userspace_pid[0] = mm_idp->u.pid;
+ kill_userspace_mm[0] = mm_idp->kill;
}