summaryrefslogtreecommitdiffstats
path: root/linux-user
diff options
context:
space:
mode:
authorPeter Maydell2015-05-26 20:46:32 +0200
committerRiku Voipio2015-06-16 07:21:01 +0200
commit876e23cb2e545148a0ee4effda5c63c861855941 (patch)
tree75a5046e01f5b4b92e6638c41e336dfd1495c4de /linux-user
parentlinux-user: Fix length handling in host_to_target_cmsg (diff)
downloadqemu-876e23cb2e545148a0ee4effda5c63c861855941.tar.gz
qemu-876e23cb2e545148a0ee4effda5c63c861855941.tar.xz
qemu-876e23cb2e545148a0ee4effda5c63c861855941.zip
linux-user: use __get_user and __put_user in cmsg conversions
The target payloads in cmsg conversions may not have the alignment required by the host. Using the get_user and put_user functions is the easiest way to handle this and also do the byte-swapping we require. (Note that prior to this commit target_to_host_cmsg was incorrectly using __put_user() rather than __get_user() for the SCM_CREDENTIALS conversion, which meant it wasn't getting the benefit of the misalignment handling.) Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/syscall.c20
1 files changed, 11 insertions, 9 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 15b1e81471..5cf265cb08 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1228,17 +1228,18 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
int *target_fd = (int *)target_data;
int i, numfds = len / sizeof(int);
- for (i = 0; i < numfds; i++)
- fd[i] = tswap32(target_fd[i]);
+ for (i = 0; i < numfds; i++) {
+ __get_user(fd[i], target_fd + i);
+ }
} else if (cmsg->cmsg_level == SOL_SOCKET
&& cmsg->cmsg_type == SCM_CREDENTIALS) {
struct ucred *cred = (struct ucred *)data;
struct target_ucred *target_cred =
(struct target_ucred *)target_data;
- __put_user(target_cred->pid, &cred->pid);
- __put_user(target_cred->uid, &cred->uid);
- __put_user(target_cred->gid, &cred->gid);
+ __get_user(cred->pid, &target_cred->pid);
+ __get_user(cred->uid, &target_cred->uid);
+ __get_user(cred->gid, &target_cred->gid);
} else {
gemu_log("Unsupported ancillary data: %d/%d\n",
cmsg->cmsg_level, cmsg->cmsg_type);
@@ -1333,8 +1334,9 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
int *target_fd = (int *)target_data;
int i, numfds = tgt_len / sizeof(int);
- for (i = 0; i < numfds; i++)
- target_fd[i] = tswap32(fd[i]);
+ for (i = 0; i < numfds; i++) {
+ __put_user(fd[i], target_fd + i);
+ }
break;
}
case SO_TIMESTAMP:
@@ -1349,8 +1351,8 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
}
/* copy struct timeval to target */
- target_tv->tv_sec = tswapal(tv->tv_sec);
- target_tv->tv_usec = tswapal(tv->tv_usec);
+ __put_user(tv->tv_sec, &target_tv->tv_sec);
+ __put_user(tv->tv_usec, &target_tv->tv_usec);
break;
}
case SCM_CREDENTIALS: