aboutsummaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2023-02-04 17:17:15 +0000
committerPeter Maydell <peter.maydell@linaro.org>2023-02-04 17:17:15 +0000
commitceabf6e500570ecfb311d8896c4ba9da8cf21f2a (patch)
treeda84cc483c875f1d70fe49683a1354912a353b58 /linux-user
parent025274ad2f1cdcbbe9fc8ef2c6dbd7e9de0714da (diff)
parent3f0744f98b07c6fd2ce9d5840726d0915b2ae7c1 (diff)
Merge tag 'linux-user-for-8.0-pull-request' of https://gitlab.com/laurent_vivier/qemu into staging
linux-user branch pull request 20230204 Implement execveat() un-parent OBJECT(cpu) when closing thread Revert fix for glibc >= 2.36 sys/mount.h Fix/update strace move target_flat.h to target subdirs Fix SO_ERROR return code of getsockopt() Fix /proc/cpuinfo output for hppa Add emulation for MADV_WIPEONFORK and MADV_KEEPONFORK in madvise() Implement SOL_ALG encryption support linux-user: Allow sendmsg() without IOV # -----BEGIN PGP SIGNATURE----- # # iQJGBAABCAAwFiEEzS913cjjpNwuT1Fz8ww4vT8vvjwFAmPeguUSHGxhdXJlbnRA # dml2aWVyLmV1AAoJEPMMOL0/L748tnQP/1A4eu33pLe4+tjBuDGt2zcGAVuz+wN9 # rcwN5BQgjILwfECfRsy9QIkC8+M496tLk4W7pNkW9x/GSpzBp9x0+066uUghsa1Q # c0bFU0FM8xpywEXvOrz3LvEWaWqeBV/R+XYMqKFaiBQXf/5kmmteei9guH42L3gV # a+d0s1cWT48TslTaga9ECbiPD9lK+yfW879+wRhex1/BetkJPzLU1hZB4vfC5YQo # XagcmLWiseT4U8uCysikOgKQE4g2bv1oJXUuYjBxW15s5/llg8e57dEboO7MFEPK # a9P3Hl1qiA5Ol3scF1I7WURmGP6UVfdhTYe1aKYHhKY7QVBVjbU7r/NkdQ3dR6Nv # db58Lkurnrf5dMksZk8+25F/fvJT0nZpnbipunZejetNjrDVPk19XK5E6kJf91hk # 3W3vOeWMp4QjThpqghnlQ3gm2XfVmCGSMIOywTKZ4/M/TP28+9zY7GZqQXQXCBMy # nJFahfVTCfiYaGAYGjlMe5CMOQ6tJ6lwxuTCl9O1X565ifMBNUj3rcte1FvO/i24 # Rk0/lQVO+tD9ImxHJrei0Y2C0xzo7V8kaB9+foAf6Ku91SY1X1FIOm81DEyAhK61 # Biv2zlNwUV0aCierrn3oLuDkviVaAg6FkLO9snPG+lQy2uxgyJJ2/Pv0OCZhniWI # 9WifjYZKAXDa # =AcC6 # -----END PGP SIGNATURE----- # gpg: Signature made Sat 04 Feb 2023 16:08:05 GMT # 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 * tag 'linux-user-for-8.0-pull-request' of https://gitlab.com/laurent_vivier/qemu: (22 commits) linux-user: Allow sendmsg() without IOV linux-user: Implement SOL_ALG encryption support linux-user: Enhance strace output for various syscalls linux-user: Show 4th argument of rt_sigprocmask() in strace linux-user: Add emulation for MADV_WIPEONFORK and MADV_KEEPONFORK in madvise() linux-user: Improve strace output of personality() and sysinfo() linux-user: Fix /proc/cpuinfo output for hppa linux-user: Fix SO_ERROR return code of getsockopt() linux-user: move target_flat.h to target subdirs linux-user: Improve strace output of getgroups() and setgroups() linux-user: Add strace output for clock_getres_time64() and futex_time64() Revert "linux-user: fix compat with glibc >= 2.36 sys/mount.h" Revert "linux-user: add more compat ioctl definitions" linux-user: add more netlink protocol constants linux-user: fix strace build w/out munlockall linux-user: un-parent OBJECT(cpu) when closing thread linux-user: Add missing MAP_HUGETLB and MAP_STACK flags in strace linux-user/syscall: Implement execveat() linux-user/syscall: Extract do_execve() from do_syscall1() linux-user/strace: Add output for execveat() syscall ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/aarch64/target_flat.h1
-rw-r--r--linux-user/arm/target_flat.h1
-rw-r--r--linux-user/generic/target_flat.h (renamed from linux-user/target_flat.h)0
-rw-r--r--linux-user/m68k/target_flat.h1
-rw-r--r--linux-user/microblaze/target_flat.h1
-rw-r--r--linux-user/mmap.c56
-rw-r--r--linux-user/sh4/target_flat.h1
-rw-r--r--linux-user/strace.c189
-rw-r--r--linux-user/strace.list64
-rw-r--r--linux-user/syscall.c312
10 files changed, 378 insertions, 248 deletions
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
index 8fe189ea6f..8fe189ea6f 100644
--- a/linux-user/target_flat.h
+++ b/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/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.
+ *
+ * However, some advice values such as MADV_DONTNEED, MADV_WIPEONFORK and
+ * MADV_KEEPONFORK are not hints and need to be emulated.
*
- * This is a hint, so ignoring and returning success is ok.
+ * 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.
*
- * 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.
+ * 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();
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"
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 9ae5a812cd..340010661c 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;
@@ -616,38 +664,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,
@@ -945,7 +961,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 +969,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 +979,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 +997,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 +1035,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 +1060,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 +1073,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 +1084,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),
@@ -1089,10 +1105,12 @@ UNUSED static struct flags mmap_flags[] = {
#ifdef TARGET_MAP_UNINITIALIZED
FLAG_TARGET(MAP_UNINITIALIZED),
#endif
+ FLAG_TARGET(MAP_HUGETLB),
+ FLAG_TARGET(MAP_STACK),
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 +1154,17 @@ UNUSED static struct flags clone_flags[] = {
FLAG_END,
};
-UNUSED static struct flags msg_flags[] = {
+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),
FLAG_GENERIC(MSG_DONTROUTE),
@@ -1156,7 +1184,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 +1206,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 +1254,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 +1274,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 +1293,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 +1377,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 +1388,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 +1408,8 @@ UNUSED static struct flags termios_lflags[] = {
FLAG_END,
};
-UNUSED static 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
@@ -1388,6 +1417,7 @@ UNUSED static struct flags mlockall_flags[] = {
#endif
FLAG_END,
};
+#endif
/* IDs of the various system clocks */
#define TARGET_CLOCK_REALTIME 0
@@ -1969,6 +1999,58 @@ 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);
+}
+
+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,
@@ -3142,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
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 3a898e2532..d8acbeec60 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 },
@@ -164,7 +167,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 },
@@ -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
@@ -315,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 },
@@ -337,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 },
@@ -361,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 },
@@ -385,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)
@@ -1043,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 },
@@ -1052,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 },
@@ -1124,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 },
@@ -1184,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 },
@@ -1196,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 },
@@ -1220,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 },
@@ -1298,10 +1308,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 },
@@ -1353,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 },
@@ -1498,7 +1508,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 },
@@ -1648,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 },
@@ -1672,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 },
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 1f8c10f8ef..1e868e9b0e 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -95,50 +95,7 @@
#include <linux/soundcard.h>
#include <linux/kd.h>
#include <linux/mtio.h>
-
-#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)
-
-#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 <linux/fs.h>
-#endif
#include <linux/fd.h>
#if defined(CONFIG_FIEMAP)
#include <linux/fiemap.h>
@@ -696,7 +653,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, \
@@ -1871,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);
@@ -2800,8 +2766,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;
@@ -3322,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;
@@ -3374,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;
}
@@ -8269,11 +8245,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
@@ -8357,6 +8339,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_execveat(CPUArchState *cpu_env, int dirfd,
+ abi_long pathname, abi_long guest_argp,
+ abi_long guest_envp, int flags)
+{
+ 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_execveat(dirfd, exec_path, argp, envp, flags));
+ } else {
+ ret = get_errno(safe_execveat(dirfd, p, argp, envp, flags));
+ }
+
+ 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
@@ -8642,7 +8737,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
@@ -8652,11 +8753,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();
@@ -8866,104 +8962,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:
- {
- 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_execveat(cpu_env, AT_FDCWD, arg1, arg2, arg3, 0);
case TARGET_NR_chdir:
if (!(p = lock_user_string(arg1)))
return -TARGET_EFAULT;