Skip to content

Instantly share code, notes, and snippets.

@zhangyoufu
Last active December 8, 2023 04:49
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save zhangyoufu/86910448ec92c7eca7e39186b79c98c2 to your computer and use it in GitHub Desktop.
The architecture-specific signal handling code may adjust RIP/RAX to restart interrupted syscall. Address set be tracer via PTRACE_SETREGS may be decreased by 2 bytes unexpectedly on i386/x86-64. To workaround this behavior, tracer have to check whether tracee is in system call and whether the errno indicates restartable.
(gdb) set $rip=0xdeadbeef
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x00000000deadbeed in ?? ()
=> 0x00000000deadbeed:
Cannot access memory at address 0xdeadbeed
// arch/x86/kernel/signal.c, arch_do_signal_or_restart
/* Did we come from a system call? */
if (syscall_get_nr(current, regs) != -1) {
/* Restart the system call - no handlers present */
switch (syscall_get_error(current, regs)) {
case -ERESTARTNOHAND:
case -ERESTARTSYS:
case -ERESTARTNOINTR:
regs->ax = regs->orig_ax;
regs->ip -= 2;
break;
case -ERESTART_RESTARTBLOCK:
regs->ax = get_nr_restart_syscall(regs);
regs->ip -= 2;
break;
}
}
// from linux/errno.h, unfortunately they does not belong to uapi
#define ERESTARTSYS 512
#define ERESTARTNOINTR 513
#define ERESTARTNOHAND 514
#define ERESTART_RESTARTBLOCK 516
ptrace(PTRACE_ATTACH, pid, NULL, NULL);
waitpid(pid, NULL, 0);
// PTRACE_POKETEXT as you wish
ptrace(PTRACE_GETREGS, pid, NULL, &regs);
regs.rip = EXPECTED_RIP_AFTER_CONTINUE;
if (regs.orig_rax != -1) {
// tracee stopped in system call
switch (regs.rax) { // errno
case -ERESTARTNOHAND:
case -ERESTARTSYS:
case -ERESTARTNOINTR:
case -ERESTART_RESTARTBLOCK:
// balance the decrease in arch_do_signal_or_restart
regs.rip += 2; // either syscall (0F 05) or int 80h (CD 80)
default:
// do nothing
}
}
ptrace(PTRACE_SETREGS, pid, NULL, &regs);
ptrace(PTRACE_DETACH, pid, NULL, NULL); // suppress SIGSTOP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment