Логотип exploitDog
Консоль
Логотип exploitDog

exploitDog

redhat логотип

CVE-2026-99018

Опубликовано: 23 окт. 2026
Источник: redhat
CVSS3: 7.8
EPSS Низкий

Описание

In the Linux kernel, the following vulnerability has been resolved: riscv: entry: gate shadow call stack reload on sstatus.SPP, not tp Under CONFIG_SHADOW_CALL_STACK, handle_exception() reloads the kernel shadow call stack pointer (gp) only when the trap came from userspace. It made that decision with scs_load_current_if_task_changed, which compares the trap-time tp (read back from sscratch into s5) against the current tp: beq\prev, tp, _skip_scs scs_load_current _skip_scs: tp is a user-writable register. A user task that sets tp to the linear-map address of its own task_struct (&current) before trapping makes the comparison succeed (can achieve by brute force with KASLR enable under our test), so the kernel skips scs_load_current and keeps running with the gp that userspace left in place. Under CONFIG_SHADOW_CALL_STACK gp is the shadow call stack pointer and load_global_pointer is a no-op, so the compiler-emitted "sd ra, -8(gp)" / "ld ra, -8(gp)" in every non-leaf function then write to, and return through, an attacker-controlled address -- an unprivileged kernel arbitrary-write and control-flow-hijack primitive. The poisoned gp is saved to task_struct.scs_sp on return, so the reload is skipped on every subsequent entry as well. Decide "came from userspace" from the hardware sstatus.SPP bit (already in s1 at this point) instead of from tp, mirroring the check that ret_from_exception already uses a few instructions later. SPP is written by hardware on trap entry and cannot be forged from U-mode. Legitimate behaviour is unchanged: user entries (SPP=0) reload the task shadow call stack, nested kernel entries (SPP=1) skip it.

A flaw was found in the Linux kernel's RISC-V architecture support. When Shadow Call Stack (SCS), a security feature designed to protect function return addresses, is enabled, the kernel incorrectly validates whether an exception originated from userspace using a user-modifiable register. An unprivileged local attacker can exploit this flaw by manipulating the register before triggering an exception, tricking the kernel into skipping the reload of the protected stack pointer. This issue allows the attacker to corrupt memory and hijack kernel control flow, leading to arbitrary code execution and privilege escalation.

Отчет

This flaw is rated as Important because a local unprivileged user can compromise kernel control-flow integrity to obtain elevated privileges instead of causing a standard system crash. Exploitation is strictly confined to RISC-V platforms built with Shadow Call Stack functionality enabled. Supported enterprise environments running on non-RISC-V architectures do not execute this architecture-specific exception code and are unaffected.

Меры по смягчению последствий

--- CME Mitigation Guidance (2026-11-02) --- Disclaimer: The following mitigation solutions are provided as a courtesy, pending the application of an official patch. This content was generated utilizing AI tools in conjunction with data from https://cmetaxonomy.org. Customers are advised to independently evaluate and test these temporary mitigations within their own infrastructure. The highest-value action is to ensure the kernel gates shadow call stack reload operations strictly on hardware exception status rather than user-writable thread-pointer registers: upgrade to the fixed Openshift/Ose Rhel Coreos builds, which gate shadow call stack pointer reload on the hardware sstatus.SPP bit instead of the user-writable tp register, closing user thread-pointer register manipulation. Until patched, this is only a concern on Linux systems on RISC-V architecture with CONFIG_SHADOW_CALL_STACK enabled — Deployments running on non-RISC-V architectures are unaffected — so Restrict untrusted local account access and prevent unauthorized local code execution on RISC-V hosts where CONFIG_SHADOW_CALL_STACK is enabled. As a compensating measure, Enforce SELinux to constrain post-exploitation actions and lateral movement if kernel control flow is hijacked, Configure SELinux confined user mappings to limit local user domains and execution privileges, Deploy EDR agents to monitor and detect anomalous privilege escalation behaviors and execution patterns, Utilize Falco or eBPF runtime security to detect unexpected root process execution and privilege alterations, Enable runtime memory error detection such as KASAN or HWASan to catch out-of-bounds accesses caused by corrupted stack pointers, and Enable Supervisor Mode Access Prevention to block the kernel from accessing or writing to userspace memory addresses. These controls limit blast radius and contain exploitation, but they do not fix the underlying improper shadow call stack pointer reload defect — apply the upstream patch to fully remediate. Highest-impact CME: CME-301 SELinux (Enforcing Mode) (medium)

Затронутые пакеты

ПлатформаПакетСостояниеРекомендацияРелиз
Red Hat Enterprise Linux 10kernelNot affected
Red Hat Enterprise Linux 6kernelNot affected
Red Hat Enterprise Linux 7kernelNot affected
Red Hat Enterprise Linux 7kernel-rtNot affected
Red Hat Enterprise Linux 8kernelNot affected
Red Hat Enterprise Linux 8kernel-rtNot affected
Red Hat Enterprise Linux 9kernelNot affected
Red Hat Enterprise Linux 9kernel-rtNot affected
Red Hat OpenShift Container Platform 4openshift/ose-rhel-coreos-8Not affected
Red Hat OpenShift Container Platform 4openshift/ose-rhel-coreos-9Not affected

Показывать по

Дополнительная информация

Статус:

Important
Дефект:
CWE-822
https://bugzilla.redhat.com/show_bug.cgi?id=2559704kernel: kernel: privilege escalation via improper shadow call stack pointer reload on RISC-V

EPSS

Процентиль: 7%
0.00175
Низкий

7.8 High

CVSS3

Связанные уязвимости

CVSS3: 7.8
ubuntu
17 дней назад

In the Linux kernel, the following vulnerability has been resolved: riscv: entry: gate shadow call stack reload on sstatus.SPP, not tp Under CONFIG_SHADOW_CALL_STACK, handle_exception() reloads the kernel shadow call stack pointer (gp) only when the trap came from userspace. It made that decision with scs_load_current_if_task_changed, which compares the trap-time tp (read back from sscratch into s5) against the current tp: beq \prev, tp, _skip_scs scs_load_current _skip_scs: tp is a user-writable register. A user task that sets tp to the linear-map address of its own task_struct (&current) before trapping makes the comparison succeed (can achieve by brute force with KASLR enable under our test), so the kernel skips scs_load_current and keeps running with the gp that userspace left in place. Under CONFIG_SHADOW_CALL_STACK gp is the shadow call stack pointer and load_global_pointer is a no-op, so the compiler-emitted "sd ra, -8(gp)" / "ld ra, -8(gp)" in every non-leaf function then ...

CVSS3: 7.8
nvd
17 дней назад

In the Linux kernel, the following vulnerability has been resolved: riscv: entry: gate shadow call stack reload on sstatus.SPP, not tp Under CONFIG_SHADOW_CALL_STACK, handle_exception() reloads the kernel shadow call stack pointer (gp) only when the trap came from userspace. It made that decision with scs_load_current_if_task_changed, which compares the trap-time tp (read back from sscratch into s5) against the current tp: beq \prev, tp, _skip_scs scs_load_current _skip_scs: tp is a user-writable register. A user task that sets tp to the linear-map address of its own task_struct (&current) before trapping makes the comparison succeed (can achieve by brute force with KASLR enable under our test), so the kernel skips scs_load_current and keeps running with the gp that userspace left in place. Under CONFIG_SHADOW_CALL_STACK gp is the shadow call stack pointer and load_global_pointer is a no-op, so the compiler-emitted "sd ra, -8(gp)" / "ld ra, -8(gp)" in every non-leaf function th

CVSS3: 7.8
debian
17 дней назад

In the Linux kernel, the following vulnerability has been resolved: r ...

CVSS3: 7.8
github
17 дней назад

In the Linux kernel, the following vulnerability has been resolved: riscv: entry: gate shadow call stack reload on sstatus.SPP, not tp Under CONFIG_SHADOW_CALL_STACK, handle_exception() reloads the kernel shadow call stack pointer (gp) only when the trap came from userspace. It made that decision with scs_load_current_if_task_changed, which compares the trap-time tp (read back from sscratch into s5) against the current tp: beq \prev, tp, _skip_scs scs_load_current _skip_scs: tp is a user-writable register. A user task that sets tp to the linear-map address of its own task_struct (&current) before trapping makes the comparison succeed (can achieve by brute force with KASLR enable under our test), so the kernel skips scs_load_current and keeps running with the gp that userspace left in place. Under CONFIG_SHADOW_CALL_STACK gp is the shadow call stack pointer and load_global_pointer is a no-op, so the compiler-emitted "sd ra, -8(gp)" / "ld ra, -8(gp)" in every non-leaf function...

EPSS

Процентиль: 7%
0.00175
Низкий

7.8 High

CVSS3