diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2023-02-04 17:17:15 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2023-02-04 17:17:15 +0000 |
commit | ceabf6e500570ecfb311d8896c4ba9da8cf21f2a (patch) | |
tree | da84cc483c875f1d70fe49683a1354912a353b58 /linux-user | |
parent | 025274ad2f1cdcbbe9fc8ef2c6dbd7e9de0714da (diff) | |
parent | 3f0744f98b07c6fd2ce9d5840726d0915b2ae7c1 (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.h | 1 | ||||
-rw-r--r-- | linux-user/arm/target_flat.h | 1 | ||||
-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.h | 1 | ||||
-rw-r--r-- | linux-user/microblaze/target_flat.h | 1 | ||||
-rw-r--r-- | linux-user/mmap.c | 56 | ||||
-rw-r--r-- | linux-user/sh4/target_flat.h | 1 | ||||
-rw-r--r-- | linux-user/strace.c | 189 | ||||
-rw-r--r-- | linux-user/strace.list | 64 | ||||
-rw-r--r-- | linux-user/syscall.c | 312 |
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; |