Feb 18, 2026·6 min read·30 visits
The NVIDIA Tegra DRM driver forgot to release PID references after using them. Local attackers with access to the GPU render node can trigger infinite kernel memory leaks, eventually causing a Denial of Service (DoS) by exhausting the slab allocator.
A resource leak vulnerability in the Linux Kernel's `drm/tegra` subsystem allows local users to exhaust kernel memory by creating zombie PID references. The flaw stems from a missing `put_pid()` call in the interaction between `get_task_pid()` and `host1x_memory_context_alloc()`, turning the Tegra driver into a black hole for process structures.
Welcome to the Linux Kernel, where memory management is manual and forgetting to take out the trash can bring down an entire system. Today's subject is the drm/tegra subsystem, the Direct Rendering Manager driver for NVIDIA's Tegra System-on-Chip (SoC) series. These chips power everything from embedded AI boxes to automotive dashboards and the Nintendo Switch. In the world of kernel drivers, managing the lifecycle of objects is critical. When a driver needs to track a user-space process, it often grabs a reference to that process's PID structure.
In C, unlike managed languages like Python or Java, there is no garbage collector to sweep up your mess. If you grab a reference to an object, you are contractually obligated to release it. It's the "pottery barn rule" of kernel development: if you touch it, you probably own it until you say otherwise. Reference counting is the mechanism that keeps the kernel sanity intact.
CVE-2025-68233 is a classic tale of "I thought you were watching the kids." One function grabbed a reference, passed it to another, and assumed the recipient would handle the cleanup. The recipient, however, just borrowed it and walked away. The result? A struct pid that lives forever, occupying kernel memory long after the actual process has died—a zombie in the truest sense.
To understand this bug, you have to understand how Linux tracks processes. The kernel uses struct pid to represent a PID. Because PIDs are shared resources (used by signals, file descriptors, and drivers), they are reference-counted. The function get_task_pid() is used to acquire a reference. Internally, this increments an atomic counter. As long as that counter is greater than zero, the kernel cannot free the memory associated with that structure.
The vulnerability resides in the interaction between a caller function in the Tegra DRM driver and host1x_memory_context_alloc(). The code logic went something like this:
get_task_pid(current, PIDTYPE_PID) to get a handle on the current process.host1x_memory_context_alloc(...) to associate a memory context with that process.host1x_memory_context_alloc took ownership of the reference.Here is the punchline: host1x_memory_context_alloc did not take ownership. It used the PID to set up some context mapping and then returned. The caller, assuming the reference was consumed, never called put_pid(). This is a resource leak. Every time this code path is triggered (likely via a specific IOCTL), the reference count on that struct pid increments. Even if the user process terminates, the struct pid remains pinned in the slab allocator because the kernel thinks the Tegra driver is still using it.
Let's look at the smoking gun. The fix is embarrassingly simple, which highlights just how easy it is to miss these things during code review. The patch was applied to drivers/gpu/drm/tegra/uapi.c (or similar call site depending on the specific kernel version structure).
The Vulnerable Pattern:
// Get a reference to the current task's PID
struct pid *pid = get_task_pid(current, PIDTYPE_PID);
// Allocate the context.
// DEVELOPER ASSUMPTION: This function consumes 'pid'.
err = host1x_memory_context_alloc(client->host, dev, pid);
if (err < 0)
goto error;
// ... execution continues, 'pid' is never put.The Fix (Commit 6b572e5154af08ee13f8d2673e86f83bc5ff86cd):
struct pid *pid = get_task_pid(current, PIDTYPE_PID);
err = host1x_memory_context_alloc(client->host, dev, pid);
// FIX: We must release our reference to the PID here.
// host1x_memory_context_alloc does not take ownership.
put_pid(pid);
if (err < 0)
goto error;It is literally one line of code: put_pid(pid). Without this line, the struct pid leaks. While a single struct pid is small (a few hundred bytes), the accumulation causes fragmentation in the kernel's slab allocator (kmalloc caches). Furthermore, if the system has limits on the number of PID structures (not just the numerical PID value, but the backing memory), this can lead to an inability to spawn new processes or allocate kernel objects.
Exploiting this is trivial but tedious. It's not a flashy RCE where you pop a shell; it's a Denial of Service (DoS) where you choke the system until it turns blue. The attack requires access to the DRM device, typically /dev/dri/renderD128 or /dev/dri/card0. On most desktop and embedded Linux systems, any user in the video or render group has this access. This means a compromised low-privilege service or a local user can trigger it.
The Attack Chain:
host1x_memory_context_alloc path. This creates a new context—and leaks one PID reference.INT_MAX.struct pid or general kmalloc pools becomes exhausted. The OOM killer might trigger, but it can't free the leaked structures because the kernel still thinks they are in use.The beauty of this attack is its stealth. It looks like legitimate heavy usage of the GPU until the system suddenly freezes.
Why does this matter? Tegra chips are frequently used in "set-and-forget" devices: automotive infotainment, medical imaging displays, and edge AI boxes. These systems often run for months or years without rebooting. A slow memory leak here is a ticking time bomb. It might take a week or a month, but eventually, the device will become unstable and crash.
From a security perspective, this is a local DoS. In a multi-tenant environment (like a shared compute cluster using Jetson boards), one malicious user can bring down the node for everyone else. While it scores low on the CVSS scale (usually around 5.5 for local DoS), the operational impact on mission-critical embedded systems is high. You don't want your car's dashboard rebooting because a background process leaked too many PIDs.
Additionally, this highlights a weakness in code auditability. The mismatch between "caller frees" and "callee frees" semantics is a perennial source of bugs in C. Unless clearly documented, host1x_memory_context_alloc is an ambiguity trap waiting to snare the next developer who touches this code.
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
Linux Kernel Linux | >= 6.0, < 6.1.159 | 6.1.159 |
Linux Kernel Linux | >= 6.2, < 6.6.118 | 6.6.118 |
Linux Kernel Linux | >= 6.7, < 6.12.60 | 6.12.60 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-401 (Memory Leak) |
| Attack Vector | Local (IOCTL) |
| CVSS v3.1 (Est) | 5.5 (Medium) |
| EPSS Score | 0.00037 |
| Kernel Subsystem | drm/tegra |
| Exploit Maturity | PoC Possible (Trivial) |
Improper Release of Memory Before Removing Last Reference ('Memory Leak')
JupyterHub is vulnerable to an unauthenticated Denial of Service (DoS) vulnerability. Prior to version 5.5.0, form-based authenticators failed to restrict the size of the username input field on failed logins, allowing remote attackers to exhaust host storage and memory resources.
The self-hosted HTTP transport mode of @arikusi/deepseek-mcp-server (an MCP server for DeepSeek V4) exposes its JSON-RPC endpoint (POST /mcp) without authentication in versions 1.4.2 through 1.7.0. Unauthenticated clients can establish Model Context Protocol sessions and invoke tools, consuming the host's configured DeepSeek API key.
A Server-Side Template Injection (SSTI) leading to Remote Code Execution (RCE) was discovered in the mcp-contextforge-gateway package before version 1.0.0. The vulnerability stems from an unsandboxed Jinja2 template rendering environment combined with an unsafe fallback mechanism using Python's native str.format() function. Attackers with template modification access could bypass static regex filters to execute arbitrary commands on the hosting platform.
CVE-2026-55596 is a critical DOM-based Cross-Site Scripting (XSS) vulnerability in the Plate rich-text editor framework (specifically within the @platejs/media package). The issue stems from an optimization fast-path that short-circuits safety parsing if a provider or source URL is already declared on an element. Consequently, serialized documents carrying malicious javascript: URLs bypass protocol sanitization and are loaded directly into iframe elements, leading to code execution.
The npm package 'pickem' is vulnerable to a terminal escape-sequence injection (CWE-150). Unsanitized terminal outputs allow attackers to execute arbitrary shell commands via clipboard hijacking (OSC 52) or manipulate terminal displays through Control Sequence Introducers (CSI).
CVE-2026-55537 is a server-side request forgery (SSRF) and time-of-check time-of-use (TOCTOU) vulnerability in the PraisonAI multi-agent framework before version 4.6.58. The flaw exists in the job-submission component's webhook URL validation logic. When DNS resolution fails during verification, the application fails open, enabling attackers to register unresolvable URLs. When a completed job triggers the webhook, the application performs a fresh DNS resolution that attackers can manipulate to target internal resources.