diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2020-07-14 20:24:00 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2020-07-14 20:24:00 +0100 |
commit | 8bfa25a46ff1082f75e7052875b5d435119dcf49 (patch) | |
tree | 0aef93d361d1e3ffabb27259d233cc40118f7234 | |
parent | d2628b1eb761a5fbf08f367da405eb3314a1f068 (diff) | |
parent | 42b16184d016d48d167229a1ddb89b3671c77440 (diff) |
Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-5.1-pull-request' into staging
linux-user branch 20200714
Fix strace errno management
Fix Coverity erros in ioctl straces
Fix some netlinks errors
Fix semtimedop
# gpg: Signature made Tue 14 Jul 2020 08:31:56 BST
# gpg: using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C
# gpg: issuer "laurent@vivier.eu"
# gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full]
# gpg: aka "Laurent Vivier <laurent@vivier.eu>" [full]
# gpg: aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full]
# Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F BE3C
* remotes/vivier2/tags/linux-user-for-5.1-pull-request:
linux-user: fix print_syscall_err() when syscall returned value is negative
linux-user: fix the errno value in print_syscall_err()
linux-user: add netlink RTM_SETLINK command
linux-user: add new netlink types
linux-user: Fix Coverity CID 1430271 / CID 1430272
linux-user: refactor ipc syscall and support of semtimedop syscall
linux-user: Use EPROTONOSUPPORT for unimplemented netlink protocols
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | linux-user/fd-trans.c | 5 | ||||
-rw-r--r-- | linux-user/strace.c | 52 | ||||
-rw-r--r-- | linux-user/syscall.c | 86 |
3 files changed, 108 insertions, 35 deletions
diff --git a/linux-user/fd-trans.c b/linux-user/fd-trans.c index c0687c52e6..1486c81aaa 100644 --- a/linux-user/fd-trans.c +++ b/linux-user/fd-trans.c @@ -133,6 +133,9 @@ enum { QEMU_IFLA_NEW_IFINDEX, QEMU_IFLA_MIN_MTU, QEMU_IFLA_MAX_MTU, + QEMU_IFLA_PROP_LIST, + QEMU_IFLA_ALT_IFNAME, + QEMU_IFLA_PERM_ADDRESS, QEMU___IFLA_MAX }; @@ -807,6 +810,7 @@ static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr) /* binary stream */ case QEMU_IFLA_ADDRESS: case QEMU_IFLA_BROADCAST: + case QEMU_IFLA_PERM_ADDRESS: /* string */ case QEMU_IFLA_IFNAME: case QEMU_IFLA_QDISC: @@ -1200,6 +1204,7 @@ static abi_long target_to_host_data_route(struct nlmsghdr *nlh) break; case RTM_NEWLINK: case RTM_DELLINK: + case RTM_SETLINK: if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ifi))) { ifi = NLMSG_DATA(nlh); ifi->ifi_type = tswap16(ifi->ifi_type); diff --git a/linux-user/strace.c b/linux-user/strace.c index 5235b2260c..13981341b3 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -724,19 +724,20 @@ print_ipc(const struct syscallname *name, * Variants for the return value output function */ -static void +static bool print_syscall_err(abi_long ret) { - const char *errstr = NULL; + const char *errstr; qemu_log(" = "); if (ret < 0) { - qemu_log("-1 errno=%d", errno); errstr = target_strerror(-ret); if (errstr) { - qemu_log(" (%s)", errstr); + qemu_log("-1 errno=%d (%s)", (int)-ret, errstr); + return true; } } + return false; } static void @@ -744,11 +745,10 @@ print_syscall_ret_addr(const struct syscallname *name, abi_long ret, abi_long arg0, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5) { - print_syscall_err(ret); - - if (ret >= 0) { - qemu_log("0x" TARGET_ABI_FMT_lx "\n", ret); + if (!print_syscall_err(ret)) { + qemu_log("0x" TARGET_ABI_FMT_lx, ret); } + qemu_log("\n"); } #if 0 /* currently unused */ @@ -765,9 +765,7 @@ print_syscall_ret_newselect(const struct syscallname *name, abi_long ret, abi_long arg0, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5) { - print_syscall_err(ret); - - if (ret >= 0) { + if (!print_syscall_err(ret)) { qemu_log(" = 0x" TARGET_ABI_FMT_lx " (", ret); print_fdset(arg0, arg1); qemu_log(","); @@ -796,9 +794,7 @@ print_syscall_ret_adjtimex(const struct syscallname *name, abi_long ret, abi_long arg0, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5) { - print_syscall_err(ret); - - if (ret >= 0) { + if (!print_syscall_err(ret)) { qemu_log(TARGET_ABI_FMT_ld, ret); switch (ret) { case TARGET_TIME_OK: @@ -833,9 +829,7 @@ print_syscall_ret_listxattr(const struct syscallname *name, abi_long ret, abi_long arg0, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5) { - print_syscall_err(ret); - - if (ret >= 0) { + if (!print_syscall_err(ret)) { qemu_log(TARGET_ABI_FMT_ld, ret); qemu_log(" (list = "); if (arg1 != 0) { @@ -866,9 +860,7 @@ print_syscall_ret_ioctl(const struct syscallname *name, abi_long ret, abi_long arg0, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5) { - print_syscall_err(ret); - - if (ret >= 0) { + if (!print_syscall_err(ret)) { qemu_log(TARGET_ABI_FMT_ld, ret); const IOCTLEntry *ie; @@ -889,8 +881,12 @@ print_syscall_ret_ioctl(const struct syscallname *name, abi_long ret, arg_type++; target_size = thunk_type_size(arg_type, 0); argptr = lock_user(VERIFY_READ, arg2, target_size, 1); - thunk_print(argptr, arg_type); - unlock_user(argptr, arg2, target_size); + if (argptr) { + thunk_print(argptr, arg_type); + unlock_user(argptr, arg2, target_size); + } else { + print_pointer(arg2, 1); + } qemu_log(")"); } } @@ -3119,8 +3115,12 @@ print_ioctl(const struct syscallname *name, arg_type++; target_size = thunk_type_size(arg_type, 0); argptr = lock_user(VERIFY_READ, arg2, target_size, 1); - thunk_print(argptr, arg_type); - unlock_user(argptr, arg2, target_size); + if (argptr) { + thunk_print(argptr, arg_type); + unlock_user(argptr, arg2, target_size); + } else { + print_pointer(arg2, 1); + } break; } break; @@ -3189,9 +3189,7 @@ print_syscall_ret(int num, abi_long ret, arg1, arg2, arg3, arg4, arg5, arg6); } else { - print_syscall_err(ret); - - if (ret >= 0) { + if (!print_syscall_err(ret)) { qemu_log(TARGET_ABI_FMT_ld, ret); } qemu_log("\n"); diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 98ea86ca81..1211e759c2 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -817,9 +817,14 @@ safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags, const struct timespec *, req, struct timespec *, rem) #endif #ifdef __NR_ipc +#ifdef __s390x__ +safe_syscall5(int, ipc, int, call, long, first, long, second, long, third, + void *, ptr) +#else safe_syscall6(int, ipc, int, call, long, first, long, second, long, third, void *, ptr, long, fifth) #endif +#endif #ifdef __NR_msgsnd safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz, int, flags) @@ -1230,7 +1235,8 @@ static inline abi_long copy_to_user_timeval64(abi_ulong target_tv_addr, defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6) || \ defined(TARGET_NR_nanosleep) || defined(TARGET_NR_clock_settime) || \ defined(TARGET_NR_utimensat) || defined(TARGET_NR_mq_timedsend) || \ - defined(TARGET_NR_mq_timedreceive) + defined(TARGET_NR_mq_timedreceive) || defined(TARGET_NR_ipc) || \ + defined(TARGET_NR_semop) || defined(TARGET_NR_semtimedop) static inline abi_long target_to_host_timespec(struct timespec *host_ts, abi_ulong target_addr) { @@ -2990,7 +2996,7 @@ static abi_long do_socket(int domain, int type, int protocol) #endif protocol == NETLINK_KOBJECT_UEVENT || protocol == NETLINK_AUDIT)) { - return -TARGET_EPFNOSUPPORT; + return -TARGET_EPROTONOSUPPORT; } if (domain == AF_PACKET || @@ -3878,25 +3884,53 @@ static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf, return 0; } -static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops) +#if defined(TARGET_NR_ipc) || defined(TARGET_NR_semop) || \ + defined(TARGET_NR_semtimedop) + +/* + * This macro is required to handle the s390 variants, which passes the + * arguments in a different order than default. + */ +#ifdef __s390x__ +#define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \ + (__nsops), (__timeout), (__sops) +#else +#define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \ + (__nsops), 0, (__sops), (__timeout) +#endif + +static inline abi_long do_semtimedop(int semid, + abi_long ptr, + unsigned nsops, + abi_long timeout) { struct sembuf sops[nsops]; + struct timespec ts, *pts = NULL; abi_long ret; + if (timeout) { + pts = &ts; + if (target_to_host_timespec(pts, timeout)) { + return -TARGET_EFAULT; + } + } + if (target_to_host_sembuf(sops, ptr, nsops)) return -TARGET_EFAULT; ret = -TARGET_ENOSYS; #ifdef __NR_semtimedop - ret = get_errno(safe_semtimedop(semid, sops, nsops, NULL)); + ret = get_errno(safe_semtimedop(semid, sops, nsops, pts)); #endif #ifdef __NR_ipc if (ret == -TARGET_ENOSYS) { - ret = get_errno(safe_ipc(IPCOP_semtimedop, semid, nsops, 0, sops, 0)); + ret = get_errno(safe_ipc(IPCOP_semtimedop, semid, + SEMTIMEDOP_IPC_ARGS(nsops, sops, (long)pts))); } #endif return ret; } +#endif struct target_msqid_ds { @@ -4056,8 +4090,13 @@ static inline abi_long do_msgsnd(int msqid, abi_long msgp, #endif #ifdef __NR_ipc if (ret == -TARGET_ENOSYS) { +#ifdef __s390x__ + ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg, + host_mb)); +#else ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg, host_mb, 0)); +#endif } #endif g_free(host_mb); @@ -4066,6 +4105,20 @@ static inline abi_long do_msgsnd(int msqid, abi_long msgp, return ret; } +#ifdef __NR_ipc +#if defined(__sparc__) +/* SPARC for msgrcv it does not use the kludge on final 2 arguments. */ +#define MSGRCV_ARGS(__msgp, __msgtyp) __msgp, __msgtyp +#elif defined(__s390x__) +/* The s390 sys_ipc variant has only five parameters. */ +#define MSGRCV_ARGS(__msgp, __msgtyp) \ + ((long int[]){(long int)__msgp, __msgtyp}) +#else +#define MSGRCV_ARGS(__msgp, __msgtyp) \ + ((long int[]){(long int)__msgp, __msgtyp}), 0 +#endif +#endif + static inline abi_long do_msgrcv(int msqid, abi_long msgp, ssize_t msgsz, abi_long msgtyp, int msgflg) @@ -4094,7 +4147,7 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp, #ifdef __NR_ipc if (ret == -TARGET_ENOSYS) { ret = get_errno(safe_ipc(IPCOP_CALL(1, IPCOP_msgrcv), msqid, msgsz, - msgflg, host_mb, msgtyp)); + msgflg, MSGRCV_ARGS(host_mb, msgtyp))); } #endif @@ -4372,7 +4425,20 @@ static abi_long do_ipc(CPUArchState *cpu_env, switch (call) { case IPCOP_semop: - ret = do_semop(first, ptr, second); + ret = do_semtimedop(first, ptr, second, 0); + break; + case IPCOP_semtimedop: + /* + * The s390 sys_ipc variant has only five parameters instead of six + * (as for default variant) and the only difference is the handling of + * SEMTIMEDOP where on s390 the third parameter is used as a pointer + * to a struct timespec where the generic variant uses fifth parameter. + */ +#if defined(TARGET_S390X) + ret = do_semtimedop(first, ptr, second, third); +#else + ret = do_semtimedop(first, ptr, second, fifth); +#endif break; case IPCOP_semget: @@ -9684,7 +9750,11 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_semop case TARGET_NR_semop: - return do_semop(arg1, arg2, arg3); + return do_semtimedop(arg1, arg2, arg3, 0); +#endif +#ifdef TARGET_NR_semtimedop + case TARGET_NR_semtimedop: + return do_semtimedop(arg1, arg2, arg3, arg4); #endif #ifdef TARGET_NR_semctl case TARGET_NR_semctl: |