]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: htx: mark htx_sl as packed since it may be realigned
authorWilly Tarreau <w@1wt.eu>
Wed, 15 May 2024 16:23:18 +0000 (18:23 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 15 May 2024 17:03:17 +0000 (19:03 +0200)
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.

include/haproxy/htx-t.h

index 7d49808c237d5c765630a60fbd0fa434b85b3572..5312ae1e23712969162839532155ea168c83592c 100644 (file)
@@ -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 {