Analysing Copy Fail, a logical flaw in the Linux kernel enabling root privilege escalation

May 7, 2026

The vulnerability CVE-2026-31431, better known as Copy Fail, is a Linux exploit that is rarely seen. Not because of its impact, which is a Local Privilege Elevation and several of these emerge each year, but due to a number of factors that we will break down throughout this article.

The first, and the one that has attracted the most attention, is this: it works on almost any Linux distribution released after 2017 using the same exploit. No tweaks, no special conditions, no need to win a TOCTOU race. You download the exploit, run it, and from an unprivileged account you become root reliably and with minimal effort.

This is possible because the vulnerability, which is a logical flaw, resides in a component present in all Linux kernels compiled since 2017. Specifically, it lies within the cryptographic subsystem, and more precisely in the AF_ALG interface, which allows it to be accessed from user space via sockets.

Through the interface provided by an AF_ALG socket, we access the kernel crypto API, including functions such as authencesn. Importantly, we are still an unprivileged user invoking functions from user space, and this API allows us to encrypt and decrypt buffers previously created by that same user.

So we have an open socket that provides access to the set of functions we need. Why this specific set? Because this is where the flaw resides.

The first step is to identify a system utility with the setuid bit set, a permission that allows a binary to execute certain operations with administrator or root privileges. Among the files we can “read” that have setuid are various system commands. The classic example is the ‘su’ command, which allows controlled execution of processes with root privileges.

As expected, the exploit opens the ‘su’ file, triggering a call to the syscall ‘read’ or similar, which results in a memory page cache being created with its contents.

Then, using the crypto API exposed by the socket, although we are not actually encrypting anything, we use this entry point as the exploitation vector for the logical flaw that we will now describe, in order to manipulate that page.

For now, it is enough to note that we have an open socket to the Linux kernel crypto API, and the contents of the ‘su’ command loaded into the system’s page cache.

The logical flaw

There is an unwritten golden rule in the kernel: it should not be possible to modify a file’s page cache without the kernel detecting it and marking that page as ‘dirty’.

When a page is marked as ‘dirty’, it means the memory content differs from the file stored on disk. At that point, the kernel schedules it to be synchronised through a write operation.

By design, to optimise load times and reuse, if someone invokes ‘su’, the kernel does not reload the binary from disk. Instead, it reuses the version already in memory because it has not been modified and matches the disk image exactly, meaning it is not marked as dirty.

Sounds reasonable, right?

Now imagine we can modify the cached page in memory and the kernel neither detects the change nor marks the page as dirty. That is precisely what is happening, and why the exploit works.

In fact, the name Copy Fail is no coincidence. It is also related to two other well known vulnerabilities of a similar nature: Dirty Pipe and, further back, Dirty Cow.

Moreover, an unprivileged user should not even be able to modify a cached page containing ‘su’, as they do not have, or should not have, the appropriate permissions.

The flaw allows, on the one hand, writing to the page cache and, on the other, having that write go unnoticed by the kernel without marking it as dirty.

The modification carried out, which is limited to four byte writes, patches certain checks within ‘su’ and alters its behaviour.

That is essentially it. Simply invoking ‘su’ will cause the kernel to execute the modified version in the page cache, resulting in a shell session with root privileges.

The exploit, step by step

There is a proof of concept published by the researchers themselves to verify whether systems are affected. It is written in Python; however, we have taken the liberty of renaming variables and adding comments to make it more instructive.

At the beginning of the exploit, we import the required modules and assign values to certain constants that appear as literals in the original version:

As mentioned, the cryptographic material is required to “speak” correctly with the socket, but we neither use it nor depend on it.

The core invocation of the exploit is as follows:

We read /usr/bin/su, which causes that page to be created in the kernel cache. Starting at offset zero, we decompress the shellcode and iterate over it in four byte chunks, which is the maximum we can write to the cached page due to the AEAD message format.

At the end, the system call executes ‘su’, but no longer the on-disk version, rather the maliciously patched one.

The function we have somewhat descriptively named abrir_socket_y_escribir (open_socket_and_write) essentially performs two tasks:

All that complexity is simply to prepare a properly structured message so that it satisfies format and cryptographic requirements, even though, as mentioned, we neither use nor rely on the result.

Once the message is prepared, we trigger the writing of those four byte chunks using the pipe function, which creates a Linux input output pipe, and splice, which directs the bytes to be patched to the cached page:

And that is it. This ultimately patches the page cache where ‘su’ resides and, once complete, the kernel, due to this logical flaw, does not mark the page cache as dirty and therefore uses it unchanged.

Analysis of the embedded shellcode patch

As you may have noticed, there is a form of hexadecimal encoded shellcode. By convention, we refer to it as shellcode:

It is not strictly shellcode, but rather a patch for ‘su’. In other words, it modifies the cached image of ‘su’, and most importantly, WITHOUT TOUCHING DISK.

This is worth emphasising. Like all diskless operations, it makes detection difficult for EDR solutions and similar tools. In SOC terms, almost undetectable.

The shell... patch is straightforward to reverse. We convert it from hexadecimal back into binary:

Can you spot the ELF header?

And once disassembled:

Simple, but serious. It simply spawns a shell, but since the process runs with root privileges, the shell inherits those privileges.

This is done in the classic way: syscall 0x69 corresponds to setuid with parameters set to zero, meaning root, followed by syscall 0x3b, equivalent to execve("/bin/sh", NULL, NULL).

Of course… AI

Another reason why this vulnerability is particularly noteworthy is that the team that discovered it relied on a proprietary Artificial Intelligence model called Xint Code, specifically fine tuned to identify vulnerabilities in code.

This is neither the first nor will it be the last case; we are already seeing this becoming the norm in vulnerability research.

More information about Copy Fail.

Kali GPT: the AI assistant for automation and analysis in Cybersecurity