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