Skip to content

AF_ALG crypto socket attack surface

AF_ALG (algif) socket ailesi, kernel'in tüm crypto subsystem'ini unprivileged userspace'e açar; bu da karmaşık ve bug açısından zengin, erişilebilir bir attack surface oluşturur.

Mechanism

Note

AF_ALG, userspace'in in-kernel crypto API'sini (cipher'lar, hash'ler, AEAD, RNG'ler) socket'ler üzerinden sürmesine izin verir — aslında dahili tüketiciler (IPsec, dm-crypt, WireGuard) için tasarlanmış bir işlevsellik. Herhangi bir unprivileged process bir tane açabilir, hiçbir capability gerekmez; ve seccomp yoksa bir container UID'sinden bağımsız olarak buna erişebilir. Yapısal kırılganlık — karmaşık reference counting, async completion callback'leri ve error-path scatter-gather handling — geniş unprivileged erişilebilirlikle birleşince burayı sürekli tekrar eden bir LPE bug kaynağı yapar.

Walkthrough

Bir crypto transform aç ve bind et, sonra üzerinde işlem yap:

int alg = socket(AF_ALG, SOCK_SEQPACKET, 0);    /* AF_ALG = 38 */
struct sockaddr_alg sa = {
    .salg_family = AF_ALG,
    .salg_type   = "aead",
    .salg_name   = "gcm(aes)",
};
bind(alg, (struct sockaddr *)&sa, sizeof(sa));
setsockopt(alg, SOL_ALG, ALG_SET_KEY, key, keylen);
int op = accept(alg, NULL, NULL);               /* child operation socket */
/* data in/out via sendmsg()/recvmsg() (and splice()) on `op` */

Parent üzerinde accept() çağrısı, her işlem için ayrı bir child socket üretir; algif_aead, algif_hash, algif_skcipher ise af_alg core'unun üzerinde demand-loaded modüllerdir.

Bu surface üzerinden erişilebilen, doğrulanmış temsili bug'lar:

  • CVE-2019-8912af_alg_release_parent() içinde UAF: bir child'ın aktif bir işlemde olup olmadığını kontrol etmeden parent'ın refcount'unu düşüren bir refcount race.
  • CVE-2021-3543aead_sendmsg() içinde NULL deref: önceki başarısız bir recvmsg() sonrasında gelen bir sendmsg(), ctx->tsgl'i NULL bırakıyordu.
  • CVE-2026-31431 ("Copy Fail") — 2017'den kalma bir in-place optimizasyonu req->src = req->dst ataması yapar ve tag page'leri sg_chain() ile output scatterlist'e zincirler. Userspace socket'i splice() ile beslediğinde, bu tag page'ler spliced dosyanın page cache'ini refere eder; böylece AEAD write cache'lenmiş dosya verisine düşer — file permission'ları bypass eden, arbitrary bir page-cache page'ine 4-byte'lık bir write. PoC: authencesn(hmac(sha256),cbc(aes))'e bind et, /usr/bin/su'nun page cache'ini pipeline'a splice() et, sonra hedef page'e düşen 4-byte'lık bir payload'u recvmsg() et; shellcode'u aşamalı yerleştirmek ve escalate etmek için tekrarla.

Warning

"Copy Fail"'deki page-cache write, kernel page cache'inde kalıcı olur ve eviction'a kadar güvenilen, on-disk bir binary'nin in-memory image'ini tüm kullanıcılar için bozar — güçlü ama gürültülü bir primitive.

Detection

Güvenilmeyen context'lerden bir AF_ALG SOCK_SEQPACKET socket oluşturulmasını flag'le; normal uygulama workload'larında bu nadirdir.

Mitigation

  • socket(AF_ALG, ...) üzerine bir seccomp filter koyarak AF_ALG socket oluşturmayı blokla.
  • Userspace crypto socket'lerine ihtiyaç yoksa ilgili config'i (örn. CONFIG_CRYPTO_USER_API_AEAD) devre dışı bırak.
  • Kernel'leri patch'li tut: yukarıdaki doğrulanmış bug'lar ilgili stable release'lerinde düzeltilmiştir (örn. "Copy Fail" 7.0 / 6.19.12 / 6.18.22 sürümlerinde fix'lendi).

References