Путеводитель по Руководству Linux

  User  |  Syst  |  Libr  |  Device  |  Files  |  Other  |  Admin  |  Head  |



   ptrace    ( 2 )

трассировка процесса (process trace)

  Name  |  Synopsis  |  Description  |  Return value  |  Error  |  Conforming to  |    Note    |  Bugs  |  See also  |

Примечание (Note)

Although arguments to ptrace() are interpreted according to the prototype given, glibc currently declares ptrace() as a variadic function with only the request argument fixed. It is recommended to always supply four arguments, even if the requested operation does not use them, setting unused/ignored arguments to 0L or (void *) 0.

In Linux kernels before 2.6.26, init(1), the process with PID 1, may not be traced.

A tracees parent continues to be the tracer even if that tracer calls execve(2).

The layout of the contents of memory and the USER area are quite operating-system- and architecture-specific. The offset supplied, and the data returned, might not entirely match with the definition of struct user.

The size of a "word" is determined by the operating-system variant (e.g., for 32-bit Linux it is 32 bits).

This page documents the way the ptrace() call works currently in Linux. Its behavior differs significantly on other flavors of UNIX. In any case, use of ptrace() is highly specific to the operating system and architecture.

Ptrace access mode checking Various parts of the kernel-user-space API (not just ptrace() operations), require so-called "ptrace access mode" checks, whose outcome determines whether an operation is permitted (or, in a few cases, causes a "read" operation to return sanitized data). These checks are performed in cases where one process can inspect sensitive information about, or in some cases modify the state of, another process. The checks are based on factors such as the credentials and capabilities of the two processes, whether or not the "target" process is dumpable, and the results of checks performed by any enabled Linux Security Module (LSM)—for example, SELinux, Yama, or Smack—and by the commoncap LSM (which is always invoked).

Prior to Linux 2.6.27, all access checks were of a single type. Since Linux 2.6.27, two access mode levels are distinguished:

PTRACE_MODE_READ For "read" operations or other operations that are less dangerous, such as: get_robust_list(2); kcmp(2); reading /proc/[pid]/auxv, /proc/[pid]/environ, or /proc/[pid]/stat; or readlink(2) of a /proc/[pid]/ns/* file.

PTRACE_MODE_ATTACH For "write" operations, or other operations that are more dangerous, such as: ptrace attaching (PTRACE_ATTACH) to another process or calling process_vm_writev(2). (PTRACE_MODE_ATTACH was effectively the default before Linux 2.6.27.)

Since Linux 4.5, the above access mode checks are combined (ORed) with one of the following modifiers:

PTRACE_MODE_FSCREDS Use the caller's filesystem UID and GID (see credentials(7)) or effective capabilities for LSM checks.

PTRACE_MODE_REALCREDS Use the caller's real UID and GID or permitted capabilities for LSM checks. This was effectively the default before Linux 4.5.

Because combining one of the credential modifiers with one of the aforementioned access modes is typical, some macros are defined in the kernel sources for the combinations:

PTRACE_MODE_READ_FSCREDS Defined as PTRACE_MODE_READ | PTRACE_MODE_FSCREDS.

PTRACE_MODE_READ_REALCREDS Defined as PTRACE_MODE_READ | PTRACE_MODE_REALCREDS.

PTRACE_MODE_ATTACH_FSCREDS Defined as PTRACE_MODE_ATTACH | PTRACE_MODE_FSCREDS.

PTRACE_MODE_ATTACH_REALCREDS Defined as PTRACE_MODE_ATTACH | PTRACE_MODE_REALCREDS.

One further modifier can be ORed with the access mode:

PTRACE_MODE_NOAUDIT (since Linux 3.3) Don't audit this access mode check. This modifier is employed for ptrace access mode checks (such as checks when reading /proc/[pid]/stat) that merely cause the output to be filtered or sanitized, rather than causing an error to be returned to the caller. In these cases, accessing the file is not a security violation and there is no reason to generate a security audit record. This modifier suppresses the generation of such an audit record for the particular access check.

Note that all of the PTRACE_MODE_* constants described in this subsection are kernel-internal, and not visible to user space. The constant names are mentioned here in order to label the various kinds of ptrace access mode checks that are performed for various system calls and accesses to various pseudofiles (e.g., under /proc). These names are used in other manual pages to provide a simple shorthand for labeling the different kernel checks.

The algorithm employed for ptrace access mode checking determines whether the calling process is allowed to perform the corresponding action on the target process. (In the case of opening /proc/[pid] files, the "calling process" is the one opening the file, and the process with the corresponding PID is the "target process".) The algorithm is as follows:

1. If the calling thread and the target thread are in the same thread group, access is always allowed.

2. If the access mode specifies PTRACE_MODE_FSCREDS, then, for the check in the next step, employ the caller's filesystem UID and GID. (As noted in credentials(7), the filesystem UID and GID almost always have the same values as the corresponding effective IDs.)

Otherwise, the access mode specifies PTRACE_MODE_REALCREDS, so use the caller's real UID and GID for the checks in the next step. (Most APIs that check the caller's UID and GID use the effective IDs. For historical reasons, the PTRACE_MODE_REALCREDS check uses the real IDs instead.)

3. Deny access if neither of the following is true:

• The real, effective, and saved-set user IDs of the target match the caller's user ID, and the real, effective, and saved-set group IDs of the target match the caller's group ID.

• The caller has the CAP_SYS_PTRACE capability in the user namespace of the target.

4. Deny access if the target process "dumpable" attribute has a value other than 1 (SUID_DUMP_USER; see the discussion of PR_SET_DUMPABLE in prctl(2)), and the caller does not have the CAP_SYS_PTRACE capability in the user namespace of the target process.

5. The kernel LSM security_ptrace_access_check() interface is invoked to see if ptrace access is permitted. The results depend on the LSM(s). The implementation of this interface in the commoncap LSM performs the following steps:

a) If the access mode includes PTRACE_MODE_FSCREDS, then use the caller's effective capability set in the following check; otherwise (the access mode specifies PTRACE_MODE_REALCREDS, so) use the caller's permitted capability set.

b) Deny access if neither of the following is true:

• The caller and the target process are in the same user namespace, and the caller's capabilities are a superset of the target process's permitted capabilities.

• The caller has the CAP_SYS_PTRACE capability in the target process's user namespace.

Note that the commoncap LSM does not distinguish between PTRACE_MODE_READ and PTRACE_MODE_ATTACH.

6. If access has not been denied by any of the preceding steps, then access is allowed.

/proc/sys/kernel/yama/ptrace_scope On systems with the Yama Linux Security Module (LSM) installed (i.e., the kernel was configured with CONFIG_SECURITY_YAMA), the /proc/sys/kernel/yama/ptrace_scope file (available since Linux 3.4) can be used to restrict the ability to trace a process with ptrace() (and thus also the ability to use tools such as strace(1) and gdb(1)). The goal of such restrictions is to prevent attack escalation whereby a compromised process can ptrace-attach to other sensitive processes (e.g., a GPG agent or an SSH session) owned by the user in order to gain additional credentials that may exist in memory and thus expand the scope of the attack.

More precisely, the Yama LSM limits two types of operations:

* Any operation that performs a ptrace access mode PTRACE_MODE_ATTACH check—for example, ptrace() PTRACE_ATTACH. (See the "Ptrace access mode checking" discussion above.)

* ptrace() PTRACE_TRACEME.

A process that has the CAP_SYS_PTRACE capability can update the /proc/sys/kernel/yama/ptrace_scope file with one of the following values:

0 ("classic ptrace permissions") No additional restrictions on operations that perform PTRACE_MODE_ATTACH checks (beyond those imposed by the commoncap and other LSMs).

The use of PTRACE_TRACEME is unchanged.

1 ("restricted ptrace") [default value] When performing an operation that requires a PTRACE_MODE_ATTACH check, the calling process must either have the CAP_SYS_PTRACE capability in the user namespace of the target process or it must have a predefined relationship with the target process. By default, the predefined relationship is that the target process must be a descendant of the caller.

A target process can employ the prctl(2) PR_SET_PTRACER operation to declare an additional PID that is allowed to perform PTRACE_MODE_ATTACH operations on the target. See the kernel source file Documentation/admin-guide/LSM/Yama.rst (or Documentation/security/Yama.txt before Linux 4.13) for further details.

The use of PTRACE_TRACEME is unchanged.

2 ("admin-only attach") Only processes with the CAP_SYS_PTRACE capability in the user namespace of the target process may perform PTRACE_MODE_ATTACH operations or trace children that employ PTRACE_TRACEME.

3 ("no attach") No process may perform PTRACE_MODE_ATTACH operations or trace children that employ PTRACE_TRACEME.

Once this value has been written to the file, it cannot be changed.

With respect to values 1 and 2, note that creating a new user namespace effectively removes the protection offered by Yama. This is because a process in the parent user namespace whose effective UID matches the UID of the creator of a child namespace has all capabilities (including CAP_SYS_PTRACE) when performing operations within the child user namespace (and further-removed descendants of that namespace). Consequently, when a process tries to use user namespaces to sandbox itself, it inadvertently weakens the protections offered by the Yama LSM.

C library/kernel differences At the system call level, the PTRACE_PEEKTEXT, PTRACE_PEEKDATA, and PTRACE_PEEKUSER requests have a different API: they store the result at the address specified by the data parameter, and the return value is the error flag. The glibc wrapper function provides the API given in DESCRIPTION above, with the result being returned via the function return value.