From 8fba672472ae0055387e9315fc2eddfa6775ca79 Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Mon, 24 Jan 2022 08:55:53 -0300 Subject: linux: Fix ancillary 64-bit time timestamp conversion (BZ #28349, BZ#28350) The __convert_scm_timestamps only updates the control message last pointer for SOL_SOCKET type, so if the message control buffer contains multiple ancillary message types the converted timestamp one might overwrite a valid message. The test checks if the extra ancillary space is correctly handled by recvmsg/recvmmsg, where if there is no extra space for the 64-bit time_t converted message the control buffer should be marked with MSG_TRUNC. It also check if recvmsg/recvmmsg handle correctly multiple ancillary data. Checked on x86_64-linux and on i686-linux-gnu on both 5.11 and 4.15 kernel. Co-authored-by: Fabian Vogt Reviewed-by: Florian Weimer --- sysdeps/unix/sysv/linux/convert_scm_timestamps.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'sysdeps/unix/sysv/linux/convert_scm_timestamps.c') diff --git a/sysdeps/unix/sysv/linux/convert_scm_timestamps.c b/sysdeps/unix/sysv/linux/convert_scm_timestamps.c index 580eb4be84..82171bf325 100644 --- a/sysdeps/unix/sysv/linux/convert_scm_timestamps.c +++ b/sysdeps/unix/sysv/linux/convert_scm_timestamps.c @@ -54,6 +54,8 @@ __convert_scm_timestamps (struct msghdr *msg, socklen_t msgsize) cmsg != NULL; cmsg = CMSG_NXTHDR (msg, cmsg)) { + last = cmsg; + if (cmsg->cmsg_level != SOL_SOCKET) continue; @@ -75,11 +77,9 @@ __convert_scm_timestamps (struct msghdr *msg, socklen_t msgsize) tvts[1] = tmp[1]; break; } - - last = cmsg; } - if (last == NULL || type == 0) + if (type == 0) return; if (CMSG_SPACE (sizeof tvts) > msgsize - msg->msg_controllen) @@ -88,10 +88,12 @@ __convert_scm_timestamps (struct msghdr *msg, socklen_t msgsize) return; } + /* Zero memory for the new cmsghdr, so reading cmsg_len field + by CMSG_NXTHDR does not trigger UB. */ + memset (msg->msg_control + msg->msg_controllen, 0, + CMSG_SPACE (sizeof tvts)); msg->msg_controllen += CMSG_SPACE (sizeof tvts); - cmsg = CMSG_NXTHDR(msg, last); - if (cmsg == NULL) - return; + cmsg = CMSG_NXTHDR (msg, last); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = type; cmsg->cmsg_len = CMSG_LEN (sizeof tvts); -- cgit 1.4.1