From: Willy Tarreau Date: Wed, 15 May 2024 16:23:18 +0000 (+0200) Subject: BUG/MEDIUM: htx: mark htx_sl as packed since it may be realigned X-Git-Tag: v3.0-dev12~43 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=276cdc11e8d9509c0373a0acb9f580097c27d51a;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: htx: mark htx_sl as packed since it may be realigned A test on MIPS64 revealed that the following reg tests would all fail at the same place in htx_replace_stline() when updating parts of the request line: reg-tests/cache/if-modified-since.vtc reg-tests/http-rules/h1or2_to_h1c.vtc reg-tests/http-rules/http_after_response.vtc reg-tests/http-rules/normalize_uri.vtc reg-tests/http-rules/path_and_pathq.vtc While the status line is normally aligned since it's the first block of the HTX, it may become unaligned once replaced. The problem is, it is a structure which contains some u16 and u32, and dereferencing them on machines not natively supporting unaligned accesses makes them crash or handle crap. Typically, MIPS/MIPS64/SPARC will crash, ARMv5 will either crash or (more likely) return swapped values and do crap, and RISCV will trap and turn to slow emulation. We can assign the htx_sl struct the packed attribute, but then this also causes the ints to fill the 2-bytes gap before them, always causing unaligned accesses for this part on such machines. The patch does a bit better, by explicitly filling this two-bytes hole, and packing the struct. This should be backported to all versions. --- diff --git a/include/haproxy/htx-t.h b/include/haproxy/htx-t.h index 7d49808c23..5312ae1e23 100644 --- a/include/haproxy/htx-t.h +++ b/include/haproxy/htx-t.h @@ -225,7 +225,9 @@ struct htx_ret { struct htx_blk *blk; /* An HTX block */ }; -/* HTX start-line */ +/* HTX start-line. This is almost always aligned except in rare cases where + * parts of the URI are rewritten, hence the packed attribute. + */ struct htx_sl { unsigned int flags; /* HTX_SL_F_* */ union { @@ -237,11 +239,16 @@ struct htx_sl { } res; } info; - /* XXX 2 bytes unused */ + /* XXX 2 bytes unused, must be present to keep the rest aligned + * (check with "pahole -C htx_sl" that len[] is aligned in case + * of doubt). + */ + char __pad_1; + char __pad_2; unsigned int len[3]; /* length of different parts of the start-line */ char l[VAR_ARRAY]; -}; +} __attribute__((packed)); /* Internal representation of an HTTP message */ struct htx {