* [PATCH 01/10] linux-user/flatload: Take mmap_lock in load_flt_binary()
2024-10-05 23:33 [PATCH 00/10] linux-user pre-PR Richard Henderson
@ 2024-10-05 23:33 ` Richard Henderson
2024-10-05 23:33 ` [PATCH 02/10] linux-user: Fix parse_elf_properties GNU0_MAGIC check Richard Henderson
` (8 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2024-10-05 23:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé <philmd@linaro.org>
load_flt_binary() calls load_flat_file() -> page_set_flags().
page_set_flags() must be called with the mmap_lock held,
otherwise it aborts:
$ qemu-arm -L stm32/lib/ stm32/bin/busybox
qemu-arm: ../accel/tcg/user-exec.c:505: page_set_flags: Assertion `have_mmap_lock()' failed.
Aborted (core dumped)
Fix by taking the lock in load_flt_binary().
Fixes: fbd3c4cff6 ("linux-user/arm: Mark the commpage executable")
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2525
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-ID: <20240822095045.72643-3-philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/flatload.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/linux-user/flatload.c b/linux-user/flatload.c
index 04d8138d12..0e4be5bf44 100644
--- a/linux-user/flatload.c
+++ b/linux-user/flatload.c
@@ -487,7 +487,10 @@ int load_flt_binary(struct linux_binprm *bprm, struct image_info *info)
stack_len += (bprm->envc + 1) * 4; /* the envp array */
+ mmap_lock();
res = load_flat_file(bprm, libinfo, 0, &stack_len);
+ mmap_unlock();
+
if (is_error(res)) {
return res;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 02/10] linux-user: Fix parse_elf_properties GNU0_MAGIC check
2024-10-05 23:33 [PATCH 00/10] linux-user pre-PR Richard Henderson
2024-10-05 23:33 ` [PATCH 01/10] linux-user/flatload: Take mmap_lock in load_flt_binary() Richard Henderson
@ 2024-10-05 23:33 ` Richard Henderson
2024-10-07 19:50 ` Philippe Mathieu-Daudé
2024-10-05 23:33 ` [PATCH 03/10] linux-user: add openat2 support in linux-user Richard Henderson
` (7 subsequent siblings)
9 siblings, 1 reply; 13+ messages in thread
From: Richard Henderson @ 2024-10-05 23:33 UTC (permalink / raw)
To: qemu-devel
Comparing a string of 4 bytes only works in little-endian.
Adjust bulk bswap to only apply to the note payload.
Perform swapping of the note header manually; the magic
is defined so that it does not need a runtime swap.
Fixes: 83f990eb5adb ("linux-user/elfload: Parse NT_GNU_PROPERTY_TYPE_0 notes")
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2596
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/elfload.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 0678c9d506..52c88a68a9 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -3121,11 +3121,11 @@ static bool parse_elf_properties(const ImageSource *src,
}
/*
- * The contents of a valid PT_GNU_PROPERTY is a sequence
- * of uint32_t -- swap them all now.
+ * The contents of a valid PT_GNU_PROPERTY is a sequence of uint32_t.
+ * Swap most of them now, beyond the header and namesz.
*/
#ifdef BSWAP_NEEDED
- for (int i = 0; i < n / 4; i++) {
+ for (int i = 4; i < n / 4; i++) {
bswap32s(note.data + i);
}
#endif
@@ -3135,15 +3135,15 @@ static bool parse_elf_properties(const ImageSource *src,
* immediately follows nhdr and is thus at the 4th word. Further, all
* of the inputs to the kernel's round_up are multiples of 4.
*/
- if (note.nhdr.n_type != NT_GNU_PROPERTY_TYPE_0 ||
- note.nhdr.n_namesz != NOTE_NAME_SZ ||
+ if (tswap32(note.nhdr.n_type) != NT_GNU_PROPERTY_TYPE_0 ||
+ tswap32(note.nhdr.n_namesz) != NOTE_NAME_SZ ||
note.data[3] != GNU0_MAGIC) {
error_setg(errp, "Invalid note in PT_GNU_PROPERTY");
return false;
}
off = sizeof(note.nhdr) + NOTE_NAME_SZ;
- datasz = note.nhdr.n_descsz + off;
+ datasz = tswap32(note.nhdr.n_descsz) + off;
if (datasz > n) {
error_setg(errp, "Invalid note size in PT_GNU_PROPERTY");
return false;
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 03/10] linux-user: add openat2 support in linux-user
2024-10-05 23:33 [PATCH 00/10] linux-user pre-PR Richard Henderson
2024-10-05 23:33 ` [PATCH 01/10] linux-user/flatload: Take mmap_lock in load_flt_binary() Richard Henderson
2024-10-05 23:33 ` [PATCH 02/10] linux-user: Fix parse_elf_properties GNU0_MAGIC check Richard Henderson
@ 2024-10-05 23:33 ` Richard Henderson
2024-10-05 23:33 ` [PATCH 04/10] linux-user: add strace support for openat2 Richard Henderson
` (6 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2024-10-05 23:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Michael Vogt, Laurent Vivier
From: Michael Vogt <mvogt@redhat.com>
This commit adds support for the `openat2()` syscall in the
`linux-user` userspace emulator.
It is implemented by extracting a new helper `maybe_do_fake_open()`
out of the exiting `do_guest_openat()` and share that with the
new `do_guest_openat2()`. Unfortunately we cannot just make
do_guest_openat2() a superset of do_guest_openat() because the
openat2() syscall is stricter with the argument checking and
will return an error for invalid flags or mode combinations (which
open()/openat() will ignore).
The implementation is similar to SYSCALL_DEFINE(openat2), i.e.
a new `copy_struct_from_user()` is used that works the same
as the kernels version to support backwards-compatibility
for struct syscall argument.
Instead of including openat2.h we create a copy of `open_how`
as `open_how_ver0` to ensure that if the structure grows we
can log a LOG_UNIMP warning.
Note that in this commit using openat2() for a "faked" file in
/proc will honor the "resolve" flags for
RESOLVE_NO_{MAGIC,SYM}LINKS for path based access to /proc/self/exe
(which is the only magic link we support for faked files).
Note it will not catch special access via e.g. dirfd. This is not
great but it seems similar to the exiting behavior when openat()
is called with a dirfd to "/proc". Here too the fake file lookup
may not catch the special file because no dirfd is used to
determine if the path is in /proc.
Signed-off-by: Michael Vogt <mvogt@redhat.com>
Buglink: https://github.com/osbuild/bootc-image-builder/issues/619
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Message-ID: <1c2c8c9db3731ed4c6fd9b10c63637c3e4caf8f5.1727795334.git.mvogt@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/syscall_defs.h | 13 +++++
linux-user/syscall.c | 105 +++++++++++++++++++++++++++++++++++++-
2 files changed, 116 insertions(+), 2 deletions(-)
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index e08d088740..de5091c977 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -2748,4 +2748,17 @@ struct target_sched_param {
abi_int sched_priority;
};
+/* from kernel's include/uapi/linux/openat2.h */
+struct target_open_how_ver0 {
+ abi_ullong flags;
+ abi_ullong mode;
+ abi_ullong resolve;
+};
+#ifndef RESOLVE_NO_MAGICLINKS
+#define RESOLVE_NO_MAGICLINKS 0x02
+#endif
+#ifndef RESOLVE_NO_SYMLINKS
+#define RESOLVE_NO_SYMLINKS 0x04
+#endif
+
#endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index a666986189..2febc3bc3f 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -602,6 +602,34 @@ static int check_zeroed_user(abi_long addr, size_t ksize, size_t usize)
return 1;
}
+/*
+ * Copies a target struct to a host struct, in a way that guarantees
+ * backwards-compatibility for struct syscall arguments.
+ *
+ * Similar to kernels uaccess.h:copy_struct_from_user()
+ */
+static int
+copy_struct_from_user(void *dst, size_t ksize, abi_ptr src, size_t usize)
+{
+ size_t size = MIN(ksize, usize);
+ size_t rest = MAX(ksize, usize) - size;
+
+ /* Deal with trailing bytes. */
+ if (usize < ksize) {
+ memset(dst + size, 0, rest);
+ } else if (usize > ksize) {
+ int ret = check_zeroed_user(src, ksize, usize);
+ if (ret <= 0) {
+ return ret ?: -TARGET_E2BIG;
+ }
+ }
+ /* Copy the interoperable parts of the struct. */
+ if (copy_from_user(dst, src, size)) {
+ return -TARGET_EFAULT;
+ }
+ return 0;
+}
+
#define safe_syscall0(type, name) \
static type safe_##name(void) \
{ \
@@ -653,6 +681,15 @@ safe_syscall3(ssize_t, read, int, fd, void *, buff, size_t, count)
safe_syscall3(ssize_t, write, int, fd, const void *, buff, size_t, count)
safe_syscall4(int, openat, int, dirfd, const char *, pathname, \
int, flags, mode_t, mode)
+
+struct open_how_ver0 {
+ __u64 flags;
+ __u64 mode;
+ __u64 resolve;
+};
+safe_syscall4(int, openat2, int, dirfd, const char *, pathname, \
+ const struct open_how_ver0 *, how, size_t, size)
+
#if defined(TARGET_NR_wait4) || defined(TARGET_NR_waitpid)
safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \
struct rusage *, rusage)
@@ -8332,8 +8369,9 @@ static int open_net_route(CPUArchState *cpu_env, int fd)
}
#endif
-int do_guest_openat(CPUArchState *cpu_env, int dirfd, const char *fname,
- int flags, mode_t mode, bool safe)
+static int maybe_do_fake_open(CPUArchState *cpu_env, int dirfd,
+ const char *fname, int flags, mode_t mode,
+ int openat2_resolve, bool safe)
{
g_autofree char *proc_name = NULL;
const char *pathname;
@@ -8370,6 +8408,12 @@ int do_guest_openat(CPUArchState *cpu_env, int dirfd, const char *fname,
}
if (is_proc_myself(pathname, "exe")) {
+ /* Honor openat2 resolve flags */
+ if ((openat2_resolve & RESOLVE_NO_MAGICLINKS) ||
+ (openat2_resolve & RESOLVE_NO_SYMLINKS)) {
+ errno = ELOOP;
+ return -1;
+ }
if (safe) {
return safe_openat(dirfd, exec_path, flags, mode);
} else {
@@ -8416,6 +8460,17 @@ int do_guest_openat(CPUArchState *cpu_env, int dirfd, const char *fname,
return fd;
}
+ return -2;
+}
+
+int do_guest_openat(CPUArchState *cpu_env, int dirfd, const char *pathname,
+ int flags, mode_t mode, bool safe)
+{
+ int fd = maybe_do_fake_open(cpu_env, dirfd, pathname, flags, mode, 0, safe);
+ if (fd > -2) {
+ return fd;
+ }
+
if (safe) {
return safe_openat(dirfd, path(pathname), flags, mode);
} else {
@@ -8423,6 +8478,49 @@ int do_guest_openat(CPUArchState *cpu_env, int dirfd, const char *fname,
}
}
+
+static int do_openat2(CPUArchState *cpu_env, abi_long dirfd,
+ abi_ptr guest_pathname, abi_ptr guest_open_how,
+ abi_ulong guest_size)
+{
+ struct open_how_ver0 how = {0};
+ char *pathname;
+ int ret;
+
+ if (guest_size < sizeof(struct target_open_how_ver0)) {
+ return -TARGET_EINVAL;
+ }
+ ret = copy_struct_from_user(&how, sizeof(how), guest_open_how, guest_size);
+ if (ret) {
+ if (ret == -TARGET_E2BIG) {
+ qemu_log_mask(LOG_UNIMP,
+ "Unimplemented openat2 open_how size: "
+ TARGET_ABI_FMT_lu "\n", guest_size);
+ }
+ return ret;
+ }
+ pathname = lock_user_string(guest_pathname);
+ if (!pathname) {
+ return -TARGET_EFAULT;
+ }
+
+ how.flags = target_to_host_bitmask(tswap64(how.flags), fcntl_flags_tbl);
+ how.mode = tswap64(how.mode);
+ how.resolve = tswap64(how.resolve);
+ int fd = maybe_do_fake_open(cpu_env, dirfd, pathname, how.flags, how.mode,
+ how.resolve, true);
+ if (fd > -2) {
+ ret = get_errno(fd);
+ } else {
+ ret = get_errno(safe_openat2(dirfd, pathname, &how,
+ sizeof(struct open_how_ver0)));
+ }
+
+ fd_trans_unregister(ret);
+ unlock_user(pathname, guest_pathname, 0);
+ return ret;
+}
+
ssize_t do_guest_readlink(const char *pathname, char *buf, size_t bufsiz)
{
ssize_t ret;
@@ -9195,6 +9293,9 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
fd_trans_unregister(ret);
unlock_user(p, arg2, 0);
return ret;
+ case TARGET_NR_openat2:
+ ret = do_openat2(cpu_env, arg1, arg2, arg3, arg4);
+ return ret;
#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
case TARGET_NR_name_to_handle_at:
ret = do_name_to_handle_at(arg1, arg2, arg3, arg4, arg5);
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 04/10] linux-user: add strace support for openat2
2024-10-05 23:33 [PATCH 00/10] linux-user pre-PR Richard Henderson
` (2 preceding siblings ...)
2024-10-05 23:33 ` [PATCH 03/10] linux-user: add openat2 support in linux-user Richard Henderson
@ 2024-10-05 23:33 ` Richard Henderson
2024-10-05 23:33 ` [PATCH 05/10] linux-user: Trace wait4()'s and waitpid()'s wstatus Richard Henderson
` (5 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2024-10-05 23:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Michael Vogt, Laurent Vivier
From: Michael Vogt <mvogt@redhat.com>
This commit adds support for the `openat2()` to `QEMU_STRACE`. It
will use the `openat2.h` header if available to create user
readable flags for the `resolve` argument but does not require
the header otherwise.
It also makes `copy_struct_from_user()` available via `qemu.h`
and `open_how_ver0` via `syscall_defs.h` so that strace.c can use
them.
Signed-off-by: Michael Vogt <mvogt@redhat.com>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Message-ID: <f02d40c7751c03af885ced6dd94e4734d4be4d8f.1727795334.git.mvogt@redhat.com>
[rth: Add braces around the expanded how structure, like strace(3)]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/qemu.h | 9 ++++++++
linux-user/syscall_defs.h | 5 +++++
linux-user/strace.c | 47 +++++++++++++++++++++++++++++++++++++++
linux-user/syscall.c | 8 +------
linux-user/strace.list | 3 +++
meson.build | 1 +
6 files changed, 66 insertions(+), 7 deletions(-)
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 2e90a97175..98ad848ab2 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -313,6 +313,15 @@ static inline bool access_ok(CPUState *cpu, int type,
int copy_from_user(void *hptr, abi_ulong gaddr, ssize_t len);
int copy_to_user(abi_ulong gaddr, void *hptr, ssize_t len);
+/*
+ * copy_struct_from_user() copies a target struct to a host struct, in
+ * a way that guarantees backwards-compatibility for struct syscall
+ * arguments.
+ *
+ * Similar to kernels uaccess.h:copy_struct_from_user()
+ */
+int copy_struct_from_user(void *dst, size_t ksize, abi_ptr src, size_t usize);
+
/* Functions for accessing guest memory. The tget and tput functions
read/write single values, byteswapping as necessary. The lock_user function
gets a pointer to a contiguous area of guest memory, but does not perform
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index de5091c977..0ade83745e 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -2749,6 +2749,11 @@ struct target_sched_param {
};
/* from kernel's include/uapi/linux/openat2.h */
+struct open_how_ver0 {
+ __u64 flags;
+ __u64 mode;
+ __u64 resolve;
+};
struct target_open_how_ver0 {
abi_ullong flags;
abi_ullong mode;
diff --git a/linux-user/strace.c b/linux-user/strace.c
index b4d1098170..d3cdd09dc1 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -13,6 +13,9 @@
#include <linux/if_packet.h>
#include <linux/in6.h>
#include <linux/netlink.h>
+#ifdef HAVE_OPENAT2_H
+#include <linux/openat2.h>
+#endif
#include <sched.h>
#include "qemu.h"
#include "user-internals.h"
@@ -1063,6 +1066,18 @@ UNUSED static const struct flags open_flags[] = {
FLAG_END,
};
+UNUSED static const struct flags openat2_resolve_flags[] = {
+#ifdef HAVE_OPENAT2_H
+ FLAG_GENERIC(RESOLVE_NO_XDEV),
+ FLAG_GENERIC(RESOLVE_NO_MAGICLINKS),
+ FLAG_GENERIC(RESOLVE_NO_SYMLINKS),
+ FLAG_GENERIC(RESOLVE_BENEATH),
+ FLAG_GENERIC(RESOLVE_IN_ROOT),
+ FLAG_GENERIC(RESOLVE_CACHED),
+#endif
+ FLAG_END,
+};
+
UNUSED static const struct flags mount_flags[] = {
#ifdef MS_BIND
FLAG_GENERIC(MS_BIND),
@@ -3483,6 +3498,38 @@ print_openat(CPUArchState *cpu_env, const struct syscallname *name,
}
#endif
+#ifdef TARGET_NR_openat2
+static void
+print_openat2(CPUArchState *cpu_env, const struct syscallname *name,
+ abi_long arg0, abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4, abi_long arg5)
+{
+ struct open_how_ver0 how;
+
+ print_syscall_prologue(name);
+ print_at_dirfd(arg0, 0);
+ print_string(arg1, 0);
+
+ if ((abi_ulong)arg3 >= sizeof(struct target_open_how_ver0) &&
+ copy_struct_from_user(&how, sizeof(how), arg2, arg3) == 0) {
+ how.flags = tswap64(how.flags);
+ how.mode = tswap64(how.mode);
+ how.resolve = tswap64(how.resolve);
+ qemu_log("{");
+ print_open_flags(how.flags, 0);
+ if (how.flags & TARGET_O_CREAT) {
+ print_file_mode(how.mode, 0);
+ }
+ print_flags(openat2_resolve_flags, how.resolve, 1);
+ qemu_log("},");
+ } else {
+ print_pointer(arg2, 0);
+ }
+ print_raw_param(TARGET_ABI_FMT_lu, arg3, 1);
+ print_syscall_epilogue(name);
+}
+#endif
+
#ifdef TARGET_NR_pidfd_send_signal
static void
print_pidfd_send_signal(CPUArchState *cpu_env, const struct syscallname *name,
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 2febc3bc3f..1354e75694 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -608,8 +608,7 @@ static int check_zeroed_user(abi_long addr, size_t ksize, size_t usize)
*
* Similar to kernels uaccess.h:copy_struct_from_user()
*/
-static int
-copy_struct_from_user(void *dst, size_t ksize, abi_ptr src, size_t usize)
+int copy_struct_from_user(void *dst, size_t ksize, abi_ptr src, size_t usize)
{
size_t size = MIN(ksize, usize);
size_t rest = MAX(ksize, usize) - size;
@@ -682,11 +681,6 @@ safe_syscall3(ssize_t, write, int, fd, const void *, buff, size_t, count)
safe_syscall4(int, openat, int, dirfd, const char *, pathname, \
int, flags, mode_t, mode)
-struct open_how_ver0 {
- __u64 flags;
- __u64 mode;
- __u64 resolve;
-};
safe_syscall4(int, openat2, int, dirfd, const char *, pathname, \
const struct open_how_ver0 *, how, size_t, size)
diff --git a/linux-user/strace.list b/linux-user/strace.list
index dfd4237d14..ef658224fc 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -715,6 +715,9 @@
#ifdef TARGET_NR_openat
{ TARGET_NR_openat, "openat" , NULL, print_openat, NULL },
#endif
+#ifdef TARGET_NR_openat2
+{ TARGET_NR_openat2, "openat2" , NULL, print_openat2, NULL },
+#endif
#ifdef TARGET_NR_osf_adjtime
{ TARGET_NR_osf_adjtime, "osf_adjtime" , NULL, NULL, NULL },
#endif
diff --git a/meson.build b/meson.build
index 10464466ff..77cb5c41d8 100644
--- a/meson.build
+++ b/meson.build
@@ -2488,6 +2488,7 @@ config_host_data.set('CONFIG_LINUX_MAGIC_H', cc.has_header('linux/magic.h'))
config_host_data.set('CONFIG_VALGRIND_H', cc.has_header('valgrind/valgrind.h'))
config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
+config_host_data.set('HAVE_OPENAT2_H', cc.has_header('linux/openat2.h'))
config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h'))
config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 05/10] linux-user: Trace wait4()'s and waitpid()'s wstatus
2024-10-05 23:33 [PATCH 00/10] linux-user pre-PR Richard Henderson
` (3 preceding siblings ...)
2024-10-05 23:33 ` [PATCH 04/10] linux-user: add strace support for openat2 Richard Henderson
@ 2024-10-05 23:33 ` Richard Henderson
2024-10-05 23:33 ` [PATCH 06/10] linux-user: Correct print_sockaddr() format Richard Henderson
` (4 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2024-10-05 23:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Ilya Leoshkevich
From: Ilya Leoshkevich <iii@linux.ibm.com>
Borrow the code for formatting the most frequent WIFEXITED() and
WIFSIGNALED() special cases from from the strace's printstatus().
Output examples:
474729 wait4(-1,0x7f00767ff0a0,0,(nil)) = 474733 (wstatus={WIFEXITED(s) && WEXITSTATUS(s) == 1})
475833 wait4(-1,0x7f7de61ff0a0,0,(nil)) = 475837 (wstatus={WIFSIGNALED(s) && WTERMSIG(s) == SIGKILL})
1168 waitpid(1171,0x7f44eea00340,0) = 1171 (wstatus={WIFSIGNALED(s) && WTERMSIG(s) == SIGKILL})
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Message-ID: <20241001193244.14939-1-iii@linux.ibm.com>
[rth: Drop extra output for NULL wstatus or error reading.]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/strace.c | 57 ++++++++++++++++++++++++++++++++++++++++++
linux-user/strace.list | 6 +++--
2 files changed, 61 insertions(+), 2 deletions(-)
diff --git a/linux-user/strace.c b/linux-user/strace.c
index d3cdd09dc1..cf9eaf71c9 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -4215,6 +4215,63 @@ print_ioctl(CPUArchState *cpu_env, const struct syscallname *name,
}
#endif
+#if defined(TARGET_NR_wait4) || defined(TARGET_NR_waitpid)
+static void print_wstatus(int wstatus)
+{
+ if (WIFSIGNALED(wstatus)) {
+ qemu_log("{WIFSIGNALED(s) && WTERMSIG(s) == ");
+ print_signal(WTERMSIG(wstatus), 1);
+ if (WCOREDUMP(wstatus)) {
+ qemu_log(" && WCOREDUMP(s)");
+ }
+ qemu_log("}");
+ } else if (WIFEXITED(wstatus)) {
+ qemu_log("{WIFEXITED(s) && WEXITSTATUS(s) == %d}",
+ WEXITSTATUS(wstatus));
+ } else {
+ print_number(wstatus, 1);
+ }
+}
+
+static void print_ret_wstatus(abi_long ret, abi_long wstatus_addr)
+{
+ int wstatus;
+
+ if (!print_syscall_err(ret)
+ && wstatus_addr
+ && get_user_s32(wstatus, wstatus_addr)) {
+ qemu_log(TARGET_ABI_FMT_ld " (wstatus=", ret);
+ print_wstatus(wstatus);
+ qemu_log(")");
+ }
+ qemu_log("\n");
+}
+#endif
+
+#ifdef TARGET_NR_wait4
+static void
+print_syscall_ret_wait4(CPUArchState *cpu_env,
+ 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_ret_wstatus(ret, arg1);
+}
+#endif
+
+#ifdef TARGET_NR_waitpid
+static void
+print_syscall_ret_waitpid(CPUArchState *cpu_env,
+ 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_ret_wstatus(ret, arg1);
+}
+#endif
+
/*
* An array of all of the syscalls we know about
*/
diff --git a/linux-user/strace.list b/linux-user/strace.list
index ef658224fc..f8899710b5 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1662,13 +1662,15 @@
{ TARGET_NR_vserver, "vserver" , NULL, NULL, NULL },
#endif
#ifdef TARGET_NR_wait4
-{ TARGET_NR_wait4, "wait4" , "%s(%d,%p,%d,%p)", NULL, NULL },
+{ TARGET_NR_wait4, "wait4" , "%s(%d,%p,%d,%p)", NULL,
+ print_syscall_ret_wait4 },
#endif
#ifdef TARGET_NR_waitid
{ TARGET_NR_waitid, "waitid" , "%s(%#x,%d,%p,%#x)", NULL, NULL },
#endif
#ifdef TARGET_NR_waitpid
-{ TARGET_NR_waitpid, "waitpid" , "%s(%d,%p,%#x)", NULL, NULL },
+{ TARGET_NR_waitpid, "waitpid", "%s(%d,%p,%#x)", NULL,
+ print_syscall_ret_waitpid },
#endif
#ifdef TARGET_NR_write
{ TARGET_NR_write, "write" , "%s(%d,%#x,%d)", NULL, NULL },
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 06/10] linux-user: Correct print_sockaddr() format
2024-10-05 23:33 [PATCH 00/10] linux-user pre-PR Richard Henderson
` (4 preceding siblings ...)
2024-10-05 23:33 ` [PATCH 05/10] linux-user: Trace wait4()'s and waitpid()'s wstatus Richard Henderson
@ 2024-10-05 23:33 ` Richard Henderson
2024-10-07 19:50 ` Philippe Mathieu-Daudé
2024-10-05 23:33 ` [PATCH 07/10] linux-user: Display sockaddr buffer as pointer Richard Henderson
` (3 subsequent siblings)
9 siblings, 1 reply; 13+ messages in thread
From: Richard Henderson @ 2024-10-05 23:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Ilya Leoshkevich
From: Philippe Mathieu-Daudé <philmd@linaro.org>
When the %addr argument can not be accessed, a double comma
is logged (the final qemu_log call prepend a comma). Move
the comma from the final qemu_log to the preceeding switch
cases that had omitted it.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20240807124306.52903-2-philmd@linaro.org>
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
[rth: Move comma into the various switch cases.]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/strace.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/linux-user/strace.c b/linux-user/strace.c
index cf9eaf71c9..dfdec58542 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -376,7 +376,7 @@ print_sockaddr(abi_ulong addr, abi_long addrlen, int last)
un->sun_path[i]; i++) {
qemu_log("%c", un->sun_path[i]);
}
- qemu_log("\"}");
+ qemu_log("\"},");
break;
}
case AF_INET: {
@@ -386,7 +386,7 @@ print_sockaddr(abi_ulong addr, abi_long addrlen, int last)
ntohs(in->sin_port));
qemu_log("sin_addr=inet_addr(\"%d.%d.%d.%d\")",
c[0], c[1], c[2], c[3]);
- qemu_log("}");
+ qemu_log("},");
break;
}
case AF_PACKET: {
@@ -417,12 +417,12 @@ print_sockaddr(abi_ulong addr, abi_long addrlen, int last)
}
qemu_log(",sll_addr=%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]);
- qemu_log("}");
+ qemu_log("},");
break;
}
case AF_NETLINK: {
struct target_sockaddr_nl *nl = (struct target_sockaddr_nl *)sa;
- qemu_log("{nl_family=AF_NETLINK,nl_pid=%u,nl_groups=%u}",
+ qemu_log("{nl_family=AF_NETLINK,nl_pid=%u,nl_groups=%u},",
tswap32(nl->nl_pid), tswap32(nl->nl_groups));
break;
}
@@ -432,14 +432,14 @@ print_sockaddr(abi_ulong addr, abi_long addrlen, int last)
qemu_log("%02x, ", sa->sa_data[i]);
}
qemu_log("%02x}", sa->sa_data[i]);
- qemu_log("}");
+ qemu_log("},");
break;
}
unlock_user(sa, addr, 0);
} else {
print_raw_param("0x"TARGET_ABI_FMT_lx, addr, 0);
}
- qemu_log(", "TARGET_ABI_FMT_ld"%s", addrlen, get_comma(last));
+ qemu_log(TARGET_ABI_FMT_ld"%s", addrlen, get_comma(last));
}
static void
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 06/10] linux-user: Correct print_sockaddr() format
2024-10-05 23:33 ` [PATCH 06/10] linux-user: Correct print_sockaddr() format Richard Henderson
@ 2024-10-07 19:50 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 13+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-10-07 19:50 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: Ilya Leoshkevich
On 5/10/24 20:33, Richard Henderson wrote:
> From: Philippe Mathieu-Daudé <philmd@linaro.org>
>
> When the %addr argument can not be accessed, a double comma
> is logged (the final qemu_log call prepend a comma). Move
> the comma from the final qemu_log to the preceeding switch
> cases that had omitted it.
>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> Message-Id: <20240807124306.52903-2-philmd@linaro.org>
> Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
> [rth: Move comma into the various switch cases.]
Thanks!
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> linux-user/strace.c | 12 ++++++------
> 1 file changed, 6 insertions(+), 6 deletions(-)
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 07/10] linux-user: Display sockaddr buffer as pointer
2024-10-05 23:33 [PATCH 00/10] linux-user pre-PR Richard Henderson
` (5 preceding siblings ...)
2024-10-05 23:33 ` [PATCH 06/10] linux-user: Correct print_sockaddr() format Richard Henderson
@ 2024-10-05 23:33 ` Richard Henderson
2024-10-05 23:33 ` [PATCH 08/10] linux-user: Factor print_buf_len() out Richard Henderson
` (2 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2024-10-05 23:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Ilya Leoshkevich
From: Philippe Mathieu-Daudé <philmd@linaro.org>
Rather than 'raw param', display as pointer to get
"NULL" instead of "0x00000000".
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Ilya Leoshkevich <iii@linux.ibm.com>
Message-ID: <20240807124306.52903-3-philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/strace.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/linux-user/strace.c b/linux-user/strace.c
index dfdec58542..b72fcd515f 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -437,7 +437,7 @@ print_sockaddr(abi_ulong addr, abi_long addrlen, int last)
}
unlock_user(sa, addr, 0);
} else {
- print_raw_param("0x"TARGET_ABI_FMT_lx, addr, 0);
+ print_pointer(addr, 0);
}
qemu_log(TARGET_ABI_FMT_ld"%s", addrlen, get_comma(last));
}
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 08/10] linux-user: Factor print_buf_len() out
2024-10-05 23:33 [PATCH 00/10] linux-user pre-PR Richard Henderson
` (6 preceding siblings ...)
2024-10-05 23:33 ` [PATCH 07/10] linux-user: Display sockaddr buffer as pointer Richard Henderson
@ 2024-10-05 23:33 ` Richard Henderson
2024-10-05 23:33 ` [PATCH 09/10] linux-user: Add strace for sendto() Richard Henderson
2024-10-05 23:33 ` [PATCH 10/10] linux-user: Add strace for recvfrom() Richard Henderson
9 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2024-10-05 23:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Ilya Leoshkevich
From: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Ilya Leoshkevich <iii@linux.ibm.com>
Message-ID: <20240807124306.52903-4-philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/strace.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/linux-user/strace.c b/linux-user/strace.c
index b72fcd515f..245153c1ce 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1670,6 +1670,13 @@ print_buf(abi_long addr, abi_long len, int last)
}
}
+static void
+print_buf_len(abi_long addr, abi_long len, int last)
+{
+ print_buf(addr, len, 0);
+ print_raw_param(TARGET_ABI_FMT_ld, len, last);
+}
+
/*
* Prints out raw parameter using given format. Caller needs
* to do byte swapping if needed.
@@ -2757,8 +2764,7 @@ static void do_print_sendrecv(const char *name, abi_long arg1)
qemu_log("%s(", name);
print_sockfd(sockfd, 0);
- print_buf(msg, len, 0);
- print_raw_param(TARGET_ABI_FMT_ld, len, 0);
+ print_buf_len(msg, len, 0);
print_flags(msg_flags, flags, 1);
qemu_log(")");
}
@@ -2776,8 +2782,7 @@ static void do_print_msgaddr(const char *name, abi_long arg1)
qemu_log("%s(", name);
print_sockfd(sockfd, 0);
- print_buf(msg, len, 0);
- print_raw_param(TARGET_ABI_FMT_ld, len, 0);
+ print_buf_len(msg, len, 0);
print_flags(msg_flags, flags, 0);
print_sockaddr(addr, addrlen, 0);
qemu_log(")");
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 09/10] linux-user: Add strace for sendto()
2024-10-05 23:33 [PATCH 00/10] linux-user pre-PR Richard Henderson
` (7 preceding siblings ...)
2024-10-05 23:33 ` [PATCH 08/10] linux-user: Factor print_buf_len() out Richard Henderson
@ 2024-10-05 23:33 ` Richard Henderson
2024-10-05 23:33 ` [PATCH 10/10] linux-user: Add strace for recvfrom() Richard Henderson
9 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2024-10-05 23:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Ilya Leoshkevich
From: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Ilya Leoshkevich <iii@linux.ibm.com>
Message-ID: <20240807124306.52903-5-philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/strace.c | 15 +++++++++++++++
linux-user/strace.list | 2 +-
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 245153c1ce..0263e6a396 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -3142,6 +3142,21 @@ print_bind(CPUArchState *cpu_env, const struct syscallname *name,
}
#endif
+#ifdef TARGET_NR_sendto
+static void
+print_sendto(CPUArchState *cpu_env, const struct syscallname *name,
+ abi_long arg0, abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4, abi_long arg5)
+{
+ print_syscall_prologue(name);
+ print_sockfd(arg0, 0);
+ print_buf_len(arg1, arg2, 0);
+ print_flags(msg_flags, arg3, 0);
+ print_sockaddr(arg4, arg5, 1);
+ print_syscall_epilogue(name);
+}
+#endif
+
#if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) || \
defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64)
static void
diff --git a/linux-user/strace.list b/linux-user/strace.list
index f8899710b5..64d24e16d0 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1288,7 +1288,7 @@
{ TARGET_NR_sendmsg, "sendmsg" , NULL, NULL, NULL },
#endif
#ifdef TARGET_NR_sendto
-{ TARGET_NR_sendto, "sendto" , NULL, NULL, NULL },
+{ TARGET_NR_sendto, "sendto" , NULL, print_sendto, NULL },
#endif
#ifdef TARGET_NR_setdomainname
{ TARGET_NR_setdomainname, "setdomainname" , NULL, NULL, NULL },
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 10/10] linux-user: Add strace for recvfrom()
2024-10-05 23:33 [PATCH 00/10] linux-user pre-PR Richard Henderson
` (8 preceding siblings ...)
2024-10-05 23:33 ` [PATCH 09/10] linux-user: Add strace for sendto() Richard Henderson
@ 2024-10-05 23:33 ` Richard Henderson
9 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2024-10-05 23:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20240807124306.52903-6-philmd@linaro.org>
[rth: Do not dump output buffers.]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/strace.c | 17 +++++++++++++++++
linux-user/strace.list | 2 +-
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 0263e6a396..c3eb3a2706 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -3142,6 +3142,23 @@ print_bind(CPUArchState *cpu_env, const struct syscallname *name,
}
#endif
+#ifdef TARGET_NR_recvfrom
+static void
+print_recvfrom(CPUArchState *cpu_env, const struct syscallname *name,
+ abi_long arg0, abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4, abi_long arg5)
+{
+ print_syscall_prologue(name);
+ print_sockfd(arg0, 0);
+ print_pointer(arg1, 0); /* output */
+ print_raw_param(TARGET_ABI_FMT_ld, arg2, 0);
+ print_flags(msg_flags, arg3, 0);
+ print_pointer(arg4, 0); /* output */
+ print_pointer(arg5, 1); /* in/out */
+ print_syscall_epilogue(name);
+}
+#endif
+
#ifdef TARGET_NR_sendto
static void
print_sendto(CPUArchState *cpu_env, const struct syscallname *name,
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 64d24e16d0..0d69fb3150 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1138,7 +1138,7 @@
{ TARGET_NR_recv, "recv" , "%s(%d,%p,%u,%d)", NULL, NULL },
#endif
#ifdef TARGET_NR_recvfrom
-{ TARGET_NR_recvfrom, "recvfrom" , NULL, NULL, NULL },
+{ TARGET_NR_recvfrom, "recvfrom" , NULL, print_recvfrom, NULL },
#endif
#ifdef TARGET_NR_recvmmsg
{ TARGET_NR_recvmmsg, "recvmmsg" , NULL, NULL, NULL },
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread