* [Qemu-devel] [PATCH v3 0/6] linux-user improvements
@ 2012-10-11 19:22 Richard Henderson
2012-10-11 19:22 ` [Qemu-devel] [PATCH 1/6] linux-user: Perform more checks on iovec lists Richard Henderson
` (5 more replies)
0 siblings, 6 replies; 11+ messages in thread
From: Richard Henderson @ 2012-10-11 19:22 UTC (permalink / raw)
To: qemu-devel; +Cc: Riku Voipio
Changes v2-v3:
* Add patch 4, rewriting __get_user. Patch 5 triggers warnings about
"assignment of read-only variable" without it.
* Rebase vs master, which includes the cpu_alpha_init fix.
Patch set available at
git://repo.or.cz/qemu/rth.git axp-next
r~
Richard Henderson (6):
linux-user: Perform more checks on iovec lists
linux-user: Implement gethostname
alpha-linux-user: Fix sigaltstack structure definition
linux-user: Rewrite __get_user/__put_user with __builtin_choose_expr
alpha-linux-user: Fix sigaction
linux-user: Fix siginfo handling
linux-user/alpha/target_signal.h | 7 +-
linux-user/qemu.h | 53 +++++-------
linux-user/signal.c | 81 ++++++++++--------
linux-user/syscall.c | 177 +++++++++++++++++++++++++--------------
linux-user/syscall_defs.h | 2 +-
5 files changed, 192 insertions(+), 128 deletions(-)
--
1.7.11.4
^ permalink raw reply [flat|nested] 11+ messages in thread* [Qemu-devel] [PATCH 1/6] linux-user: Perform more checks on iovec lists 2012-10-11 19:22 [Qemu-devel] [PATCH v3 0/6] linux-user improvements Richard Henderson @ 2012-10-11 19:22 ` Richard Henderson 2012-10-11 19:22 ` [Qemu-devel] [PATCH 2/6] linux-user: Implement gethostname Richard Henderson ` (4 subsequent siblings) 5 siblings, 0 replies; 11+ messages in thread From: Richard Henderson @ 2012-10-11 19:22 UTC (permalink / raw) To: qemu-devel; +Cc: Riku Voipio Validate count between 0 and IOV_MAX. Limit total length of operation in the same way the kernel does. Signed-off-by: Richard Henderson <rth@twiddle.net> --- linux-user/syscall.c | 162 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 102 insertions(+), 60 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 471d060..8708b31 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1744,55 +1744,96 @@ static abi_long do_getsockopt(int sockfd, int level, int optname, return ret; } -/* FIXME - * lock_iovec()/unlock_iovec() have a return code of 0 for success where - * other lock functions have a return code of 0 for failure. - */ -static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr, - int count, int copy) +static struct iovec *lock_iovec(int type, abi_ulong target_addr, + int count, int copy) { struct target_iovec *target_vec; - abi_ulong base; + struct iovec *vec; + abi_ulong total_len, max_len; int i; - target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1); - if (!target_vec) - return -TARGET_EFAULT; - for(i = 0;i < count; i++) { - base = tswapal(target_vec[i].iov_base); - vec[i].iov_len = tswapal(target_vec[i].iov_len); - if (vec[i].iov_len != 0) { - vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy); - /* Don't check lock_user return value. We must call writev even - if a element has invalid base address. */ + if (count == 0) { + errno = 0; + return NULL; + } + if (count > IOV_MAX) { + errno = EINVAL; + return NULL; + } + + vec = calloc(count, sizeof(struct iovec)); + if (vec == NULL) { + errno = ENOMEM; + return NULL; + } + + target_vec = lock_user(VERIFY_READ, target_addr, + count * sizeof(struct target_iovec), 1); + if (target_vec == NULL) { + errno = EFAULT; + goto fail2; + } + + /* ??? If host page size > target page size, this will result in a + value larger than what we can actually support. */ + max_len = 0x7fffffff & TARGET_PAGE_MASK; + total_len = 0; + + for (i = 0; i < count; i++) { + abi_ulong base = tswapal(target_vec[i].iov_base); + abi_long len = tswapal(target_vec[i].iov_len); + + if (len < 0) { + errno = EINVAL; + goto fail; + } else if (len == 0) { + /* Zero length pointer is ignored. */ + vec[i].iov_base = 0; } else { - /* zero length pointer is ignored */ - vec[i].iov_base = NULL; + vec[i].iov_base = lock_user(type, base, len, copy); + if (!vec[i].iov_base) { + errno = EFAULT; + goto fail; + } + if (len > max_len - total_len) { + len = max_len - total_len; + } } + vec[i].iov_len = len; + total_len += len; } - unlock_user (target_vec, target_addr, 0); - return 0; + + unlock_user(target_vec, target_addr, 0); + return vec; + + fail: + free(vec); + fail2: + unlock_user(target_vec, target_addr, 0); + return NULL; } -static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr, - int count, int copy) +static void unlock_iovec(struct iovec *vec, abi_ulong target_addr, + int count, int copy) { struct target_iovec *target_vec; - abi_ulong base; int i; - target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1); - if (!target_vec) - return -TARGET_EFAULT; - for(i = 0;i < count; i++) { - if (target_vec[i].iov_base) { - base = tswapal(target_vec[i].iov_base); + target_vec = lock_user(VERIFY_READ, target_addr, + count * sizeof(struct target_iovec), 1); + if (target_vec) { + for (i = 0; i < count; i++) { + abi_ulong base = tswapal(target_vec[i].iov_base); + abi_long len = tswapal(target_vec[i].iov_base); + if (len < 0) { + break; + } unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0); } + unlock_user(target_vec, target_addr, 0); } - unlock_user (target_vec, target_addr, 0); - return 0; + free(vec); } /* do_socket() Must return target values and target errnos. */ @@ -1888,8 +1929,7 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, ret = target_to_host_sockaddr(msg.msg_name, tswapal(msgp->msg_name), msg.msg_namelen); if (ret) { - unlock_user_struct(msgp, target_msg, send ? 0 : 1); - return ret; + goto out2; } } else { msg.msg_name = NULL; @@ -1900,9 +1940,13 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, msg.msg_flags = tswap32(msgp->msg_flags); count = tswapal(msgp->msg_iovlen); - vec = alloca(count * sizeof(struct iovec)); target_vec = tswapal(msgp->msg_iov); - lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send); + vec = lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, + target_vec, count, send); + if (vec == NULL) { + ret = -host_to_target_errno(errno); + goto out2; + } msg.msg_iovlen = count; msg.msg_iov = vec; @@ -1932,6 +1976,7 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, out: unlock_iovec(vec, target_vec, count, !send); +out2: unlock_user_struct(msgp, target_msg, send ? 0 : 1); return ret; } @@ -7184,26 +7229,24 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; case TARGET_NR_readv: { - int count = arg3; - struct iovec *vec; - - vec = alloca(count * sizeof(struct iovec)); - if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0) - goto efault; - ret = get_errno(readv(arg1, vec, count)); - unlock_iovec(vec, arg2, count, 1); + struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0); + if (vec != NULL) { + ret = get_errno(readv(arg1, vec, arg3)); + unlock_iovec(vec, arg2, arg3, 1); + } else { + ret = -host_to_target_errno(errno); + } } break; case TARGET_NR_writev: { - int count = arg3; - struct iovec *vec; - - vec = alloca(count * sizeof(struct iovec)); - if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0) - goto efault; - ret = get_errno(writev(arg1, vec, count)); - unlock_iovec(vec, arg2, count, 0); + struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); + if (vec != NULL) { + ret = get_errno(writev(arg1, vec, arg3)); + unlock_iovec(vec, arg2, arg3, 0); + } else { + ret = -host_to_target_errno(errno); + } } break; case TARGET_NR_getsid: @@ -8628,14 +8671,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #ifdef TARGET_NR_vmsplice case TARGET_NR_vmsplice: { - int count = arg3; - struct iovec *vec; - - vec = alloca(count * sizeof(struct iovec)); - if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0) - goto efault; - ret = get_errno(vmsplice(arg1, vec, count, arg4)); - unlock_iovec(vec, arg2, count, 0); + struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); + if (vec != NULL) { + ret = get_errno(vmsplice(arg1, vec, arg3, arg4)); + unlock_iovec(vec, arg2, arg3, 0); + } else { + ret = -host_to_target_errno(errno); + } } break; #endif -- 1.7.11.4 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH 2/6] linux-user: Implement gethostname 2012-10-11 19:22 [Qemu-devel] [PATCH v3 0/6] linux-user improvements Richard Henderson 2012-10-11 19:22 ` [Qemu-devel] [PATCH 1/6] linux-user: Perform more checks on iovec lists Richard Henderson @ 2012-10-11 19:22 ` Richard Henderson 2012-10-11 19:43 ` Peter Maydell 2012-10-11 19:22 ` [Qemu-devel] [PATCH 3/6] alpha-linux-user: Fix sigaltstack structure definition Richard Henderson ` (3 subsequent siblings) 5 siblings, 1 reply; 11+ messages in thread From: Richard Henderson @ 2012-10-11 19:22 UTC (permalink / raw) To: qemu-devel; +Cc: Riku Voipio Signed-off-by: Richard Henderson <rth@twiddle.net> --- linux-user/syscall.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 8708b31..462d11b 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8864,6 +8864,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; } #endif +#ifdef TARGET_NR_gethostname + case TARGET_NR_gethostname: + { + char *name = lock_user(VERIFY_WRITE, arg1, arg2, 0); + if (name) { + ret = get_errno(gethostname(name, arg2)); + unlock_user(name, arg1, arg2); + } else { + ret = -TARGET_EFAULT; + } + break; + } +#endif default: unimplemented: gemu_log("qemu: Unsupported syscall: %d\n", num); -- 1.7.11.4 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] [PATCH 2/6] linux-user: Implement gethostname 2012-10-11 19:22 ` [Qemu-devel] [PATCH 2/6] linux-user: Implement gethostname Richard Henderson @ 2012-10-11 19:43 ` Peter Maydell 0 siblings, 0 replies; 11+ messages in thread From: Peter Maydell @ 2012-10-11 19:43 UTC (permalink / raw) To: Richard Henderson; +Cc: Riku Voipio, qemu-devel On 11 October 2012 20:22, Richard Henderson <rth@twiddle.net> wrote: > Signed-off-by: Richard Henderson <rth@twiddle.net> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> -- PMM ^ permalink raw reply [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH 3/6] alpha-linux-user: Fix sigaltstack structure definition 2012-10-11 19:22 [Qemu-devel] [PATCH v3 0/6] linux-user improvements Richard Henderson 2012-10-11 19:22 ` [Qemu-devel] [PATCH 1/6] linux-user: Perform more checks on iovec lists Richard Henderson 2012-10-11 19:22 ` [Qemu-devel] [PATCH 2/6] linux-user: Implement gethostname Richard Henderson @ 2012-10-11 19:22 ` Richard Henderson 2012-10-11 19:22 ` [Qemu-devel] [PATCH 4/6] linux-user: Rewrite __get_user/__put_user with __builtin_choose_expr Richard Henderson ` (2 subsequent siblings) 5 siblings, 0 replies; 11+ messages in thread From: Richard Henderson @ 2012-10-11 19:22 UTC (permalink / raw) To: qemu-devel; +Cc: Riku Voipio Signed-off-by: Richard Henderson <rth@twiddle.net> --- linux-user/alpha/target_signal.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/linux-user/alpha/target_signal.h b/linux-user/alpha/target_signal.h index 94f15f6..d3822da 100644 --- a/linux-user/alpha/target_signal.h +++ b/linux-user/alpha/target_signal.h @@ -6,9 +6,10 @@ /* this struct defines a stack used during syscall handling */ typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_long ss_flags; - abi_ulong ss_size; + abi_ulong ss_sp; + int32_t ss_flags; + int32_t dummy; + abi_ulong ss_size; } target_stack_t; -- 1.7.11.4 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH 4/6] linux-user: Rewrite __get_user/__put_user with __builtin_choose_expr 2012-10-11 19:22 [Qemu-devel] [PATCH v3 0/6] linux-user improvements Richard Henderson ` (2 preceding siblings ...) 2012-10-11 19:22 ` [Qemu-devel] [PATCH 3/6] alpha-linux-user: Fix sigaltstack structure definition Richard Henderson @ 2012-10-11 19:22 ` Richard Henderson 2012-10-11 19:52 ` Richard Henderson 2012-10-11 19:22 ` [Qemu-devel] [PATCH 5/6] alpha-linux-user: Fix sigaction Richard Henderson 2012-10-11 19:22 ` [Qemu-devel] [PATCH 6/6] linux-user: Fix siginfo handling Richard Henderson 5 siblings, 1 reply; 11+ messages in thread From: Richard Henderson @ 2012-10-11 19:22 UTC (permalink / raw) To: qemu-devel; +Cc: Riku Voipio The previous formuation with multiple assignments to __typeof(*hptr) falls down when hptr is qualified const. E.g. with const struct S *p, p->f is also qualified const. With this formulation, there's no assignment to any local variable. Signed-off-by: Richard Henderson <rth@twiddle.net> --- linux-user/qemu.h | 50 ++++++++++++++++++++------------------------------ 1 file changed, 20 insertions(+), 30 deletions(-) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index fc4cc00..39b2c9c 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -284,36 +284,26 @@ static inline int access_ok(int type, abi_ulong addr, abi_ulong size) (type == VERIFY_READ) ? PAGE_READ : (PAGE_READ | PAGE_WRITE)) == 0; } -/* NOTE __get_user and __put_user use host pointers and don't check access. */ -/* These are usually used to access struct data members once the - * struct has been locked - usually with lock_user_struct(). - */ -#define __put_user(x, hptr)\ -({ __typeof(*hptr) pu_ = (x);\ - switch(sizeof(*hptr)) {\ - case 1: break;\ - case 2: pu_ = tswap16(pu_); break; \ - case 4: pu_ = tswap32(pu_); break; \ - case 8: pu_ = tswap64(pu_); break; \ - default: abort();\ - }\ - memcpy(hptr, &pu_, sizeof(pu_)); \ - 0;\ -}) - -#define __get_user(x, hptr) \ -({ __typeof(*hptr) gu_; \ - memcpy(&gu_, hptr, sizeof(gu_)); \ - switch(sizeof(*hptr)) {\ - case 1: break; \ - case 2: gu_ = tswap16(gu_); break; \ - case 4: gu_ = tswap32(gu_); break; \ - case 8: gu_ = tswap64(gu_); break; \ - default: abort();\ - }\ - (x) = gu_; \ - 0;\ -}) +/* NOTE __get_user and __put_user use host pointers and don't check access. + These are usually used to access struct data members once the struct has + been locked - usually with lock_user_struct. */ +#define __put_user(x, hptr) \ +(*(hptr) = \ + __builtin_choose_expr(sizeof(*(hptr)) == 1, (uint8_t)(x), \ + __builtin_choose_expr(sizeof(*(hptr)) == 2, tswap16((uint16_t)(x)), \ + __builtin_choose_expr(sizeof(*(hptr)) == 4, tswap32((uint32_t)(x)), \ + __builtin_choose_expr(sizeof(*(hptr)) == 8, tswap64((uint64_t)(x)), \ + abort())))), \ + 0) + +#define __get_user(x, hptr) \ +((x) = \ + __builtin_choose_expr(sizeof(*(hptr)) == 1, *(hptr), \ + __builtin_choose_expr(sizeof(*(hptr)) == 2, tswap16(*(hptr)), \ + __builtin_choose_expr(sizeof(*(hptr)) == 4, tswap32(*(hptr)), \ + __builtin_choose_expr(sizeof(*(hptr)) == 8, tswap64(*(hptr)), \ + abort())))), \ + 0) /* put_user()/get_user() take a guest address and check access */ /* These are usually used to access an atomic data type, such as an int, -- 1.7.11.4 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] [PATCH 4/6] linux-user: Rewrite __get_user/__put_user with __builtin_choose_expr 2012-10-11 19:22 ` [Qemu-devel] [PATCH 4/6] linux-user: Rewrite __get_user/__put_user with __builtin_choose_expr Richard Henderson @ 2012-10-11 19:52 ` Richard Henderson 2012-10-12 11:10 ` Riku Voipio 0 siblings, 1 reply; 11+ messages in thread From: Richard Henderson @ 2012-10-11 19:52 UTC (permalink / raw) To: qemu-devel; +Cc: Riku Voipio On 10/11/2012 12:22 PM, Richard Henderson wrote: > The previous formuation with multiple assignments to __typeof(*hptr) falls > down when hptr is qualified const. E.g. with const struct S *p, p->f is > also qualified const. > > With this formulation, there's no assignment to any local variable. > > Signed-off-by: Richard Henderson <rth@twiddle.net> Scratch that... I lost the unaligned access capability. I'll have to re-work the patch. r~ ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] [PATCH 4/6] linux-user: Rewrite __get_user/__put_user with __builtin_choose_expr 2012-10-11 19:52 ` Richard Henderson @ 2012-10-12 11:10 ` Riku Voipio 2012-10-12 14:43 ` Richard Henderson 0 siblings, 1 reply; 11+ messages in thread From: Riku Voipio @ 2012-10-12 11:10 UTC (permalink / raw) To: Richard Henderson; +Cc: qemu-devel Hi, On Thu, Oct 11, 2012 at 12:52:27PM -0700, Richard Henderson wrote: > On 10/11/2012 12:22 PM, Richard Henderson wrote: > > The previous formuation with multiple assignments to __typeof(*hptr) falls > > down when hptr is qualified const. E.g. with const struct S *p, p->f is > > also qualified const. > > > > With this formulation, there's no assignment to any local variable. > > > > Signed-off-by: Richard Henderson <rth@twiddle.net> > Scratch that... I lost the unaligned access capability. > I'll have to re-work the patch. I've just prepared the rest of your patch for pending pull request[1]. Since changing __get_user/__put_user impacts more than just sigaction, do you mind if we put this patch (and thus sigaction change as well) to a later pull request? Riku [1] http://git.linaro.org/gitweb?p=people/rikuvoipio/qemu.git;a=shortlog;h=refs/heads/linux-user-for-upstream ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] [PATCH 4/6] linux-user: Rewrite __get_user/__put_user with __builtin_choose_expr 2012-10-12 11:10 ` Riku Voipio @ 2012-10-12 14:43 ` Richard Henderson 0 siblings, 0 replies; 11+ messages in thread From: Richard Henderson @ 2012-10-12 14:43 UTC (permalink / raw) To: Riku Voipio; +Cc: qemu-devel On 10/12/2012 04:10 AM, Riku Voipio wrote: > Since changing __get_user/__put_user impacts more than just sigaction, > do you mind if we put this patch (and thus sigaction change as well) > to a later pull request? Certainly. r~ ^ permalink raw reply [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH 5/6] alpha-linux-user: Fix sigaction 2012-10-11 19:22 [Qemu-devel] [PATCH v3 0/6] linux-user improvements Richard Henderson ` (3 preceding siblings ...) 2012-10-11 19:22 ` [Qemu-devel] [PATCH 4/6] linux-user: Rewrite __get_user/__put_user with __builtin_choose_expr Richard Henderson @ 2012-10-11 19:22 ` Richard Henderson 2012-10-11 19:22 ` [Qemu-devel] [PATCH 6/6] linux-user: Fix siginfo handling Richard Henderson 5 siblings, 0 replies; 11+ messages in thread From: Richard Henderson @ 2012-10-11 19:22 UTC (permalink / raw) To: qemu-devel; +Cc: Riku Voipio Unconditional bswap replaced by __get_user/__put_user. Signed-off-by: Richard Henderson <rth@twiddle.net> --- linux-user/signal.c | 22 ++++++++-------------- linux-user/syscall_defs.h | 2 +- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index 15bc4e8..1969877 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -586,28 +586,22 @@ int do_sigaction(int sig, const struct target_sigaction *act, sig, act, oact); #endif if (oact) { - oact->_sa_handler = tswapal(k->_sa_handler); -#if defined(TARGET_MIPS) || defined (TARGET_ALPHA) - oact->sa_flags = bswap32(k->sa_flags); -#else - oact->sa_flags = tswapal(k->sa_flags); -#endif + __put_user(k->_sa_handler, &oact->_sa_handler); + __put_user(k->sa_flags, &oact->sa_flags); #if !defined(TARGET_MIPS) - oact->sa_restorer = tswapal(k->sa_restorer); + __put_user(k->sa_restorer, &oact->sa_restorer); #endif + /* Not swapped. */ oact->sa_mask = k->sa_mask; } if (act) { /* FIXME: This is not threadsafe. */ - k->_sa_handler = tswapal(act->_sa_handler); -#if defined(TARGET_MIPS) || defined (TARGET_ALPHA) - k->sa_flags = bswap32(act->sa_flags); -#else - k->sa_flags = tswapal(act->sa_flags); -#endif + __get_user(k->_sa_handler, &act->_sa_handler); + __get_user(k->sa_flags, &act->sa_flags); #if !defined(TARGET_MIPS) - k->sa_restorer = tswapal(act->sa_restorer); + __get_user(k->sa_restorer, &act->sa_restorer); #endif + /* To be swapped in target_to_host_sigset. */ k->sa_mask = act->sa_mask; /* we update the host linux signal state */ diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index a98cbf7..8ca70b9 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -540,7 +540,7 @@ int do_sigaction(int sig, const struct target_sigaction *act, struct target_old_sigaction { abi_ulong _sa_handler; abi_ulong sa_mask; - abi_ulong sa_flags; + int32_t sa_flags; }; struct target_rt_sigaction { -- 1.7.11.4 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH 6/6] linux-user: Fix siginfo handling 2012-10-11 19:22 [Qemu-devel] [PATCH v3 0/6] linux-user improvements Richard Henderson ` (4 preceding siblings ...) 2012-10-11 19:22 ` [Qemu-devel] [PATCH 5/6] alpha-linux-user: Fix sigaction Richard Henderson @ 2012-10-11 19:22 ` Richard Henderson 5 siblings, 0 replies; 11+ messages in thread From: Richard Henderson @ 2012-10-11 19:22 UTC (permalink / raw) To: qemu-devel; +Cc: Riku Voipio Compare signal numbers in the proper domain. Convert all of the fields for SIGIO and SIGCHLD. Signed-off-by: Richard Henderson <rth@twiddle.net> --- linux-user/qemu.h | 3 +++ linux-user/signal.c | 59 +++++++++++++++++++++++++++++++++++----------------- linux-user/syscall.c | 2 +- 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 39b2c9c..35c16d1 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -219,6 +219,9 @@ unsigned long init_guest_space(unsigned long host_start, #include "qemu-log.h" +/* syscall.c */ +int host_to_target_waitstatus(int status); + /* strace.c */ void print_syscall(int num, abi_long arg1, abi_long arg2, abi_long arg3, diff --git a/linux-user/signal.c b/linux-user/signal.c index 1969877..407619a 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -202,46 +202,67 @@ void target_to_host_old_sigset(sigset_t *sigset, static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo, const siginfo_t *info) { - int sig; - sig = host_to_target_signal(info->si_signo); + int sig = host_to_target_signal(info->si_signo); tinfo->si_signo = sig; tinfo->si_errno = 0; tinfo->si_code = info->si_code; - if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || - sig == SIGBUS || sig == SIGTRAP) { - /* should never come here, but who knows. The information for - the target is irrelevant */ + + if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV + || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) { + /* Should never come here, but who knows. The information for + the target is irrelevant. */ tinfo->_sifields._sigfault._addr = 0; - } else if (sig == SIGIO) { + } else if (sig == TARGET_SIGIO) { + tinfo->_sifields._sigpoll._band = info->si_band; tinfo->_sifields._sigpoll._fd = info->si_fd; + } else if (sig == TARGET_SIGCHLD) { + tinfo->_sifields._sigchld._pid = info->si_pid; + tinfo->_sifields._sigchld._uid = info->si_uid; + tinfo->_sifields._sigchld._status + = host_to_target_waitstatus(info->si_status); + tinfo->_sifields._sigchld._utime = info->si_utime; + tinfo->_sifields._sigchld._stime = info->si_stime; } else if (sig >= TARGET_SIGRTMIN) { tinfo->_sifields._rt._pid = info->si_pid; tinfo->_sifields._rt._uid = info->si_uid; /* XXX: potential problem if 64 bit */ - tinfo->_sifields._rt._sigval.sival_ptr = - (abi_ulong)(unsigned long)info->si_value.sival_ptr; + tinfo->_sifields._rt._sigval.sival_ptr + = (abi_ulong)(unsigned long)info->si_value.sival_ptr; } } static void tswap_siginfo(target_siginfo_t *tinfo, const target_siginfo_t *info) { - int sig; - sig = info->si_signo; + int sig = info->si_signo; tinfo->si_signo = tswap32(sig); tinfo->si_errno = tswap32(info->si_errno); tinfo->si_code = tswap32(info->si_code); - if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || - sig == SIGBUS || sig == SIGTRAP) { - tinfo->_sifields._sigfault._addr = - tswapal(info->_sifields._sigfault._addr); - } else if (sig == SIGIO) { - tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd); + + if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV + || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) { + tinfo->_sifields._sigfault._addr + = tswapal(info->_sifields._sigfault._addr); + } else if (sig == TARGET_SIGIO) { + tinfo->_sifields._sigpoll._band + = tswap32(info->_sifields._sigpoll._band); + tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd); + } else if (sig == TARGET_SIGCHLD) { + tinfo->_sifields._sigchld._pid + = tswap32(info->_sifields._sigchld._pid); + tinfo->_sifields._sigchld._uid + = tswap32(info->_sifields._sigchld._uid); + tinfo->_sifields._sigchld._status + = tswap32(info->_sifields._sigchld._status); + tinfo->_sifields._sigchld._utime + = tswapal(info->_sifields._sigchld._utime); + tinfo->_sifields._sigchld._stime + = tswapal(info->_sifields._sigchld._stime); } else if (sig >= TARGET_SIGRTMIN) { tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid); tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid); - tinfo->_sifields._rt._sigval.sival_ptr = - tswapal(info->_sifields._rt._sigval.sival_ptr); + tinfo->_sifields._rt._sigval.sival_ptr + = tswapal(info->_sifields._rt._sigval.sival_ptr); } } diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 462d11b..612683f 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -4918,7 +4918,7 @@ static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout, /* Map host to target signal numbers for the wait family of syscalls. Assume all other status bits are the same. */ -static int host_to_target_waitstatus(int status) +int host_to_target_waitstatus(int status) { if (WIFSIGNALED(status)) { return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f); -- 1.7.11.4 ^ permalink raw reply related [flat|nested] 11+ messages in thread
end of thread, other threads:[~2012-10-12 14:43 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-10-11 19:22 [Qemu-devel] [PATCH v3 0/6] linux-user improvements Richard Henderson 2012-10-11 19:22 ` [Qemu-devel] [PATCH 1/6] linux-user: Perform more checks on iovec lists Richard Henderson 2012-10-11 19:22 ` [Qemu-devel] [PATCH 2/6] linux-user: Implement gethostname Richard Henderson 2012-10-11 19:43 ` Peter Maydell 2012-10-11 19:22 ` [Qemu-devel] [PATCH 3/6] alpha-linux-user: Fix sigaltstack structure definition Richard Henderson 2012-10-11 19:22 ` [Qemu-devel] [PATCH 4/6] linux-user: Rewrite __get_user/__put_user with __builtin_choose_expr Richard Henderson 2012-10-11 19:52 ` Richard Henderson 2012-10-12 11:10 ` Riku Voipio 2012-10-12 14:43 ` Richard Henderson 2012-10-11 19:22 ` [Qemu-devel] [PATCH 5/6] alpha-linux-user: Fix sigaction Richard Henderson 2012-10-11 19:22 ` [Qemu-devel] [PATCH 6/6] linux-user: Fix siginfo handling Richard Henderson
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.