From: Matt Turner Date: Wed, 12 Aug 2026 03:13:20 +0000 (-0400) Subject: linux: align the ancillary buffer in tst-socket-timestamp X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=059e1cd67bc81ac31ac208e00c3200d45f02dbd9;p=thirdparty%2Fglibc.git linux: align the ancillary buffer in tst-socket-timestamp 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 --- diff --git a/sysdeps/unix/sysv/linux/tst-socket-timestamp.c b/sysdeps/unix/sysv/linux/tst-socket-timestamp.c index a5ab72e39c..c77ac7b439 100644 --- a/sysdeps/unix/sysv/linux/tst-socket-timestamp.c +++ b/sysdeps/unix/sysv/linux/tst-socket-timestamp.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -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. */ {