提交 26edcf41 编写于 作者: T ths

copy_from_user_fdset() update, by Thayne Harbaugh.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3779 c046a42c-6fe2-441c-8c8c-71466251a162
上级 01ba9816
...@@ -443,50 +443,66 @@ abi_long do_brk(abi_ulong new_brk) ...@@ -443,50 +443,66 @@ abi_long do_brk(abi_ulong new_brk)
} }
} }
static inline fd_set *target_to_host_fds(fd_set *fds, static inline abi_long copy_from_user_fdset(fd_set *fds,
abi_long *target_fds, int n) abi_ulong target_fds_addr,
int n)
{ {
#if !defined(BSWAP_NEEDED) && !defined(WORDS_BIGENDIAN) int i, nw, j, k;
return (fd_set *)target_fds; abi_ulong b, *target_fds;
#else
int i, b; nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
if (target_fds) { if (!(target_fds = lock_user(VERIFY_READ,
FD_ZERO(fds); target_fds_addr,
for(i = 0;i < n; i++) { sizeof(abi_ulong) * nw,
b = (tswapl(target_fds[i / TARGET_ABI_BITS]) >> 1)))
(i & (TARGET_ABI_BITS - 1))) & 1; return -TARGET_EFAULT;
if (b)
FD_SET(i, fds); FD_ZERO(fds);
k = 0;
for (i = 0; i < nw; i++) {
/* grab the abi_ulong */
__get_user(b, &target_fds[i]);
for (j = 0; j < TARGET_ABI_BITS; j++) {
/* check the bit inside the abi_ulong */
if ((b >> j) & 1)
FD_SET(k, fds);
k++;
} }
return fds;
} else {
return NULL;
} }
#endif
unlock_user(target_fds, target_fds_addr, 0);
return 0;
} }
static inline void host_to_target_fds(abi_long *target_fds, static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
fd_set *fds, int n) const fd_set *fds,
int n)
{ {
#if !defined(BSWAP_NEEDED) && !defined(WORDS_BIGENDIAN)
/* nothing to do */
#else
int i, nw, j, k; int i, nw, j, k;
abi_long v; abi_long v;
abi_ulong *target_fds;
if (target_fds) { nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS; if (!(target_fds = lock_user(VERIFY_WRITE,
k = 0; target_fds_addr,
for(i = 0;i < nw; i++) { sizeof(abi_ulong) * nw,
v = 0; 0)))
for(j = 0; j < TARGET_ABI_BITS; j++) { return -TARGET_EFAULT;
v |= ((FD_ISSET(k, fds) != 0) << j);
k++; k = 0;
} for (i = 0; i < nw; i++) {
target_fds[i] = tswapl(v); v = 0;
for (j = 0; j < TARGET_ABI_BITS; j++) {
v |= ((FD_ISSET(k, fds) != 0) << j);
k++;
} }
__put_user(v, &target_fds[i]);
} }
#endif
unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
return 0;
} }
#if defined(__alpha__) #if defined(__alpha__)
...@@ -565,74 +581,57 @@ static inline abi_long host_to_target_timeval(abi_ulong target_addr, ...@@ -565,74 +581,57 @@ static inline abi_long host_to_target_timeval(abi_ulong target_addr,
/* do_select() must return target values and target errnos. */ /* do_select() must return target values and target errnos. */
static abi_long do_select(int n, static abi_long do_select(int n,
abi_ulong rfd_p, abi_ulong wfd_p, abi_ulong rfd_addr, abi_ulong wfd_addr,
abi_ulong efd_p, abi_ulong target_tv) abi_ulong efd_addr, abi_ulong target_tv_addr)
{ {
fd_set rfds, wfds, efds; fd_set rfds, wfds, efds;
fd_set *rfds_ptr, *wfds_ptr, *efds_ptr; fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
abi_long *target_rfds, *target_wfds, *target_efds;
struct timeval tv, *tv_ptr; struct timeval tv, *tv_ptr;
abi_long ret; abi_long ret;
int ok;
if (rfd_p) { if (rfd_addr) {
target_rfds = lock_user(VERIFY_WRITE, rfd_p, sizeof(abi_long) * n, 1); if (copy_from_user_fdset(&rfds, rfd_addr, n))
if (!target_rfds) { return -TARGET_EFAULT;
ret = -TARGET_EFAULT; rfds_ptr = &rfds;
goto end;
}
rfds_ptr = target_to_host_fds(&rfds, target_rfds, n);
} else { } else {
target_rfds = NULL;
rfds_ptr = NULL; rfds_ptr = NULL;
} }
if (wfd_p) { if (wfd_addr) {
target_wfds = lock_user(VERIFY_WRITE, wfd_p, sizeof(abi_long) * n, 1); if (copy_from_user_fdset(&wfds, wfd_addr, n))
if (!target_wfds) { return -TARGET_EFAULT;
ret = -TARGET_EFAULT; wfds_ptr = &wfds;
goto end;
}
wfds_ptr = target_to_host_fds(&wfds, target_wfds, n);
} else { } else {
target_wfds = NULL;
wfds_ptr = NULL; wfds_ptr = NULL;
} }
if (efd_p) { if (efd_addr) {
target_efds = lock_user(VERIFY_WRITE, efd_p, sizeof(abi_long) * n, 1); if (copy_from_user_fdset(&efds, efd_addr, n))
if (!target_efds) { return -TARGET_EFAULT;
ret = -TARGET_EFAULT; efds_ptr = &efds;
goto end;
}
efds_ptr = target_to_host_fds(&efds, target_efds, n);
} else { } else {
target_efds = NULL;
efds_ptr = NULL; efds_ptr = NULL;
} }
if (target_tv) { if (target_tv_addr) {
target_to_host_timeval(&tv, target_tv); target_to_host_timeval(&tv, target_tv_addr);
tv_ptr = &tv; tv_ptr = &tv;
} else { } else {
tv_ptr = NULL; tv_ptr = NULL;
} }
ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr)); ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
ok = !is_error(ret);
if (ok) { if (!is_error(ret)) {
host_to_target_fds(target_rfds, rfds_ptr, n); if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
host_to_target_fds(target_wfds, wfds_ptr, n); return -TARGET_EFAULT;
host_to_target_fds(target_efds, efds_ptr, n); if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
return -TARGET_EFAULT;
if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
return -TARGET_EFAULT;
if (target_tv) { if (target_tv_addr)
host_to_target_timeval(target_tv, &tv); host_to_target_timeval(target_tv_addr, &tv);
}
} }
end:
unlock_user(target_rfds, rfd_p, ok ? sizeof(abi_long) * n : 0);
unlock_user(target_wfds, wfd_p, ok ? sizeof(abi_long) * n : 0);
unlock_user(target_efds, efd_p, ok ? sizeof(abi_long) * n : 0);
return ret; return ret;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册