From: Chen Gang <gang.chen.5...@gmail.com> After fix this issue, qemu can run i386 wine notepad.exe successfully. But the initialization performance is not quite well.
Signed-off-by: Chen Gang <gang.chen.5...@gmail.com> --- linux-user/syscall.c | 30 +++++++++++++++++------------- linux-user/syscall_defs.h | 20 +++++++++----------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 973cc2f..521749c 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1181,17 +1181,18 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh, struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh); abi_long msg_controllen; abi_ulong target_cmsg_addr; - struct target_cmsghdr *target_cmsg; + struct target_cmsghdr *target_cmsg, *base; socklen_t space = 0; msg_controllen = tswapal(target_msgh->msg_controllen); if (msg_controllen < sizeof (struct target_cmsghdr)) goto the_end; target_cmsg_addr = tswapal(target_msgh->msg_control); - target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1); - if (!target_cmsg) + base = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1); + if (!base) { return -TARGET_EFAULT; - + } + target_cmsg = base; while (cmsg && target_cmsg) { void *data = CMSG_DATA(cmsg); void *target_data = TARGET_CMSG_DATA(target_cmsg); @@ -1247,7 +1248,7 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh, } cmsg = CMSG_NXTHDR(msgh, cmsg); - target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg); + target_cmsg = TARGET_CMSG_NXTHDR(base, msg_controllen, target_cmsg); } unlock_user(target_cmsg, target_cmsg_addr, 0); the_end: @@ -1259,19 +1260,22 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh, struct msghdr *msgh) { struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh); - abi_long msg_controllen; + abi_long msg_controllen, size; abi_ulong target_cmsg_addr; - struct target_cmsghdr *target_cmsg; + struct target_cmsghdr *target_cmsg, *base; socklen_t space = 0; - msg_controllen = tswapal(target_msgh->msg_controllen); - if (msg_controllen < sizeof (struct target_cmsghdr)) + size = tswapal(target_msgh->msg_controllen); + if (size < sizeof(struct target_cmsghdr)) { goto the_end; + } target_cmsg_addr = tswapal(target_msgh->msg_control); - target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0); - if (!target_cmsg) + base = lock_user(VERIFY_WRITE, target_cmsg_addr, size, 0); + if (!base) { return -TARGET_EFAULT; - + } + msg_controllen = size; + target_cmsg = base; while (cmsg && target_cmsg) { void *data = CMSG_DATA(cmsg); void *target_data = TARGET_CMSG_DATA(target_cmsg); @@ -1389,7 +1393,7 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh, msg_controllen -= tgt_space; space += tgt_space; cmsg = CMSG_NXTHDR(msgh, cmsg); - target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg); + target_cmsg = TARGET_CMSG_NXTHDR(base, size, target_cmsg); } unlock_user(target_cmsg, target_cmsg_addr, space); the_end: diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 5256fe5..aec2f23 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -234,7 +234,8 @@ struct target_cmsghdr { }; #define TARGET_CMSG_DATA(cmsg) ((unsigned char *) ((struct target_cmsghdr *) (cmsg) + 1)) -#define TARGET_CMSG_NXTHDR(mhdr, cmsg) __target_cmsg_nxthdr (mhdr, cmsg) +#define TARGET_CMSG_NXTHDR(base, size, cmsg) __target_cmsg_nxthdr(base, size, \ + cmsg) #define TARGET_CMSG_ALIGN(len) (((len) + sizeof (abi_long) - 1) \ & (size_t) ~(sizeof (abi_long) - 1)) #define TARGET_CMSG_SPACE(len) (TARGET_CMSG_ALIGN (len) \ @@ -242,17 +243,14 @@ struct target_cmsghdr { #define TARGET_CMSG_LEN(len) (TARGET_CMSG_ALIGN (sizeof (struct target_cmsghdr)) + (len)) static __inline__ struct target_cmsghdr * -__target_cmsg_nxthdr (struct target_msghdr *__mhdr, struct target_cmsghdr *__cmsg) +__target_cmsg_nxthdr(void *base, abi_long size, struct target_cmsghdr *msg) { - struct target_cmsghdr *__ptr; - - __ptr = (struct target_cmsghdr *)((unsigned char *) __cmsg - + TARGET_CMSG_ALIGN (tswapal(__cmsg->cmsg_len))); - if ((unsigned long)((char *)(__ptr+1) - (char *)(size_t)tswapal(__mhdr->msg_control)) - > tswapal(__mhdr->msg_controllen)) - /* No more entries. */ - return (struct target_cmsghdr *)0; - return __cmsg; + msg = (struct target_cmsghdr *)((unsigned char *)msg + + TARGET_CMSG_ALIGN(tswapal(msg->cmsg_len))); + if ((unsigned long)((char *)(msg + 1) - (char *)base) > size) { + return NULL; + } + return msg; } struct target_mmsghdr { -- 1.9.1