mirror of https://github.com/mkerrisk/man-pages
2279 lines
61 KiB
Groff
2279 lines
61 KiB
Groff
.\" Copyright (c) 1993 Michael Haardt <michael@moria.de>
|
|
.\" Fri Apr 2 11:32:09 MET DST 1993
|
|
.\"
|
|
.\" and changes Copyright (C) 1999 Mike Coleman (mkc@acm.org)
|
|
.\" -- major revision to fully document ptrace semantics per recent Linux
|
|
.\" kernel (2.2.10) and glibc (2.1.2)
|
|
.\" Sun Nov 7 03:18:35 CST 1999
|
|
.\"
|
|
.\" and Copyright (c) 2011, Denys Vlasenko <vda.linux@googlemail.com>
|
|
.\"
|
|
.\" %%%LICENSE_START(GPLv2+_DOC_FULL)
|
|
.\" This is free documentation; you can redistribute it and/or
|
|
.\" modify it under the terms of the GNU General Public License as
|
|
.\" published by the Free Software Foundation; either version 2 of
|
|
.\" the License, or (at your option) any later version.
|
|
.\"
|
|
.\" The GNU General Public License's references to "object code"
|
|
.\" and "executables" are to be interpreted as the output of any
|
|
.\" document formatting or typesetting system, including
|
|
.\" intermediate and printed output.
|
|
.\"
|
|
.\" This manual is distributed in the hope that it will be useful,
|
|
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
.\" GNU General Public License for more details.
|
|
.\"
|
|
.\" You should have received a copy of the GNU General Public
|
|
.\" License along with this manual; if not, see
|
|
.\" <http://www.gnu.org/licenses/>.
|
|
.\" %%%LICENSE_END
|
|
.\"
|
|
.\" Modified Fri Jul 23 23:47:18 1993 by Rik Faith <faith@cs.unc.edu>
|
|
.\" Modified Fri Jan 31 16:46:30 1997 by Eric S. Raymond <esr@thyrsus.com>
|
|
.\" Modified Thu Oct 7 17:28:49 1999 by Andries Brouwer <aeb@cwi.nl>
|
|
.\" Modified, 27 May 2004, Michael Kerrisk <mtk.manpages@gmail.com>
|
|
.\" Added notes on capability requirements
|
|
.\"
|
|
.\" 2006-03-24, Chuck Ebbert <76306.1226@compuserve.com>
|
|
.\" Added PTRACE_SETOPTIONS, PTRACE_GETEVENTMSG, PTRACE_GETSIGINFO,
|
|
.\" PTRACE_SETSIGINFO, PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP
|
|
.\" (Thanks to Blaisorblade, Daniel Jacobowitz and others who helped.)
|
|
.\" 2011-09, major update by Denys Vlasenko <vda.linux@googlemail.com>
|
|
.\" 2015-01, Kees Cook <keescook@chromium.org>
|
|
.\" Added PTRACE_O_TRACESECCOMP, PTRACE_EVENT_SECCOMP
|
|
.\"
|
|
.\" FIXME The following are undocumented
|
|
.\" PTRACE_GETWMMXREGS ARM
|
|
.\" PTRACE_SETWMMXREGS ARM
|
|
.\" PTRACE_GET_THREAD_AREA Various architectures
|
|
.\" PTRACE_SET_THREAD_AREA Various architectures
|
|
.\" PTRACE_SET_SYSCALL ARM and ARM64
|
|
.\" PTRACE_GETCRUNCHREGS ARM
|
|
.\" PTRACE_SETCRUNCHREGS ARM
|
|
.\" PTRACE_GETVFPREGS ARM and ARM64
|
|
.\" PTRACE_SETVFPREGS ARM and ARM64
|
|
.\" PTRACE_GETHBPREGS ARM and ARM64
|
|
.\" PTRACE_SETHBPREGS ARM and ARM64
|
|
.\" PTRACE_SINGLEBLOCK Various architectures
|
|
.\" and others that can be found in the arch/*/include/uapi/asm/ptrace files
|
|
.\"
|
|
.TH PTRACE 2 2015-12-05 "Linux" "Linux Programmer's Manual"
|
|
.SH NAME
|
|
ptrace \- process trace
|
|
.SH SYNOPSIS
|
|
.nf
|
|
.B #include <sys/ptrace.h>
|
|
.sp
|
|
.BI "long ptrace(enum __ptrace_request " request ", pid_t " pid ", "
|
|
.BI " void *" addr ", void *" data );
|
|
.fi
|
|
.SH DESCRIPTION
|
|
The
|
|
.BR ptrace ()
|
|
system call provides a means by which one process (the "tracer")
|
|
may observe and control the execution of another process (the "tracee"),
|
|
and examine and change the tracee's memory and registers.
|
|
It is primarily used to implement breakpoint debugging and system
|
|
call tracing.
|
|
.LP
|
|
A tracee first needs to be attached to the tracer.
|
|
Attachment and subsequent commands are per thread:
|
|
in a multithreaded process,
|
|
every thread can be individually attached to a
|
|
(potentially different) tracer,
|
|
or left not attached and thus not debugged.
|
|
Therefore, "tracee" always means "(one) thread",
|
|
never "a (possibly multithreaded) process".
|
|
Ptrace commands are always sent to
|
|
a specific tracee using a call of the form
|
|
|
|
ptrace(PTRACE_foo, pid, ...)
|
|
|
|
where
|
|
.I pid
|
|
is the thread ID of the corresponding Linux thread.
|
|
.LP
|
|
(Note that in this page, a "multithreaded process"
|
|
means a thread group consisting of threads created using the
|
|
.BR clone (2)
|
|
.B CLONE_THREAD
|
|
flag.)
|
|
.LP
|
|
A process can initiate a trace by calling
|
|
.BR fork (2)
|
|
and having the resulting child do a
|
|
.BR PTRACE_TRACEME ,
|
|
followed (typically) by an
|
|
.BR execve (2).
|
|
Alternatively, one process may commence tracing another process using
|
|
.B PTRACE_ATTACH
|
|
or
|
|
.BR PTRACE_SEIZE .
|
|
.LP
|
|
While being traced, the tracee will stop each time a signal is delivered,
|
|
even if the signal is being ignored.
|
|
(An exception is
|
|
.BR SIGKILL ,
|
|
which has its usual effect.)
|
|
The tracer will be notified at its next call to
|
|
.BR waitpid (2)
|
|
(or one of the related "wait" system calls); that call will return a
|
|
.I status
|
|
value containing information that indicates
|
|
the cause of the stop in the tracee.
|
|
While the tracee is stopped,
|
|
the tracer can use various ptrace requests to inspect and modify the tracee.
|
|
The tracer then causes the tracee to continue,
|
|
optionally ignoring the delivered signal
|
|
(or even delivering a different signal instead).
|
|
.LP
|
|
If the
|
|
.B PTRACE_O_TRACEEXEC
|
|
option is not in effect, all successful calls to
|
|
.BR execve (2)
|
|
by the traced process will cause it to be sent a
|
|
.B SIGTRAP
|
|
signal,
|
|
giving the parent a chance to gain control before the new program
|
|
begins execution.
|
|
.LP
|
|
When the tracer is finished tracing, it can cause the tracee to continue
|
|
executing in a normal, untraced mode via
|
|
.BR PTRACE_DETACH .
|
|
.LP
|
|
The value of
|
|
.I request
|
|
determines the action to be performed:
|
|
.TP
|
|
.B PTRACE_TRACEME
|
|
Indicate that this process is to be traced by its parent.
|
|
A process probably shouldn't make this request if its parent
|
|
isn't expecting to trace it.
|
|
.RI ( pid ,
|
|
.IR addr ,
|
|
and
|
|
.IR data
|
|
are ignored.)
|
|
.IP
|
|
The
|
|
.B PTRACE_TRACEME
|
|
request is used only by the tracee;
|
|
the remaining requests are used only by the tracer.
|
|
In the following requests,
|
|
.I pid
|
|
specifies the thread ID of the tracee to be acted on.
|
|
For requests other than
|
|
.BR PTRACE_ATTACH ,
|
|
.BR PTRACE_SEIZE ,
|
|
.BR PTRACE_INTERRUPT ,
|
|
and
|
|
.BR PTRACE_KILL ,
|
|
the tracee must be stopped.
|
|
.TP
|
|
.BR PTRACE_PEEKTEXT ", " PTRACE_PEEKDATA
|
|
Read a word at the address
|
|
.I addr
|
|
in the tracee's memory, returning the word as the result of the
|
|
.BR ptrace ()
|
|
call.
|
|
Linux does not have separate text and data address spaces,
|
|
so these two requests are currently equivalent.
|
|
.RI ( data
|
|
is ignored; but see NOTES.)
|
|
.TP
|
|
.B PTRACE_PEEKUSER
|
|
.\" PTRACE_PEEKUSR in kernel source, but glibc uses PTRACE_PEEKUSER,
|
|
.\" and that is the name that seems common on other systems.
|
|
Read a word at offset
|
|
.I addr
|
|
in the tracee's USER area,
|
|
which holds the registers and other information about the process
|
|
(see
|
|
.IR <sys/user.h> ).
|
|
The word is returned as the result of the
|
|
.BR ptrace ()
|
|
call.
|
|
Typically, the offset must be word-aligned, though this might vary by
|
|
architecture.
|
|
See NOTES.
|
|
.RI ( data
|
|
is ignored; but see NOTES.)
|
|
.TP
|
|
.BR PTRACE_POKETEXT ", " PTRACE_POKEDATA
|
|
Copy the word
|
|
.I data
|
|
to the address
|
|
.I addr
|
|
in the tracee's memory.
|
|
As for
|
|
.BR PTRACE_PEEKTEXT
|
|
and
|
|
.BR PTRACE_PEEKDATA ,
|
|
these two requests are currently equivalent.
|
|
.TP
|
|
.B PTRACE_POKEUSER
|
|
.\" PTRACE_POKEUSR in kernel source, but glibc uses PTRACE_POKEUSER,
|
|
.\" and that is the name that seems common on other systems.
|
|
Copy the word
|
|
.I data
|
|
to offset
|
|
.I addr
|
|
in the tracee's USER area.
|
|
As for
|
|
.BR PTRACE_PEEKUSER ,
|
|
the offset must typically be word-aligned.
|
|
In order to maintain the integrity of the kernel,
|
|
some modifications to the USER area are disallowed.
|
|
.\" FIXME In the preceding sentence, which modifications are disallowed,
|
|
.\" and when they are disallowed, how does user space discover that fact?
|
|
.TP
|
|
.BR PTRACE_GETREGS ", " PTRACE_GETFPREGS
|
|
Copy the tracee's general-purpose or floating-point registers,
|
|
respectively, to the address
|
|
.I data
|
|
in the tracer.
|
|
See
|
|
.I <sys/user.h>
|
|
for information on the format of this data.
|
|
.RI ( addr
|
|
is ignored.)
|
|
Note that SPARC systems have the meaning of
|
|
.I data
|
|
and
|
|
.I addr
|
|
reversed; that is,
|
|
.I data
|
|
is ignored and the registers are copied to the address
|
|
.IR addr .
|
|
.B PTRACE_GETREGS
|
|
and
|
|
.B PTRACE_GETFPREGS
|
|
are not present on all architectures.
|
|
.TP
|
|
.BR PTRACE_GETREGSET " (since Linux 2.6.34)"
|
|
Read the tracee's registers.
|
|
.I addr
|
|
specifies, in an architecture-dependent way, the type of registers to be read.
|
|
.B NT_PRSTATUS
|
|
(with numerical value 1)
|
|
usually results in reading of general-purpose registers.
|
|
If the CPU has, for example,
|
|
floating-point and/or vector registers, they can be retrieved by setting
|
|
.I addr
|
|
to the corresponding
|
|
.B NT_foo
|
|
constant.
|
|
.I data
|
|
points to a
|
|
.BR "struct iovec" ,
|
|
which describes the destination buffer's location and length.
|
|
On return, the kernel modifies
|
|
.B iov.len
|
|
to indicate the actual number of bytes returned.
|
|
.TP
|
|
.BR PTRACE_SETREGS ", " PTRACE_SETFPREGS
|
|
Modify the tracee's general-purpose or floating-point registers,
|
|
respectively, from the address
|
|
.I data
|
|
in the tracer.
|
|
As for
|
|
.BR PTRACE_POKEUSER ,
|
|
some general-purpose register modifications may be disallowed.
|
|
.\" FIXME . In the preceding sentence, which modifications are disallowed,
|
|
.\" and when they are disallowed, how does user space discover that fact?
|
|
.RI ( addr
|
|
is ignored.)
|
|
Note that SPARC systems have the meaning of
|
|
.I data
|
|
and
|
|
.I addr
|
|
reversed; that is,
|
|
.I data
|
|
is ignored and the registers are copied from the address
|
|
.IR addr .
|
|
.B PTRACE_SETREGS
|
|
and
|
|
.B PTRACE_SETFPREGS
|
|
are not present on all architectures.
|
|
.TP
|
|
.BR PTRACE_SETREGSET " (since Linux 2.6.34)"
|
|
Modify the tracee's registers.
|
|
The meaning of
|
|
.I addr
|
|
and
|
|
.I data
|
|
is analogous to
|
|
.BR PTRACE_GETREGSET .
|
|
.TP
|
|
.BR PTRACE_GETSIGINFO " (since Linux 2.3.99-pre6)"
|
|
Retrieve information about the signal that caused the stop.
|
|
Copy a
|
|
.I siginfo_t
|
|
structure (see
|
|
.BR sigaction (2))
|
|
from the tracee to the address
|
|
.I data
|
|
in the tracer.
|
|
.RI ( addr
|
|
is ignored.)
|
|
.TP
|
|
.BR PTRACE_SETSIGINFO " (since Linux 2.3.99-pre6)"
|
|
Set signal information:
|
|
copy a
|
|
.I siginfo_t
|
|
structure from the address
|
|
.I data
|
|
in the tracer to the tracee.
|
|
This will affect only signals that would normally be delivered to
|
|
the tracee and were caught by the tracer.
|
|
It may be difficult to tell
|
|
these normal signals from synthetic signals generated by
|
|
.BR ptrace ()
|
|
itself.
|
|
.RI ( addr
|
|
is ignored.)
|
|
.TP
|
|
.BR PTRACE_PEEKSIGINFO " (since Linux 3.10)"
|
|
.\" commit 84c751bd4aebbaae995fe32279d3dba48327bad4
|
|
Retrieve
|
|
.I siginfo_t
|
|
structures without removing signals from a queue.
|
|
.I addr
|
|
points to a
|
|
.I ptrace_peeksiginfo_args
|
|
structure that specifies the ordinal position from which
|
|
copying of signals should start,
|
|
and the number of signals to copy.
|
|
.I siginfo_t
|
|
structures are copied into the buffer pointed to by
|
|
.IR data .
|
|
The return value contains the number of copied signals (zero indicates
|
|
that there is no signal corresponding to the specified ordinal position).
|
|
Within the returned
|
|
.I siginfo
|
|
structures,
|
|
the
|
|
.IR si_code
|
|
field includes information
|
|
.RB ( __SI_CHLD ,
|
|
.BR __SI_FAULT ,
|
|
etc.) that are not otherwise exposed to user space.
|
|
.PP
|
|
.in +10n
|
|
.nf
|
|
struct ptrace_peeksiginfo_args {
|
|
u64 off; /* Ordinal position in queue at which
|
|
to start copying signals */
|
|
u32 flags; /* PTRACE_PEEKSIGINFO_SHARED or 0 */
|
|
s32 nr; /* Number of signals to copy */
|
|
};
|
|
.fi
|
|
|
|
Currently, there is only one flag,
|
|
.BR PTRACE_PEEKSIGINFO_SHARED ,
|
|
for dumping signals from the process-wide signal queue.
|
|
If this flag is not set,
|
|
signals are read from the per-thread queue of the specified thread.
|
|
.in
|
|
.PP
|
|
.TP
|
|
.BR PTRACE_GETSIGMASK " (since Linux 3.11)"
|
|
.\" commit 29000caecbe87b6b66f144f72111f0d02fbbf0c1
|
|
Place a copy of the mask of blocked signals (see
|
|
.BR sigprocmask (2))
|
|
in the buffer pointed to by
|
|
.IR data ,
|
|
which should be a pointer to a buffer of type
|
|
.IR sigset_t .
|
|
The
|
|
.I addr
|
|
argument contains the size of the buffer pointed to by
|
|
.IR data
|
|
(i.e.,
|
|
.IR sizeof(sigset_t) ).
|
|
.TP
|
|
.BR PTRACE_SETSIGMASK " (since Linux 3.11)"
|
|
Change the mask of blocked signals (see
|
|
.BR sigprocmask (2))
|
|
to the value specified in the buffer pointed to by
|
|
.IR data ,
|
|
which should be a pointer to a buffer of type
|
|
.IR sigset_t .
|
|
The
|
|
.I addr
|
|
argument contains the size of the buffer pointed to by
|
|
.IR data
|
|
(i.e.,
|
|
.IR sizeof(sigset_t) ).
|
|
.TP
|
|
.BR PTRACE_SETOPTIONS " (since Linux 2.4.6; see BUGS for caveats)"
|
|
Set ptrace options from
|
|
.IR data .
|
|
.RI ( addr
|
|
is ignored.)
|
|
.IR data
|
|
is interpreted as a bit mask of options,
|
|
which are specified by the following flags:
|
|
.RS
|
|
.TP
|
|
.BR PTRACE_O_EXITKILL " (since Linux 3.8)"
|
|
.\" commit 992fb6e170639b0849bace8e49bf31bd37c4123
|
|
If a tracer sets this flag, a
|
|
.B SIGKILL
|
|
signal will be sent to every tracee if the tracer exits.
|
|
This option is useful for ptrace jailers that
|
|
want to ensure that tracees can never escape the tracer's control.
|
|
.TP
|
|
.BR PTRACE_O_TRACECLONE " (since Linux 2.5.46)"
|
|
Stop the tracee at the next
|
|
.BR clone (2)
|
|
and automatically start tracing the newly cloned process,
|
|
which will start with a
|
|
.BR SIGSTOP ,
|
|
or
|
|
.B PTRACE_EVENT_STOP
|
|
if
|
|
.B PTRACE_SEIZE
|
|
was used.
|
|
A
|
|
.BR waitpid (2)
|
|
by the tracer will return a
|
|
.I status
|
|
value such that
|
|
|
|
.nf
|
|
status>>8 == (SIGTRAP | (PTRACE_EVENT_CLONE<<8))
|
|
.fi
|
|
|
|
The PID of the new process can be retrieved with
|
|
.BR PTRACE_GETEVENTMSG .
|
|
.IP
|
|
This option may not catch
|
|
.BR clone (2)
|
|
calls in all cases.
|
|
If the tracee calls
|
|
.BR clone (2)
|
|
with the
|
|
.B CLONE_VFORK
|
|
flag,
|
|
.B PTRACE_EVENT_VFORK
|
|
will be delivered instead
|
|
if
|
|
.B PTRACE_O_TRACEVFORK
|
|
is set; otherwise if the tracee calls
|
|
.BR clone (2)
|
|
with the exit signal set to
|
|
.BR SIGCHLD ,
|
|
.B PTRACE_EVENT_FORK
|
|
will be delivered if
|
|
.B PTRACE_O_TRACEFORK
|
|
is set.
|
|
.TP
|
|
.BR PTRACE_O_TRACEEXEC " (since Linux 2.5.46)"
|
|
Stop the tracee at the next
|
|
.BR execve (2).
|
|
A
|
|
.BR waitpid (2)
|
|
by the tracer will return a
|
|
.I status
|
|
value such that
|
|
|
|
.nf
|
|
status>>8 == (SIGTRAP | (PTRACE_EVENT_EXEC<<8))
|
|
.fi
|
|
|
|
If the execing thread is not a thread group leader,
|
|
the thread ID is reset to thread group leader's ID before this stop.
|
|
Since Linux 3.0, the former thread ID can be retrieved with
|
|
.BR PTRACE_GETEVENTMSG .
|
|
.TP
|
|
.BR PTRACE_O_TRACEEXIT " (since Linux 2.5.60)"
|
|
Stop the tracee at exit.
|
|
A
|
|
.BR waitpid (2)
|
|
by the tracer will return a
|
|
.I status
|
|
value such that
|
|
|
|
.nf
|
|
status>>8 == (SIGTRAP | (PTRACE_EVENT_EXIT<<8))
|
|
.fi
|
|
|
|
The tracee's exit status can be retrieved with
|
|
.BR PTRACE_GETEVENTMSG .
|
|
.IP
|
|
The tracee is stopped early during process exit,
|
|
when registers are still available,
|
|
allowing the tracer to see where the exit occurred,
|
|
whereas the normal exit notification is done after the process
|
|
is finished exiting.
|
|
Even though context is available,
|
|
the tracer cannot prevent the exit from happening at this point.
|
|
.TP
|
|
.BR PTRACE_O_TRACEFORK " (since Linux 2.5.46)"
|
|
Stop the tracee at the next
|
|
.BR fork (2)
|
|
and automatically start tracing the newly forked process,
|
|
which will start with a
|
|
.BR SIGSTOP ,
|
|
or
|
|
.B PTRACE_EVENT_STOP
|
|
if
|
|
.B PTRACE_SEIZE
|
|
was used.
|
|
A
|
|
.BR waitpid (2)
|
|
by the tracer will return a
|
|
.I status
|
|
value such that
|
|
|
|
.nf
|
|
status>>8 == (SIGTRAP | (PTRACE_EVENT_FORK<<8))
|
|
.fi
|
|
|
|
The PID of the new process can be retrieved with
|
|
.BR PTRACE_GETEVENTMSG .
|
|
.TP
|
|
.BR PTRACE_O_TRACESYSGOOD " (since Linux 2.4.6)"
|
|
When delivering system call traps, set bit 7 in the signal number
|
|
(i.e., deliver
|
|
.IR "SIGTRAP|0x80" ).
|
|
This makes it easy for the tracer to distinguish
|
|
normal traps from those caused by a system call.
|
|
.RB ( PTRACE_O_TRACESYSGOOD
|
|
may not work on all architectures.)
|
|
.TP
|
|
.BR PTRACE_O_TRACEVFORK " (since Linux 2.5.46)"
|
|
Stop the tracee at the next
|
|
.BR vfork (2)
|
|
and automatically start tracing the newly vforked process,
|
|
which will start with a
|
|
.BR SIGSTOP ,
|
|
or
|
|
.B PTRACE_EVENT_STOP
|
|
if
|
|
.B PTRACE_SEIZE
|
|
was used.
|
|
A
|
|
.BR waitpid (2)
|
|
by the tracer will return a
|
|
.I status
|
|
value such that
|
|
|
|
.nf
|
|
status>>8 == (SIGTRAP | (PTRACE_EVENT_VFORK<<8))
|
|
.fi
|
|
|
|
The PID of the new process can be retrieved with
|
|
.BR PTRACE_GETEVENTMSG .
|
|
.TP
|
|
.BR PTRACE_O_TRACEVFORKDONE " (since Linux 2.5.60)"
|
|
Stop the tracee at the completion of the next
|
|
.BR vfork (2).
|
|
A
|
|
.BR waitpid (2)
|
|
by the tracer will return a
|
|
.I status
|
|
value such that
|
|
|
|
.nf
|
|
status>>8 == (SIGTRAP | (PTRACE_EVENT_VFORK_DONE<<8))
|
|
.fi
|
|
|
|
The PID of the new process can (since Linux 2.6.18) be retrieved with
|
|
.BR PTRACE_GETEVENTMSG .
|
|
.TP
|
|
.BR PTRACE_O_TRACESECCOMP " (since Linux 3.5)"
|
|
Stop the tracee when a
|
|
.BR seccomp (2)
|
|
.BR SECCOMP_RET_TRACE
|
|
rule is triggered.
|
|
A
|
|
.BR waitpid (2)
|
|
by the tracer will return a
|
|
.I status
|
|
value such that
|
|
|
|
.nf
|
|
status>>8 == (SIGTRAP | (PTRACE_EVENT_SECCOMP<<8))
|
|
.fi
|
|
|
|
While this triggers a
|
|
.BR PTRACE_EVENT
|
|
stop, it is similar to a syscall-enter-stop, in that the tracee has
|
|
not yet entered the syscall that seccomp triggered on.
|
|
The seccomp event message data (from the
|
|
.BR SECCOMP_RET_DATA
|
|
portion of the seccomp filter rule) can be retrieved with
|
|
.BR PTRACE_GETEVENTMSG .
|
|
.TP
|
|
.BR PTRACE_O_SUSPEND_SECCOMP " (since Linux 4.3)"
|
|
.\" commit 13c4a90119d28cfcb6b5bdd820c233b86c2b0237
|
|
Suspend the tracee's seccomp protections.
|
|
This applies regardless of mode, and
|
|
can be used when the tracee has not yet installed seccomp filters.
|
|
That is, a valid use case is to suspend a tracee's seccomp protections
|
|
before they are installed by the tracee,
|
|
let the tracee install the filters,
|
|
and then clear this flag when the filters should be resumed.
|
|
Setting this option requires that the tracer have the
|
|
.BR CAP_SYS_ADMIN
|
|
capability,
|
|
not have any seccomp protections installed, and not have
|
|
.BR PTRACE_O_SUSPEND_SECCOMP
|
|
set on itself.
|
|
.RE
|
|
.TP
|
|
.BR PTRACE_GETEVENTMSG " (since Linux 2.5.46)"
|
|
Retrieve a message (as an
|
|
.IR "unsigned long" )
|
|
about the ptrace event
|
|
that just happened, placing it at the address
|
|
.I data
|
|
in the tracer.
|
|
For
|
|
.BR PTRACE_EVENT_EXIT ,
|
|
this is the tracee's exit status.
|
|
For
|
|
.BR PTRACE_EVENT_FORK ,
|
|
.BR PTRACE_EVENT_VFORK ,
|
|
.BR PTRACE_EVENT_VFORK_DONE ,
|
|
and
|
|
.BR PTRACE_EVENT_CLONE ,
|
|
this is the PID of the new process.
|
|
For
|
|
.BR PTRACE_EVENT_SECCOMP ,
|
|
this is the
|
|
.BR seccomp (2)
|
|
filter's
|
|
.BR SECCOMP_RET_DATA
|
|
associated with the triggered rule.
|
|
.RI ( addr
|
|
is ignored.)
|
|
.TP
|
|
.B PTRACE_CONT
|
|
Restart the stopped tracee process.
|
|
If
|
|
.I data
|
|
is nonzero,
|
|
it is interpreted as the number of a signal to be delivered to the tracee;
|
|
otherwise, no signal is delivered.
|
|
Thus, for example, the tracer can control
|
|
whether a signal sent to the tracee is delivered or not.
|
|
.RI ( addr
|
|
is ignored.)
|
|
.TP
|
|
.BR PTRACE_SYSCALL ", " PTRACE_SINGLESTEP
|
|
Restart the stopped tracee as for
|
|
.BR PTRACE_CONT ,
|
|
but arrange for the tracee to be stopped at
|
|
the next entry to or exit from a system call,
|
|
or after execution of a single instruction, respectively.
|
|
(The tracee will also, as usual, be stopped upon receipt of a signal.)
|
|
From the tracer's perspective, the tracee will appear to have been
|
|
stopped by receipt of a
|
|
.BR SIGTRAP .
|
|
So, for
|
|
.BR PTRACE_SYSCALL ,
|
|
for example, the idea is to inspect
|
|
the arguments to the system call at the first stop,
|
|
then do another
|
|
.B PTRACE_SYSCALL
|
|
and inspect the return value of the system call at the second stop.
|
|
The
|
|
.I data
|
|
argument is treated as for
|
|
.BR PTRACE_CONT .
|
|
.RI ( addr
|
|
is ignored.)
|
|
.TP
|
|
.BR PTRACE_SYSEMU ", " PTRACE_SYSEMU_SINGLESTEP " (since Linux 2.6.14)"
|
|
For
|
|
.BR PTRACE_SYSEMU ,
|
|
continue and stop on entry to the next system call,
|
|
which will not be executed.
|
|
For
|
|
.BR PTRACE_SYSEMU_SINGLESTEP ,
|
|
do the same but also singlestep if not a system call.
|
|
This call is used by programs like
|
|
User Mode Linux that want to emulate all the tracee's system calls.
|
|
The
|
|
.I data
|
|
argument is treated as for
|
|
.BR PTRACE_CONT .
|
|
The
|
|
.I addr
|
|
argument is ignored.
|
|
These requests are currently
|
|
.\" As at 3.7
|
|
supported only on x86.
|
|
.TP
|
|
.BR PTRACE_LISTEN " (since Linux 3.4)"
|
|
Restart the stopped tracee, but prevent it from executing.
|
|
The resulting state of the tracee is similar to a process which
|
|
has been stopped by a
|
|
.B SIGSTOP
|
|
(or other stopping signal).
|
|
See the "group-stop" subsection for additional information.
|
|
.B PTRACE_LISTEN
|
|
works only on tracees attached by
|
|
.BR PTRACE_SEIZE .
|
|
.TP
|
|
.B PTRACE_KILL
|
|
Send the tracee a
|
|
.B SIGKILL
|
|
to terminate it.
|
|
.RI ( addr
|
|
and
|
|
.I data
|
|
are ignored.)
|
|
.IP
|
|
.I This operation is deprecated; do not use it!
|
|
Instead, send a
|
|
.BR SIGKILL
|
|
directly using
|
|
.BR kill (2)
|
|
or
|
|
.BR tgkill (2).
|
|
The problem with
|
|
.B PTRACE_KILL
|
|
is that it requires the tracee to be in signal-delivery-stop,
|
|
otherwise it may not work
|
|
(i.e., may complete successfully but won't kill the tracee).
|
|
By contrast, sending a
|
|
.B SIGKILL
|
|
directly has no such limitation.
|
|
.\" [Note from Denys Vlasenko:
|
|
.\" deprecation suggested by Oleg Nesterov. He prefers to deprecate it
|
|
.\" instead of describing (and needing to support) PTRACE_KILL's quirks.]
|
|
.TP
|
|
.BR PTRACE_INTERRUPT " (since Linux 3.4)"
|
|
Stop a tracee.
|
|
If the tracee is running or sleeping in kernel space and
|
|
.B PTRACE_SYSCALL
|
|
is in effect,
|
|
the system call is interrupted and syscall-exit-stop is reported.
|
|
(The interrupted system call is restarted when the tracee is restarted.)
|
|
If the tracee was already stopped by a signal and
|
|
.B PTRACE_LISTEN
|
|
was sent to it,
|
|
the tracee stops with
|
|
.B PTRACE_EVENT_STOP
|
|
and
|
|
.I WSTOPSIG(status)
|
|
returns the stop signal.
|
|
If any other ptrace-stop is generated at the same time (for example,
|
|
if a signal is sent to the tracee), this ptrace-stop happens.
|
|
If none of the above applies (for example, if the tracee is running in user
|
|
space), it stops with
|
|
.B PTRACE_EVENT_STOP
|
|
with
|
|
.I WSTOPSIG(status)
|
|
==
|
|
.BR SIGTRAP .
|
|
.B PTRACE_INTERRUPT
|
|
only works on tracees attached by
|
|
.BR PTRACE_SEIZE .
|
|
.TP
|
|
.B PTRACE_ATTACH
|
|
Attach to the process specified in
|
|
.IR pid ,
|
|
making it a tracee of the calling process.
|
|
.\" No longer true (removed by Denys Vlasenko, 2011, who remarks:
|
|
.\" "I think it isn't true in non-ancient 2.4 and in 2.6/3.x.
|
|
.\" Basically, it's not true for any Linux in practical use.
|
|
.\" ; the behavior of the tracee is as if it had done a
|
|
.\" .BR PTRACE_TRACEME .
|
|
.\" The calling process actually becomes the parent of the tracee
|
|
.\" process for most purposes (e.g., it will receive
|
|
.\" notification of tracee events and appears in
|
|
.\" .BR ps (1)
|
|
.\" output as the tracee's parent), but a
|
|
.\" .BR getppid (2)
|
|
.\" by the tracee will still return the PID of the original parent.
|
|
The tracee is sent a
|
|
.BR SIGSTOP ,
|
|
but will not necessarily have stopped
|
|
by the completion of this call; use
|
|
.BR waitpid (2)
|
|
to wait for the tracee to stop.
|
|
See the "Attaching and detaching" subsection for additional information.
|
|
.RI ( addr
|
|
and
|
|
.I data
|
|
are ignored.)
|
|
|
|
Processes that are not dumpable (see the description of
|
|
.BR PR_SET_DUMPABLE
|
|
in
|
|
.BR prctl (2))
|
|
can not be attached via
|
|
.BR ptrace (2)
|
|
.BR PTRACE_ATTACH .
|
|
.TP
|
|
.BR PTRACE_SEIZE " (since Linux 3.4)"
|
|
Attach to the process specified in
|
|
.IR pid ,
|
|
making it a tracee of the calling process.
|
|
Unlike
|
|
.BR PTRACE_ATTACH ,
|
|
.B PTRACE_SEIZE
|
|
does not stop the process.
|
|
Group-stops are reported as
|
|
.B PTRACE_EVENT_STOP
|
|
and
|
|
.I WSTOPSIG(status)
|
|
returns the stop signal.
|
|
Automatically attached children stop with
|
|
.B PTRACE_EVENT_STOP
|
|
and
|
|
.I WSTOPSIG(status)
|
|
returns
|
|
.B SIGTRAP
|
|
instead of having
|
|
.B SIGSTOP
|
|
signal delivered to them.
|
|
.BR execve (2)
|
|
does not deliver an extra
|
|
.BR SIGTRAP .
|
|
Only a
|
|
.BR PTRACE_SEIZE d
|
|
process can accept
|
|
.B PTRACE_INTERRUPT
|
|
and
|
|
.B PTRACE_LISTEN
|
|
commands.
|
|
The "seized" behavior just described is inherited by
|
|
children that are automatically attached using
|
|
.BR PTRACE_O_TRACEFORK ,
|
|
.BR PTRACE_O_TRACEVFORK ,
|
|
and
|
|
.BR PTRACE_O_TRACECLONE .
|
|
.I addr
|
|
must be zero.
|
|
.I data
|
|
contains a bit mask of ptrace options to activate immediately.
|
|
.TP
|
|
.B PTRACE_DETACH
|
|
Restart the stopped tracee as for
|
|
.BR PTRACE_CONT ,
|
|
but first detach from it.
|
|
Under Linux, a tracee can be detached in this way regardless
|
|
of which method was used to initiate tracing.
|
|
.RI ( addr
|
|
is ignored.)
|
|
.SS Death under ptrace
|
|
When a (possibly multithreaded) process receives a killing signal
|
|
(one whose disposition is set to
|
|
.B SIG_DFL
|
|
and whose default action is to kill the process),
|
|
all threads exit.
|
|
Tracees report their death to their tracer(s).
|
|
Notification of this event is delivered via
|
|
.BR waitpid (2).
|
|
.LP
|
|
Note that the killing signal will first cause signal-delivery-stop
|
|
(on one tracee only),
|
|
and only after it is injected by the tracer
|
|
(or after it was dispatched to a thread which isn't traced),
|
|
will death from the signal happen on
|
|
.I all
|
|
tracees within a multithreaded process.
|
|
(The term "signal-delivery-stop" is explained below.)
|
|
.LP
|
|
.B SIGKILL
|
|
does not generate signal-delivery-stop and
|
|
therefore the tracer can't suppress it.
|
|
.B SIGKILL
|
|
kills even within system calls
|
|
(syscall-exit-stop is not generated prior to death by
|
|
.BR SIGKILL ).
|
|
The net effect is that
|
|
.B SIGKILL
|
|
always kills the process (all its threads),
|
|
even if some threads of the process are ptraced.
|
|
.LP
|
|
When the tracee calls
|
|
.BR _exit (2),
|
|
it reports its death to its tracer.
|
|
Other threads are not affected.
|
|
.LP
|
|
When any thread executes
|
|
.BR exit_group (2),
|
|
every tracee in its thread group reports its death to its tracer.
|
|
.LP
|
|
If the
|
|
.B PTRACE_O_TRACEEXIT
|
|
option is on,
|
|
.B PTRACE_EVENT_EXIT
|
|
will happen before actual death.
|
|
This applies to exits via
|
|
.BR exit (2),
|
|
.BR exit_group (2),
|
|
and signal deaths (except
|
|
.BR SIGKILL ,
|
|
depending on the kernel version; see BUGS below),
|
|
and when threads are torn down on
|
|
.BR execve (2)
|
|
in a multithreaded process.
|
|
.LP
|
|
The tracer cannot assume that the ptrace-stopped tracee exists.
|
|
There are many scenarios when the tracee may die while stopped (such as
|
|
.BR SIGKILL ).
|
|
Therefore, the tracer must be prepared to handle an
|
|
.B ESRCH
|
|
error on any ptrace operation.
|
|
Unfortunately, the same error is returned if the tracee
|
|
exists but is not ptrace-stopped
|
|
(for commands which require a stopped tracee),
|
|
or if it is not traced by the process which issued the ptrace call.
|
|
The tracer needs to keep track of the stopped/running state of the tracee,
|
|
and interpret
|
|
.B ESRCH
|
|
as "tracee died unexpectedly" only if it knows that the tracee has
|
|
been observed to enter ptrace-stop.
|
|
Note that there is no guarantee that
|
|
.I waitpid(WNOHANG)
|
|
will reliably report the tracee's death status if a
|
|
ptrace operation returned
|
|
.BR ESRCH .
|
|
.I waitpid(WNOHANG)
|
|
may return 0 instead.
|
|
In other words, the tracee may be "not yet fully dead",
|
|
but already refusing ptrace requests.
|
|
.LP
|
|
The tracer can't assume that the tracee
|
|
.I always
|
|
ends its life by reporting
|
|
.I WIFEXITED(status)
|
|
or
|
|
.IR WIFSIGNALED(status) ;
|
|
there are cases where this does not occur.
|
|
For example, if a thread other than thread group leader does an
|
|
.BR execve (2),
|
|
it disappears;
|
|
its PID will never be seen again,
|
|
and any subsequent ptrace stops will be reported under
|
|
the thread group leader's PID.
|
|
.SS Stopped states
|
|
A tracee can be in two states: running or stopped.
|
|
For the purposes of ptrace, a tracee which is blocked in a system call
|
|
(such as
|
|
.BR read (2),
|
|
.BR pause (2),
|
|
etc.)
|
|
is nevertheless considered to be running, even if the tracee is blocked
|
|
for a long time.
|
|
The state of the tracee after
|
|
.BR PTRACE_LISTEN
|
|
is somewhat of a gray area: it is not in any ptrace-stop (ptrace commands
|
|
won't work on it, and it will deliver
|
|
.BR waitpid (2)
|
|
notifications),
|
|
but it also may be considered "stopped" because
|
|
it is not executing instructions (is not scheduled), and if it was
|
|
in group-stop before
|
|
.BR PTRACE_LISTEN ,
|
|
it will not respond to signals until
|
|
.B SIGCONT
|
|
is received.
|
|
.LP
|
|
There are many kinds of states when the tracee is stopped, and in ptrace
|
|
discussions they are often conflated.
|
|
Therefore, it is important to use precise terms.
|
|
.LP
|
|
In this manual page, any stopped state in which the tracee is ready
|
|
to accept ptrace commands from the tracer is called
|
|
.IR ptrace-stop .
|
|
Ptrace-stops can
|
|
be further subdivided into
|
|
.IR signal-delivery-stop ,
|
|
.IR group-stop ,
|
|
.IR syscall-stop ,
|
|
and so on.
|
|
These stopped states are described in detail below.
|
|
.LP
|
|
When the running tracee enters ptrace-stop, it notifies its tracer using
|
|
.BR waitpid (2)
|
|
(or one of the other "wait" system calls).
|
|
Most of this manual page assumes that the tracer waits with:
|
|
.LP
|
|
pid = waitpid(pid_or_minus_1, &status, __WALL);
|
|
.LP
|
|
Ptrace-stopped tracees are reported as returns with
|
|
.I pid
|
|
greater than 0 and
|
|
.I WIFSTOPPED(status)
|
|
true.
|
|
.\" Denys Vlasenko:
|
|
.\" Do we require __WALL usage, or will just using 0 be ok? (With 0,
|
|
.\" I am not 100% sure there aren't ugly corner cases.) Are the
|
|
.\" rules different if user wants to use waitid? Will waitid require
|
|
.\" WEXITED?
|
|
.\"
|
|
.LP
|
|
The
|
|
.B __WALL
|
|
flag does not include the
|
|
.B WSTOPPED
|
|
and
|
|
.B WEXITED
|
|
flags, but implies their functionality.
|
|
.LP
|
|
Setting the
|
|
.B WCONTINUED
|
|
flag when calling
|
|
.BR waitpid (2)
|
|
is not recommended: the "continued" state is per-process and
|
|
consuming it can confuse the real parent of the tracee.
|
|
.LP
|
|
Use of the
|
|
.B WNOHANG
|
|
flag may cause
|
|
.BR waitpid (2)
|
|
to return 0 ("no wait results available yet")
|
|
even if the tracer knows there should be a notification.
|
|
Example:
|
|
.nf
|
|
|
|
errno = 0;
|
|
ptrace(PTRACE_CONT, pid, 0L, 0L);
|
|
if (errno == ESRCH) {
|
|
/* tracee is dead */
|
|
r = waitpid(tracee, &status, __WALL | WNOHANG);
|
|
/* r can still be 0 here! */
|
|
}
|
|
.fi
|
|
.\" FIXME .
|
|
.\" waitid usage? WNOWAIT?
|
|
.\" describe how wait notifications queue (or not queue)
|
|
.LP
|
|
The following kinds of ptrace-stops exist: signal-delivery-stops,
|
|
group-stops,
|
|
.B PTRACE_EVENT
|
|
stops, syscall-stops.
|
|
They all are reported by
|
|
.BR waitpid (2)
|
|
with
|
|
.I WIFSTOPPED(status)
|
|
true.
|
|
They may be differentiated by examining the value
|
|
.IR status>>8 ,
|
|
and if there is ambiguity in that value, by querying
|
|
.BR PTRACE_GETSIGINFO .
|
|
(Note: the
|
|
.I WSTOPSIG(status)
|
|
macro can't be used to perform this examination,
|
|
because it returns the value
|
|
.IR "(status>>8)\ &\ 0xff" .)
|
|
.SS Signal-delivery-stop
|
|
When a (possibly multithreaded) process receives any signal except
|
|
.BR SIGKILL ,
|
|
the kernel selects an arbitrary thread which handles the signal.
|
|
(If the signal is generated with
|
|
.BR tgkill (2),
|
|
the target thread can be explicitly selected by the caller.)
|
|
If the selected thread is traced, it enters signal-delivery-stop.
|
|
At this point, the signal is not yet delivered to the process,
|
|
and can be suppressed by the tracer.
|
|
If the tracer doesn't suppress the signal,
|
|
it passes the signal to the tracee in the next ptrace restart request.
|
|
This second step of signal delivery is called
|
|
.I "signal injection"
|
|
in this manual page.
|
|
Note that if the signal is blocked,
|
|
signal-delivery-stop doesn't happen until the signal is unblocked,
|
|
with the usual exception that
|
|
.B SIGSTOP
|
|
can't be blocked.
|
|
.LP
|
|
Signal-delivery-stop is observed by the tracer as
|
|
.BR waitpid (2)
|
|
returning with
|
|
.I WIFSTOPPED(status)
|
|
true, with the signal returned by
|
|
.IR WSTOPSIG(status) .
|
|
If the signal is
|
|
.BR SIGTRAP ,
|
|
this may be a different kind of ptrace-stop;
|
|
see the "Syscall-stops" and "execve" sections below for details.
|
|
If
|
|
.I WSTOPSIG(status)
|
|
returns a stopping signal, this may be a group-stop; see below.
|
|
.SS Signal injection and suppression
|
|
After signal-delivery-stop is observed by the tracer,
|
|
the tracer should restart the tracee with the call
|
|
.LP
|
|
ptrace(PTRACE_restart, pid, 0, sig)
|
|
.LP
|
|
where
|
|
.B PTRACE_restart
|
|
is one of the restarting ptrace requests.
|
|
If
|
|
.I sig
|
|
is 0, then a signal is not delivered.
|
|
Otherwise, the signal
|
|
.I sig
|
|
is delivered.
|
|
This operation is called
|
|
.I "signal injection"
|
|
in this manual page, to distinguish it from signal-delivery-stop.
|
|
.LP
|
|
The
|
|
.I sig
|
|
value may be different from the
|
|
.I WSTOPSIG(status)
|
|
value: the tracer can cause a different signal to be injected.
|
|
.LP
|
|
Note that a suppressed signal still causes system calls to return
|
|
prematurely.
|
|
In this case, system calls will be restarted: the tracer will
|
|
observe the tracee to reexecute the interrupted system call (or
|
|
.BR restart_syscall (2)
|
|
system call for a few system calls which use a different mechanism
|
|
for restarting) if the tracer uses
|
|
.BR PTRACE_SYSCALL .
|
|
Even system calls (such as
|
|
.BR poll (2))
|
|
which are not restartable after signal are restarted after
|
|
signal is suppressed;
|
|
however, kernel bugs exist which cause some system calls to fail with
|
|
.B EINTR
|
|
even though no observable signal is injected to the tracee.
|
|
.LP
|
|
Restarting ptrace commands issued in ptrace-stops other than
|
|
signal-delivery-stop are not guaranteed to inject a signal, even if
|
|
.I sig
|
|
is nonzero.
|
|
No error is reported; a nonzero
|
|
.I sig
|
|
may simply be ignored.
|
|
Ptrace users should not try to "create a new signal" this way: use
|
|
.BR tgkill (2)
|
|
instead.
|
|
.LP
|
|
The fact that signal injection requests may be ignored
|
|
when restarting the tracee after
|
|
ptrace stops that are not signal-delivery-stops
|
|
is a cause of confusion among ptrace users.
|
|
One typical scenario is that the tracer observes group-stop,
|
|
mistakes it for signal-delivery-stop, restarts the tracee with
|
|
|
|
ptrace(PTRACE_restart, pid, 0, stopsig)
|
|
|
|
with the intention of injecting
|
|
.IR stopsig ,
|
|
but
|
|
.I stopsig
|
|
gets ignored and the tracee continues to run.
|
|
.LP
|
|
The
|
|
.B SIGCONT
|
|
signal has a side effect of waking up (all threads of)
|
|
a group-stopped process.
|
|
This side effect happens before signal-delivery-stop.
|
|
The tracer can't suppress this side effect (it can
|
|
only suppress signal injection, which only causes the
|
|
.BR SIGCONT
|
|
handler to not be executed in the tracee, if such a handler is installed).
|
|
In fact, waking up from group-stop may be followed by
|
|
signal-delivery-stop for signal(s)
|
|
.I other than
|
|
.BR SIGCONT ,
|
|
if they were pending when
|
|
.B SIGCONT
|
|
was delivered.
|
|
In other words,
|
|
.B SIGCONT
|
|
may be not the first signal observed by the tracee after it was sent.
|
|
.LP
|
|
Stopping signals cause (all threads of) a process to enter group-stop.
|
|
This side effect happens after signal injection, and therefore can be
|
|
suppressed by the tracer.
|
|
.LP
|
|
In Linux 2.4 and earlier, the
|
|
.B SIGSTOP
|
|
signal can't be injected.
|
|
.\" In the Linux 2.4 sources, in arch/i386/kernel/signal.c::do_signal(),
|
|
.\" there is:
|
|
.\"
|
|
.\" /* The debugger continued. Ignore SIGSTOP. */
|
|
.\" if (signr == SIGSTOP)
|
|
.\" continue;
|
|
.LP
|
|
.B PTRACE_GETSIGINFO
|
|
can be used to retrieve a
|
|
.I siginfo_t
|
|
structure which corresponds to the delivered signal.
|
|
.B PTRACE_SETSIGINFO
|
|
may be used to modify it.
|
|
If
|
|
.B PTRACE_SETSIGINFO
|
|
has been used to alter
|
|
.IR siginfo_t ,
|
|
the
|
|
.I si_signo
|
|
field and the
|
|
.I sig
|
|
parameter in the restarting command must match,
|
|
otherwise the result is undefined.
|
|
.SS Group-stop
|
|
When a (possibly multithreaded) process receives a stopping signal,
|
|
all threads stop.
|
|
If some threads are traced, they enter a group-stop.
|
|
Note that the stopping signal will first cause signal-delivery-stop
|
|
(on one tracee only), and only after it is injected by the tracer
|
|
(or after it was dispatched to a thread which isn't traced),
|
|
will group-stop be initiated on
|
|
.I all
|
|
tracees within the multithreaded process.
|
|
As usual, every tracee reports its group-stop separately
|
|
to the corresponding tracer.
|
|
.LP
|
|
Group-stop is observed by the tracer as
|
|
.BR waitpid (2)
|
|
returning with
|
|
.I WIFSTOPPED(status)
|
|
true, with the stopping signal available via
|
|
.IR WSTOPSIG(status) .
|
|
The same result is returned by some other classes of ptrace-stops,
|
|
therefore the recommended practice is to perform the call
|
|
.LP
|
|
ptrace(PTRACE_GETSIGINFO, pid, 0, &siginfo)
|
|
.LP
|
|
The call can be avoided if the signal is not
|
|
.BR SIGSTOP ,
|
|
.BR SIGTSTP ,
|
|
.BR SIGTTIN ,
|
|
or
|
|
.BR SIGTTOU ;
|
|
only these four signals are stopping signals.
|
|
If the tracer sees something else, it can't be a group-stop.
|
|
Otherwise, the tracer needs to call
|
|
.BR PTRACE_GETSIGINFO .
|
|
If
|
|
.B PTRACE_GETSIGINFO
|
|
fails with
|
|
.BR EINVAL ,
|
|
then it is definitely a group-stop.
|
|
(Other failure codes are possible, such as
|
|
.B ESRCH
|
|
("no such process") if a
|
|
.B SIGKILL
|
|
killed the tracee.)
|
|
.LP
|
|
If tracee was attached using
|
|
.BR PTRACE_SEIZE ,
|
|
group-stop is indicated by
|
|
.BR PTRACE_EVENT_STOP :
|
|
.IR "status>>16 == PTRACE_EVENT_STOP" .
|
|
This allows detection of group-stops
|
|
without requiring an extra
|
|
.B PTRACE_GETSIGINFO
|
|
call.
|
|
.LP
|
|
As of Linux 2.6.38,
|
|
after the tracer sees the tracee ptrace-stop and until it
|
|
restarts or kills it, the tracee will not run,
|
|
and will not send notifications (except
|
|
.B SIGKILL
|
|
death) to the tracer, even if the tracer enters into another
|
|
.BR waitpid (2)
|
|
call.
|
|
.LP
|
|
The kernel behavior described in the previous paragraph
|
|
causes a problem with transparent handling of stopping signals.
|
|
If the tracer restarts the tracee after group-stop,
|
|
the stopping signal
|
|
is effectively ignored\(emthe tracee doesn't remain stopped, it runs.
|
|
If the tracer doesn't restart the tracee before entering into the next
|
|
.BR waitpid (2),
|
|
future
|
|
.B SIGCONT
|
|
signals will not be reported to the tracer;
|
|
this would cause the
|
|
.B SIGCONT
|
|
signals to have no effect on the tracee.
|
|
.LP
|
|
Since Linux 3.4, there is a method to overcome this problem: instead of
|
|
.BR PTRACE_CONT ,
|
|
a
|
|
.B PTRACE_LISTEN
|
|
command can be used to restart a tracee in a way where it does not execute,
|
|
but waits for a new event which it can report via
|
|
.BR waitpid (2)
|
|
(such as when
|
|
it is restarted by a
|
|
.BR SIGCONT ).
|
|
.SS PTRACE_EVENT stops
|
|
If the tracer sets
|
|
.B PTRACE_O_TRACE_*
|
|
options, the tracee will enter ptrace-stops called
|
|
.B PTRACE_EVENT
|
|
stops.
|
|
.LP
|
|
.B PTRACE_EVENT
|
|
stops are observed by the tracer as
|
|
.BR waitpid (2)
|
|
returning with
|
|
.IR WIFSTOPPED(status) ,
|
|
and
|
|
.I WSTOPSIG(status)
|
|
returns
|
|
.BR SIGTRAP .
|
|
An additional bit is set in the higher byte of the status word:
|
|
the value
|
|
.I status>>8
|
|
will be
|
|
|
|
(SIGTRAP | PTRACE_EVENT_foo << 8).
|
|
|
|
The following events exist:
|
|
.TP
|
|
.B PTRACE_EVENT_VFORK
|
|
Stop before return from
|
|
.BR vfork (2)
|
|
or
|
|
.BR clone (2)
|
|
with the
|
|
.B CLONE_VFORK
|
|
flag.
|
|
When the tracee is continued after this stop, it will wait for child to
|
|
exit/exec before continuing its execution
|
|
(in other words, the usual behavior on
|
|
.BR vfork (2)).
|
|
.TP
|
|
.B PTRACE_EVENT_FORK
|
|
Stop before return from
|
|
.BR fork (2)
|
|
or
|
|
.BR clone (2)
|
|
with the exit signal set to
|
|
.BR SIGCHLD .
|
|
.TP
|
|
.B PTRACE_EVENT_CLONE
|
|
Stop before return from
|
|
.BR clone (2).
|
|
.TP
|
|
.B PTRACE_EVENT_VFORK_DONE
|
|
Stop before return from
|
|
.BR vfork (2)
|
|
or
|
|
.BR clone (2)
|
|
with the
|
|
.B CLONE_VFORK
|
|
flag,
|
|
but after the child unblocked this tracee by exiting or execing.
|
|
.LP
|
|
For all four stops described above,
|
|
the stop occurs in the parent (i.e., the tracee),
|
|
not in the newly created thread.
|
|
.BR PTRACE_GETEVENTMSG
|
|
can be used to retrieve the new thread's ID.
|
|
.TP
|
|
.B PTRACE_EVENT_EXEC
|
|
Stop before return from
|
|
.BR execve (2).
|
|
Since Linux 3.0,
|
|
.BR PTRACE_GETEVENTMSG
|
|
returns the former thread ID.
|
|
.TP
|
|
.B PTRACE_EVENT_EXIT
|
|
Stop before exit (including death from
|
|
.BR exit_group (2)),
|
|
signal death, or exit caused by
|
|
.BR execve (2)
|
|
in a multithreaded process.
|
|
.B PTRACE_GETEVENTMSG
|
|
returns the exit status.
|
|
Registers can be examined
|
|
(unlike when "real" exit happens).
|
|
The tracee is still alive; it needs to be
|
|
.BR PTRACE_CONT ed
|
|
or
|
|
.BR PTRACE_DETACH ed
|
|
to finish exiting.
|
|
.TP
|
|
.B PTRACE_EVENT_STOP
|
|
Stop induced by
|
|
.B PTRACE_INTERRUPT
|
|
command, or group-stop, or initial ptrace-stop when a new child is attached
|
|
(only if attached using
|
|
.BR PTRACE_SEIZE ).
|
|
.TP
|
|
.B PTRACE_EVENT_SECCOMP
|
|
Stop triggered by a
|
|
.BR seccomp (2)
|
|
rule on tracee syscall entry when
|
|
.BR PTRACE_O_TRACESECCOMP
|
|
has been set by the tracer.
|
|
The seccomp event message data (from the
|
|
.BR SECCOMP_RET_DATA
|
|
portion of the seccomp filter rule) can be retrieved with
|
|
.BR PTRACE_GETEVENTMSG .
|
|
.LP
|
|
.B PTRACE_GETSIGINFO
|
|
on
|
|
.B PTRACE_EVENT
|
|
stops returns
|
|
.B SIGTRAP
|
|
in
|
|
.IR si_signo ,
|
|
with
|
|
.I si_code
|
|
set to
|
|
.IR "(event<<8)\ |\ SIGTRAP" .
|
|
.SS Syscall-stops
|
|
If the tracee was restarted by
|
|
.BR PTRACE_SYSCALL ,
|
|
the tracee enters
|
|
syscall-enter-stop just prior to entering any system call.
|
|
If the tracer restarts the tracee with
|
|
.BR PTRACE_SYSCALL ,
|
|
the tracee enters syscall-exit-stop when the system call is finished,
|
|
or if it is interrupted by a signal.
|
|
(That is, signal-delivery-stop never happens between syscall-enter-stop
|
|
and syscall-exit-stop; it happens
|
|
.I after
|
|
syscall-exit-stop.)
|
|
.LP
|
|
Other possibilities are that the tracee may stop in a
|
|
.B PTRACE_EVENT
|
|
stop, exit (if it entered
|
|
.BR _exit (2)
|
|
or
|
|
.BR exit_group (2)),
|
|
be killed by
|
|
.BR SIGKILL ,
|
|
or die silently (if it is a thread group leader, the
|
|
.BR execve (2)
|
|
happened in another thread,
|
|
and that thread is not traced by the same tracer;
|
|
this situation is discussed later).
|
|
.LP
|
|
Syscall-enter-stop and syscall-exit-stop are observed by the tracer as
|
|
.BR waitpid (2)
|
|
returning with
|
|
.I WIFSTOPPED(status)
|
|
true, and
|
|
.I WSTOPSIG(status)
|
|
giving
|
|
.BR SIGTRAP .
|
|
If the
|
|
.B PTRACE_O_TRACESYSGOOD
|
|
option was set by the tracer, then
|
|
.I WSTOPSIG(status)
|
|
will give the value
|
|
.IR "(SIGTRAP\ |\ 0x80)" .
|
|
.LP
|
|
Syscall-stops can be distinguished from signal-delivery-stop with
|
|
.B SIGTRAP
|
|
by querying
|
|
.BR PTRACE_GETSIGINFO
|
|
for the following cases:
|
|
.TP
|
|
.IR si_code " <= 0"
|
|
.B SIGTRAP
|
|
was delivered as a result of a user-space action,
|
|
for example, a system call
|
|
.RB ( tgkill (2),
|
|
.BR kill (2),
|
|
.BR sigqueue (3),
|
|
etc.),
|
|
expiration of a POSIX timer,
|
|
change of state on a POSIX message queue,
|
|
or completion of an asynchronous I/O request.
|
|
.TP
|
|
.IR si_code " == SI_KERNEL (0x80)"
|
|
.B SIGTRAP
|
|
was sent by the kernel.
|
|
.TP
|
|
.IR si_code " == SIGTRAP or " si_code " == (SIGTRAP|0x80)"
|
|
This is a syscall-stop.
|
|
.LP
|
|
However, syscall-stops happen very often (twice per system call),
|
|
and performing
|
|
.B PTRACE_GETSIGINFO
|
|
for every syscall-stop may be somewhat expensive.
|
|
.LP
|
|
Some architectures allow the cases to be distinguished
|
|
by examining registers.
|
|
For example, on x86,
|
|
.I rax
|
|
==
|
|
.RB - ENOSYS
|
|
in syscall-enter-stop.
|
|
Since
|
|
.B SIGTRAP
|
|
(like any other signal) always happens
|
|
.I after
|
|
syscall-exit-stop,
|
|
and at this point
|
|
.I rax
|
|
almost never contains
|
|
.RB - ENOSYS ,
|
|
the
|
|
.B SIGTRAP
|
|
looks like "syscall-stop which is not syscall-enter-stop";
|
|
in other words, it looks like a
|
|
"stray syscall-exit-stop" and can be detected this way.
|
|
But such detection is fragile and is best avoided.
|
|
.LP
|
|
Using the
|
|
.B PTRACE_O_TRACESYSGOOD
|
|
option is the recommended method to distinguish syscall-stops
|
|
from other kinds of ptrace-stops,
|
|
since it is reliable and does not incur a performance penalty.
|
|
.LP
|
|
Syscall-enter-stop and syscall-exit-stop are
|
|
indistinguishable from each other by the tracer.
|
|
The tracer needs to keep track of the sequence of
|
|
ptrace-stops in order to not misinterpret syscall-enter-stop as
|
|
syscall-exit-stop or vice versa.
|
|
The rule is that syscall-enter-stop is
|
|
always followed by syscall-exit-stop,
|
|
.B PTRACE_EVENT
|
|
stop or the tracee's death;
|
|
no other kinds of ptrace-stop can occur in between.
|
|
.LP
|
|
If after syscall-enter-stop,
|
|
the tracer uses a restarting command other than
|
|
.BR PTRACE_SYSCALL ,
|
|
syscall-exit-stop is not generated.
|
|
.LP
|
|
.B PTRACE_GETSIGINFO
|
|
on syscall-stops returns
|
|
.B SIGTRAP
|
|
in
|
|
.IR si_signo ,
|
|
with
|
|
.I si_code
|
|
set to
|
|
.B SIGTRAP
|
|
or
|
|
.IR (SIGTRAP|0x80) .
|
|
.SS PTRACE_SINGLESTEP, PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP stops
|
|
[Details of these kinds of stops are yet to be documented.]
|
|
.\"
|
|
.\" FIXME .
|
|
.\" document stops occurring with PTRACE_SINGLESTEP, PTRACE_SYSEMU,
|
|
.\" PTRACE_SYSEMU_SINGLESTEP
|
|
.SS Informational and restarting ptrace commands
|
|
Most ptrace commands (all except
|
|
.BR PTRACE_ATTACH ,
|
|
.BR PTRACE_SEIZE ,
|
|
.BR PTRACE_TRACEME ,
|
|
.BR PTRACE_INTERRUPT ,
|
|
and
|
|
.BR PTRACE_KILL )
|
|
require the tracee to be in a ptrace-stop, otherwise they fail with
|
|
.BR ESRCH .
|
|
.LP
|
|
When the tracee is in ptrace-stop,
|
|
the tracer can read and write data to
|
|
the tracee using informational commands.
|
|
These commands leave the tracee in ptrace-stopped state:
|
|
.LP
|
|
.nf
|
|
ptrace(PTRACE_PEEKTEXT/PEEKDATA/PEEKUSER, pid, addr, 0);
|
|
ptrace(PTRACE_POKETEXT/POKEDATA/POKEUSER, pid, addr, long_val);
|
|
ptrace(PTRACE_GETREGS/GETFPREGS, pid, 0, &struct);
|
|
ptrace(PTRACE_SETREGS/SETFPREGS, pid, 0, &struct);
|
|
ptrace(PTRACE_GETREGSET, pid, NT_foo, &iov);
|
|
ptrace(PTRACE_SETREGSET, pid, NT_foo, &iov);
|
|
ptrace(PTRACE_GETSIGINFO, pid, 0, &siginfo);
|
|
ptrace(PTRACE_SETSIGINFO, pid, 0, &siginfo);
|
|
ptrace(PTRACE_GETEVENTMSG, pid, 0, &long_var);
|
|
ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_flags);
|
|
.fi
|
|
.LP
|
|
Note that some errors are not reported.
|
|
For example, setting signal information
|
|
.RI ( siginfo )
|
|
may have no effect in some ptrace-stops, yet the call may succeed
|
|
(return 0 and not set
|
|
.IR errno );
|
|
querying
|
|
.B PTRACE_GETEVENTMSG
|
|
may succeed and return some random value if current ptrace-stop
|
|
is not documented as returning a meaningful event message.
|
|
.LP
|
|
The call
|
|
|
|
ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_flags);
|
|
|
|
affects one tracee.
|
|
The tracee's current flags are replaced.
|
|
Flags are inherited by new tracees created and "auto-attached" via active
|
|
.BR PTRACE_O_TRACEFORK ,
|
|
.BR PTRACE_O_TRACEVFORK ,
|
|
or
|
|
.BR PTRACE_O_TRACECLONE
|
|
options.
|
|
.LP
|
|
Another group of commands makes the ptrace-stopped tracee run.
|
|
They have the form:
|
|
.LP
|
|
ptrace(cmd, pid, 0, sig);
|
|
.LP
|
|
where
|
|
.I cmd
|
|
is
|
|
.BR PTRACE_CONT ,
|
|
.BR PTRACE_LISTEN ,
|
|
.BR PTRACE_DETACH ,
|
|
.BR PTRACE_SYSCALL ,
|
|
.BR PTRACE_SINGLESTEP ,
|
|
.BR PTRACE_SYSEMU ,
|
|
or
|
|
.BR PTRACE_SYSEMU_SINGLESTEP .
|
|
If the tracee is in signal-delivery-stop,
|
|
.I sig
|
|
is the signal to be injected (if it is nonzero).
|
|
Otherwise,
|
|
.I sig
|
|
may be ignored.
|
|
(When restarting a tracee from a ptrace-stop other than signal-delivery-stop,
|
|
recommended practice is to always pass 0 in
|
|
.IR sig .)
|
|
.SS Attaching and detaching
|
|
A thread can be attached to the tracer using the call
|
|
|
|
ptrace(PTRACE_ATTACH, pid, 0, 0);
|
|
|
|
or
|
|
|
|
ptrace(PTRACE_SEIZE, pid, 0, PTRACE_O_flags);
|
|
|
|
.B PTRACE_ATTACH
|
|
sends
|
|
.B SIGSTOP
|
|
to this thread.
|
|
If the tracer wants this
|
|
.B SIGSTOP
|
|
to have no effect, it needs to suppress it.
|
|
Note that if other signals are concurrently sent to
|
|
this thread during attach,
|
|
the tracer may see the tracee enter signal-delivery-stop
|
|
with other signal(s) first!
|
|
The usual practice is to reinject these signals until
|
|
.B SIGSTOP
|
|
is seen, then suppress
|
|
.B SIGSTOP
|
|
injection.
|
|
The design bug here is that a ptrace attach and a concurrently delivered
|
|
.B SIGSTOP
|
|
may race and the concurrent
|
|
.B SIGSTOP
|
|
may be lost.
|
|
.\"
|
|
.\" FIXME . Describe how to attach to a thread which is already group-stopped.
|
|
.LP
|
|
Since attaching sends
|
|
.B SIGSTOP
|
|
and the tracer usually suppresses it, this may cause a stray
|
|
.B EINTR
|
|
return from the currently executing system call in the tracee,
|
|
as described in the "Signal injection and suppression" section.
|
|
.LP
|
|
Since Linux 3.4,
|
|
.B PTRACE_SEIZE
|
|
can be used instead of
|
|
.BR PTRACE_ATTACH .
|
|
.B PTRACE_SEIZE
|
|
does not stop the attached process.
|
|
If you need to stop
|
|
it after attach (or at any other time) without sending it any signals,
|
|
use
|
|
.B PTRACE_INTERRUPT
|
|
command.
|
|
.LP
|
|
The request
|
|
|
|
ptrace(PTRACE_TRACEME, 0, 0, 0);
|
|
|
|
turns the calling thread into a tracee.
|
|
The thread continues to run (doesn't enter ptrace-stop).
|
|
A common practice is to follow the
|
|
.B PTRACE_TRACEME
|
|
with
|
|
|
|
raise(SIGSTOP);
|
|
|
|
and allow the parent (which is our tracer now) to observe our
|
|
signal-delivery-stop.
|
|
.LP
|
|
If the
|
|
.BR PTRACE_O_TRACEFORK ,
|
|
.BR PTRACE_O_TRACEVFORK ,
|
|
or
|
|
.BR PTRACE_O_TRACECLONE
|
|
options are in effect, then children created by, respectively,
|
|
.BR vfork (2)
|
|
or
|
|
.BR clone (2)
|
|
with the
|
|
.B CLONE_VFORK
|
|
flag,
|
|
.BR fork (2)
|
|
or
|
|
.BR clone (2)
|
|
with the exit signal set to
|
|
.BR SIGCHLD ,
|
|
and other kinds of
|
|
.BR clone (2),
|
|
are automatically attached to the same tracer which traced their parent.
|
|
.B SIGSTOP
|
|
is delivered to the children, causing them to enter
|
|
signal-delivery-stop after they exit the system call which created them.
|
|
.LP
|
|
Detaching of the tracee is performed by:
|
|
|
|
ptrace(PTRACE_DETACH, pid, 0, sig);
|
|
|
|
.B PTRACE_DETACH
|
|
is a restarting operation;
|
|
therefore it requires the tracee to be in ptrace-stop.
|
|
If the tracee is in signal-delivery-stop, a signal can be injected.
|
|
Otherwise, the
|
|
.I sig
|
|
parameter may be silently ignored.
|
|
.LP
|
|
If the tracee is running when the tracer wants to detach it,
|
|
the usual solution is to send
|
|
.B SIGSTOP
|
|
(using
|
|
.BR tgkill (2),
|
|
to make sure it goes to the correct thread),
|
|
wait for the tracee to stop in signal-delivery-stop for
|
|
.B SIGSTOP
|
|
and then detach it (suppressing
|
|
.B SIGSTOP
|
|
injection).
|
|
A design bug is that this can race with concurrent
|
|
.BR SIGSTOP s.
|
|
Another complication is that the tracee may enter other ptrace-stops
|
|
and needs to be restarted and waited for again, until
|
|
.B SIGSTOP
|
|
is seen.
|
|
Yet another complication is to be sure that
|
|
the tracee is not already ptrace-stopped,
|
|
because no signal delivery happens while it is\(emnot even
|
|
.BR SIGSTOP .
|
|
.\" FIXME . Describe how to detach from a group-stopped tracee so that it
|
|
.\" doesn't run, but continues to wait for SIGCONT.
|
|
.LP
|
|
If the tracer dies, all tracees are automatically detached and restarted,
|
|
unless they were in group-stop.
|
|
Handling of restart from group-stop is currently buggy,
|
|
but the "as planned" behavior is to leave tracee stopped and waiting for
|
|
.BR SIGCONT .
|
|
If the tracee is restarted from signal-delivery-stop,
|
|
the pending signal is injected.
|
|
.SS execve(2) under ptrace
|
|
.\" clone(2) CLONE_THREAD says:
|
|
.\" If any of the threads in a thread group performs an execve(2),
|
|
.\" then all threads other than the thread group leader are terminated,
|
|
.\" and the new program is executed in the thread group leader.
|
|
.\"
|
|
When one thread in a multithreaded process calls
|
|
.BR execve (2),
|
|
the kernel destroys all other threads in the process,
|
|
.\" In kernel 3.1 sources, see fs/exec.c::de_thread()
|
|
and resets the thread ID of the execing thread to the
|
|
thread group ID (process ID).
|
|
(Or, to put things another way, when a multithreaded process does an
|
|
.BR execve (2),
|
|
at completion of the call, it appears as though the
|
|
.BR execve (2)
|
|
occurred in the thread group leader, regardless of which thread did the
|
|
.BR execve (2).)
|
|
This resetting of the thread ID looks very confusing to tracers:
|
|
.IP * 3
|
|
All other threads stop in
|
|
.B PTRACE_EVENT_EXIT
|
|
stop, if the
|
|
.BR PTRACE_O_TRACEEXIT
|
|
option was turned on.
|
|
Then all other threads except the thread group leader report
|
|
death as if they exited via
|
|
.BR _exit (2)
|
|
with exit code 0.
|
|
.IP *
|
|
The execing tracee changes its thread ID while it is in the
|
|
.BR execve (2).
|
|
(Remember, under ptrace, the "pid" returned from
|
|
.BR waitpid (2),
|
|
or fed into ptrace calls, is the tracee's thread ID.)
|
|
That is, the tracee's thread ID is reset to be the same as its process ID,
|
|
which is the same as the thread group leader's thread ID.
|
|
.IP *
|
|
Then a
|
|
.B PTRACE_EVENT_EXEC
|
|
stop happens, if the
|
|
.BR PTRACE_O_TRACEEXEC
|
|
option was turned on.
|
|
.IP *
|
|
If the thread group leader has reported its
|
|
.B PTRACE_EVENT_EXIT
|
|
stop by this time,
|
|
it appears to the tracer that
|
|
the dead thread leader "reappears from nowhere".
|
|
(Note: the thread group leader does not report death via
|
|
.I WIFEXITED(status)
|
|
until there is at least one other live thread.
|
|
This eliminates the possibility that the tracer will see
|
|
it dying and then reappearing.)
|
|
If the thread group leader was still alive,
|
|
for the tracer this may look as if thread group leader
|
|
returns from a different system call than it entered,
|
|
or even "returned from a system call even though
|
|
it was not in any system call".
|
|
If the thread group leader was not traced
|
|
(or was traced by a different tracer), then during
|
|
.BR execve (2)
|
|
it will appear as if it has become a tracee of
|
|
the tracer of the execing tracee.
|
|
.LP
|
|
All of the above effects are the artifacts of
|
|
the thread ID change in the tracee.
|
|
.LP
|
|
The
|
|
.B PTRACE_O_TRACEEXEC
|
|
option is the recommended tool for dealing with this situation.
|
|
First, it enables
|
|
.BR PTRACE_EVENT_EXEC
|
|
stop,
|
|
which occurs before
|
|
.BR execve (2)
|
|
returns.
|
|
In this stop, the tracer can use
|
|
.B PTRACE_GETEVENTMSG
|
|
to retrieve the tracee's former thread ID.
|
|
(This feature was introduced in Linux 3.0.)
|
|
Second, the
|
|
.B PTRACE_O_TRACEEXEC
|
|
option disables legacy
|
|
.B SIGTRAP
|
|
generation on
|
|
.BR execve (2).
|
|
.LP
|
|
When the tracer receives
|
|
.B PTRACE_EVENT_EXEC
|
|
stop notification,
|
|
it is guaranteed that except this tracee and the thread group leader,
|
|
no other threads from the process are alive.
|
|
.LP
|
|
On receiving the
|
|
.B PTRACE_EVENT_EXEC
|
|
stop notification,
|
|
the tracer should clean up all its internal
|
|
data structures describing the threads of this process,
|
|
and retain only one data structure\(emone which
|
|
describes the single still running tracee, with
|
|
|
|
thread ID == thread group ID == process ID.
|
|
.LP
|
|
Example: two threads call
|
|
.BR execve (2)
|
|
at the same time:
|
|
.LP
|
|
.nf
|
|
*** we get syscall-enter-stop in thread 1: **
|
|
PID1 execve("/bin/foo", "foo" <unfinished ...>
|
|
*** we issue PTRACE_SYSCALL for thread 1 **
|
|
*** we get syscall-enter-stop in thread 2: **
|
|
PID2 execve("/bin/bar", "bar" <unfinished ...>
|
|
*** we issue PTRACE_SYSCALL for thread 2 **
|
|
*** we get PTRACE_EVENT_EXEC for PID0, we issue PTRACE_SYSCALL **
|
|
*** we get syscall-exit-stop for PID0: **
|
|
PID0 <... execve resumed> ) = 0
|
|
.fi
|
|
.LP
|
|
If the
|
|
.B PTRACE_O_TRACEEXEC
|
|
option is
|
|
.I not
|
|
in effect for the execing tracee,
|
|
and if the tracee was
|
|
.BR PTRACE_ATTACH ed
|
|
rather that
|
|
.BR PTRACE_SEIZE d,
|
|
the kernel delivers an extra
|
|
.B SIGTRAP
|
|
to the tracee after
|
|
.BR execve (2)
|
|
returns.
|
|
This is an ordinary signal (similar to one which can be
|
|
generated by
|
|
.IR "kill -TRAP" ),
|
|
not a special kind of ptrace-stop.
|
|
Employing
|
|
.B PTRACE_GETSIGINFO
|
|
for this signal returns
|
|
.I si_code
|
|
set to 0
|
|
.RI ( SI_USER ).
|
|
This signal may be blocked by signal mask,
|
|
and thus may be delivered (much) later.
|
|
.LP
|
|
Usually, the tracer (for example,
|
|
.BR strace (1))
|
|
would not want to show this extra post-execve
|
|
.B SIGTRAP
|
|
signal to the user, and would suppress its delivery to the tracee (if
|
|
.B SIGTRAP
|
|
is set to
|
|
.BR SIG_DFL ,
|
|
it is a killing signal).
|
|
However, determining
|
|
.I which
|
|
.B SIGTRAP
|
|
to suppress is not easy.
|
|
Setting the
|
|
.B PTRACE_O_TRACEEXEC
|
|
option or using
|
|
.B PTRACE_SEIZE
|
|
and thus suppressing this extra
|
|
.B SIGTRAP
|
|
is the recommended approach.
|
|
.SS Real parent
|
|
The ptrace API (ab)uses the standard UNIX parent/child signaling over
|
|
.BR waitpid (2).
|
|
This used to cause the real parent of the process to stop receiving
|
|
several kinds of
|
|
.BR waitpid (2)
|
|
notifications when the child process is traced by some other process.
|
|
.LP
|
|
Many of these bugs have been fixed, but as of Linux 2.6.38 several still
|
|
exist; see BUGS below.
|
|
.LP
|
|
As of Linux 2.6.38, the following is believed to work correctly:
|
|
.IP * 3
|
|
exit/death by signal is reported first to the tracer, then,
|
|
when the tracer consumes the
|
|
.BR waitpid (2)
|
|
result, to the real parent (to the real parent only when the
|
|
whole multithreaded process exits).
|
|
If the tracer and the real parent are the same process,
|
|
the report is sent only once.
|
|
.SH RETURN VALUE
|
|
On success, the
|
|
.B PTRACE_PEEK*
|
|
requests return the requested data (but see NOTES),
|
|
while other requests return zero.
|
|
.LP
|
|
On error, all requests return \-1, and
|
|
.I errno
|
|
is set appropriately.
|
|
Since the value returned by a successful
|
|
.B PTRACE_PEEK*
|
|
request may be \-1, the caller must clear
|
|
.I errno
|
|
before the call, and then check it afterward
|
|
to determine whether or not an error occurred.
|
|
.SH ERRORS
|
|
.TP
|
|
.B EBUSY
|
|
(i386 only) There was an error with allocating or freeing a debug register.
|
|
.TP
|
|
.B EFAULT
|
|
There was an attempt to read from or write to an invalid area in
|
|
the tracer's or the tracee's memory,
|
|
probably because the area wasn't mapped or accessible.
|
|
Unfortunately, under Linux, different variations of this fault
|
|
will return
|
|
.B EIO
|
|
or
|
|
.B EFAULT
|
|
more or less arbitrarily.
|
|
.TP
|
|
.B EINVAL
|
|
An attempt was made to set an invalid option.
|
|
.TP
|
|
.B EIO
|
|
.I request
|
|
is invalid, or an attempt was made to read from or
|
|
write to an invalid area in the tracer's or the tracee's memory,
|
|
or there was a word-alignment violation,
|
|
or an invalid signal was specified during a restart request.
|
|
.TP
|
|
.B EPERM
|
|
The specified process cannot be traced.
|
|
This could be because the
|
|
tracer has insufficient privileges (the required capability is
|
|
.BR CAP_SYS_PTRACE );
|
|
unprivileged processes cannot trace processes that they
|
|
cannot send signals to or those running
|
|
set-user-ID/set-group-ID programs, for obvious reasons.
|
|
Alternatively, the process may already be being traced,
|
|
or (on kernels before 2.6.26) be
|
|
.BR init (1)
|
|
(PID 1).
|
|
.TP
|
|
.B ESRCH
|
|
The specified process does not exist, or is not currently being traced
|
|
by the caller, or is not stopped
|
|
(for requests that require a stopped tracee).
|
|
.SH CONFORMING TO
|
|
SVr4, 4.3BSD.
|
|
.SH NOTES
|
|
Although arguments to
|
|
.BR ptrace ()
|
|
are interpreted according to the prototype given,
|
|
glibc currently declares
|
|
.BR ptrace ()
|
|
as a variadic function with only the
|
|
.I request
|
|
argument fixed.
|
|
It is recommended to always supply four arguments,
|
|
even if the requested operation does not use them,
|
|
setting unused/ignored arguments to
|
|
.I 0L
|
|
or
|
|
.IR "(void\ *)\ 0".
|
|
.LP
|
|
In Linux kernels before 2.6.26,
|
|
.\" See commit 00cd5c37afd5f431ac186dd131705048c0a11fdb
|
|
.BR init (1),
|
|
the process with PID 1, may not be traced.
|
|
.LP
|
|
A tracees parent continues to be the tracer even if that tracer calls
|
|
.BR execve (2).
|
|
.LP
|
|
The layout of the contents of memory and the USER area are
|
|
quite operating-system- and architecture-specific.
|
|
The offset supplied, and the data returned,
|
|
might not entirely match with the definition of
|
|
.IR "struct user" .
|
|
.\" See http://lkml.org/lkml/2008/5/8/375
|
|
.LP
|
|
The size of a "word" is determined by the operating-system variant
|
|
(e.g., for 32-bit Linux it is 32 bits).
|
|
.LP
|
|
This page documents the way the
|
|
.BR ptrace ()
|
|
call works currently in Linux.
|
|
Its behavior differs significantly on other flavors of UNIX.
|
|
In any case, use of
|
|
.BR ptrace ()
|
|
is highly specific to the operating system and architecture.
|
|
.\"
|
|
.SS /proc/sys/kernel/yama/ptrace_scope
|
|
On systems with the Yama Linux Security Module installed, the
|
|
.I /proc/sys/kernel/yama/ptrace_scope
|
|
(available since Linux 3.4)
|
|
.\" commit 2d514487faf188938a4ee4fb3464eeecfbdcf8eb
|
|
can be used to restrict the ability to trace a process with
|
|
.BR ptrace (2)
|
|
(and thus also the ability to use tools such as
|
|
.BR strace (1)
|
|
and
|
|
.BR gdb (1)).
|
|
The goal of such restrictions is to prevent attack escalation whereby
|
|
a compromised process can ptrace-attach to other sensitive processes
|
|
(e.g., a GPG agent or an SSH session) owned by the user in order
|
|
to gain additional credentials and thus expand the scope of the attack.
|
|
|
|
A process with the
|
|
.B CAP_SYS_PTRACE
|
|
capability can update this file with one of the following values:
|
|
.TP
|
|
0 ("classic ptrace permissions")
|
|
A process can
|
|
.B PTRACE_ATTACH
|
|
to any other process running under the same UID,
|
|
as long as the tracee is dumpable (i.e., it did
|
|
not transition UIDs or start start privileged, and it has not employed
|
|
the
|
|
.BR prctl (2)
|
|
.B PR_SET_DUMPABLE
|
|
operation to make itself nondumpable).
|
|
|
|
The use of
|
|
.BR PTRACE_TRACEME
|
|
is unchanged.
|
|
.TP
|
|
1 ("restricted ptrace")
|
|
A process must have a predefined relationship
|
|
with the tracee to which it wants to
|
|
.BR PTRACE_ATTACH .
|
|
By default,
|
|
the predefined relationship is that the tracee is a child of the
|
|
caller and the aforementioned classic criteria are also met.
|
|
To specify a different process that may trace it, a tracee can employ the
|
|
.BR prctl (2)
|
|
.B PR_SET_PTRACER
|
|
operation to declare a different PID that is allowed to
|
|
.BR PTRACE_ATTACH
|
|
to the tracee.
|
|
(See the kernel source file
|
|
.IR Documentation/security/Yama.txt
|
|
for further details.)
|
|
|
|
The use of
|
|
.BR PTRACE_TRACEME
|
|
is unchanged.
|
|
.TP
|
|
2 ("admin-only attach")
|
|
Only processes with the
|
|
.B CAP_SYS_PTRACE
|
|
capability may use
|
|
.BR PTRACE_ATTACH
|
|
or trace children that employ
|
|
.BR PTRACE_TRACEME .
|
|
.TP
|
|
3 ("no attach")
|
|
No process may use
|
|
.BR PTRACE_ATTACH
|
|
or trace children that employ
|
|
.BR PTRACE_TRACEME .
|
|
|
|
Once this value has been written to the file, it cannot be changed.
|
|
.\"
|
|
.SS C library/kernel differences
|
|
At the system call level, the
|
|
.BR PTRACE_PEEKTEXT ,
|
|
.BR PTRACE_PEEKDATA ,
|
|
and
|
|
.BR PTRACE_PEEKUSER
|
|
requests have a different API: they store the result
|
|
at the address specified by the
|
|
.I data
|
|
parameter, and the return value is the error flag.
|
|
The glibc wrapper function provides the API given in DESCRIPTION above,
|
|
with the result being returned via the function return value.
|
|
.SH BUGS
|
|
On hosts with 2.6 kernel headers,
|
|
.B PTRACE_SETOPTIONS
|
|
is declared with a different value than the one for 2.4.
|
|
This leads to applications compiled with 2.6 kernel
|
|
headers failing when run on 2.4 kernels.
|
|
This can be worked around by redefining
|
|
.B PTRACE_SETOPTIONS
|
|
to
|
|
.BR PTRACE_OLDSETOPTIONS ,
|
|
if that is defined.
|
|
.LP
|
|
Group-stop notifications are sent to the tracer, but not to real parent.
|
|
Last confirmed on 2.6.38.6.
|
|
.LP
|
|
If a thread group leader is traced and exits by calling
|
|
.BR _exit (2),
|
|
.\" Note from Denys Vlasenko:
|
|
.\" Here "exits" means any kind of death - _exit, exit_group,
|
|
.\" signal death. Signal death and exit_group cases are trivial,
|
|
.\" though: since signal death and exit_group kill all other threads
|
|
.\" too, "until all other threads exit" thing happens rather soon
|
|
.\" in these cases. Therefore, only _exit presents observably
|
|
.\" puzzling behavior to ptrace users: thread leader _exit's,
|
|
.\" but WIFEXITED isn't reported! We are trying to explain here
|
|
.\" why it is so.
|
|
a
|
|
.B PTRACE_EVENT_EXIT
|
|
stop will happen for it (if requested), but the subsequent
|
|
.B WIFEXITED
|
|
notification will not be delivered until all other threads exit.
|
|
As explained above, if one of other threads calls
|
|
.BR execve (2),
|
|
the death of the thread group leader will
|
|
.I never
|
|
be reported.
|
|
If the execed thread is not traced by this tracer,
|
|
the tracer will never know that
|
|
.BR execve (2)
|
|
happened.
|
|
One possible workaround is to
|
|
.B PTRACE_DETACH
|
|
the thread group leader instead of restarting it in this case.
|
|
Last confirmed on 2.6.38.6.
|
|
.\" FIXME . need to test/verify this scenario
|
|
.LP
|
|
A
|
|
.B SIGKILL
|
|
signal may still cause a
|
|
.B PTRACE_EVENT_EXIT
|
|
stop before actual signal death.
|
|
This may be changed in the future;
|
|
.B SIGKILL
|
|
is meant to always immediately kill tasks even under ptrace.
|
|
Last confirmed on Linux 3.13.
|
|
.LP
|
|
Some system calls return with
|
|
.B EINTR
|
|
if a signal was sent to a tracee, but delivery was suppressed by the tracer.
|
|
(This is very typical operation: it is usually
|
|
done by debuggers on every attach, in order to not introduce
|
|
a bogus
|
|
.BR SIGSTOP ).
|
|
As of Linux 3.2.9, the following system calls are affected
|
|
(this list is likely incomplete):
|
|
.BR epoll_wait (2),
|
|
and
|
|
.BR read (2)
|
|
from an
|
|
.BR inotify (7)
|
|
file descriptor.
|
|
The usual symptom of this bug is that when you attach to
|
|
a quiescent process with the command
|
|
|
|
strace \-p <process-ID>
|
|
|
|
then, instead of the usual
|
|
and expected one-line output such as
|
|
.nf
|
|
|
|
restart_syscall(<... resuming interrupted call ...>_
|
|
|
|
.fi
|
|
or
|
|
.nf
|
|
|
|
select(6, [5], NULL, [5], NULL_
|
|
|
|
.fi
|
|
('_' denotes the cursor position), you observe more than one line.
|
|
For example:
|
|
.nf
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, {15370, 690928118}) = 0
|
|
epoll_wait(4,_
|
|
|
|
.fi
|
|
What is not visible here is that the process was blocked in
|
|
.BR epoll_wait (2)
|
|
before
|
|
.BR strace (1)
|
|
has attached to it.
|
|
Attaching caused
|
|
.BR epoll_wait (2)
|
|
to return to user space with the error
|
|
.BR EINTR .
|
|
In this particular case, the program reacted to
|
|
.B EINTR
|
|
by checking the current time, and then executing
|
|
.BR epoll_wait (2)
|
|
again.
|
|
(Programs which do not expect such "stray"
|
|
.BR EINTR
|
|
errors may behave in an unintended way upon an
|
|
.BR strace (1)
|
|
attach.)
|
|
.SH SEE ALSO
|
|
.BR gdb (1),
|
|
.BR strace (1),
|
|
.BR clone (2),
|
|
.BR execve (2),
|
|
.BR fork (2),
|
|
.BR gettid (2),
|
|
.BR prctl (2),
|
|
.BR seccomp (2),
|
|
.BR sigaction (2),
|
|
.BR tgkill (2),
|
|
.BR vfork (2),
|
|
.BR waitpid (2),
|
|
.BR exec (3),
|
|
.BR capabilities (7),
|
|
.BR signal (7)
|