Skip to content

Commit da780c4

Browse files
benzeagregkh
authored andcommitted
um: work around sched_yield not yielding in time-travel mode
[ Upstream commit 887c5c1 ] sched_yield by a userspace may not actually cause scheduling in time-travel mode as no time has passed. In the case seen it appears to be a badly implemented userspace spinlock in ASAN. Unfortunately, with time-travel it causes an extreme slowdown or even deadlock depending on the kernel configuration (CONFIG_UML_MAX_USERSPACE_ITERATIONS). Work around it by accounting time to the process whenever it executes a sched_yield syscall. Signed-off-by: Benjamin Berg <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Johannes Berg <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 0a205fd commit da780c4

File tree

2 files changed

+13
-0
lines changed

2 files changed

+13
-0
lines changed

arch/um/include/linux/time-internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ extern void time_travel_not_configured(void);
8383
#define time_travel_del_event(...) time_travel_not_configured()
8484
#endif /* CONFIG_UML_TIME_TRAVEL_SUPPORT */
8585

86+
extern unsigned long tt_extra_sched_jiffies;
87+
8688
/*
8789
* Without CONFIG_UML_TIME_TRAVEL_SUPPORT this is a linker error if used,
8890
* which is intentional since we really shouldn't link it in that case.

arch/um/kernel/skas/syscall.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@ void handle_syscall(struct uml_pt_regs *r)
3131
goto out;
3232

3333
syscall = UPT_SYSCALL_NR(r);
34+
35+
/*
36+
* If no time passes, then sched_yield may not actually yield, causing
37+
* broken spinlock implementations in userspace (ASAN) to hang for long
38+
* periods of time.
39+
*/
40+
if ((time_travel_mode == TT_MODE_INFCPU ||
41+
time_travel_mode == TT_MODE_EXTERNAL) &&
42+
syscall == __NR_sched_yield)
43+
tt_extra_sched_jiffies += 1;
44+
3445
if (syscall >= 0 && syscall < __NR_syscalls) {
3546
unsigned long ret = EXECUTE_SYSCALL(syscall, regs);
3647

0 commit comments

Comments
 (0)