From ba0fef0dd91dca2db6d1187c47b5d52592f4bee2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 4 Nov 2022 18:36:28 +0100 Subject: [PATCH 01/22] linux-user/strace: Constify struct flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit print_flags() takes a const pointer. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Laurent Vivier Message-Id: <20221104173632.1052-2-philmd@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/strace.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index 9ae5a812cd..25c47f0316 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -945,7 +945,7 @@ print_syscall_ret_ioctl(CPUArchState *cpu_env, const struct syscallname *name, } #endif -UNUSED static struct flags access_flags[] = { +UNUSED static const struct flags access_flags[] = { FLAG_GENERIC(F_OK), FLAG_GENERIC(R_OK), FLAG_GENERIC(W_OK), @@ -953,7 +953,7 @@ UNUSED static struct flags access_flags[] = { FLAG_END, }; -UNUSED static struct flags at_file_flags[] = { +UNUSED static const struct flags at_file_flags[] = { #ifdef AT_EACCESS FLAG_GENERIC(AT_EACCESS), #endif @@ -963,14 +963,14 @@ UNUSED static struct flags at_file_flags[] = { FLAG_END, }; -UNUSED static struct flags unlinkat_flags[] = { +UNUSED static const struct flags unlinkat_flags[] = { #ifdef AT_REMOVEDIR FLAG_GENERIC(AT_REMOVEDIR), #endif FLAG_END, }; -UNUSED static struct flags mode_flags[] = { +UNUSED static const struct flags mode_flags[] = { FLAG_GENERIC(S_IFSOCK), FLAG_GENERIC(S_IFLNK), FLAG_GENERIC(S_IFREG), @@ -981,14 +981,14 @@ UNUSED static struct flags mode_flags[] = { FLAG_END, }; -UNUSED static struct flags open_access_flags[] = { +UNUSED static const struct flags open_access_flags[] = { FLAG_TARGET(O_RDONLY), FLAG_TARGET(O_WRONLY), FLAG_TARGET(O_RDWR), FLAG_END, }; -UNUSED static struct flags open_flags[] = { +UNUSED static const struct flags open_flags[] = { FLAG_TARGET(O_APPEND), FLAG_TARGET(O_CREAT), FLAG_TARGET(O_DIRECTORY), @@ -1019,7 +1019,7 @@ UNUSED static struct flags open_flags[] = { FLAG_END, }; -UNUSED static struct flags mount_flags[] = { +UNUSED static const struct flags mount_flags[] = { #ifdef MS_BIND FLAG_GENERIC(MS_BIND), #endif @@ -1044,7 +1044,7 @@ UNUSED static struct flags mount_flags[] = { FLAG_END, }; -UNUSED static struct flags umount2_flags[] = { +UNUSED static const struct flags umount2_flags[] = { #ifdef MNT_FORCE FLAG_GENERIC(MNT_FORCE), #endif @@ -1057,7 +1057,7 @@ UNUSED static struct flags umount2_flags[] = { FLAG_END, }; -UNUSED static struct flags mmap_prot_flags[] = { +UNUSED static const struct flags mmap_prot_flags[] = { FLAG_GENERIC(PROT_NONE), FLAG_GENERIC(PROT_EXEC), FLAG_GENERIC(PROT_READ), @@ -1068,7 +1068,7 @@ UNUSED static struct flags mmap_prot_flags[] = { FLAG_END, }; -UNUSED static struct flags mmap_flags[] = { +UNUSED static const struct flags mmap_flags[] = { FLAG_TARGET(MAP_SHARED), FLAG_TARGET(MAP_PRIVATE), FLAG_TARGET(MAP_ANONYMOUS), @@ -1092,7 +1092,7 @@ UNUSED static struct flags mmap_flags[] = { FLAG_END, }; -UNUSED static struct flags clone_flags[] = { +UNUSED static const struct flags clone_flags[] = { FLAG_GENERIC(CLONE_VM), FLAG_GENERIC(CLONE_FS), FLAG_GENERIC(CLONE_FILES), @@ -1136,7 +1136,7 @@ UNUSED static struct flags clone_flags[] = { FLAG_END, }; -UNUSED static struct flags msg_flags[] = { +UNUSED static const struct flags msg_flags[] = { /* send */ FLAG_GENERIC(MSG_CONFIRM), FLAG_GENERIC(MSG_DONTROUTE), @@ -1156,7 +1156,7 @@ UNUSED static struct flags msg_flags[] = { FLAG_END, }; -UNUSED static struct flags statx_flags[] = { +UNUSED static const struct flags statx_flags[] = { #ifdef AT_EMPTY_PATH FLAG_GENERIC(AT_EMPTY_PATH), #endif @@ -1178,7 +1178,7 @@ UNUSED static struct flags statx_flags[] = { FLAG_END, }; -UNUSED static struct flags statx_mask[] = { +UNUSED static const struct flags statx_mask[] = { /* This must come first, because it includes everything. */ #ifdef STATX_ALL FLAG_GENERIC(STATX_ALL), @@ -1226,7 +1226,7 @@ UNUSED static struct flags statx_mask[] = { FLAG_END, }; -UNUSED static struct flags falloc_flags[] = { +UNUSED static const struct flags falloc_flags[] = { FLAG_GENERIC(FALLOC_FL_KEEP_SIZE), FLAG_GENERIC(FALLOC_FL_PUNCH_HOLE), #ifdef FALLOC_FL_NO_HIDE_STALE @@ -1246,7 +1246,7 @@ UNUSED static struct flags falloc_flags[] = { #endif }; -UNUSED static struct flags termios_iflags[] = { +UNUSED static const struct flags termios_iflags[] = { FLAG_TARGET(IGNBRK), FLAG_TARGET(BRKINT), FLAG_TARGET(IGNPAR), @@ -1265,7 +1265,7 @@ UNUSED static struct flags termios_iflags[] = { FLAG_END, }; -UNUSED static struct flags termios_oflags[] = { +UNUSED static const struct flags termios_oflags[] = { FLAG_TARGET(OPOST), FLAG_TARGET(OLCUC), FLAG_TARGET(ONLCR), @@ -1349,7 +1349,7 @@ UNUSED static struct enums termios_cflags_CSIZE[] = { ENUM_END, }; -UNUSED static struct flags termios_cflags[] = { +UNUSED static const struct flags termios_cflags[] = { FLAG_TARGET(CSTOPB), FLAG_TARGET(CREAD), FLAG_TARGET(PARENB), @@ -1360,7 +1360,7 @@ UNUSED static struct flags termios_cflags[] = { FLAG_END, }; -UNUSED static struct flags termios_lflags[] = { +UNUSED static const struct flags termios_lflags[] = { FLAG_TARGET(ISIG), FLAG_TARGET(ICANON), FLAG_TARGET(XCASE), @@ -1380,7 +1380,7 @@ UNUSED static struct flags termios_lflags[] = { FLAG_END, }; -UNUSED static struct flags mlockall_flags[] = { +UNUSED static const struct flags mlockall_flags[] = { FLAG_TARGET(MCL_CURRENT), FLAG_TARGET(MCL_FUTURE), #ifdef MCL_ONFAULT From 24acb7b4743ff6e9454e8407668b77d432cf23f7 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 4 Nov 2022 18:36:29 +0100 Subject: [PATCH 02/22] linux-user/strace: Extract print_execve_argv() from print_execve() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to add print_execveat() which re-use common code from print_execve(), extract print_execve_argv() from it. Signed-off-by: Drew DeVault Message-Id: <20221104081015.706009-1-sir@cmpwn.com> [PMD: Split of bigger patch, filled description, fixed style] Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Laurent Vivier Message-Id: <20221104173632.1052-3-philmd@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/strace.c | 71 +++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index 25c47f0316..3d11d2f759 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -616,38 +616,6 @@ print_semctl(CPUArchState *cpu_env, const struct syscallname *name, } #endif -static void -print_execve(CPUArchState *cpu_env, const struct syscallname *name, - abi_long arg1, abi_long arg2, abi_long arg3, - abi_long arg4, abi_long arg5, abi_long arg6) -{ - abi_ulong arg_ptr_addr; - char *s; - - if (!(s = lock_user_string(arg1))) - return; - qemu_log("%s(\"%s\",{", name->name, s); - unlock_user(s, arg1, 0); - - for (arg_ptr_addr = arg2; ; arg_ptr_addr += sizeof(abi_ulong)) { - abi_ulong *arg_ptr, arg_addr; - - arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1); - if (!arg_ptr) - return; - arg_addr = tswapal(*arg_ptr); - unlock_user(arg_ptr, arg_ptr_addr, 0); - if (!arg_addr) - break; - if ((s = lock_user_string(arg_addr))) { - qemu_log("\"%s\",", s); - unlock_user(s, arg_addr, 0); - } - } - - qemu_log("NULL})"); -} - #ifdef TARGET_NR_ipc static void print_ipc(CPUArchState *cpu_env, const struct syscallname *name, @@ -1969,6 +1937,45 @@ print_execv(CPUArchState *cpu_env, const struct syscallname *name, } #endif +static void +print_execve_argv(abi_long argv, int last) +{ + abi_ulong arg_ptr_addr; + char *s; + + qemu_log("{"); + for (arg_ptr_addr = argv; ; arg_ptr_addr += sizeof(abi_ulong)) { + abi_ulong *arg_ptr, arg_addr; + + arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1); + if (!arg_ptr) { + return; + } + arg_addr = tswapal(*arg_ptr); + unlock_user(arg_ptr, arg_ptr_addr, 0); + if (!arg_addr) { + break; + } + s = lock_user_string(arg_addr); + if (s) { + qemu_log("\"%s\",", s); + unlock_user(s, arg_addr, 0); + } + } + qemu_log("NULL}%s", get_comma(last)); +} + +static void +print_execve(CPUArchState *cpu_env, const struct syscallname *name, + abi_long arg1, abi_long arg2, abi_long arg3, + abi_long arg4, abi_long arg5, abi_long arg6) +{ + print_syscall_prologue(name); + print_string(arg1, 0); + print_execve_argv(arg2, 1); + print_syscall_epilogue(name); +} + #if defined(TARGET_NR_faccessat) || defined(TARGET_NR_faccessat2) static void print_faccessat(CPUArchState *cpu_env, const struct syscallname *name, From 5667a1aebe93e2bb2ca435f1eef2f1e187b005bf Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 4 Nov 2022 18:36:30 +0100 Subject: [PATCH 03/22] linux-user/strace: Add output for execveat() syscall MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Drew DeVault Message-Id: <20221104081015.706009-1-sir@cmpwn.com> Suggested-by: Helge Deller [PMD: Split of bigger patch] Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Laurent Vivier Message-Id: <20221104173632.1052-4-philmd@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/strace.c | 23 +++++++++++++++++++++++ linux-user/strace.list | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index 3d11d2f759..7bccb4f0c0 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -1104,6 +1104,16 @@ UNUSED static const struct flags clone_flags[] = { FLAG_END, }; +UNUSED static const struct flags execveat_flags[] = { +#ifdef AT_EMPTY_PATH + FLAG_GENERIC(AT_EMPTY_PATH), +#endif +#ifdef AT_SYMLINK_NOFOLLOW + FLAG_GENERIC(AT_SYMLINK_NOFOLLOW), +#endif + FLAG_END, +}; + UNUSED static const struct flags msg_flags[] = { /* send */ FLAG_GENERIC(MSG_CONFIRM), @@ -1976,6 +1986,19 @@ print_execve(CPUArchState *cpu_env, const struct syscallname *name, print_syscall_epilogue(name); } +static void +print_execveat(CPUArchState *cpu_env, const struct syscallname *name, + abi_long arg1, abi_long arg2, abi_long arg3, + abi_long arg4, abi_long arg5, abi_long arg6) +{ + print_syscall_prologue(name); + print_at_dirfd(arg1, 0); + print_string(arg2, 0); + print_execve_argv(arg3, 0); + print_flags(execveat_flags, arg5, 1); + print_syscall_epilogue(name); +} + #if defined(TARGET_NR_faccessat) || defined(TARGET_NR_faccessat2) static void print_faccessat(CPUArchState *cpu_env, const struct syscallname *name, diff --git a/linux-user/strace.list b/linux-user/strace.list index 3a898e2532..bb21c05414 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -164,7 +164,7 @@ { TARGET_NR_execve, "execve" , NULL, print_execve, NULL }, #endif #ifdef TARGET_NR_execveat -{ TARGET_NR_execveat, "execveat" , NULL, NULL, NULL }, +{ TARGET_NR_execveat, "execveat" , NULL, print_execveat, NULL }, #endif #ifdef TARGET_NR_exec_with_loader { TARGET_NR_exec_with_loader, "exec_with_loader" , NULL, NULL, NULL }, From 156e1f67182f61cce113ab5e69e3a73af43ba2cb Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 4 Nov 2022 18:36:31 +0100 Subject: [PATCH 04/22] linux-user/syscall: Extract do_execve() from do_syscall1() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit execve() is a particular case of execveat(). In order to add do_execveat(), first factor do_execve() out. Signed-off-by: Drew DeVault Message-Id: <20221104081015.706009-1-sir@cmpwn.com> [PMD: Split of bigger patch, filled description, fixed style] Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Laurent Vivier Message-Id: <20221104173632.1052-5-philmd@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 211 +++++++++++++++++++++++-------------------- 1 file changed, 114 insertions(+), 97 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 1f8c10f8ef..11236d16a3 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8357,6 +8357,119 @@ static int do_openat(CPUArchState *cpu_env, int dirfd, const char *pathname, int return safe_openat(dirfd, path(pathname), flags, mode); } +static int do_execve(CPUArchState *cpu_env, + abi_long pathname, abi_long guest_argp, + abi_long guest_envp) +{ + int ret; + char **argp, **envp; + int argc, envc; + abi_ulong gp; + abi_ulong addr; + char **q; + void *p; + + argc = 0; + + for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) { + if (get_user_ual(addr, gp)) { + return -TARGET_EFAULT; + } + if (!addr) { + break; + } + argc++; + } + envc = 0; + for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) { + if (get_user_ual(addr, gp)) { + return -TARGET_EFAULT; + } + if (!addr) { + break; + } + envc++; + } + + argp = g_new0(char *, argc + 1); + envp = g_new0(char *, envc + 1); + + for (gp = guest_argp, q = argp; gp; gp += sizeof(abi_ulong), q++) { + if (get_user_ual(addr, gp)) { + goto execve_efault; + } + if (!addr) { + break; + } + *q = lock_user_string(addr); + if (!*q) { + goto execve_efault; + } + } + *q = NULL; + + for (gp = guest_envp, q = envp; gp; gp += sizeof(abi_ulong), q++) { + if (get_user_ual(addr, gp)) { + goto execve_efault; + } + if (!addr) { + break; + } + *q = lock_user_string(addr); + if (!*q) { + goto execve_efault; + } + } + *q = NULL; + + /* + * Although execve() is not an interruptible syscall it is + * a special case where we must use the safe_syscall wrapper: + * if we allow a signal to happen before we make the host + * syscall then we will 'lose' it, because at the point of + * execve the process leaves QEMU's control. So we use the + * safe syscall wrapper to ensure that we either take the + * signal as a guest signal, or else it does not happen + * before the execve completes and makes it the other + * program's problem. + */ + p = lock_user_string(pathname); + if (!p) { + goto execve_efault; + } + + if (is_proc_myself(p, "exe")) { + ret = get_errno(safe_execve(exec_path, argp, envp)); + } else { + ret = get_errno(safe_execve(p, argp, envp)); + } + + unlock_user(p, pathname, 0); + + goto execve_end; + +execve_efault: + ret = -TARGET_EFAULT; + +execve_end: + for (gp = guest_argp, q = argp; *q; gp += sizeof(abi_ulong), q++) { + if (get_user_ual(addr, gp) || !addr) { + break; + } + unlock_user(*q, addr, 0); + } + for (gp = guest_envp, q = envp; *q; gp += sizeof(abi_ulong), q++) { + if (get_user_ual(addr, gp) || !addr) { + break; + } + unlock_user(*q, addr, 0); + } + + g_free(argp); + g_free(envp); + return ret; +} + #define TIMER_MAGIC 0x0caf0000 #define TIMER_MAGIC_MASK 0xffff0000 @@ -8867,103 +8980,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, return ret; #endif case TARGET_NR_execve: - { - char **argp, **envp; - int argc, envc; - abi_ulong gp; - abi_ulong guest_argp; - abi_ulong guest_envp; - abi_ulong addr; - char **q; - - argc = 0; - guest_argp = arg2; - for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) { - if (get_user_ual(addr, gp)) - return -TARGET_EFAULT; - if (!addr) - break; - argc++; - } - envc = 0; - guest_envp = arg3; - for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) { - if (get_user_ual(addr, gp)) - return -TARGET_EFAULT; - if (!addr) - break; - envc++; - } - - argp = g_new0(char *, argc + 1); - envp = g_new0(char *, envc + 1); - - for (gp = guest_argp, q = argp; gp; - gp += sizeof(abi_ulong), q++) { - if (get_user_ual(addr, gp)) - goto execve_efault; - if (!addr) - break; - if (!(*q = lock_user_string(addr))) - goto execve_efault; - } - *q = NULL; - - for (gp = guest_envp, q = envp; gp; - gp += sizeof(abi_ulong), q++) { - if (get_user_ual(addr, gp)) - goto execve_efault; - if (!addr) - break; - if (!(*q = lock_user_string(addr))) - goto execve_efault; - } - *q = NULL; - - if (!(p = lock_user_string(arg1))) - goto execve_efault; - /* Although execve() is not an interruptible syscall it is - * a special case where we must use the safe_syscall wrapper: - * if we allow a signal to happen before we make the host - * syscall then we will 'lose' it, because at the point of - * execve the process leaves QEMU's control. So we use the - * safe syscall wrapper to ensure that we either take the - * signal as a guest signal, or else it does not happen - * before the execve completes and makes it the other - * program's problem. - */ - if (is_proc_myself(p, "exe")) { - ret = get_errno(safe_execve(exec_path, argp, envp)); - } else { - ret = get_errno(safe_execve(p, argp, envp)); - } - unlock_user(p, arg1, 0); - - goto execve_end; - - execve_efault: - ret = -TARGET_EFAULT; - - execve_end: - for (gp = guest_argp, q = argp; *q; - gp += sizeof(abi_ulong), q++) { - if (get_user_ual(addr, gp) - || !addr) - break; - unlock_user(*q, addr, 0); - } - for (gp = guest_envp, q = envp; *q; - gp += sizeof(abi_ulong), q++) { - if (get_user_ual(addr, gp) - || !addr) - break; - unlock_user(*q, addr, 0); - } - - g_free(argp); - g_free(envp); - } - return ret; + return do_execve(cpu_env, arg1, arg2, arg3); case TARGET_NR_chdir: if (!(p = lock_user_string(arg1))) return -TARGET_EFAULT; From 55bbe4d5ee52e77951dda62b08e37cd0dd8ddb5b Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 4 Nov 2022 18:36:32 +0100 Subject: [PATCH 05/22] linux-user/syscall: Implement execveat() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit References: https://gitlab.com/qemu-project/qemu/-/issues/1007 Signed-off-by: Drew DeVault Reviewed-by: Laurent Vivier Message-Id: <20221104081015.706009-1-sir@cmpwn.com> Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20221104173632.1052-6-philmd@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 11236d16a3..3e72bd333e 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -696,7 +696,8 @@ safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \ #endif safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \ int, options, struct rusage *, rusage) -safe_syscall3(int, execve, const char *, filename, char **, argv, char **, envp) +safe_syscall5(int, execveat, int, dirfd, const char *, filename, + char **, argv, char **, envp, int, flags) #if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \ defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64) safe_syscall6(int, pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, \ @@ -8357,9 +8358,9 @@ static int do_openat(CPUArchState *cpu_env, int dirfd, const char *pathname, int return safe_openat(dirfd, path(pathname), flags, mode); } -static int do_execve(CPUArchState *cpu_env, +static int do_execveat(CPUArchState *cpu_env, int dirfd, abi_long pathname, abi_long guest_argp, - abi_long guest_envp) + abi_long guest_envp, int flags) { int ret; char **argp, **envp; @@ -8439,9 +8440,9 @@ static int do_execve(CPUArchState *cpu_env, } if (is_proc_myself(p, "exe")) { - ret = get_errno(safe_execve(exec_path, argp, envp)); + ret = get_errno(safe_execveat(dirfd, exec_path, argp, envp, flags)); } else { - ret = get_errno(safe_execve(p, argp, envp)); + ret = get_errno(safe_execveat(dirfd, p, argp, envp, flags)); } unlock_user(p, pathname, 0); @@ -8979,8 +8980,10 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, unlock_user(p, arg2, 0); return ret; #endif + case TARGET_NR_execveat: + return do_execveat(cpu_env, arg1, arg2, arg3, arg4, arg5); case TARGET_NR_execve: - return do_execve(cpu_env, arg1, arg2, arg3); + return do_execveat(cpu_env, AT_FDCWD, arg1, arg2, arg3, 0); case TARGET_NR_chdir: if (!(p = lock_user_string(arg1))) return -TARGET_EFAULT; From e2c649e5b5b334b0b2598f6213130dd71d1c0df8 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 13 Dec 2022 17:02:24 +0100 Subject: [PATCH 06/22] linux-user: Add missing MAP_HUGETLB and MAP_STACK flags in strace Add two missing mmap flags. Signed-off-by: Helge Deller Reviewed-by: Laurent Vivier Message-Id: Signed-off-by: Laurent Vivier --- linux-user/strace.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux-user/strace.c b/linux-user/strace.c index 7bccb4f0c0..5027289bdd 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -1057,6 +1057,8 @@ UNUSED static const struct flags mmap_flags[] = { #ifdef TARGET_MAP_UNINITIALIZED FLAG_TARGET(MAP_UNINITIALIZED), #endif + FLAG_TARGET(MAP_HUGETLB), + FLAG_TARGET(MAP_STACK), FLAG_END, }; From 6490d9aa62ef3cbbac2bf584fb0f3e737ab05e44 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 24 Jan 2023 10:10:19 -1000 Subject: [PATCH 07/22] linux-user: un-parent OBJECT(cpu) when closing thread MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reinstates commit 52f0c1607671293afcdb2acc2f83e9bccbfa74bb: While forcing the CPU to unrealize by hand does trigger the clean-up code we never fully free resources because refcount never reaches zero. This is because QOM automatically added objects without an explicit parent to /unattached/, incrementing the refcount. Instead of manually triggering unrealization just unparent the object and let the device machinery deal with that for us. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/866 Signed-off-by: Alex Bennée Reviewed-by: Laurent Vivier Message-Id: <20220811151413.3350684-2-alex.bennee@linaro.org> The original patch tickled a problem in target/arm, and was reverted. But that problem is fixed as of commit 3b07a936d3bf. Signed-off-by: Richard Henderson Message-Id: <20230124201019.3935934-1-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 3e72bd333e..dbf51e500b 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8756,7 +8756,13 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, if (CPU_NEXT(first_cpu)) { TaskState *ts = cpu->opaque; - object_property_set_bool(OBJECT(cpu), "realized", false, NULL); + if (ts->child_tidptr) { + put_user_u32(0, ts->child_tidptr); + do_sys_futex(g2h(cpu, ts->child_tidptr), + FUTEX_WAKE, INT_MAX, NULL, NULL, 0); + } + + object_unparent(OBJECT(cpu)); object_unref(OBJECT(cpu)); /* * At this point the CPU should be unrealized and removed @@ -8766,11 +8772,6 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, pthread_mutex_unlock(&clone_lock); - if (ts->child_tidptr) { - put_user_u32(0, ts->child_tidptr); - do_sys_futex(g2h(cpu, ts->child_tidptr), - FUTEX_WAKE, INT_MAX, NULL, NULL, 0); - } thread_cpu = NULL; g_free(ts); rcu_unregister_thread(); From d237b416b9499441b6833b91609ec840efd832b6 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 18 Jan 2023 04:01:44 -0500 Subject: [PATCH 08/22] linux-user: fix strace build w/out munlockall MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mike Frysinger Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20230118090144.31155-1-vapier@gentoo.org> Signed-off-by: Laurent Vivier --- linux-user/strace.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index 5027289bdd..081fc87344 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -1360,7 +1360,8 @@ UNUSED static const struct flags termios_lflags[] = { FLAG_END, }; -UNUSED static const struct flags mlockall_flags[] = { +#ifdef TARGET_NR_mlockall +static const struct flags mlockall_flags[] = { FLAG_TARGET(MCL_CURRENT), FLAG_TARGET(MCL_FUTURE), #ifdef MCL_ONFAULT @@ -1368,6 +1369,7 @@ UNUSED static const struct flags mlockall_flags[] = { #endif FLAG_END, }; +#endif /* IDs of the various system clocks */ #define TARGET_CLOCK_REALTIME 0 From d5dbbfe67e23ec35f7226c958bc3a76fd43ae10e Mon Sep 17 00:00:00 2001 From: Letu Ren Date: Sun, 1 Jan 2023 22:11:05 +0800 Subject: [PATCH 09/22] linux-user: add more netlink protocol constants Currently, qemu strace only prints four protocol contants. This patch adds others listed in "linux/netlink.h". Signed-off-by: Letu Ren Message-Id: <20230101141105.12024-1-fantasquex@gmail.com> Signed-off-by: Laurent Vivier --- linux-user/strace.c | 48 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/linux-user/strace.c b/linux-user/strace.c index 081fc87344..f38227ba5d 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -506,21 +506,69 @@ print_socket_protocol(int domain, int type, int protocol) case NETLINK_ROUTE: qemu_log("NETLINK_ROUTE"); break; + case NETLINK_UNUSED: + qemu_log("NETLINK_UNUSED"); + break; + case NETLINK_USERSOCK: + qemu_log("NETLINK_USERSOCK"); + break; + case NETLINK_FIREWALL: + qemu_log("NETLINK_FIREWALL"); + break; + case NETLINK_SOCK_DIAG: + qemu_log("NETLINK_SOCK_DIAG"); + break; + case NETLINK_NFLOG: + qemu_log("NETLINK_NFLOG"); + break; + case NETLINK_XFRM: + qemu_log("NETLINK_XFRM"); + break; + case NETLINK_SELINUX: + qemu_log("NETLINK_SELINUX"); + break; + case NETLINK_ISCSI: + qemu_log("NETLINK_ISCSI"); + break; case NETLINK_AUDIT: qemu_log("NETLINK_AUDIT"); break; + case NETLINK_FIB_LOOKUP: + qemu_log("NETLINK_FIB_LOOKUP"); + break; + case NETLINK_CONNECTOR: + qemu_log("NETLINK_CONNECTOR"); + break; case NETLINK_NETFILTER: qemu_log("NETLINK_NETFILTER"); break; + case NETLINK_IP6_FW: + qemu_log("NETLINK_IP6_FW"); + break; + case NETLINK_DNRTMSG: + qemu_log("NETLINK_DNRTMSG"); + break; case NETLINK_KOBJECT_UEVENT: qemu_log("NETLINK_KOBJECT_UEVENT"); break; + case NETLINK_GENERIC: + qemu_log("NETLINK_GENERIC"); + break; + case NETLINK_SCSITRANSPORT: + qemu_log("NETLINK_SCSITRANSPORT"); + break; + case NETLINK_ECRYPTFS: + qemu_log("NETLINK_ECRYPTFS"); + break; case NETLINK_RDMA: qemu_log("NETLINK_RDMA"); break; case NETLINK_CRYPTO: qemu_log("NETLINK_CRYPTO"); break; + case NETLINK_SMC: + qemu_log("NETLINK_SMC"); + break; default: qemu_log("%d", protocol); break; From 9f0246539ae84a5e21efd1cc4516fc343f08115a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Tue, 10 Jan 2023 12:49:00 -0500 Subject: [PATCH 10/22] Revert "linux-user: add more compat ioctl definitions" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit c5495f4ecb0cdaaf2e9dddeb48f1689cdb520ca0. glibc has fixed (in 2.36.9000-40-g774058d729) the problem that caused a clash when both sys/mount.h annd linux/mount.h are included, and backported this to the 2.36 stable release too: https://sourceware.org/glibc/wiki/Release/2.36#Usage_of_.3Clinux.2Fmount.h.3E_and_.3Csys.2Fmount.h.3E It is saner for QEMU to remove the workaround it applied for glibc 2.36 and expect distros to ship the 2.36 maint release with the fix. This avoids needing to add a further workaround to QEMU to deal with the fact that linux/brtfs.h now also pulls in linux/mount.h via linux/fs.h since Linux 6.1 Signed-off-by: Daniel P. Berrangé Reviewed-by: Marc-André Lureau Message-Id: <20230110174901.2580297-2-berrange@redhat.com> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index dbf51e500b..b88f8ee96f 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -111,31 +111,6 @@ #define FS_IOC32_SETFLAGS _IOW('f', 2, int) #define FS_IOC32_GETVERSION _IOR('v', 1, int) #define FS_IOC32_SETVERSION _IOW('v', 2, int) - -#define BLKGETSIZE64 _IOR(0x12,114,size_t) -#define BLKDISCARD _IO(0x12,119) -#define BLKIOMIN _IO(0x12,120) -#define BLKIOOPT _IO(0x12,121) -#define BLKALIGNOFF _IO(0x12,122) -#define BLKPBSZGET _IO(0x12,123) -#define BLKDISCARDZEROES _IO(0x12,124) -#define BLKSECDISCARD _IO(0x12,125) -#define BLKROTATIONAL _IO(0x12,126) -#define BLKZEROOUT _IO(0x12,127) - -#define FIBMAP _IO(0x00,1) -#define FIGETBSZ _IO(0x00,2) - -struct file_clone_range { - __s64 src_fd; - __u64 src_offset; - __u64 src_length; - __u64 dest_offset; -}; - -#define FICLONE _IOW(0x94, 9, int) -#define FICLONERANGE _IOW(0x94, 13, struct file_clone_range) - #else #include #endif From 6003159ce18faad4e1bc7bf9c85669019cd4950e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Tue, 10 Jan 2023 12:49:01 -0500 Subject: [PATCH 11/22] Revert "linux-user: fix compat with glibc >= 2.36 sys/mount.h" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 3cd3df2a9584e6f753bb62a0028bd67124ab5532. glibc has fixed (in 2.36.9000-40-g774058d729) the problem that caused a clash when both sys/mount.h annd linux/mount.h are included, and backported this to the 2.36 stable release too: https://sourceware.org/glibc/wiki/Release/2.36#Usage_of_.3Clinux.2Fmount.h.3E_and_.3Csys.2Fmount.h.3E It is saner for QEMU to remove the workaround it applied for glibc 2.36 and expect distros to ship the 2.36 maint release with the fix. This avoids needing to add a further workaround to QEMU to deal with the fact that linux/brtfs.h now also pulls in linux/mount.h via linux/fs.h since Linux 6.1 Signed-off-by: Daniel P. Berrangé Reviewed-by: Marc-André Lureau Message-Id: <20230110174901.2580297-3-berrange@redhat.com> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 18 ------------------ meson.build | 2 -- 2 files changed, 20 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index b88f8ee96f..210db5f0be 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -95,25 +95,7 @@ #include #include #include - -#ifdef HAVE_SYS_MOUNT_FSCONFIG -/* - * glibc >= 2.36 linux/mount.h conflicts with sys/mount.h, - * which in turn prevents use of linux/fs.h. So we have to - * define the constants ourselves for now. - */ -#define FS_IOC_GETFLAGS _IOR('f', 1, long) -#define FS_IOC_SETFLAGS _IOW('f', 2, long) -#define FS_IOC_GETVERSION _IOR('v', 1, long) -#define FS_IOC_SETVERSION _IOW('v', 2, long) -#define FS_IOC_FIEMAP _IOWR('f', 11, struct fiemap) -#define FS_IOC32_GETFLAGS _IOR('f', 1, int) -#define FS_IOC32_SETFLAGS _IOW('f', 2, int) -#define FS_IOC32_GETVERSION _IOR('v', 1, int) -#define FS_IOC32_SETVERSION _IOW('v', 2, int) -#else #include -#endif #include #if defined(CONFIG_FIEMAP) #include diff --git a/meson.build b/meson.build index 6d3b665629..cccd19f864 100644 --- a/meson.build +++ b/meson.build @@ -2046,8 +2046,6 @@ config_host_data.set('HAVE_OPTRESET', cc.has_header_symbol('getopt.h', 'optreset')) config_host_data.set('HAVE_IPPROTO_MPTCP', cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP')) -config_host_data.set('HAVE_SYS_MOUNT_FSCONFIG', - cc.has_header_symbol('sys/mount.h', 'FSCONFIG_SET_FLAG')) # has_member config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID', From dfd8c5e9b383c36ed6d9559afe331a38967998a8 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 15 Jan 2023 12:35:17 +0100 Subject: [PATCH 12/22] linux-user: Add strace output for clock_getres_time64() and futex_time64() Add the two syscalls to strace output to avoid "Unknown syscall" message. Signed-off-by: Helge Deller Reviewed-by: Laurent Vivier Message-Id: <20230115113517.25143-1-deller@gmx.de> Signed-off-by: Laurent Vivier --- linux-user/strace.list | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/linux-user/strace.list b/linux-user/strace.list index bb21c05414..64db8e6b84 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -86,6 +86,9 @@ { TARGET_NR_clock_getres, "clock_getres" , NULL, print_clock_getres, print_syscall_ret_clock_getres }, #endif +#ifdef TARGET_NR_clock_getres_time64 +{ TARGET_NR_clock_getres_time64, "clock_getres_time64" , NULL, NULL, NULL }, +#endif #ifdef TARGET_NR_clock_gettime { TARGET_NR_clock_gettime, "clock_gettime" , NULL, print_clock_gettime, print_syscall_ret_clock_gettime }, @@ -275,6 +278,9 @@ #ifdef TARGET_NR_futex { TARGET_NR_futex, "futex" , NULL, print_futex, NULL }, #endif +#ifdef TARGET_NR_futex_time64 +{ TARGET_NR_futex_time64, "futex_time64" , NULL, NULL, NULL }, +#endif #ifdef TARGET_NR_futimesat { TARGET_NR_futimesat, "futimesat" , NULL, print_futimesat, NULL }, #endif From 6a848b522e189824f25bcfe9ec856c1f85e93fa3 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 15 Jan 2023 22:00:57 +0100 Subject: [PATCH 13/22] linux-user: Improve strace output of getgroups() and setgroups() Make the strace look nicer for those syscalls. Signed-off-by: Helge Deller Reviewed-by: Laurent Vivier Message-Id: <20230115210057.445132-1-deller@gmx.de> Signed-off-by: Laurent Vivier --- linux-user/strace.list | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/linux-user/strace.list b/linux-user/strace.list index 64db8e6b84..cf291d02ed 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -321,10 +321,10 @@ { TARGET_NR_getgid32, "getgid32" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_getgroups -{ TARGET_NR_getgroups, "getgroups" , NULL, NULL, NULL }, +{ TARGET_NR_getgroups, "getgroups" , "%s(%d,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_getgroups32 -{ TARGET_NR_getgroups32, "getgroups32" , NULL, NULL, NULL }, +{ TARGET_NR_getgroups32, "getgroups32" , "%s(%d,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_gethostname { TARGET_NR_gethostname, "gethostname" , NULL, NULL, NULL }, @@ -1304,10 +1304,10 @@ { TARGET_NR_setgid32, "setgid32" , "%s(%u)", NULL, NULL }, #endif #ifdef TARGET_NR_setgroups -{ TARGET_NR_setgroups, "setgroups" , NULL, NULL, NULL }, +{ TARGET_NR_setgroups, "setgroups" , "%s(%d,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_setgroups32 -{ TARGET_NR_setgroups32, "setgroups32" , NULL, NULL, NULL }, +{ TARGET_NR_setgroups32, "setgroups32" , "%s(%d,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_sethae { TARGET_NR_sethae, "sethae" , NULL, NULL, NULL }, From 95fc5ed4a86b0d173bf55daf32e1697d11062648 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sat, 28 Jan 2023 19:46:25 -0500 Subject: [PATCH 14/22] linux-user: move target_flat.h to target subdirs This makes target_flat.h behave like every other target_xxx.h header. It also makes it actually work -- while the current header says adding a header to the target subdir overrides the common one, it doesn't. This is for two reasons: * meson.build adds -Ilinux-user before -Ilinux-user/$arch * the compiler search path for "target_flat.h" looks in the same dir as the source file before searching -I paths. This can be seen with the xtensa port -- the subdir settings aren't used which breaks stack setup. Move it to the generic/ subdir and add include stubs like every other target_xxx.h header is handled. Signed-off-by: Mike Frysinger Reviewed-by: Richard Henderson Message-Id: <20230129004625.11228-1-vapier@gentoo.org> Signed-off-by: Laurent Vivier --- linux-user/aarch64/target_flat.h | 1 + linux-user/arm/target_flat.h | 1 + linux-user/{ => generic}/target_flat.h | 0 linux-user/m68k/target_flat.h | 1 + linux-user/microblaze/target_flat.h | 1 + linux-user/sh4/target_flat.h | 1 + 6 files changed, 5 insertions(+) create mode 100644 linux-user/aarch64/target_flat.h create mode 100644 linux-user/arm/target_flat.h rename linux-user/{ => generic}/target_flat.h (100%) create mode 100644 linux-user/m68k/target_flat.h create mode 100644 linux-user/microblaze/target_flat.h create mode 100644 linux-user/sh4/target_flat.h diff --git a/linux-user/aarch64/target_flat.h b/linux-user/aarch64/target_flat.h new file mode 100644 index 0000000000..bc83224cea --- /dev/null +++ b/linux-user/aarch64/target_flat.h @@ -0,0 +1 @@ +#include "../generic/target_flat.h" diff --git a/linux-user/arm/target_flat.h b/linux-user/arm/target_flat.h new file mode 100644 index 0000000000..bc83224cea --- /dev/null +++ b/linux-user/arm/target_flat.h @@ -0,0 +1 @@ +#include "../generic/target_flat.h" diff --git a/linux-user/target_flat.h b/linux-user/generic/target_flat.h similarity index 100% rename from linux-user/target_flat.h rename to linux-user/generic/target_flat.h diff --git a/linux-user/m68k/target_flat.h b/linux-user/m68k/target_flat.h new file mode 100644 index 0000000000..bc83224cea --- /dev/null +++ b/linux-user/m68k/target_flat.h @@ -0,0 +1 @@ +#include "../generic/target_flat.h" diff --git a/linux-user/microblaze/target_flat.h b/linux-user/microblaze/target_flat.h new file mode 100644 index 0000000000..bc83224cea --- /dev/null +++ b/linux-user/microblaze/target_flat.h @@ -0,0 +1 @@ +#include "../generic/target_flat.h" diff --git a/linux-user/sh4/target_flat.h b/linux-user/sh4/target_flat.h new file mode 100644 index 0000000000..bc83224cea --- /dev/null +++ b/linux-user/sh4/target_flat.h @@ -0,0 +1 @@ +#include "../generic/target_flat.h" From cb88b7c214511736fa3bc1d9e57b23efcc61d8ab Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Fri, 27 Jan 2023 21:25:27 +0100 Subject: [PATCH 15/22] linux-user: Fix SO_ERROR return code of getsockopt() Add translation for the host error return code of: getsockopt(19, SOL_SOCKET, SO_ERROR, [ECONNREFUSED], [4]) = 0 This fixes the testsuite of the cockpit debian package with a hppa-linux guest on a x86-64 host. Signed-off-by: Helge Deller Reviewed-by: Richard Henderson Reviewed-by: Laurent Vivier Message-Id: Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 210db5f0be..1c42df6518 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -2758,8 +2758,13 @@ get_timeout: ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv)); if (ret < 0) return ret; - if (optname == SO_TYPE) { + switch (optname) { + case SO_TYPE: val = host_to_target_sock_type(val); + break; + case SO_ERROR: + val = host_to_target_errno(val); + break; } if (len > lv) len = lv; From e0174afeea23e56765db56fbbe465ed1fcbdd07a Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Fri, 27 Jan 2023 21:10:49 +0100 Subject: [PATCH 16/22] linux-user: Fix /proc/cpuinfo output for hppa MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hppa architectures provides an own output for the emulated /proc/cpuinfo file. Some userspace applications count (even if that's not the recommended way) the number of lines which start with "processor:" and assume that this number then reflects the number of online CPUs. Since those 3 architectures don't provide any such line, applications may assume "0" CPUs. One such issue can be seen in debian bug report: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1024653 Avoid such issues by adding a "processor:" line for each of the online CPUs. Signed-off-by: Helge Deller Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Laurent Vivier Message-Id: Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 1c42df6518..55d53b344b 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8232,11 +8232,17 @@ static int open_cpuinfo(CPUArchState *cpu_env, int fd) #if defined(TARGET_HPPA) static int open_cpuinfo(CPUArchState *cpu_env, int fd) { - dprintf(fd, "cpu family\t: PA-RISC 1.1e\n"); - dprintf(fd, "cpu\t\t: PA7300LC (PCX-L2)\n"); - dprintf(fd, "capabilities\t: os32\n"); - dprintf(fd, "model\t\t: 9000/778/B160L\n"); - dprintf(fd, "model name\t: Merlin L2 160 QEMU (9000/778/B160L)\n"); + int i, num_cpus; + + num_cpus = sysconf(_SC_NPROCESSORS_ONLN); + for (i = 0; i < num_cpus; i++) { + dprintf(fd, "processor\t: %d\n", i); + dprintf(fd, "cpu family\t: PA-RISC 1.1e\n"); + dprintf(fd, "cpu\t\t: PA7300LC (PCX-L2)\n"); + dprintf(fd, "capabilities\t: os32\n"); + dprintf(fd, "model\t\t: 9000/778/B160L - " + "Merlin L2 160 QEMU (9000/778/B160L)\n\n"); + } return 0; } #endif From ab6c497e7eb8a9dca45978e5118f5c67bb74ab62 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Fri, 27 Jan 2023 21:18:58 +0100 Subject: [PATCH 17/22] linux-user: Improve strace output of personality() and sysinfo() Make the strace look nicer for those two syscalls. Signed-off-by: Helge Deller Reviewed-by: Richard Henderson Reviewed-by: Laurent Vivier Message-Id: Signed-off-by: Laurent Vivier --- linux-user/strace.list | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/linux-user/strace.list b/linux-user/strace.list index cf291d02ed..3a1f61803a 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -1049,7 +1049,8 @@ { TARGET_NR_perfctr, "perfctr" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_personality -{ TARGET_NR_personality, "personality" , NULL, NULL, NULL }, +{ TARGET_NR_personality, "personality" , "%s(0x"TARGET_ABI_FMT_lx")", NULL, + print_syscall_ret_addr }, #endif #ifdef TARGET_NR_pipe { TARGET_NR_pipe, "pipe" , NULL, NULL, NULL }, @@ -1504,7 +1505,7 @@ { TARGET_NR_sysfs, "sysfs" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_sysinfo -{ TARGET_NR_sysinfo, "sysinfo" , NULL, NULL, NULL }, +{ TARGET_NR_sysinfo, "sysinfo" , "%s(%p)", NULL, NULL }, #endif #ifdef TARGET_NR_sys_kexec_load { TARGET_NR_sys_kexec_load, "sys_kexec_load" , NULL, NULL, NULL }, From 4530deb1fe81152ae2384a56eb7edb5467f894fa Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 13 Dec 2022 18:03:09 +0100 Subject: [PATCH 18/22] linux-user: Add emulation for MADV_WIPEONFORK and MADV_KEEPONFORK in madvise() Both parameters have a different value on the parisc platform, so first translate the target value into a host value for usage in the native madvise() syscall. Those parameters are often used by security sensitive applications (e.g. tor browser, boringssl, ...) which expect the call to return a proper return code on failure, so return -EINVAL if qemu fails to forward the syscall to the host OS. While touching this code, enhance the comments about MADV_DONTNEED. Tested with testcase of tor browser when running hppa-linux guest on x86-64 host. Signed-off-by: Helge Deller Acked-by: Ilya Leoshkevich Reviewed-by: Laurent Vivier Message-Id: Signed-off-by: Laurent Vivier --- linux-user/mmap.c | 56 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/linux-user/mmap.c b/linux-user/mmap.c index 10f5079331..28135c9e6a 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -857,7 +857,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size, return new_addr; } -static bool can_passthrough_madv_dontneed(abi_ulong start, abi_ulong end) +static bool can_passthrough_madvise(abi_ulong start, abi_ulong end) { ulong addr; @@ -901,23 +901,53 @@ abi_long target_madvise(abi_ulong start, abi_ulong len_in, int advice) return -TARGET_EINVAL; } + /* Translate for some architectures which have different MADV_xxx values */ + switch (advice) { + case TARGET_MADV_DONTNEED: /* alpha */ + advice = MADV_DONTNEED; + break; + case TARGET_MADV_WIPEONFORK: /* parisc */ + advice = MADV_WIPEONFORK; + break; + case TARGET_MADV_KEEPONFORK: /* parisc */ + advice = MADV_KEEPONFORK; + break; + /* we do not care about the other MADV_xxx values yet */ + } + /* - * A straight passthrough may not be safe because qemu sometimes turns - * private file-backed mappings into anonymous mappings. + * Most advice values are hints, so ignoring and returning success is ok. * - * This is a hint, so ignoring and returning success is ok. + * However, some advice values such as MADV_DONTNEED, MADV_WIPEONFORK and + * MADV_KEEPONFORK are not hints and need to be emulated. * - * This breaks MADV_DONTNEED, completely implementing which is quite - * complicated. However, there is one low-hanging fruit: mappings that are - * known to have the same semantics in the host and the guest. In this case - * passthrough is safe, so do it. + * A straight passthrough for those may not be safe because qemu sometimes + * turns private file-backed mappings into anonymous mappings. + * can_passthrough_madvise() helps to check if a passthrough is possible by + * comparing mappings that are known to have the same semantics in the host + * and the guest. In this case passthrough is safe. + * + * We pass through MADV_WIPEONFORK and MADV_KEEPONFORK if possible and + * return failure if not. + * + * MADV_DONTNEED is passed through as well, if possible. + * If passthrough isn't possible, we nevertheless (wrongly!) return + * success, which is broken but some userspace programs fail to work + * otherwise. Completely implementing such emulation is quite complicated + * though. */ mmap_lock(); - if (advice == TARGET_MADV_DONTNEED && - can_passthrough_madv_dontneed(start, end)) { - ret = get_errno(madvise(g2h_untagged(start), len, MADV_DONTNEED)); - if (ret == 0) { - page_reset_target_data(start, start + len); + switch (advice) { + case MADV_WIPEONFORK: + case MADV_KEEPONFORK: + ret = -EINVAL; + /* fall through */ + case MADV_DONTNEED: + if (can_passthrough_madvise(start, end)) { + ret = get_errno(madvise(g2h_untagged(start), len, advice)); + if ((advice == MADV_DONTNEED) && (ret == 0)) { + page_reset_target_data(start, start + len); + } } } mmap_unlock(); From 7020e2fd9e1d23b16c8ef86a217a865f5ec66cbe Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Mon, 30 Jan 2023 23:20:53 +0100 Subject: [PATCH 19/22] linux-user: Show 4th argument of rt_sigprocmask() in strace Add output for the missing 4th parameter (size_t sigsetsize). Signed-off-by: Helge Deller Reviewed-by: Richard Henderson Reviewed-by: Laurent Vivier Message-Id: Signed-off-by: Laurent Vivier --- linux-user/strace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index f38227ba5d..340010661c 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -3224,7 +3224,8 @@ print_rt_sigprocmask(CPUArchState *cpu_env, const struct syscallname *name, } qemu_log("%s,", how); print_pointer(arg1, 0); - print_pointer(arg2, 1); + print_pointer(arg2, 0); + print_raw_param("%u", arg3, 1); print_syscall_epilogue(name); } #endif From 93cf7e6c4abdbc5e678088cee4e08f615ad39766 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Mon, 12 Dec 2022 19:01:32 +0100 Subject: [PATCH 20/22] linux-user: Enhance strace output for various syscalls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add appropriate strace printf formats for various Linux syscalls. Signed-off-by: Helge Deller Reviewed-by: Philippe Mathieu-Daudé Message-Id: Signed-off-by: Laurent Vivier --- linux-user/strace.list | 43 ++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/linux-user/strace.list b/linux-user/strace.list index 3a1f61803a..d8acbeec60 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -343,7 +343,7 @@ { TARGET_NR_getpagesize, "getpagesize" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_getpeername -{ TARGET_NR_getpeername, "getpeername" , NULL, NULL, NULL }, +{ TARGET_NR_getpeername, "getpeername" , "%s(%d,%p,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_getpgid { TARGET_NR_getpgid, "getpgid" , "%s(%u)", NULL, NULL }, @@ -367,19 +367,19 @@ { TARGET_NR_getrandom, "getrandom", "%s(%p,%u,%u)", NULL, NULL }, #endif #ifdef TARGET_NR_getresgid -{ TARGET_NR_getresgid, "getresgid" , NULL, NULL, NULL }, +{ TARGET_NR_getresgid, "getresgid" , "%s(%p,%p,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_getresgid32 { TARGET_NR_getresgid32, "getresgid32" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_getresuid -{ TARGET_NR_getresuid, "getresuid" , NULL, NULL, NULL }, +{ TARGET_NR_getresuid, "getresuid" , "%s(%p,%p,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_getresuid32 { TARGET_NR_getresuid32, "getresuid32" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_getrlimit -{ TARGET_NR_getrlimit, "getrlimit" , NULL, NULL, NULL }, +{ TARGET_NR_getrlimit, "getrlimit" , "%s(%d,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_get_robust_list { TARGET_NR_get_robust_list, "get_robust_list" , NULL, NULL, NULL }, @@ -391,10 +391,10 @@ { TARGET_NR_getsid, "getsid" , "%s(%d)", NULL, NULL }, #endif #ifdef TARGET_NR_getsockname -{ TARGET_NR_getsockname, "getsockname" , NULL, NULL, NULL }, +{ TARGET_NR_getsockname, "getsockname" , "%s(%d,%p,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_getsockopt -{ TARGET_NR_getsockopt, "getsockopt" , NULL, NULL, NULL }, +{ TARGET_NR_getsockopt, "getsockopt" , "%s(%d,%d,%d,%p,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_get_thread_area #if defined(TARGET_I386) && defined(TARGET_ABI32) @@ -1059,10 +1059,10 @@ { TARGET_NR_pivot_root, "pivot_root" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_poll -{ TARGET_NR_poll, "poll" , NULL, NULL, NULL }, +{ TARGET_NR_poll, "poll" , "%s(%p,%u,%d)", NULL, NULL }, #endif #ifdef TARGET_NR_ppoll -{ TARGET_NR_ppoll, "ppoll" , NULL, NULL, NULL }, +{ TARGET_NR_ppoll, "ppoll" , "%s(%p,%u,%p,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_prctl { TARGET_NR_prctl, "prctl" , NULL, NULL, NULL }, @@ -1131,7 +1131,7 @@ { TARGET_NR_reboot, "reboot" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_recv -{ TARGET_NR_recv, "recv" , NULL, NULL, NULL }, +{ TARGET_NR_recv, "recv" , "%s(%d,%p,%u,%d)", NULL, NULL }, #endif #ifdef TARGET_NR_recvfrom { TARGET_NR_recvfrom, "recvfrom" , NULL, NULL, NULL }, @@ -1191,7 +1191,7 @@ { TARGET_NR_rt_sigqueueinfo, "rt_sigqueueinfo" , NULL, print_rt_sigqueueinfo, NULL }, #endif #ifdef TARGET_NR_rt_sigreturn -{ TARGET_NR_rt_sigreturn, "rt_sigreturn" , NULL, NULL, NULL }, +{ TARGET_NR_rt_sigreturn, "rt_sigreturn" , "%s(%p)", NULL, NULL }, #endif #ifdef TARGET_NR_rt_sigsuspend { TARGET_NR_rt_sigsuspend, "rt_sigsuspend" , NULL, NULL, NULL }, @@ -1203,16 +1203,19 @@ { TARGET_NR_rt_tgsigqueueinfo, "rt_tgsigqueueinfo" , NULL, print_rt_tgsigqueueinfo, NULL }, #endif #ifdef TARGET_NR_sched_getaffinity -{ TARGET_NR_sched_getaffinity, "sched_getaffinity" , NULL, NULL, NULL }, +{ TARGET_NR_sched_getaffinity, "sched_getaffinity" , "%s(%d,%u,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_sched_get_affinity { TARGET_NR_sched_get_affinity, "sched_get_affinity" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_sched_getattr -{ TARGET_NR_sched_getattr, "sched_getattr" , NULL, NULL, NULL }, +{ TARGET_NR_sched_getattr, "sched_getattr" , "%s(%d,%p,%u,%u)", NULL, NULL }, +#endif +#ifdef TARGET_NR_sched_setattr +{ TARGET_NR_sched_setattr, "sched_setattr" , "%s(%p,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_sched_getparam -{ TARGET_NR_sched_getparam, "sched_getparam" , NULL, NULL, NULL }, +{ TARGET_NR_sched_getparam, "sched_getparam" , "%s(%d,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_sched_get_priority_max { TARGET_NR_sched_get_priority_max, "sched_get_priority_max" , NULL, NULL, NULL }, @@ -1227,7 +1230,7 @@ { TARGET_NR_sched_rr_get_interval, "sched_rr_get_interval" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_sched_setaffinity -{ TARGET_NR_sched_setaffinity, "sched_setaffinity" , NULL, NULL, NULL }, +{ TARGET_NR_sched_setaffinity, "sched_setaffinity" , "%s(%d,%u,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_sched_setatt { TARGET_NR_sched_setatt, "sched_setatt" , NULL, NULL, NULL }, @@ -1360,23 +1363,23 @@ { TARGET_NR_setreuid32, "setreuid32" , "%s(%u,%u)", NULL, NULL }, #endif #ifdef TARGET_NR_setrlimit -{ TARGET_NR_setrlimit, "setrlimit" , NULL, NULL, NULL }, +{ TARGET_NR_setrlimit, "setrlimit" , "%s(%d,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_set_robust_list -{ TARGET_NR_set_robust_list, "set_robust_list" , NULL, NULL, NULL }, +{ TARGET_NR_set_robust_list, "set_robust_list" , "%s(%p,%u)", NULL, NULL }, #endif #ifdef TARGET_NR_setsid { TARGET_NR_setsid, "setsid" , "%s()", NULL, NULL }, #endif #ifdef TARGET_NR_setsockopt -{ TARGET_NR_setsockopt, "setsockopt" , NULL, NULL, NULL }, +{ TARGET_NR_setsockopt, "setsockopt" , "%s(%d,%d,%d,%p,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_set_thread_area { TARGET_NR_set_thread_area, "set_thread_area", "%s(0x"TARGET_ABI_FMT_lx")", NULL, NULL }, #endif #ifdef TARGET_NR_set_tid_address -{ TARGET_NR_set_tid_address, "set_tid_address" , NULL, NULL, NULL }, +{ TARGET_NR_set_tid_address, "set_tid_address" , "%s(%p)", NULL, NULL }, #endif #ifdef TARGET_NR_settimeofday { TARGET_NR_settimeofday, "settimeofday" , NULL, print_settimeofday, NULL }, @@ -1655,7 +1658,7 @@ { TARGET_NR_vserver, "vserver" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_wait4 -{ TARGET_NR_wait4, "wait4" , NULL, NULL, NULL }, +{ TARGET_NR_wait4, "wait4" , "%s(%d,%p,%d,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_waitid { TARGET_NR_waitid, "waitid" , "%s(%#x,%d,%p,%#x)", NULL, NULL }, @@ -1679,7 +1682,7 @@ { TARGET_NR_sync_file_range2, "sync_file_range2", NULL, NULL, NULL }, #endif #ifdef TARGET_NR_pipe2 -{ TARGET_NR_pipe2, "pipe2", NULL, NULL, NULL }, +{ TARGET_NR_pipe2, "pipe2", "%s(%p,%d)", NULL, NULL }, #endif #ifdef TARGET_NR_pidfd_open { TARGET_NR_pidfd_open, "pidfd_open", "%s(%d,%u)", NULL, NULL }, From 27404b6c15c1cddae54e1044c8da815eade109fa Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Mon, 12 Dec 2022 18:34:15 +0100 Subject: [PATCH 21/22] linux-user: Implement SOL_ALG encryption support Add suport to handle SOL_ALG packets via sendmsg() and recvmsg(). This allows emulated userspace to use encryption functionality. Tested with the debian ell package with hppa guest on x86_64 host. Signed-off-by: Helge Deller Reviewed-by: Laurent Vivier Message-Id: <20221212173416.90590-1-deller@gmx.de> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 55d53b344b..a0d2beddaa 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1829,6 +1829,14 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh, __get_user(cred->pid, &target_cred->pid); __get_user(cred->uid, &target_cred->uid); __get_user(cred->gid, &target_cred->gid); + } else if (cmsg->cmsg_level == SOL_ALG) { + uint32_t *dst = (uint32_t *)data; + + memcpy(dst, target_data, len); + /* fix endianess of first 32-bit word */ + if (len >= sizeof(uint32_t)) { + *dst = tswap32(*dst); + } } else { qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type); From 3f0744f98b07c6fd2ce9d5840726d0915b2ae7c1 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Mon, 12 Dec 2022 18:34:16 +0100 Subject: [PATCH 22/22] linux-user: Allow sendmsg() without IOV Applications do call sendmsg() without any IOV, e.g.: sendmsg(4, {msg_name=NULL, msg_namelen=0, msg_iov=NULL, msg_iovlen=0, msg_control=[{cmsg_len=36, cmsg_level=SOL_ALG, cmsg_type=0x2}], msg_controllen=40, msg_flags=0}, MSG_MORE) = 0 sendmsg(4, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="The quick brown fox jumps over t"..., iov_len=183}], msg_iovlen=1, msg_control=[{cmsg_len=20, cmsg_level=SOL_ALG, cmsg_type=0x3}], msg_controllen=24, msg_flags=0}, 0) = 183 The function do_sendrecvmsg_locked() is used for sndmsg() and recvmsg() and calls lock_iovec() to lock the IOV into memory. For the first sendmsg() above it returns NULL and thus wrongly skips the call the host sendmsg() syscall, which will break the calling application. Fix this issue by: - allowing sendmsg() even with empty IOV - skip recvmsg() if IOV is NULL - skip both if the return code of do_sendrecvmsg_locked() != 0, which indicates some failure like EFAULT on the IOV Tested with the debian "ell" package with hppa guest on x86_64 host. Signed-off-by: Helge Deller Reviewed-by: Laurent Vivier Message-Id: <20221212173416.90590-2-deller@gmx.de> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index a0d2beddaa..1e868e9b0e 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -3293,7 +3293,10 @@ static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp, target_vec, count, send); if (vec == NULL) { ret = -host_to_target_errno(errno); - goto out2; + /* allow sending packet without any iov, e.g. with MSG_MORE flag */ + if (!send || ret) { + goto out2; + } } msg.msg_iovlen = count; msg.msg_iov = vec; @@ -3345,7 +3348,9 @@ static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp, } out: - unlock_iovec(vec, target_vec, count, !send); + if (vec) { + unlock_iovec(vec, target_vec, count, !send); + } out2: return ret; }