XFRM xfrmi_changelink UAF (CVE-2025-38500)¶
xfrmi_changelink(), bircollect_mdxfrm interface üzerindeki değişiklikleri reddetmiyordu; bu da o özel device'ın, hâlâ per-netnscollect_mdpointer'ı tarafından sahiplenilirken normal xfrmi hash'ine eklenmesine yol açıyordu — network-namespace teardown sırasında bir double free (use-after-free).
CVE identifier note
Burada anlatılan xfrmi_changelink / collect_md use-after-free, NVD'de
CVE-2025-38500 olarak takip ediliyor ve mainline commit
a90b2a1aaacbcf0f91d7e4868ad6c51c5dee814b ile düzeltilmiş. CVE-2025-39965
alias'ı ise bazı tracker'larda komşu bir xfrm fix için kullanılıyor; asıl
referans olarak bug'ı (collect_md üzerinde xfrmi_changelink) kabul et ve
numaraya güvenmeden önce kesin CVE-to-commit eşleşmesini kendi dağıtımının
advisory'sine karşı doğrula.
Mechanism¶
Invariant: a collect_md xfrm interface is owned by exactly one pointer
collect_md property'siyle oluşturulan bir xfrm interface, her network namespace
için bir singleton'dır. Yalnızca xfrmi_net->collect_md_xfrmi üzerinden
erişilebilir ve normal xfrmi_net->xfrmi hash'inin dışında bilinçli olarak
tutulur. collect_md property'si sadece device creation sırasında
ayarlanabilir; dolayısıyla xfrmi_changelink() (link-change path'i) böyle bir
interface'i değiştirmeye yönelik her girişimi reddetmek zorundadır.
Bug şu: bunu zorlayan guard yalnızca interface'in xfrmi_locate() ile bulunduğu
branch'te çalışıyordu — ve xfrmi_locate() bilinçli olarak collect_md
interface'ini döndürmüyor. Yani changelink, collect_md device'ı üzerinde
çağrıldığında check atlanıyordu. Kod da singleton'ı, hâlâ collect_md_xfrmi
tarafından referans edilmesine ek olarak xfrmi_net->xfrmi hash'ine
yerleştiriyordu. Artık iki owner tek bir struct xfrm_if'e işaret ediyor.
Network namespace teardown edildiğinde her iki owner da aynı object'i free eder:
hash walk onu free eder, ardından collect_md teardown onu tekrar free eder — bir
double free, device unregistration sırasında UAF / kernel panic olarak gözlenir.
Genel şekli için refcount-imbalance-uaf'ye bak.
Fix, collect_md check'ini daha erkene taşır ve netdev_priv()'den zaten elde
edilebilen xi'yi kullanır; böylece hedef bir collect_md interface olduğunda
xfrmi_changelink(), herhangi bir list insertion'dan önce başarısız olur. Etkilenen
dosya net/xfrm/xfrm_interface_core.c.
Walkthrough¶
Bu, bir network namespace üzerinde CAP_NET_ADMIN'e sahip bir context tarafından
tetiklenebilir (örneğin netns'in sahibi olan unprivileged bir user namespace içindeki
root). Yalnızca yetkili bir lab ortamında çalıştır.
- Taze bir network namespace içinde bir
collect_mdxfrm interface oluştur:
# ip netns add lab
# ip netns exec lab ip link add xfrm-md type xfrm if_id 1 collect_md
# ip netns exec lab ip -d link show xfrm-md
xfrm-md@NONE: <NOARP> ... xfrm if_id 0x1 collect_md ...
- Vulnerable bir kernel'de link'i "change" et. Guard atlandığı için bu,
-EINVALdöndürmek yerine başarılı olur ve singleton'ı double-list eder:
Patched bir kernel'de aynı komut temiz şekilde başarısız olur:
- Double free'yi patlatmak için namespace'i free et. Netns'i silmek, artık çift sahipli olan interface'i iki kez free eden teardown path'ini çalıştırır:
KASAN'lı bir kernel, unregistration sırasında double free / UAF'i raporlar:
BUG: KASAN: slab-use-after-free in xfrmi_dev_uninit / netdev teardown
Call Trace:
...
xfrmi_exit_batch_rtnl
cleanup_net
Turning the double free into a primitive
Sabit boyutlu bir struct xfrm_if object'inin double free'si, alışılmış heap
teknikleriyle escalate edilebilir: free edilmiş iki slot'tan birini kontrollü bir
object ile reclaim et (slab-grooming,
kmalloc-cache-feng-shui), ya da bir cross-cache
page-level primitive'e dönüştür (cross-cache-attack).
Kontrol path'i, root için alışıldık commit-creds ile sonlanır.
Detection¶
- KASAN/
CONFIG_SLUB_DEBUG, netns teardown sırasında slab-use-after-free'yi işaretler. - Davranışsal olarak: bir user+net namespace oluşturan, bir
collect_mdxfrm interface ekleyen, onun üzerinde birRTM_NEWLINKchange yapan ve ardından namespace'i silen unprivileged bir process, tam olarak bu trigger dizisidir.
Mitigation¶
- Fix'i (
a90b2a1aaacbcf0f91d7e4868ad6c51c5dee814b) ve onun stable backport'larını uygula; bu değişiklikxfrmi_changelink()'incollect_mdinterface'lerini reddetmesini sağlar. - Unprivileged user namespace'lerin gerekmediği yerlerde onları kısıtla (bunları
sunan dağıtımlarda
kernel.unprivileged_userns_clone=0); böyleceCAP_NET_ADMIN-in-namespace path'i ortadan kalkar. - Genel slab hardening (
CONFIG_SLAB_FREELIST_HARDENED,init_on_free=1), free edilmiş object'i weaponize etmenin maliyetini artırır.