Blame SOURCES/bz1819519-fix-handling-hpack-zero-bytes-overwrite.patch

ef7dd4
From 4e372dc350be5c72b88546bf03392a5793cea179 Mon Sep 17 00:00:00 2001
ef7dd4
From: Willy Tarreau <w@1wt.eu>
ef7dd4
Date: Sun, 29 Mar 2020 08:53:31 +0200
ef7dd4
Subject: BUG/CRITICAL: hpack: never index a header into the headroom after
ef7dd4
 wrapping
ef7dd4

ef7dd4
The HPACK header table is implemented as a wrapping list inside a contigous
ef7dd4
area. Headers names and values are stored from right to left while indexes
ef7dd4
are stored from left to right. When there's no more room to store a new one,
ef7dd4
we wrap to the right again, or possibly defragment it if needed. The condition
ef7dd4
do use the right part (called tailroom) or the left part (called headroom)
ef7dd4
depends on the location of the last inserted header. After wrapping happens,
ef7dd4
the code forces to stick to tailroom by pretending there's no more headroom,
ef7dd4
so that the size fit test always fails. The problem is that nothing prevents
ef7dd4
from storing a header with an empty name and empty value, resulting in a
ef7dd4
total size of zero bytes, which satisfies the condition to use the headroom.
ef7dd4
Doing this in a wrapped buffer results in changing the "front" header index
ef7dd4
and causing miscalculations on the available size and the addresses of the
ef7dd4
next headers. This may even allow to overwrite some parts of the index,
ef7dd4
opening the possibility to perform arbitrary writes into a 32-bit relative
ef7dd4
address space.
ef7dd4

ef7dd4
This patch fixes the issue by making sure the headroom is considered only
ef7dd4
when the buffer does not wrap, instead of relying on the zero size. This
ef7dd4
must be backported to all versions supporting H2, which is as far as 1.8.
ef7dd4

ef7dd4
Many thanks to Felix Wilhelm of Google Project Zero for responsibly
ef7dd4
reporting this problem with a reproducer and a detailed analysis.
ef7dd4
---
ef7dd4
 src/hpack-tbl.c | 4 ++--
ef7dd4
 1 file changed, 2 insertions(+), 2 deletions(-)
ef7dd4

ef7dd4
diff --git a/src/hpack-tbl.c b/src/hpack-tbl.c
ef7dd4
index 70d7f35834..727ff7a17b 100644
ef7dd4
--- a/src/hpack-tbl.c
ef7dd4
+++ b/src/hpack-tbl.c
ef7dd4
@@ -346,9 +346,9 @@ int hpack_dht_insert(struct hpack_dht *dht, struct ist name, struct ist value)
ef7dd4
 	 * room left in the tail to suit the protocol, but tests show that in
ef7dd4
 	 * practice it almost never happens in other situations so the extra
ef7dd4
 	 * test is useless and we simply fill the headroom as long as it's
ef7dd4
-	 * available.
ef7dd4
+	 * available and we don't wrap.
ef7dd4
 	 */
ef7dd4
-	if (headroom >= name.len + value.len) {
ef7dd4
+	if (prev == dht->front && headroom >= name.len + value.len) {
ef7dd4
 		/* install upfront and update ->front */
ef7dd4
 		dht->dte[head].addr = dht->dte[dht->front].addr - (name.len + value.len);
ef7dd4
 		dht->front = head;
ef7dd4
-- 
ef7dd4
2.20.1
ef7dd4