Skip to content

net/sched CAKE qdisc OOB read (CVE-2021-47243)

CAKE qdisc'inin TCP-option parser'ı, option uzunluğunu sınırlamadan option'ları dolaşır ve packet buffer'ının ötesini okur — gerçek bir sch_cake out-of-bounds bug'ı. Not: bu başlıktaki CVE (CVE-2024-36974) bir CAKE bug'ını tanımlamaz; aşağıdaki uyarıya bakın.

CVE atıf uyarısı

NVD ve distro tracker'larına karşı doğrulandı: CVE-2024-36974 bir taprio qdisc bug'ıdır, CAKE değil. Açıklaması "net/sched: taprio: always validate TCA_TAPRIO_ATTR_PRIOMAP" der — userspace'in ikinci taprio_change() çağrısında valide edilmemiş bir priomap inject etmesine izin veren bir missing-validation sorunudur. sch_cake'te bir out-of-bounds write değildir.

Gerçek sch_cake out-of-bounds memory-safety bug'ı CVE-2021-47243'tür — "sch_cake: Fix out of bounds when parsing TCP options and header" — ve bu bir out-of-bounds read'tir, write değil. Bu sayfa o gerçek CAKE bug'ını belgeler; başlıktaki CVE/"OOB write" eşleşmesini unverified sayın.

Mechanism

Note

CAKE (Common Applications Kept Enhanced, net/sched/sch_cake.c) bir ACK filter olarak davranabilir: bir TCP pure-ACK'in gereksiz ve droppable olup olmadığına karar vermek için packet'in TCP header'ını parse eder ve TCP option'larını dolaşır. Helper'lar şunlardır: cake_get_tcphdr() (TCP header'ı bul/valide et), cake_get_tcpopt() (belirli bir option'ı bul) ve cake_tcph_may_drop() (iki ACK'in option'larını karşılaştır).

Option walker, her option'ın kendi-bildirdiği length byte'ını kullanarak options alanı boyunca ilerler. Bug, eksik bir lower-bound check'tir:

  • Bir option'ın kalan bildirilen length'i 1 olduğunda, loop yine de gövdeye girer, bir byte (opcode) okur ve — opcode ne TCPOPT_EOL ne de TCPOPT_NOP ise — ilerlemek için bir byte daha (length field'ı) okur. O ikinci read, bildirilen 1-byte'lık option'ın ötesine geçer ve options buffer'ının out of bounds'unu okuyabilir.

  • İlgili olarak, cake_get_tcphdr() TCP data-offset'i (doff) valide etmiyordu. doff < 5 ile CAKE, aslında bir TCP header olmayan byte'ları header gibi ele alır, arbitrary trailing packet/skb belleğini option olarak parse eder — yine amaçlanan bound'ların ötesini okur.

İhlal edilen invariant basittir: kalan option uzunluğu içinde / valide edilmiş bir doff ile sınırlanan header içinde yattığını önce kanıtlamadığın bir option byte'ını asla dereference etme. CAKE, bir unprivileged process'in üretebileceği trafiğe uygulanan bir queueing discipline olduğundan (ve unprivileged kullanıcıların CAP_NET_ADMIN tuttuğu bir network namespace'inde attach edilebildiğinden), parser attacker-shaped packet'ler üzerinde çalışır ve bir parsing kaymasını ulaşılabilir bir kernel OOB'ına çevirir.

Walkthrough

Bug, CAKE'i ACK filtering ile attach edip ona option alanı / doff'u bozuk crafted TCP segment'leri besleyerek tetiklenir.

  1. Bir user+network namespace'inden (unprivileged kullanıcılar kendi netns'leri içinde CAP_NET_ADMIN alır), ACK filter enable edilmiş halde CAKE'i attach edin:
unshare -Urn   # new user+net namespace, root-in-ns
ip link set lo up
tc qdisc add dev lo root cake ack-filter
  1. TCP header'ı bozuk olan TCP trafiği üretin, böylece parser option bound'ların ötesine sürülsün:
- Set the TCP data offset (doff) to < 5 so cake_get_tcphdr() accepts a
  too-short / non-header region, OR
- Emit a TCP segment whose final option declares length == 1 with a
  non-EOL/non-NOP opcode, so cake_tcph_may_drop()/cake_get_tcpopt() reads
  one byte beyond the option area.

Pratikte bu, byte'ları doğrudan crafting eden bir raw socket / packet socket (ya da scapy) ile yapılır, sonra CAKE-attached device üzerinden gönderilir, böylece cake_ack_filter() onları parse eder.

  1. Out-of-bounds erişimi gözlemleyin. Bir KASAN kernel'inde skb linear/option bölgesinin ötesindeki read raporlanır:
BUG: KASAN: slab-out-of-bounds in cake_tcph_may_drop+...
Read of size 1 at addr ffff8881... by task ...
 cake_tcph_may_drop
 cake_ack_filter
 cake_enqueue
Upstream fix

Fix ("sch_cake: Fix out of bounds when parsing TCP options and header", upstream commit 8b71e35df15a / CVE-2021-47243 olarak backport edildi), cake_get_tcphdr()'a bir doff validation'ı ekler, böylece doff < 5 bir header garbage olarak parse edilmek yerine reddedilir, ve walker'da ekstra option byte'ı okumadan önce bir length check ekler. Bu, benzer TCP-input fix commit'i 9609dad263f8 ("ipv4: tcp_input: fix stack out of bounds when parsing TCP options") üzerine modellenmiştir. Bug, ACK-filter feature'ı ile, commit 8b7138814f29 ("sch_cake: Add optional ACK filter")'de tanıtıldı.

Detection

  • KASAN/KFENCE build'leri OOB'ı fuzzing ya da test sırasında doğrudan cake_tcph_may_drop / cake_get_tcpopt içinde yakalar.
  • Runtime'da, CAKE kullanmayan host'larda beklenmedik bir tc qdisc ... cake ack-filter, özellikle kısa ömürlü unprivileged network namespace'leri içinde oluşturulduğunda, niş net/sched parser'larına ulaşma girişimleri için makul bir hunting sinyalidir.

Mitigation

  • sch_cake doff/option-length fix'ini içeren bir kernel'e patch'leyin (CVE-2021-47243). Başlıkta adı geçen taprio sorunu için CVE-2024-36974'ü patch'leyin ("always validate TCA_TAPRIO_ATTR_PRIOMAP").
  • Attack surface'i azaltın: kernel.unprivileged_userns_clone=0 (ya da eşdeğer sysctl) set edin, böylece unprivileged kullanıcılar taze bir netns'te CAP_NET_ADMIN elde edip arbitrary qdisc'ler attach edemesin.
  • CAKE/ACK-filtering gerekmediği yerde onu load/attach etmeyin.

References