ngtcp2: avoid supplying 0 length `msg_control` to sendmsg()

Testing on macOS 12.4, sendmsg() fails with EINVAL when a msg_control
buffer is provided in sengmsg(), even though msg_controllen was set to
0.

Initialize msg.msg_controllen just as needed and also perform the size
assertion only when needed.

Closes #9039
This commit is contained in:
Stefan Eissing 2022-06-22 15:25:40 +02:00 коммит произвёл Daniel Stenberg
Родитель 71bbabb167
Коммит 8135d420ee
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 5CC908FDB71E12C2
1 изменённых файлов: 5 добавлений и 9 удалений

Просмотреть файл

@ -1653,25 +1653,22 @@ static CURLcode do_sendmsg(size_t *psent, struct Curl_easy *data, int sockfd,
struct iovec msg_iov = {(void *)pkt, pktlen}; struct iovec msg_iov = {(void *)pkt, pktlen};
struct msghdr msg = {0}; struct msghdr msg = {0};
uint8_t msg_ctrl[32]; uint8_t msg_ctrl[32];
size_t ctrllen = 0;
ssize_t sent; ssize_t sent;
#if defined(__linux__) && defined(UDP_SEGMENT) #if defined(__linux__) && defined(UDP_SEGMENT)
struct cmsghdr *cm; struct cmsghdr *cm;
#endif #endif
*psent = 0; *psent = 0;
assert(sizeof(msg_ctrl) >= CMSG_SPACE(sizeof(uint16_t)));
msg.msg_iov = &msg_iov; msg.msg_iov = &msg_iov;
msg.msg_iovlen = 1; msg.msg_iovlen = 1;
msg.msg_control = msg_ctrl;
msg.msg_controllen = sizeof(msg_ctrl);
#if defined(__linux__) && defined(UDP_SEGMENT) #if defined(__linux__) && defined(UDP_SEGMENT)
if(pktlen > gsolen) { if(pktlen > gsolen) {
ctrllen += CMSG_SPACE(sizeof(uint16_t)); /* Only set this, when we need it. macOS, for example,
* does not seem to like a msg_control of length 0. */
msg.msg_control = msg_ctrl;
assert(sizeof(msg_ctrl) >= CMSG_SPACE(sizeof(uint16_t)));
msg.msg_controllen = CMSG_SPACE(sizeof(uint16_t));
cm = CMSG_FIRSTHDR(&msg); cm = CMSG_FIRSTHDR(&msg);
cm->cmsg_level = SOL_UDP; cm->cmsg_level = SOL_UDP;
cm->cmsg_type = UDP_SEGMENT; cm->cmsg_type = UDP_SEGMENT;
@ -1680,7 +1677,6 @@ static CURLcode do_sendmsg(size_t *psent, struct Curl_easy *data, int sockfd,
} }
#endif #endif
msg.msg_controllen = ctrllen;
while((sent = sendmsg(sockfd, &msg, 0)) == -1 && SOCKERRNO == EINTR) while((sent = sendmsg(sockfd, &msg, 0)) == -1 && SOCKERRNO == EINTR)
; ;