this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix `recvmsg`/`sendmsg` alignment issues

Fixes #761

Linux CMSGs are aligned to 8 bytes, but BSD CMSgs are aligned to 4 bytes.

We were correctly adding 4 to the length of BSD message to account for the extra 4 bytes in the message length field, but we were still aligning the data to 4 bytes. This fixes that by aligning to 8 bytes instead.

+22 -9
+6 -5
src/kernel/emulation/linux/network/recvmsg.c
··· 38 38 else if (msg->msg_control != NULL && msg->msg_controllen > 0) 39 39 { 40 40 // __simple_printf("controllen=%d\n", msg->msg_controllen); 41 - lchdr = (struct linux_cmsghdr*) malloc(msg->msg_controllen + 4); 41 + lmsg.msg_controllen = LINUX_CMSG_ALIGN(msg->msg_controllen + LINUX_BSD_CMSGHDR_SIZE_DIFFERENCE); // FIXME: there could be multiple control messages in a message 42 + lchdr = (struct linux_cmsghdr*) malloc(lmsg.msg_controllen); 42 43 lmsg.msg_control = lchdr; 43 - lmsg.msg_controllen = msg->msg_controllen + 4; // FIXME: there could be multiple control messages in a message 44 44 } 45 45 else 46 46 { ··· 86 86 87 87 // __simple_printf("Linux msg at %d -> BSD at %d\n", lpos, bpos); 88 88 89 - bnext->cmsg_len = lnext->cmsg_len - (sizeof(struct linux_cmsghdr) - sizeof(struct bsd_cmsghdr)); 89 + bnext->cmsg_len = lnext->cmsg_len - LINUX_BSD_CMSGHDR_SIZE_DIFFERENCE; 90 90 bnext->cmsg_level = socket_level_linux_to_bsd(lnext->cmsg_level); 91 91 bnext->cmsg_type = lnext->cmsg_type; 92 92 93 93 // __simple_printf("About to copy %d bytes\n", lnext->cmsg_len - sizeof(struct linux_cmsghdr)); 94 94 95 - memcpy(bnext->cmsg_data, lnext->cmsg_data, lnext->cmsg_len - sizeof(struct linux_cmsghdr)); 96 - msg->msg_controllen -= 4; 95 + size_t actual_data_size = lnext->cmsg_len - sizeof(struct linux_cmsghdr); 96 + memcpy(bnext->cmsg_data, lnext->cmsg_data, actual_data_size); 97 + msg->msg_controllen -= LINUX_CMSG_SPACE(actual_data_size) - BSD_CMSG_SPACE(actual_data_size); 97 98 98 99 lpos += ALIGN(lnext->cmsg_len, sizeof(unsigned long)); 99 100 bpos += ALIGN(bnext->cmsg_len, 4);
+10
src/kernel/emulation/linux/network/recvmsg.h
··· 49 49 50 50 #define LINUX_SYS_RECVMSG 17 51 51 52 + #define BSD_CMSG_ALIGN(len) (((len) + sizeof(uint32_t) - 1) & (size_t)~(sizeof(uint32_t) - 1)) 53 + #define BSD_CMSG_SPACE(len) (BSD_CMSG_ALIGN(sizeof(struct bsd_cmsghdr)) + BSD_CMSG_ALIGN(len)) 54 + #define BSD_CMSG_LEN(len) (BSD_CMSG_ALIGN(sizeof(struct bsd_cmsghdr)) + (len)) 55 + 56 + #define LINUX_CMSG_ALIGN(len) (((len) + sizeof(unsigned long) - 1) & (size_t)~(sizeof(unsigned long) - 1)) 57 + #define LINUX_CMSG_SPACE(len) (LINUX_CMSG_ALIGN(sizeof(struct linux_cmsghdr)) + LINUX_CMSG_ALIGN(len)) 58 + #define LINUX_CMSG_LEN(len) (LINUX_CMSG_ALIGN(sizeof(struct linux_cmsghdr)) + (len)) 59 + 60 + #define LINUX_BSD_CMSGHDR_SIZE_DIFFERENCE (sizeof(struct linux_cmsghdr) - sizeof(struct bsd_cmsghdr)) 61 + 52 62 #endif 53 63
+6 -4
src/kernel/emulation/linux/network/sendmsg.c
··· 45 45 struct bsd_cmsghdr* bchdr; 46 46 47 47 bchdr = (struct bsd_cmsghdr*) msg->msg_control; 48 - lchdr = (struct linux_cmsghdr*) malloc(msg->msg_controllen + 4); 48 + 49 + lmsg.msg_controllen = LINUX_CMSG_ALIGN(msg->msg_controllen + LINUX_BSD_CMSGHDR_SIZE_DIFFERENCE); 50 + 51 + lchdr = (struct linux_cmsghdr*)malloc(lmsg.msg_controllen); 49 52 50 53 lmsg.msg_control = lchdr; 51 - lmsg.msg_controllen = msg->msg_controllen + 4; 52 54 53 - lchdr->cmsg_len = bchdr->cmsg_len; 55 + lchdr->cmsg_len = bchdr->cmsg_len + LINUX_BSD_CMSGHDR_SIZE_DIFFERENCE; 54 56 lchdr->cmsg_level = socket_level_bsd_to_linux(bchdr->cmsg_level); 55 57 lchdr->cmsg_type = bchdr->cmsg_type; 56 58 57 59 memcpy(lchdr->cmsg_data, bchdr->cmsg_data, 58 - lchdr->cmsg_len - sizeof(struct bsd_cmsghdr)); 60 + bchdr->cmsg_len - sizeof(struct bsd_cmsghdr)); 59 61 } 60 62 else 61 63 {