ptrace.2: BUGS: ptrace() may set errno to zero

ptrace() with requests PTRACE_PEEKTEXT, PTRACE_PEEKDATA and
PTRACE_PEEKUSER can set errno to zero. AFAICS this is for a good
reason (so that you can tell the difference between a successful
PEEK with a result of -1 and a failed PEEK, even if you forget to
clear errno yourself), but it technically violates the rules
described in the errno.3 manpage.

glibc snippet from sysdeps/unix/sysv/linux/ptrace.c:

  res = INLINE_SYSCALL (ptrace, 4, request, pid, addr, data);
  if (res >= 0 && request > 0 && request < 4)
    {
      __set_errno (0);
      return ret;
    }

reproducer:

$ cat ptrace_test.c
char foobar_data[4] = "ABCD";
int main(void) {
  pid_t child = fork();
  if (child == -1) err(1, "fork");
  if (child == 0) {
    if (prctl(PR_SET_PDEATHSIG, SIGKILL)) err(1, "prctl");
    while (1) sleep(1);
  }
  int status;
  if (ptrace(PTRACE_ATTACH, child, NULL, NULL)) err(1, "attach");
  if (waitpid(child, &status, 0) != child) err(1, "wait");
  errno = EINVAL;
  unsigned int res = ptrace(PTRACE_PEEKDATA, child, foobar_data, NULL);
  printf("errno after PEEKDATA: %d\n", errno);
  printf("PEEKDATA result: 0x%x\n", res);
}
$ gcc -o ptrace_test ptrace_test.c -Wall
$ ./ptrace_test
errno after PEEKDATA: 0
PEEKDATA result: 0x44434241

Signed-off-by: Jann Horn <jannh@google.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
This commit is contained in:
Jann Horn 2018-06-22 17:44:41 +02:00 committed by Michael Kerrisk
parent d6868c69b3
commit c62b945324
1 changed files with 6 additions and 0 deletions

View File

@ -2777,6 +2777,12 @@ again.
errors may behave in an unintended way upon an
.BR strace (1)
attach.)
.PP
Contrary to the normal rules, the glibc wrapper for
.BR ptrace ()
can set
.I errno
to zero.
.SH SEE ALSO
.BR gdb (1),
.BR ltrace (1),