Skip to content

QEMU eth_get_gso_type reachable assertion (CVE-2020-27617)

QEMU'nun network helper katmanında guest-to-host bir denial of service; burada tanınan bir Layer-3 protokolünden yoksun bir paket eth_get_gso_type()'a ulaşır, bir g_assert'i tetikler ve host QEMU process'ini abort eder.

Mechanism

Note

Emüle bir NIC segmentation offload (TSO/GSO) sunduğunda, QEMU'nun net/eth.c içindeki paylaşılan Ethernet helper'ı eth_get_gso_type(), paketin Layer-3 EtherType'ını bir GSO type'a map'ler. Kod, L3 protokolünün her zaman tanıdığı bir şey (IPv4 / IPv6) olduğunu varsaydı ve bu varsayımı bir runtime check yerine bir assertion olarak kodladı. Bir guest, L3 protokol değeri ikisi de olmayan bir frame gönderebilir — assertion'ın koşulu false olur, g_assert tetiklenir ve QEMU abort() çağırır. Bu bir reachable assertion (CWE-617): attacker-controlled input, yalnızca "imkânsız" internal state'leri yakalamak için tasarlanmış bir assert'i sürer. Abort host QEMU process'ini öldürdüğü için, unprivileged bir guest guest→host sınırını temiz bir denial of service olarak aşar.

Bir reachable assertion, memory corruption'ın daha yumuşak bir kuzenidir: OOB write yok, ama aynı sınır aşımı ve DoS sonucu. OOB device durumları qemu-es1370-audio-oob-access ve qemu-arm-gic-oob-heap-access ile karşılaştırın.

Walkthrough

Public, hâlihazırda patch'lenmiş advisory'den (QEMU launchpad bug 1878067, oss-security, Red Hat / SUSE). Yalnızca kavramsal reproduction.

  1. Guest, transmit path'i paketleri GSO/offload helper'ı üzerinden çalıştıran bir emüle NIC'i sürer.
  2. Ethernet payload'ı geçerli bir L3 protokolüne sahip olmayan (IPv4/IPv6'nın varsayıldığı yerde eksik ya da tanınmayan bir EtherType) bir frame gönderir.
  3. Send path eth_get_gso_type()'a ulaşır; protokol varsayılan durumu sağlamaz, assertion'ın koşulu false olur ve g_assert, abort()'u tetikler.
  4. Host QEMU process'i sonlanır — tek bir hazırlanmış paketten bir host DoS.

Warning

Tarihsel, patch'lenmiş bir sorun (QEMU ~4.2.1 / 5.0, fuzzing yoluyla bulundu). Bu giriş kavramsal kalır; tetikleyici basitçe "geçerli L3 protokolü olmayan bir paket"tir.

Reachable-assertion → graceful-handling (shape of the fix)
/* before: assert that the L3 protocol is one of the expected cases */
/* g_assert(...);                      // attacker-reachable -> abort() */

/* after: handle the unexpected protocol without aborting */
default:
    return 0;   /* no GSO; drop/treat as non-offloaded instead of abort */

Detection

  • Host tarafı: QEMU, eth_get_gso_type (net/eth.c) üzerinden geçen bir backtrace ile abort() / SIGABRT yoluyla çıkar; host loglarında glib "assertion failed" mesajları.
  • Behavioral: QEMU ölümünden hemen önce offload-capable bir NIC'e malformed/yok L3 EtherType'lı frame'ler yayan bir guest, sinyaldir.
  • Tek bir guest'e bağlı crash-loop, bir tesadüf yerine kasıtlı bir DoS'a işaret eder.

Mitigation

  • eth_get_gso_type() içindeki assert'i kaldıran ve beklenmeyen L3 protokolünü zarif bir şekilde ele alan CVE-2020-27617 için upstream QEMU fix'ini uygulayın (distro backport'ları: Debian, Ubuntu, Red Hat, SUSE).
  • Defense-in-depth: QEMU'yu confine edin (seccomp, SELinux/sVirt) ve otomatik restart/quarantine uygulayın ki bir assert-abort sınırlı bir kesinti olsun.
  • Mümkün olan yerde QEMU'yu, network path'inde assertion'ları process abort'ları yerine kurtarılabilir hatalar olarak ele alacak şekilde derleyin.

References

  • QEMU launchpad bug 1878067 — assertion failure in eth_get_gso_type: https://bugs.launchpad.net/qemu/+bug/1878067
  • oss-security — CVE-2020-27617 (assert failure via eth_get_gso_type): https://www.openwall.com/lists/oss-security/2020/11/02/1
  • Red Hat Bugzilla 1891668 — CVE-2020-27617: https://bugzilla.redhat.com/show_bug.cgi?id=1891668