diff --git a/src/kernel/emulation/linux/network/recvmsg.c b/src/kernel/emulation/linux/network/recvmsg.c index d78065e13..c4e51cabb 100644 --- a/src/kernel/emulation/linux/network/recvmsg.c +++ b/src/kernel/emulation/linux/network/recvmsg.c @@ -38,9 +38,9 @@ long sys_recvmsg_nocancel(int socket, struct bsd_msghdr* msg, int flags) else if (msg->msg_control != NULL && msg->msg_controllen > 0) { // __simple_printf("controllen=%d\n", msg->msg_controllen); - lchdr = (struct linux_cmsghdr*) malloc(msg->msg_controllen + 4); + lmsg.msg_controllen = LINUX_CMSG_ALIGN(msg->msg_controllen + LINUX_BSD_CMSGHDR_SIZE_DIFFERENCE); // FIXME: there could be multiple control messages in a message + lchdr = (struct linux_cmsghdr*) malloc(lmsg.msg_controllen); lmsg.msg_control = lchdr; - lmsg.msg_controllen = msg->msg_controllen + 4; // FIXME: there could be multiple control messages in a message } else { @@ -86,14 +86,15 @@ long sys_recvmsg_nocancel(int socket, struct bsd_msghdr* msg, int flags) // __simple_printf("Linux msg at %d -> BSD at %d\n", lpos, bpos); - bnext->cmsg_len = lnext->cmsg_len - (sizeof(struct linux_cmsghdr) - sizeof(struct bsd_cmsghdr)); + bnext->cmsg_len = lnext->cmsg_len - LINUX_BSD_CMSGHDR_SIZE_DIFFERENCE; bnext->cmsg_level = socket_level_linux_to_bsd(lnext->cmsg_level); bnext->cmsg_type = lnext->cmsg_type; // __simple_printf("About to copy %d bytes\n", lnext->cmsg_len - sizeof(struct linux_cmsghdr)); - memcpy(bnext->cmsg_data, lnext->cmsg_data, lnext->cmsg_len - sizeof(struct linux_cmsghdr)); - msg->msg_controllen -= 4; + size_t actual_data_size = lnext->cmsg_len - sizeof(struct linux_cmsghdr); + memcpy(bnext->cmsg_data, lnext->cmsg_data, actual_data_size); + msg->msg_controllen -= LINUX_CMSG_SPACE(actual_data_size) - BSD_CMSG_SPACE(actual_data_size); lpos += ALIGN(lnext->cmsg_len, sizeof(unsigned long)); bpos += ALIGN(bnext->cmsg_len, 4); diff --git a/src/kernel/emulation/linux/network/recvmsg.h b/src/kernel/emulation/linux/network/recvmsg.h index 0ac78eed8..e2e94fef3 100644 --- a/src/kernel/emulation/linux/network/recvmsg.h +++ b/src/kernel/emulation/linux/network/recvmsg.h @@ -49,5 +49,15 @@ int socket_level_linux_to_bsd(int level); #define LINUX_SYS_RECVMSG 17 +#define BSD_CMSG_ALIGN(len) (((len) + sizeof(uint32_t) - 1) & (size_t)~(sizeof(uint32_t) - 1)) +#define BSD_CMSG_SPACE(len) (BSD_CMSG_ALIGN(sizeof(struct bsd_cmsghdr)) + BSD_CMSG_ALIGN(len)) +#define BSD_CMSG_LEN(len) (BSD_CMSG_ALIGN(sizeof(struct bsd_cmsghdr)) + (len)) + +#define LINUX_CMSG_ALIGN(len) (((len) + sizeof(unsigned long) - 1) & (size_t)~(sizeof(unsigned long) - 1)) +#define LINUX_CMSG_SPACE(len) (LINUX_CMSG_ALIGN(sizeof(struct linux_cmsghdr)) + LINUX_CMSG_ALIGN(len)) +#define LINUX_CMSG_LEN(len) (LINUX_CMSG_ALIGN(sizeof(struct linux_cmsghdr)) + (len)) + +#define LINUX_BSD_CMSGHDR_SIZE_DIFFERENCE (sizeof(struct linux_cmsghdr) - sizeof(struct bsd_cmsghdr)) + #endif diff --git a/src/kernel/emulation/linux/network/sendmsg.c b/src/kernel/emulation/linux/network/sendmsg.c index 99489c041..470e1b69c 100644 --- a/src/kernel/emulation/linux/network/sendmsg.c +++ b/src/kernel/emulation/linux/network/sendmsg.c @@ -45,17 +45,19 @@ long sys_sendmsg_nocancel(int socket, const struct bsd_msghdr* msg, int flags) struct bsd_cmsghdr* bchdr; bchdr = (struct bsd_cmsghdr*) msg->msg_control; - lchdr = (struct linux_cmsghdr*) malloc(msg->msg_controllen + 4); + + lmsg.msg_controllen = LINUX_CMSG_ALIGN(msg->msg_controllen + LINUX_BSD_CMSGHDR_SIZE_DIFFERENCE); + + lchdr = (struct linux_cmsghdr*)malloc(lmsg.msg_controllen); lmsg.msg_control = lchdr; - lmsg.msg_controllen = msg->msg_controllen + 4; - lchdr->cmsg_len = bchdr->cmsg_len; + lchdr->cmsg_len = bchdr->cmsg_len + LINUX_BSD_CMSGHDR_SIZE_DIFFERENCE; lchdr->cmsg_level = socket_level_bsd_to_linux(bchdr->cmsg_level); lchdr->cmsg_type = bchdr->cmsg_type; memcpy(lchdr->cmsg_data, bchdr->cmsg_data, - lchdr->cmsg_len - sizeof(struct bsd_cmsghdr)); + bchdr->cmsg_len - sizeof(struct bsd_cmsghdr)); } else {