]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
linux: align the ancillary buffer in tst-socket-timestamp
authorMatt Turner <mattst88@gmail.com>
Wed, 12 Aug 2026 03:13:20 +0000 (23:13 -0400)
committerFlorian Weimer <fweimer@redhat.com>
Wed, 12 Aug 2026 08:39:13 +0000 (10:39 +0200)
The test places the ancillary buffer so that it ends against a PROT_NONE
page, at cmsg - (CMSG_SPACE (tsize) + slack).  CMSG_SPACE (sizeof (struct
timeval)) is a multiple of the alignment of struct cmsghdr, so the start of
the buffer inherits the alignment of the slack, and one of the slack sizes
the test uses is 4.

msg_control has to be suitably aligned for struct cmsghdr: recvmsg and the
CMSG_* macros both read cmsg_len from the start of the buffer, and it is a
size_t.  On a target that does not fix up unaligned accesses in hardware,
reading it from a misaligned address traps into the kernel.  On alpha each
one is reported:

  ld-linux.so.2(48878): unaligned trap at 0000000120001e3c: ... 29 2

five per run, all from the loop over the control messages in
do_recvmsg_slack_ancillary.  The test still passes, since the kernel
completes the access and returns.

Round the start of the buffer down to the alignment, and add the alignment
minus one to the requested allocation so the rounding cannot move the start
outside it.  A slack that is not a multiple of the alignment then leaves the
buffer ending a few bytes short of the guard page rather than against it; the
overruns the guard page is there to catch are a whole timestamp rather than a
few bytes, so they are still caught.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
sysdeps/unix/sysv/linux/tst-socket-timestamp.c

index a5ab72e39c05be5015fd4206550443f085d01b10..c77ac7b439f3e17405da1e53945b7c88c53d40f8 100644 (file)
@@ -19,6 +19,7 @@
 #include <array_length.h>
 #include <arpa/inet.h>
 #include <errno.h>
+#include <libc-pointer-arith.h>
 #include <string.h>
 #include <stdio.h>
 #include <support/check.h>
@@ -65,7 +66,15 @@ do_recvmsg_slack_ancillary (bool use_multi_call, int s, void *cmsg,
       .iov_len = sizeof (payload)
     };
   size_t msg_controllen = CMSG_SPACE (tsize) + slack;
-  char *msg_control = cmsg - msg_controllen;
+  /* The buffer has to be suitably aligned for struct cmsghdr, since both
+     recvmsg and the CMSG_* macros below read cmsg_len from its start, so
+     round the start down.  The caller reserves the extra bytes this may
+     consume.  A slack that is not a multiple of the alignment then leaves
+     the buffer ending just short of the guard page rather than against it,
+     which still catches the overruns this is looking for: they are a whole
+     timestamp, not a few bytes.  */
+  char *msg_control = PTR_ALIGN_DOWN ((char *) cmsg - msg_controllen,
+                                     __alignof__ (struct cmsghdr));
   memset (msg_control, 0x55, msg_controllen);
   struct mmsghdr mmhdr =
     {
@@ -142,10 +151,13 @@ static void
 do_test_slack_space (void)
 {
   /* Setup the ancillary data buffer with an extra page with PROT_NONE to
-     check the possible timestamp conversion on some systems.  */
+     check the possible timestamp conversion on some systems.  Request
+     __alignof__ (struct cmsghdr) - 1 extra bytes to cover the rounding down
+     of the buffer start in do_recvmsg_slack_ancillary.  */
   struct support_next_to_fault nf =
-    support_next_to_fault_allocate (slack_max_size);
-  void *msgbuf = nf.buffer + slack_max_size;
+    support_next_to_fault_allocate (slack_max_size
+                                   + __alignof__ (struct cmsghdr) - 1);
+  void *msgbuf = nf.buffer + nf.length;
 
   /* Enable the timestamp using struct timeval precision.  */
   {