Remediation Guides

Ensure ptrace_scope Is Restricted: How to Set kernel.yama.ptrace_scope on Linux

26 September 2026 8 min read

“Ensure ptrace_scope is restricted” is a CIS benchmark check that fails when the Yama kernel setting kernel.yama.ptrace_scope is 0. At 0, any process can attach to and read the memory of other processes running as the same user. To fix it, add kernel.yama.ptrace_scope = 1 to /etc/sysctl.d/60-kernel_sysctl.conf and run sysctl -w kernel.yama.ptrace_scope=1.

On Red Hat Enterprise Linux 9 and its rebuilds, a file shipped by the distribution sets the value to 0, so hosts fail out of the box. Ubuntu ships a file that sets 1, so a failure there means someone changed it.

What the scanner is actually detecting

This finding comes from a Tenable compliance scan (Nessus or another Tenable product) running a CIS Linux benchmark audit file over an authenticated SSH session. It is a configuration check that reports PASSED or FAILED, not a vulnerability plugin, and there is no CVE behind it. The remediation text covers both the running kernel value and the sysctl files that set it at boot, so you need to fix both.

The title and item number depend on the benchmark and its version:

Tenable audit Item title
CIS Rocky Linux 9 v2.0.0 L1 Server, CIS Red Hat Enterprise Linux 9 v2.0.0 L1 Server 1.5.2 Ensure ptrace_scope is restricted
CIS Red Hat EL8 Server L1 v3.0.0 1.4.2 Ensure ptrace_scope is restricted
CIS Ubuntu Linux 22.04 LTS v2.0.0, CIS Ubuntu Linux 24.04 LTS v1.0.0, CIS Debian Linux 12 v1.1.0 (L1 Server) 1.5.2 Ensure ptrace_scope is restricted
CIS Debian Linux 12 v2.0.0, CIS Ubuntu Linux 24.04 LTS v2.0.0 (L1 Server) 1.5.3 Ensure kernel.yama.ptrace_scope is configured
CIS Red Hat Enterprise Linux 10 v1.0.0 L1 Server 1.5.7 Ensure kernel.yama.ptrace_scope is configured
DISA Red Hat Enterprise Linux 9 STIG RHEL-09-213080 RHEL 9 must restrict usage of ptrace to descendant processes

Search your report by title rather than item number, because numbering shifts between versions. The accepted value also differs. The Rocky Linux 9, RHEL 9, RHEL 8 and Ubuntu 22.04 audits above document only 1, and so does the RHEL 9 STIG. The Ubuntu 24.04, Debian 12 and RHEL 10 audits accept 1, 2 or 3.

Real-world risk, stated honestly

ptrace lets one process observe and control another, including reading and changing its memory and registers. It is what gdb and strace use. The kernel documentation describes the concern directly: if one application is compromised, an attacker can attach to the user’s other processes, such as SSH sessions or a GPG agent, and pull credentials out of memory. The four values are:

  • 0 (classic): a process can attach to any other process running under the same UID, as long as it is dumpable.
  • 1 (restricted): a process can only attach to its own descendants, unless the target names an allowed debugger with prctl(PR_SET_PTRACER). Processes with CAP_SYS_PTRACE, normally root, are not restricted.
  • 2 (admin-only): only processes with CAP_SYS_PTRACE can attach, and the same applies to tracing children that call PTRACE_TRACEME.
  • 3 (no attach): no process can attach at all. Once set, the value cannot be changed until the next boot.

The restriction is wider than the ptrace() call itself. Per ptrace(2), Yama limits every operation that performs a PTRACE_MODE_ATTACH check, and process_vm_readv(2) uses such a check to read another process’s memory.

Keep the scope in proportion. This is local hardening: the attacker must already be running code as that user. It does nothing against root, and ptrace(2) notes that user namespaces weaken values 1 and 2 for processes that use them to sandbox themselves. The Debian 12 v2.0.0 audit text adds that value 2 cuts off the exploit path for CVE-2026-46333, a kernel ptrace access-check flaw, on unpatched systems. The real fix for that CVE is a kernel update.

How to confirm it on the host

# 1. Live value (expect 1, or 2 or 3 if your audit accepts them)
sysctl kernel.yama.ptrace_scope

# 2. Is Yama active? (the list should include yama)
cat /sys/kernel/security/lsm; echo

# 3. Every sysctl file that sets it
grep -Hs 'ptrace_scope' /etc/sysctl.conf /etc/sysctl.d/*.conf /run/sysctl.d/*.conf 
  /usr/local/lib/sysctl.d/*.conf /usr/lib/sysctl.d/*.conf /lib/sysctl.d/*.conf

# 4. Files in the order systemd applies them at boot
#    (older Debian and Ubuntu: /lib/systemd/systemd-sysctl)
/usr/lib/systemd/systemd-sysctl --cat-config --no-pager | grep -E '^# /|ptrace_scope'

# 5. RHEL family: which package owns the vendor file
rpm -qf /usr/lib/sysctl.d/10-default-yama-scope.conf

On the RHEL 9 family, step 3 normally shows /usr/lib/sysctl.d/10-default-yama-scope.conf setting 0. It belongs to the elfutils-default-yama-scope package, which elfutils-libs requires, and the package’s install scriptlet applies that file to the running kernel whenever the package is installed or updated. On Ubuntu, /etc/sysctl.d/10-ptrace.conf from the procps package sets 1.

Precedence decides which line wins. Per sysctl.d(5), files must end in .conf and are sorted by file name regardless of directory, so the last name wins, and a file in /etc replaces a file with the same name in /usr/lib. Per sysctl(8), sysctl –system reads /etc/sysctl.conf last.

How to fix it

Step 1: comment out lines that set 0 (all distributions)

For each file under /etc that the grep listed with a 0:

sudo sed -ri 's/^s*kernel.yama.ptrace_scopes*=s*0b/# &/' /etc/sysctl.conf

Do not edit files under /usr/lib/sysctl.d. They belong to packages and are restored on update.

Step 2: set the value persistently

printf '%sn' 'kernel.yama.ptrace_scope = 1' | sudo tee -a /etc/sysctl.d/60-kernel_sysctl.conf

This is the file name the CIS remediation uses, and the 60 prefix sorts after vendor files numbered 10. If the file already has a ptrace_scope line, edit it instead of adding a second one.

Step 3: mask the vendor file (RHEL, Rocky, AlmaLinux, Oracle Linux)

sudo ln -s /dev/null /etc/sysctl.d/10-default-yama-scope.conf

sysctl.d(5) documents a /dev/null symlink with the same name as the way to disable a vendor file. Your 60 file already wins at boot, but without the mask, the next update of elfutils-default-yama-scope puts 0 back into the running kernel until the host reboots.

Step 4: apply it to the running kernel

sudo sysctl -w kernel.yama.ptrace_scope=1
sudo sysctl --system

The second command reloads every file and prints what it applies. The last kernel.yama.ptrace_scope line in its output should be 1.

Choosing 2 or 3 instead

Use 2 on servers where only root ever debugs, but only if your audit version accepts it. Use 3 only on hosts that will never need ptrace, and test on one machine first: nothing, root included, can lower it again without a reboot.

How to verify the fix and rescan

  1. Run sysctl kernel.yama.ptrace_scope and confirm the value.
  2. If strace is installed, test the behavior as a normal user. With 1 or 2, the first attach should fail with “Operation not permitted”, while the sudo attach still works (press Ctrl+C to detach):
    sleep 300 &
    strace -p $!
    sudo strace -p $!
    kill %1
  3. Reboot once if you can, then repeat step 1 to prove that no later file puts the old value back.
  4. Rerun the same compliance scan with the same audit file and credentials. If the scan cannot read /etc/sysctl.d or run sysctl, see our guide to configuring SSH and sudo credentials for Linux authenticated scans.

What can break and how to roll back

  • Value 1. A normal user can no longer run gdb -p or strace -p against a process that is not their own child, and the same applies to other tools that attach to a running process as the same user. Starting a program under the tool (gdb ./prog, strace ./prog) still works, and so does sudo gdb -p PID. Crash handlers that use PR_SET_PTRACER, which the kernel documentation says KDE, Chromium, Firefox and Wine do, keep working.
  • Value 2. Everything above, plus normal users can no longer trace even their own children, so developers need sudo for any debugging.
  • Value 3. No debugging or tracing at all until reboot, for any user.
  • Rollback. Remove the line from /etc/sysctl.d/60-kernel_sysctl.conf, remove the /dev/null symlink, uncomment anything you disabled, and run sudo sysctl -w kernel.yama.ptrace_scope=0 (writing the value needs CAP_SYS_PTRACE). If 3 was applied, remove it from the files and reboot.

For a one-off debugging session, attach with sudo rather than lowering the setting for the whole host.

Common false positive reasons

  • Half-applied fix. Running only sysctl -w passes the live check but not the file check, and writing only the file does the opposite until the next boot.
  • No explicit line. ptrace(2) lists 1 as the default when Yama is built in, so a host can show 1 live with no configuration line. The remediation still asks for one.
  • Stricter value, older audit. If you chose 2 or 3 and an audit that documents only 1 (or the RHEL 9 STIG) fails, check the policy value before calling it a false positive.
  • Package update. On RHEL-family hosts without the mask from step 3, the value drops to 0 after an elfutils update. That is a real regression.
  • Yama not active. If /proc/sys/kernel/yama/ptrace_scope does not exist, the kernel was built without CONFIG_SECURITY_YAMA or Yama is not in the active LSM list. No sysctl file can fix that; you need a kernel with Yama enabled.
  • Scanning inside a container. The kernel documentation describes Yama’s protections as system-wide, so a container sees the host’s value. Fix it on the host.

FAQ

Should I set kernel.yama.ptrace_scope to 1, 2 or 3?

1 satisfies every audit version listed above and the RHEL 9 STIG, and it keeps normal debugging workflows. Choose 2 only where your audit accepts it and only root debugs. Avoid 3 unless you are sure nobody will need ptrace before the next reboot.

Does restricted ptrace stop root from debugging?

No. Under 1 and 2, processes with CAP_SYS_PTRACE, normally root, can still attach, so sudo gdb -p and sudo strace -p work. Only 3 blocks root.

Do I need to reboot after the change?

No. sysctl -w applies immediately. A reboot is only useful to prove the setting survives boot.

Why did the value go back to 0 on a RHEL 9 host?

Usually because an update of elfutils-default-yama-scope reapplied its file, or because a file that sorts after yours sets 0. Mask the vendor file as in step 3 and check the order with systemd-sysctl –cat-config.

Tracking this finding across many hosts

On a large RHEL-family estate, the recurring problem is the host where a package update quietly puts 0 back. If you use SITEY, you can upload the .nessus export from the compliance scan and have its AI draft a host-specific remediation script. The script runs only after a human approves it, its agents deploy it on Linux endpoints, and a re-test then verifies the finding is closed.

Sources

SITEY closes the loop, not just the report.Discover, validate, fix and verify in your own infrastructure.

See pricing