Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e40cd10c authored by Aurelien Jarno's avatar Aurelien Jarno Committed by Ingo Molnar
Browse files

x86: clear DF before calling signal handler



The Linux kernel currently does not clear the direction flag before
calling a signal handler, whereas the x86/x86-64 ABI requires that.

Linux had this behavior/bug forever, but this becomes a real problem
with gcc version 4.3, which assumes that the direction flag is
correctly cleared at the entry of a function.

This patches changes the setup_frame() functions to clear the
direction before entering the signal handler.

Signed-off-by: default avatarAurelien Jarno <aurelien@aurel32.net>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Acked-by: default avatarH. Peter Anvin <hpa@zytor.com>
parent ce4796d1
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -500,7 +500,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
	regs->ss = __USER32_DS;
	regs->ss = __USER32_DS;


	set_fs(USER_DS);
	set_fs(USER_DS);
	regs->flags &= ~X86_EFLAGS_TF;
	regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
	if (test_thread_flag(TIF_SINGLESTEP))
	if (test_thread_flag(TIF_SINGLESTEP))
		ptrace_notify(SIGTRAP);
		ptrace_notify(SIGTRAP);


@@ -600,7 +600,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
	regs->ss = __USER32_DS;
	regs->ss = __USER32_DS;


	set_fs(USER_DS);
	set_fs(USER_DS);
	regs->flags &= ~X86_EFLAGS_TF;
	regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
	if (test_thread_flag(TIF_SINGLESTEP))
	if (test_thread_flag(TIF_SINGLESTEP))
		ptrace_notify(SIGTRAP);
		ptrace_notify(SIGTRAP);


+2 −2
Original line number Original line Diff line number Diff line
@@ -407,7 +407,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
	 * The tracer may want to single-step inside the
	 * The tracer may want to single-step inside the
	 * handler too.
	 * handler too.
	 */
	 */
	regs->flags &= ~TF_MASK;
	regs->flags &= ~(TF_MASK | X86_EFLAGS_DF);
	if (test_thread_flag(TIF_SINGLESTEP))
	if (test_thread_flag(TIF_SINGLESTEP))
		ptrace_notify(SIGTRAP);
		ptrace_notify(SIGTRAP);


@@ -500,7 +500,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
	 * The tracer may want to single-step inside the
	 * The tracer may want to single-step inside the
	 * handler too.
	 * handler too.
	 */
	 */
	regs->flags &= ~TF_MASK;
	regs->flags &= ~(TF_MASK | X86_EFLAGS_DF);
	if (test_thread_flag(TIF_SINGLESTEP))
	if (test_thread_flag(TIF_SINGLESTEP))
		ptrace_notify(SIGTRAP);
		ptrace_notify(SIGTRAP);


+1 −1
Original line number Original line Diff line number Diff line
@@ -295,7 +295,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
	   see include/asm-x86_64/uaccess.h for details. */
	   see include/asm-x86_64/uaccess.h for details. */
	set_fs(USER_DS);
	set_fs(USER_DS);


	regs->flags &= ~X86_EFLAGS_TF;
	regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
	if (test_thread_flag(TIF_SINGLESTEP))
	if (test_thread_flag(TIF_SINGLESTEP))
		ptrace_notify(SIGTRAP);
		ptrace_notify(SIGTRAP);
#ifdef DEBUG_SIG
#ifdef DEBUG_SIG