[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 07/13] linux-user: Fix sched_get/setaffinity conversi
From: |
Laurent Vivier |
Subject: |
[Qemu-devel] [PULL 07/13] linux-user: Fix sched_get/setaffinity conversion |
Date: |
Tue, 23 Jan 2018 15:48:01 +0100 |
From: Samuel Thibault <address@hidden>
sched_get/setaffinity linux-user syscalls were missing conversions for
little/big endian, which is hairy since longs may not be the same size
either.
For simplicity, this just introduces loops to convert bit by bit like is
done for select.
Signed-off-by: Samuel Thibault <address@hidden>
Reviewed-by: Laurent Vivier <address@hidden>
Message-Id: <address@hidden>
Signed-off-by: Laurent Vivier <address@hidden>
---
linux-user/syscall.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 73 insertions(+), 8 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 41ded90ee6..143e4a959d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7731,6 +7731,73 @@ static TargetFdTrans target_inotify_trans = {
};
#endif
+static int target_to_host_cpu_mask(unsigned long *host_mask,
+ size_t host_size,
+ abi_ulong target_addr,
+ size_t target_size)
+{
+ unsigned target_bits = sizeof(abi_ulong) * 8;
+ unsigned host_bits = sizeof(*host_mask) * 8;
+ abi_ulong *target_mask;
+ unsigned i, j;
+
+ assert(host_size >= target_size);
+
+ target_mask = lock_user(VERIFY_READ, target_addr, target_size, 1);
+ if (!target_mask) {
+ return -TARGET_EFAULT;
+ }
+ memset(host_mask, 0, host_size);
+
+ for (i = 0 ; i < target_size / sizeof(abi_ulong); i++) {
+ unsigned bit = i * target_bits;
+ abi_ulong val;
+
+ __get_user(val, &target_mask[i]);
+ for (j = 0; j < target_bits; j++, bit++) {
+ if (val & (1UL << j)) {
+ host_mask[bit / host_bits] |= 1UL << (bit % host_bits);
+ }
+ }
+ }
+
+ unlock_user(target_mask, target_addr, 0);
+ return 0;
+}
+
+static int host_to_target_cpu_mask(const unsigned long *host_mask,
+ size_t host_size,
+ abi_ulong target_addr,
+ size_t target_size)
+{
+ unsigned target_bits = sizeof(abi_ulong) * 8;
+ unsigned host_bits = sizeof(*host_mask) * 8;
+ abi_ulong *target_mask;
+ unsigned i, j;
+
+ assert(host_size >= target_size);
+
+ target_mask = lock_user(VERIFY_WRITE, target_addr, target_size, 0);
+ if (!target_mask) {
+ return -TARGET_EFAULT;
+ }
+
+ for (i = 0 ; i < target_size / sizeof(abi_ulong); i++) {
+ unsigned bit = i * target_bits;
+ abi_ulong val = 0;
+
+ for (j = 0; j < target_bits; j++, bit++) {
+ if (host_mask[bit / host_bits] & (1UL << (bit % host_bits))) {
+ val |= 1UL << j;
+ }
+ }
+ __put_user(val, &target_mask[i]);
+ }
+
+ unlock_user(target_mask, target_addr, target_size);
+ return 0;
+}
+
/* do_syscall() should always have a single exit point at the end so
that actions, such as logging of syscall results, can be performed.
All errnos that do_syscall() returns must be -TARGET_<errcode>. */
@@ -10376,6 +10443,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long
arg1,
mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
mask = alloca(mask_size);
+ memset(mask, 0, mask_size);
ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
if (!is_error(ret)) {
@@ -10395,9 +10463,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long
arg1,
ret = arg2;
}
- if (copy_to_user(arg3, mask, ret)) {
- goto efault;
- }
+ ret = host_to_target_cpu_mask(mask, mask_size, arg3, arg2);
}
}
break;
@@ -10415,13 +10481,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long
arg1,
break;
}
mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
-
mask = alloca(mask_size);
- if (!lock_user_struct(VERIFY_READ, p, arg3, 1)) {
- goto efault;
+
+ ret = target_to_host_cpu_mask(mask, mask_size, arg3, arg2);
+ if (ret) {
+ break;
}
- memcpy(mask, p, arg2);
- unlock_user_struct(p, arg2, 0);
ret = get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
}
--
2.14.3
- [Qemu-devel] [PULL 03/13] linux-user: Fix length calculations in host_to_target_cmsg(), (continued)
- [Qemu-devel] [PULL 03/13] linux-user: Fix length calculations in host_to_target_cmsg(), Laurent Vivier, 2018/01/23
- [Qemu-devel] [PULL 08/13] linux-user: Add AT_SECURE auxval, Laurent Vivier, 2018/01/23
- [Qemu-devel] [PULL 09/13] linux-user: Add getcpu() support, Laurent Vivier, 2018/01/23
- [Qemu-devel] [PULL 10/13] linux-user: remove nmi.c and fw-path-provider.c, Laurent Vivier, 2018/01/23
- [Qemu-devel] [PULL 13/13] linux-user: implement renameat2, Laurent Vivier, 2018/01/23
- [Qemu-devel] [PULL 02/13] linux-user: wrap fork() in a start/end exclusive section, Laurent Vivier, 2018/01/23
- [Qemu-devel] [PULL 04/13] linux-user: Don't use CMSG_ALIGN(sizeof struct cmsghdr), Laurent Vivier, 2018/01/23
- [Qemu-devel] [PULL 07/13] linux-user: Fix sched_get/setaffinity conversion,
Laurent Vivier <=
- [Qemu-devel] [PULL 11/13] linux-user: Propagate siginfo_t through to handle_cpu_signal(), Laurent Vivier, 2018/01/23
- [Qemu-devel] [PULL 12/13] page_unprotect(): handle calls to pages that are PAGE_WRITE, Laurent Vivier, 2018/01/23
- [Qemu-devel] [PULL 06/13] linux-user/mmap.c: Avoid choosing NULL as start address, Laurent Vivier, 2018/01/23
- Re: [Qemu-devel] [PULL 00/13] Linux user for 2.12 patches, Peter Maydell, 2018/01/25