data built 2026-10-19T13:16:53Z

Look up another CVE · open CVE-2026-90347 in the interactive tracker

CVE-2026-90347

arm64: ptrace: Keep 'orig_x0' in-sync with x0 on syscall entry

8.4 EPSS 0.2% AV:L

Published 2026-09-17 (31 days ago) by the Linux kernel CNA. Subsystem arch/arm64. Debian urgency: not yet assigned.

What to do, per Debian release

Debian's own status for CVE-2026-90347 in every release this site tracks, and what each one means in practice. Every status below is the one the Debian Security Team publishes for this CVE. source

ReleaseStatus VersionWhat this means
Debian 12bookwormvulnerable6.1.190-1No fix published anywhere yet, neither in Debian nor upstream for the series bookworm tracks. Watch the Debian tracker page for this CVE. Advisories for bookworm have historically landed a median of 23 days after publication.
Debian 13trixievulnerable6.12.113-1No fix published anywhere yet, neither in Debian nor upstream for the series trixie tracks. Watch the Debian tracker page for this CVE. Advisories for trixie have historically landed a median of 11 days after publication.
Debian 14forkyfixed7.2.6-1Update the kernel and reboot. Fixed in 7.2.6-1. A running kernel keeps the old code until the machine restarts.
Debian unstablesidfixed7.2.6-1Update the kernel and reboot. Fixed in 7.2.6-1. A running kernel keeps the old code until the machine restarts.

The vulnerability

What the bug is

Commit e057b9477232 ("arm64: syscall: Ensure saved x0 is kept in-sync with tracer updates") attempted to resolve a long-standing issue with syscall entry tracing, where a tracer is able to manipulate the first syscall argument without being subjected to seccomp or audit checking. Unfortunately, that fix was incomplete [1], as it failed to update 'orig_x0' between a tracer updating x0 during a seccomp ptrace exit (SECCOMP_RET_TRACE) and the seccomp filter being re-evaluated. Rather than add hooks to the core seccomp code, instead move the synchronisation code into the ptrace GPR and syscall setting code so that 'orig_x0' is kept up to date with x0 whenever we're stopped on the syscall entry path.

Where it lives

The fix touches these files. If the subsystem is one you do not use, the practical exposure is lower, though the package is still the vulnerable one.

arch/arm64/kernel/ptrace.c

What this is
PTRACE SUPPORTMAINTAINERS section matched on arch/*/*/ptrace*.c · Maintained
Show whether Debian builds this, per release

Debian builds this code. Every release below compiles the affected file into the kernels it ships.

  • bookworm, trixie, forky, sidy
y
built into the kernel image on every flavour - only a patch removes it

From the configuration Debian publishes for every kernel flavour it builds. It covers only the architectures Debian ships a linux-config package for, and nothing about a kernel you built yourself. Debian's own status above stays authoritative about the source package.MAINTAINERS Debian linux-config packages

Signals

Published
2026-09-17 (31 days ago)source
CVSS
8.4 high
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:Nsource recompute it
Attack vector
local (AV:L)source
EPSS
0.17%, higher than 5.9% of all CVEssource
CISA KEV
not listedthe KEV catalogue
Debian urgency
not yet assignedsource
Subsystem
arch/arm64

Upstream fixes

The versions the CNA records as introducing and fixing this, and the commit for each. source

IntroducedFixed inCommit
4.86.18.57e9e2854fcff5
4.87.2.6f433869f2384
4.87.388b839ce497c

Why the CNA scored it this way

Quoted from the kernel CNA's own scoring file, word for word. A highlighted metric carries the most severe value CVSS v3.1 defines for it, which is what pushes the score up. source

AV:LAttack vector, local
The attacker-controlled value is x0 written by ptrace(PTRACE_SETREGSET, NT_PRSTATUS) into gpr_set() while the tracee is stopped in syscall_trace_enter() after ptrace_report_syscall_entry() or ptrace_event(PTRACE_EVENT_SECCOMP) from SECCOMP_RET_TRACE. That write is a local ptrace syscall, not a received protocol message.
AC:LAttack complexity, low
The tracer owns the stop: waitpid() for the PTRACE_SYSCALL enter-stop or PTRACE_EVENT_SECCOMP trap, PTRACE_SETREGSET to replace regs[0], then PTRACE_CONT. el0_svc_common() then reaches secure_computing() with orig_x0 still equal to the pre-ptrace x0. No race or uninfluenced layout is required.
PR:LPrivileges required, low
__ptrace_may_access() allows a same-uid tracer, and default yama ptrace_scope (YAMA_SCOPE_RELATIONAL) permits PTRACE_TRACEME or PTRACE_ATTACH to a descendant without CAP_SYS_PTRACE. An ordinary user can fork, trace the child, and issue PTRACE_SETREGSET; init-namespace root is not required.
UI:NUser interaction, none
The attacker issues PTRACE_TRACEME/PTRACE_SYSCALL, PTRACE_SETREGSET of NT_PRSTATUS, and the in-flight syscall on their own descendant. No separate victim action such as mounting a filesystem or opening a file is required.
S:CScope, changed
populate_seccomp_data() exposes orig_x0 as sd.args[0] to a parent-installed seccomp filter (container runtime, systemd RestrictNamespaces, Android minijail). gpr_set() updates regs[0] without orig_x0, so invoke_syscall() via SC_ARM64_REGS_TO_ARGS runs a denied first argument while the filter still allows the old orig_x0, escaping that sandbox.
C:HConfidentiality impact, high
syscall_get_arguments() returns stale orig_x0 to seccomp while __arm64_sys_* wrappers take regs[0]. A tracer starts an allowed openat(dfd) or socket(domain) and replaces x0 with a blocked directory fd or AF_NETLINK/AF_PACKET, so the syscall discloses files or netlink state the filter was written to deny.
I:HIntegrity impact, high
arm64 clone() takes clone_flags in x0 (CONFIG_CLONE_BACKWARDS). After gpr_set() writes regs[0] without orig_x0, __seccomp_filter() (including the SECCOMP_RET_TRACE recheck) still sees the allowed flags while invoke_syscall() honors CLONE_NEWUSER/CLONE_NEWNS the policy forbade; substituting write/ioctl's fd in x0 likewise modifies data the filter blocked.
A:NAvailability impact, none
The bug is orig_x0 remaining stale after gpr_set() so populate_seccomp_data() and audit_syscall_entry() inspect the wrong first argument. That is a seccomp/audit policy bypass, not memory corruption, and it does not oops, panic, deadlock, or hang the kernel.