From c7128c9fd58ee92cae70c7cd1d53acc529cebbbb Mon Sep 17 00:00:00 2001 From: Petar Jovanovic Date: Thu, 21 Mar 2013 07:57:36 +0000 Subject: [PATCH 1/3] linux-user: change do_semop to return target errno when unsuccessful do_semop() is called from two places, and one of these fails to convert return error to target errno when semop fails. This patch changes the function to always return target errno in case of an unsuccessful call. Signed-off-by: Petar Jovanovic Reviewed-by: Peter Maydell Signed-off-by: Riku Voipio --- linux-user/syscall.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 1f07621ff..d6d20502e 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -2764,7 +2764,7 @@ static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops) if (target_to_host_sembuf(sops, ptr, nsops)) return -TARGET_EFAULT; - return semop(semid, sops, nsops); + return get_errno(semop(semid, sops, nsops)); } struct target_msqid_ds @@ -6957,7 +6957,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_semop case TARGET_NR_semop: - ret = get_errno(do_semop(arg1, arg2, arg3)); + ret = do_semop(arg1, arg2, arg3); break; #endif #ifdef TARGET_NR_semctl From 9ab709be595bef9956ea550a95e14e157cb5704e Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Tue, 9 Apr 2013 01:02:34 +0000 Subject: [PATCH 2/3] linux-user: fix undefined shift in copy_to_user_fdset If TARGET_ABI_BITS is bigger than 32 we shift by more than the size of int. Signed-off-by: Andreas Schwab Reviewed-by: Peter Maydell Signed-off-by: Riku Voipio --- linux-user/syscall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index d6d20502e..5a786f2fe 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -914,7 +914,7 @@ static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr, for (i = 0; i < nw; i++) { v = 0; for (j = 0; j < TARGET_ABI_BITS; j++) { - v |= ((FD_ISSET(k, fds) != 0) << j); + v |= ((abi_ulong)(FD_ISSET(k, fds) != 0) << j); k++; } __put_user(v, &target_fds[i]); From 03903ffcfb5a7c75e52da97d00eb9d0bb0660f28 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Tue, 9 Apr 2013 05:41:33 +0000 Subject: [PATCH 3/3] linux-user: fix setgroups/getgroups for non-UID16 archs Don't assume target_id is a short. Signed-off-by: Andreas Schwab Signed-off-by: Riku Voipio --- linux-user/syscall.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 5a786f2fe..c705960d7 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -7743,12 +7743,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, if (gidsetsize == 0) break; if (!is_error(ret)) { - target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0); + target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * sizeof(target_id), 0); if (!target_grouplist) goto efault; for(i = 0;i < ret; i++) target_grouplist[i] = tswapid(high2lowgid(grouplist[i])); - unlock_user(target_grouplist, arg2, gidsetsize * 2); + unlock_user(target_grouplist, arg2, gidsetsize * sizeof(target_id)); } } break; @@ -7760,7 +7760,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, int i; if (gidsetsize) { grouplist = alloca(gidsetsize * sizeof(gid_t)); - target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1); + target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * sizeof(target_id), 1); if (!target_grouplist) { ret = -TARGET_EFAULT; goto fail;