Commit 8bfa25a4 authored by Peter Maydell's avatar Peter Maydell
Browse files

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: default avatarPeter Maydell <peter.maydell@linaro.org>
parents d2628b1e 42b16184
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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);
+25 −27
Original line number Diff line number Diff line
@@ -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);
            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);
                    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");
+78 −8
Original line number Diff line number Diff line
@@ -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: