Skip to content

Commit 6b5c804

Browse files
author
Al Viro
committed
arm: new way of handling ERESTART_RESTARTBLOCK
new "syscall start" flag; handled in syscall_trace() by switching syscall number to that of syscall_restart(2). Restarts of that kind (ERESTART_RESTARTBLOCK) are handled by setting that bit; syscall number is not modified until the actual call. Signed-off-by: Al Viro <[email protected]>
1 parent 21c1176 commit 6b5c804

File tree

3 files changed

+13
-28
lines changed

3 files changed

+13
-28
lines changed

arch/arm/include/asm/thread_info.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
148148
#define TIF_NOTIFY_RESUME 2 /* callback before returning to user */
149149
#define TIF_SYSCALL_TRACE 8
150150
#define TIF_SYSCALL_AUDIT 9
151+
#define TIF_SYSCALL_RESTARTSYS 10
151152
#define TIF_POLLING_NRFLAG 16
152153
#define TIF_USING_IWMMXT 17
153154
#define TIF_MEMDIE 18 /* is terminating due to OOM killer */
@@ -163,9 +164,11 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
163164
#define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)
164165
#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
165166
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
167+
#define _TIF_SYSCALL_RESTARTSYS (1 << TIF_SYSCALL_RESTARTSYS)
166168

167169
/* Checks for any syscall work in entry-common.S */
168-
#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT)
170+
#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
171+
_TIF_SYSCALL_RESTARTSYS)
169172

170173
/*
171174
* Change these and you break ASM code in entry-common.S

arch/arm/kernel/ptrace.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <linux/hw_breakpoint.h>
2525
#include <linux/regset.h>
2626
#include <linux/audit.h>
27+
#include <linux/unistd.h>
2728

2829
#include <asm/pgtable.h>
2930
#include <asm/traps.h>
@@ -916,6 +917,8 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
916917
audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0,
917918
regs->ARM_r1, regs->ARM_r2, regs->ARM_r3);
918919

920+
if (why == 0 && test_and_clear_thread_flag(TIF_SYSCALL_RESTARTSYS))
921+
scno = __NR_restart_syscall - __NR_SYSCALL_BASE;
919922
if (!test_thread_flag(TIF_SYSCALL_TRACE))
920923
return scno;
921924
if (!(current->ptrace & PT_PTRACED))

arch/arm/kernel/signal.c

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -624,12 +624,10 @@ static void do_signal(struct pt_regs *regs, int syscall)
624624
case -ERESTARTNOHAND:
625625
case -ERESTARTSYS:
626626
case -ERESTARTNOINTR:
627+
case -ERESTART_RESTARTBLOCK:
627628
regs->ARM_r0 = regs->ARM_ORIG_r0;
628629
regs->ARM_pc = restart_addr;
629630
break;
630-
case -ERESTART_RESTARTBLOCK:
631-
regs->ARM_r0 = -EINTR;
632-
break;
633631
}
634632
}
635633

@@ -647,12 +645,14 @@ static void do_signal(struct pt_regs *regs, int syscall)
647645
* debugger has chosen to restart at a different PC.
648646
*/
649647
if (regs->ARM_pc == restart_addr) {
650-
if (retval == -ERESTARTNOHAND
648+
if (retval == -ERESTARTNOHAND ||
649+
retval == -ERESTART_RESTARTBLOCK
651650
|| (retval == -ERESTARTSYS
652651
&& !(ka.sa.sa_flags & SA_RESTART))) {
653652
regs->ARM_r0 = -EINTR;
654653
regs->ARM_pc = continue_addr;
655654
}
655+
clear_thread_flag(TIF_SYSCALL_RESTARTSYS);
656656
}
657657

658658
if (test_thread_flag(TIF_RESTORE_SIGMASK))
@@ -679,29 +679,8 @@ static void do_signal(struct pt_regs *regs, int syscall)
679679
* ignore the restart.
680680
*/
681681
if (retval == -ERESTART_RESTARTBLOCK
682-
&& regs->ARM_pc == continue_addr) {
683-
if (thumb_mode(regs)) {
684-
regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE;
685-
regs->ARM_pc -= 2;
686-
} else {
687-
#if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT)
688-
regs->ARM_r7 = __NR_restart_syscall;
689-
regs->ARM_pc -= 4;
690-
#else
691-
u32 __user *usp;
692-
693-
regs->ARM_sp -= 4;
694-
usp = (u32 __user *)regs->ARM_sp;
695-
696-
if (put_user(regs->ARM_pc, usp) == 0) {
697-
regs->ARM_pc = KERN_RESTART_CODE;
698-
} else {
699-
regs->ARM_sp += 4;
700-
force_sigsegv(0, current);
701-
}
702-
#endif
703-
}
704-
}
682+
&& regs->ARM_pc == restart_addr)
683+
set_thread_flag(TIF_SYSCALL_RESTARTSYS);
705684
}
706685

707686
/* If there's no signal to deliver, we just put the saved sigmask

0 commit comments

Comments
 (0)