diff options
author | Patrick Mooney <pmooney@pfmooney.com> | 2016-02-17 01:18:15 +0000 |
---|---|---|
committer | Patrick Mooney <pmooney@pfmooney.com> | 2016-02-17 15:13:36 +0000 |
commit | 177e2292c928a9dca0cb63322b5c028a5ffa502b (patch) | |
tree | dd3c6a88c751074c8feb262177bbeb55d884a779 | |
parent | 4812ce10322644e76510aadb0e5572c4baec2039 (diff) | |
download | illumos-joyent-release-20160218.tar.gz |
OS-5157 lxbrand pselect failure on 32bit ltprelease-20160218
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
-rw-r--r-- | usr/src/uts/common/brand/lx/syscall/lx_poll.c | 62 |
1 files changed, 46 insertions, 16 deletions
diff --git a/usr/src/uts/common/brand/lx/syscall/lx_poll.c b/usr/src/uts/common/brand/lx/syscall/lx_poll.c index fd50f18a68..1d92a55ddf 100644 --- a/usr/src/uts/common/brand/lx/syscall/lx_poll.c +++ b/usr/src/uts/common/brand/lx/syscall/lx_poll.c @@ -675,9 +675,22 @@ lx_select(int nfds, long *rfds, long *wfds, long *efds, return (lx_select_common(nfds, rfds, wfds, efds, tsp, NULL)); } + +typedef struct { + uintptr_t lpsa_addr; + unsigned long lpsa_len; +} lx_pselect_sig_arg_t; + +#if defined(_LP64) +typedef struct { + caddr32_t lpsa_addr; + uint32_t lpsa_len; +} lx_pselect_sig_arg32_t; +#endif /* defined(_LP64) */ + long lx_pselect(int nfds, long *rfds, long *wfds, long *efds, - timespec_t *timeoutp, uintptr_t setp) + timespec_t *timeoutp, void *setp) { timespec_t ts, *tsp = NULL; k_sigset_t kset, *ksetp = NULL; @@ -702,25 +715,42 @@ lx_pselect(int nfds, long *rfds, long *wfds, long *efds, tsp = &ts; } if (setp != NULL) { - struct { - lx_sigset_t *addr; - size_t size; - } ps_lx_sigset; - lx_sigset_t lset; + lx_sigset_t lset, *sigaddr = NULL; - if (copyin((void *)setp, &ps_lx_sigset, sizeof (ps_lx_sigset))) - return (set_errno(EFAULT)); + if (get_udatamodel() == DATAMODEL_NATIVE) { + lx_pselect_sig_arg_t lpsa; - /* - * Yes, that's right: Linux forces a size to be passed only - * so it can check that it's the size of a sigset_t. - */ - if (ps_lx_sigset.size != sizeof (lx_sigset_t)) - return (set_errno(EINVAL)); + if (copyin(setp, &lpsa, sizeof (lpsa)) != 0) + return (set_errno(EFAULT)); + /* + * Linux forces a size to be passed only so it can + * check that it's the size of a sigset_t. + */ + if (lpsa.lpsa_len != sizeof (lx_sigset_t)) + return (set_errno(EINVAL)); + + sigaddr = (lx_sigset_t *)lpsa.lpsa_addr; + } +#if defined(_LP64) + else { + lx_pselect_sig_arg32_t lpsa32; + + if (copyin(setp, &lpsa32, sizeof (lpsa32)) != 0) + return (set_errno(EFAULT)); + /* + * Linux forces a size to be passed only so it can + * check that it's the size of a sigset_t. + */ + if (lpsa32.lpsa_len != sizeof (lx_sigset_t)) + return (set_errno(EINVAL)); + + sigaddr = (lx_sigset_t *)(uint64_t)lpsa32.lpsa_addr; + } +#endif /* defined(_LP64) */ /* This is where we check if the sigset is *really* NULL. */ - if (ps_lx_sigset.addr != NULL) { - if (copyin(ps_lx_sigset.addr, &lset, sizeof (lset))) + if (sigaddr != NULL) { + if (copyin(sigaddr, &lset, sizeof (lset)) != 0) return (set_errno(EFAULT)); lx_ltos_sigset(&lset, &kset); |