Skip to content

Commit a7d4888

Browse files
jmberg-intelrichardweinberger
authored andcommitted
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: 468f659 ("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>
1 parent 47da297 commit a7d4888

File tree

3 files changed

+8
-4
lines changed

3 files changed

+8
-4
lines changed

arch/um/include/shared/skas/mm_id.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ struct mm_id {
1212
int pid;
1313
} u;
1414
unsigned long stack;
15+
int kill;
1516
};
1617

1718
#endif

arch/um/kernel/tlb.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -352,12 +352,11 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
352352

353353
/* This is not an else because ret is modified above */
354354
if (ret) {
355+
struct mm_id *mm_idp = &current->mm->context.id;
356+
355357
printk(KERN_ERR "fix_range_common: failed, killing current "
356358
"process: %d\n", task_tgid_vnr(current));
357-
/* We are under mmap_lock, release it such that current can terminate */
358-
mmap_write_unlock(current->mm);
359-
force_sig(SIGKILL);
360-
do_signal(&current->thread.regs);
359+
mm_idp->kill = 1;
361360
}
362361
}
363362

arch/um/os-Linux/skas/process.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ static int userspace_tramp(void *stack)
300300
}
301301

302302
int userspace_pid[NR_CPUS];
303+
int kill_userspace_mm[NR_CPUS];
303304

304305
/**
305306
* start_userspace() - prepare a new userspace process
@@ -393,6 +394,8 @@ void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
393394
interrupt_end();
394395

395396
while (1) {
397+
if (kill_userspace_mm[0])
398+
fatal_sigsegv();
396399

397400
/*
398401
* This can legitimately fail if the process loads a
@@ -714,4 +717,5 @@ void reboot_skas(void)
714717
void __switch_mm(struct mm_id *mm_idp)
715718
{
716719
userspace_pid[0] = mm_idp->u.pid;
720+
kill_userspace_mm[0] = mm_idp->kill;
717721
}

0 commit comments

Comments
 (0)