From: Christopher Faulet Date: Mon, 28 Feb 2022 14:29:56 +0000 (+0100) Subject: BUG/MEDIUM: htx: Fix a possible null derefs in htx_xfer_blks() X-Git-Tag: v2.6-dev3~106 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=234a10aa9bce34781b5b0b4c4ffb595e7563eb41;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: htx: Fix a possible null derefs in htx_xfer_blks() In htx_xfer_blks() function, when headers or trailers are partially transferred, we rollback the copy by removing copied blocks. Internally, all blocks between and are removed. But if the transfer was stopped because we failed to reserve a block, the variable is NULL. Thus, we must not try to remove it. It is unexpected to call htx_remove_blk() in this case. htx_remove_blk() was updated to test variable inside the existing BUG_ON(). The block must be defined. For now, this bug may only be encountered when H2 trailers are copied. On H2 headers, the destination buffer is empty. Thus a swap is performed. This patch should fix the issue #1578. It must be backported as far as 2.4. --- diff --git a/src/htx.c b/src/htx.c index 3cc1a34b05..7e5bd46186 100644 --- a/src/htx.c +++ b/src/htx.c @@ -336,7 +336,7 @@ struct htx_blk *htx_remove_blk(struct htx *htx, struct htx_blk *blk) enum htx_blk_type type; uint32_t pos, addr, sz; - BUG_ON(htx->head == -1); + BUG_ON(!blk || htx->head == -1); /* This is the last block in use */ if (htx->head == htx->tail) { @@ -739,12 +739,14 @@ struct htx_ret htx_xfer_blks(struct htx *dst, struct htx *src, uint32_t count, } if (unlikely(dstref)) { - /* Headers or trailers part was partially xferred, so rollback the copy - * by removing all block between and , both included. + /* Headers or trailers part was partially xferred, so rollback + * the copy by removing all block between and , + * both included. may be NULL. */ while (dstref && dstref != dstblk) dstref = htx_remove_blk(dst, dstref); - htx_remove_blk(dst, dstblk); + if (dstblk) + htx_remove_blk(dst, dstblk); /* HTX message is empty, it means the headers or trailers * part is too big to be copied at once.