blob: 125fcbe4237cb3c7a3cb7d6574d1f8534097369b [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/*
2 * Linux syscalls
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard31e31b82003-02-18 22:55:36 +00004 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * along with this program; if not, see <http://www.gnu.org/licenses/>.
bellard31e31b82003-02-18 22:55:36 +000018 */
Eduardo Habkostd5b3a9b2009-06-09 18:26:31 -030019#define _ATFILE_SOURCE
Peter Maydelld39594e2016-01-26 18:17:02 +000020#include "qemu/osdep.h"
Veronia Bahaaf348b6d2016-03-20 19:16:19 +020021#include "qemu/cutils.h"
22#include "qemu/path.h"
Shu-Chun Weng9bdfa4d2019-08-19 11:09:47 -070023#include "qemu/memfd.h"
Markus Armbrusterdc5e9ac2019-08-12 07:23:49 +020024#include "qemu/queue.h"
Richard Henderson720ace22023-03-15 17:43:14 +000025#include "qemu/plugin.h"
Helge Dellerfe080592022-12-15 08:27:46 +010026#include "target_mman.h"
bellard31e31b82003-02-18 22:55:36 +000027#include <elf.h>
28#include <endian.h>
John Spencerc56dc772012-12-10 07:59:46 +010029#include <grp.h>
thsd08d3bb2007-03-19 13:09:22 +000030#include <sys/ipc.h>
31#include <sys/msg.h>
bellard31e31b82003-02-18 22:55:36 +000032#include <sys/wait.h>
bellard31e31b82003-02-18 22:55:36 +000033#include <sys/mount.h>
John Spencer586b0be2012-12-26 00:49:49 +010034#include <sys/file.h>
35#include <sys/fsuid.h>
36#include <sys/personality.h>
ths39b9aae2007-02-11 18:36:44 +000037#include <sys/prctl.h>
bellard31e31b82003-02-18 22:55:36 +000038#include <sys/resource.h>
bellard31e31b82003-02-18 22:55:36 +000039#include <sys/swap.h>
Peter Maydelle0eb2102014-03-17 12:15:35 +000040#include <linux/capability.h>
bellard31e31b82003-02-18 22:55:36 +000041#include <sched.h>
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +020042#include <sys/timex.h>
bellard31e31b82003-02-18 22:55:36 +000043#include <sys/socket.h>
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +020044#include <linux/sockios.h>
aurel32607175e2009-04-15 16:11:59 +000045#include <sys/un.h>
bellard31e31b82003-02-18 22:55:36 +000046#include <sys/uio.h>
Felix Janda0839f112016-09-30 19:40:21 -040047#include <poll.h>
bellard32f36bc2003-03-30 21:29:48 +000048#include <sys/times.h>
bellard8853f862004-02-22 14:57:26 +000049#include <sys/shm.h>
thsfa294812007-02-02 22:05:00 +000050#include <sys/sem.h>
bellard56c8f682005-11-28 22:28:41 +000051#include <sys/statfs.h>
bellardebc05482003-09-30 21:08:41 +000052#include <utime.h>
bellarda5448a72004-06-19 16:59:03 +000053#include <sys/sysinfo.h>
Laurent Viviere36800c2015-10-02 14:48:09 +020054#include <sys/signalfd.h>
bellard72f03902003-02-18 23:33:18 +000055//#include <sys/user.h>
Shu-Chun Weng22db1212020-12-18 11:32:12 -080056#include <netinet/in.h>
bellard8853f862004-02-22 14:57:26 +000057#include <netinet/ip.h>
bellard7854b052003-03-29 17:22:23 +000058#include <netinet/tcp.h>
Shu-Chun Wengfe51b0a2020-12-18 11:32:11 -080059#include <netinet/udp.h>
Laurent Vivier86fcd942011-03-30 01:35:23 +020060#include <linux/wireless.h>
Jing Huang920394d2012-07-24 13:59:23 +000061#include <linux/icmp.h>
Helge Delleree1ac3a2017-02-18 23:31:30 +010062#include <linux/icmpv6.h>
Shu-Chun Weng6addf062020-09-28 18:48:01 -070063#include <linux/if_tun.h>
Shu-Chun Weng22db1212020-12-18 11:32:12 -080064#include <linux/in6.h>
Helge Delleree1ac3a2017-02-18 23:31:30 +010065#include <linux/errqueue.h>
Marco A L Barbosad6d6d6f2017-10-05 10:55:30 -030066#include <linux/random.h>
Riku Voipiod80a1902014-10-01 16:05:46 +030067#ifdef CONFIG_TIMERFD
68#include <sys/timerfd.h>
69#endif
Riku Voipioc2882b92009-08-12 15:08:24 +030070#ifdef CONFIG_EVENTFD
71#include <sys/eventfd.h>
72#endif
Peter Maydell3b6edd12011-02-15 18:35:05 +000073#ifdef CONFIG_EPOLL
74#include <sys/epoll.h>
75#endif
An-Cheng Huanga790ae32011-08-09 12:34:06 -070076#ifdef CONFIG_ATTR
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010077#include "qemu/xattr.h"
An-Cheng Huanga790ae32011-08-09 12:34:06 -070078#endif
Peter Maydella8fd1ab2013-02-08 07:31:55 +000079#ifdef CONFIG_SENDFILE
80#include <sys/sendfile.h>
81#endif
Thomas Huth4a9d5f82020-11-18 18:10:51 +010082#ifdef HAVE_SYS_KCOV_H
Aleksandar Markovicbd27e672020-01-16 23:49:50 +010083#include <sys/kcov.h>
84#endif
bellard31e31b82003-02-18 22:55:36 +000085
86#define termios host_termios
87#define winsize host_winsize
88#define termio host_termio
bellard04369ff2003-03-20 22:33:23 +000089#define sgttyb host_sgttyb /* same as target */
90#define tchars host_tchars /* same as target */
91#define ltchars host_ltchars /* same as target */
bellard31e31b82003-02-18 22:55:36 +000092
93#include <linux/termios.h>
94#include <linux/unistd.h>
bellard31e31b82003-02-18 22:55:36 +000095#include <linux/cdrom.h>
96#include <linux/hdreg.h>
97#include <linux/soundcard.h>
bellard19b84f32003-05-08 15:41:49 +000098#include <linux/kd.h>
balrog8fbd6b52008-09-20 03:03:09 +000099#include <linux/mtio.h>
Martin Mohring350d1772009-05-04 21:21:41 +0300100#include <linux/fs.h>
Yunqiang Suab22b4d2019-09-04 14:59:24 +0200101#include <linux/fd.h>
Peter Maydelldace20d2011-01-10 13:11:24 +0000102#if defined(CONFIG_FIEMAP)
Peter Maydell285da2b2011-01-06 15:04:18 +0000103#include <linux/fiemap.h>
Peter Maydelldace20d2011-01-10 13:11:24 +0000104#endif
Ulrich Hechtf7680a52009-10-16 17:00:44 +0200105#include <linux/fb.h>
Cortland Tölva6c753a62018-10-08 09:35:20 -0700106#if defined(CONFIG_USBFS)
107#include <linux/usbdevice_fs.h>
Cortland Tölvaa1333672018-10-08 09:35:21 -0700108#include <linux/usb/ch9.h>
Cortland Tölva6c753a62018-10-08 09:35:20 -0700109#endif
Ulrich Hechtf7680a52009-10-16 17:00:44 +0200110#include <linux/vt.h>
Alexander Graf56e904e2012-01-31 18:42:06 +0100111#include <linux/dm-ioctl.h>
Laurent Vivierc07ecc62013-01-07 11:40:06 +0000112#include <linux/reboot.h>
Laurent Vivier7ff7b662013-07-02 14:04:12 +0100113#include <linux/route.h>
Laurent Vivierf57d4192013-08-30 01:46:41 +0200114#include <linux/filter.h>
Andreas Färberfff8c532014-01-18 07:38:30 +0100115#include <linux/blkpg.h>
Laurent Viviera82ea932016-06-27 00:18:22 +0200116#include <netpacket/packet.h>
Laurent Vivier6c5b5642016-05-22 18:56:19 +0200117#include <linux/netlink.h>
Yunqiang Suf31dddd2019-06-19 16:17:11 +0200118#include <linux/if_alg.h>
Filip Bozuta68365f92020-01-15 20:36:35 +0100119#include <linux/rtc.h>
Filip Bozuta1c4c6fc2020-01-15 20:36:41 +0100120#include <sound/asound.h>
Thomas Huth48f670e2020-11-18 18:10:52 +0100121#ifdef HAVE_BTRFS_H
Filip Bozutad6092e02020-08-23 21:50:07 +0200122#include <linux/btrfs.h>
123#endif
Chen Gange865b972020-06-05 09:32:21 +0800124#ifdef HAVE_DRM_H
125#include <libdrm/drm.h>
Chen Gang913b03c2020-08-02 21:39:38 +0800126#include <libdrm/i915_drm.h>
Chen Gange865b972020-06-05 09:32:21 +0800127#endif
pbrookd7e40362008-05-23 16:06:43 +0000128#include "linux_loop.h"
Riku Voipio18cb0082014-02-19 12:59:58 +0200129#include "uname.h"
bellard31e31b82003-02-18 22:55:36 +0000130
bellard3ef693a2003-03-23 20:17:16 +0000131#include "qemu.h"
Peter Maydell3b249d22021-09-08 16:44:03 +0100132#include "user-internals.h"
Peter Maydella44d57a2021-09-08 16:43:58 +0100133#include "strace.h"
Peter Maydell2113aed2021-09-08 16:43:59 +0100134#include "signal-common.h"
Peter Maydell3ad0a762021-09-08 16:44:00 +0100135#include "loader.h"
Peter Maydell5423e6d2021-09-08 16:44:01 +0100136#include "user-mmap.h"
Richard Hendersonbbf15aa2021-11-17 16:14:00 +0100137#include "user/safe-syscall.h"
Richard Henderson5ebdd772019-03-14 13:10:53 -0700138#include "qemu/guest-random.h"
Alex Bennée01ef6b92020-04-03 20:11:46 +0100139#include "qemu/selfmap.h"
Emilio G. Cotac36f7a62018-10-21 13:27:44 -0400140#include "user/syscall-trace.h"
Richard Henderson5da40632021-11-17 15:46:05 +0100141#include "special-errno.h"
Richard Henderson51977e22019-03-12 19:22:20 -0700142#include "qapi/error.h"
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200143#include "fd-trans.h"
Philippe Mathieu-Daudédcb32f12020-01-01 12:23:00 +0100144#include "tcg/tcg.h"
Helge Dellerbd5ccd62022-10-24 22:18:09 +0200145#include "cpu_loop-common.h"
bellard31e31b82003-02-18 22:55:36 +0000146
Peter Maydell5ea2fc82016-08-02 18:41:27 +0100147#ifndef CLONE_IO
148#define CLONE_IO 0x80000000 /* Clone io context */
149#endif
150
151/* We can't directly call the host clone syscall, because this will
152 * badly confuse libc (breaking mutexes, for example). So we must
153 * divide clone flags into:
154 * * flag combinations that look like pthread_create()
155 * * flag combinations that look like fork()
156 * * flags we can implement within QEMU itself
157 * * flags we can't support and will return an error for
158 */
159/* For thread creation, all these flags must be present; for
160 * fork, none must be present.
161 */
162#define CLONE_THREAD_FLAGS \
163 (CLONE_VM | CLONE_FS | CLONE_FILES | \
164 CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM)
165
166/* These flags are ignored:
167 * CLONE_DETACHED is now ignored by the kernel;
168 * CLONE_IO is just an optimisation hint to the I/O scheduler
169 */
170#define CLONE_IGNORED_FLAGS \
171 (CLONE_DETACHED | CLONE_IO)
172
Helge Deller895ce8b2022-11-29 12:08:20 +0100173#ifndef CLONE_PIDFD
174# define CLONE_PIDFD 0x00001000
175#endif
176
Peter Maydell5ea2fc82016-08-02 18:41:27 +0100177/* Flags for fork which we can implement within QEMU itself */
178#define CLONE_OPTIONAL_FORK_FLAGS \
Helge Deller895ce8b2022-11-29 12:08:20 +0100179 (CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_PIDFD | \
Peter Maydell5ea2fc82016-08-02 18:41:27 +0100180 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID)
181
182/* Flags for thread creation which we can implement within QEMU itself */
183#define CLONE_OPTIONAL_THREAD_FLAGS \
184 (CLONE_SETTLS | CLONE_PARENT_SETTID | \
185 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | CLONE_PARENT)
186
187#define CLONE_INVALID_FORK_FLAGS \
188 (~(CSIGNAL | CLONE_OPTIONAL_FORK_FLAGS | CLONE_IGNORED_FLAGS))
189
190#define CLONE_INVALID_THREAD_FLAGS \
191 (~(CSIGNAL | CLONE_THREAD_FLAGS | CLONE_OPTIONAL_THREAD_FLAGS | \
192 CLONE_IGNORED_FLAGS))
193
194/* CLONE_VFORK is special cased early in do_fork(). The other flag bits
195 * have almost all been allocated. We cannot support any of
196 * CLONE_NEWNS, CLONE_NEWCGROUP, CLONE_NEWUTS, CLONE_NEWIPC,
197 * CLONE_NEWUSER, CLONE_NEWPID, CLONE_NEWNET, CLONE_PTRACE, CLONE_UNTRACED.
198 * The checks against the invalid thread masks above will catch these.
199 * (The one remaining unallocated bit is 0x1000 which used to be CLONE_PID.)
200 */
pbrook30813ce2008-06-02 15:45:44 +0000201
Timothy E Baldwin71a8f7f2016-05-12 18:47:45 +0100202/* Define DEBUG_ERESTARTSYS to force every syscall to be restarted
203 * once. This exercises the codepaths for restart.
204 */
205//#define DEBUG_ERESTARTSYS
bellard31e31b82003-02-18 22:55:36 +0000206
bellard1a9353d2003-03-16 20:28:50 +0000207//#include <linux/msdos_fs.h>
Richard Henderson540a7362021-11-14 11:35:37 +0100208#define VFAT_IOCTL_READDIR_BOTH \
209 _IOC(_IOC_READ, 'r', 1, (sizeof(struct linux_dirent) + 256) * 2)
210#define VFAT_IOCTL_READDIR_SHORT \
211 _IOC(_IOC_READ, 'r', 2, (sizeof(struct linux_dirent) + 256) * 2)
bellard1a9353d2003-03-16 20:28:50 +0000212
bellard70a194b2003-08-11 22:20:16 +0000213#undef _syscall0
214#undef _syscall1
215#undef _syscall2
216#undef _syscall3
217#undef _syscall4
218#undef _syscall5
bellard83fcb512006-06-14 13:37:16 +0000219#undef _syscall6
bellard70a194b2003-08-11 22:20:16 +0000220
bellard83fcb512006-06-14 13:37:16 +0000221#define _syscall0(type,name) \
blueswir18fcd3692008-08-17 20:26:25 +0000222static type name (void) \
bellard83fcb512006-06-14 13:37:16 +0000223{ \
224 return syscall(__NR_##name); \
bellard70a194b2003-08-11 22:20:16 +0000225}
226
bellard83fcb512006-06-14 13:37:16 +0000227#define _syscall1(type,name,type1,arg1) \
blueswir18fcd3692008-08-17 20:26:25 +0000228static type name (type1 arg1) \
bellard83fcb512006-06-14 13:37:16 +0000229{ \
230 return syscall(__NR_##name, arg1); \
bellard70a194b2003-08-11 22:20:16 +0000231}
232
bellard83fcb512006-06-14 13:37:16 +0000233#define _syscall2(type,name,type1,arg1,type2,arg2) \
blueswir18fcd3692008-08-17 20:26:25 +0000234static type name (type1 arg1,type2 arg2) \
bellard83fcb512006-06-14 13:37:16 +0000235{ \
236 return syscall(__NR_##name, arg1, arg2); \
bellard70a194b2003-08-11 22:20:16 +0000237}
238
bellard83fcb512006-06-14 13:37:16 +0000239#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
blueswir18fcd3692008-08-17 20:26:25 +0000240static type name (type1 arg1,type2 arg2,type3 arg3) \
bellard83fcb512006-06-14 13:37:16 +0000241{ \
242 return syscall(__NR_##name, arg1, arg2, arg3); \
bellard70a194b2003-08-11 22:20:16 +0000243}
244
bellard83fcb512006-06-14 13:37:16 +0000245#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
blueswir18fcd3692008-08-17 20:26:25 +0000246static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
bellard83fcb512006-06-14 13:37:16 +0000247{ \
248 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
bellard70a194b2003-08-11 22:20:16 +0000249}
250
bellard83fcb512006-06-14 13:37:16 +0000251#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
252 type5,arg5) \
blueswir18fcd3692008-08-17 20:26:25 +0000253static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
bellard83fcb512006-06-14 13:37:16 +0000254{ \
255 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
bellard70a194b2003-08-11 22:20:16 +0000256}
bellard83fcb512006-06-14 13:37:16 +0000257
258
259#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
260 type5,arg5,type6,arg6) \
blueswir18fcd3692008-08-17 20:26:25 +0000261static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
262 type6 arg6) \
bellard83fcb512006-06-14 13:37:16 +0000263{ \
264 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
265}
266
bellard70a194b2003-08-11 22:20:16 +0000267
bellard31e31b82003-02-18 22:55:36 +0000268#define __NR_sys_uname __NR_uname
bellard72f03902003-02-18 23:33:18 +0000269#define __NR_sys_getcwd1 __NR_getcwd
bellard72f03902003-02-18 23:33:18 +0000270#define __NR_sys_getdents __NR_getdents
bellarddab2ed92003-03-22 15:23:14 +0000271#define __NR_sys_getdents64 __NR_getdents64
thsc6cda172007-10-09 03:42:34 +0000272#define __NR_sys_getpriority __NR_getpriority
bellard66fb9762003-03-23 01:06:05 +0000273#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +0200274#define __NR_sys_rt_tgsigqueueinfo __NR_rt_tgsigqueueinfo
ths7494b0f2007-02-11 18:26:53 +0000275#define __NR_sys_syslog __NR_syslog
Alistair Francis14690292020-03-18 15:47:01 -0700276#if defined(__NR_futex)
277# define __NR_sys_futex __NR_futex
278#endif
279#if defined(__NR_futex_time64)
280# define __NR_sys_futex_time64 __NR_futex_time64
281#endif
Aleksandar Rikaloefa92182019-06-28 12:43:34 +0200282#define __NR_sys_statx __NR_statx
bellard31e31b82003-02-18 22:55:36 +0000283
Peter Maydellb1cef6d2018-01-25 16:19:49 +0000284#if defined(__alpha__) || defined(__x86_64__) || defined(__s390x__)
bellard9af9eaa2003-04-07 21:34:41 +0000285#define __NR__llseek __NR_lseek
286#endif
287
James Hogana29e5ba2014-03-25 21:51:08 +0000288/* Newer kernel ports have llseek() instead of _llseek() */
289#if defined(TARGET_NR_llseek) && !defined(TARGET_NR__llseek)
290#define TARGET_NR__llseek TARGET_NR_llseek
291#endif
292
Helge Deller78721302021-02-10 07:12:14 +0100293/* some platforms need to mask more bits than just TARGET_O_NONBLOCK */
294#ifndef TARGET_O_NONBLOCK_MASK
295#define TARGET_O_NONBLOCK_MASK TARGET_O_NONBLOCK
296#endif
297
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +0000298#define __NR_sys_gettid __NR_gettid
299_syscall0(int, sys_gettid)
Peter Maydell2b3f64c2018-04-19 13:57:40 +0100300
301/* For the 64-bit guest on 32-bit host case we must emulate
302 * getdents using getdents64, because otherwise the host
303 * might hand us back more dirent records than we can fit
304 * into the guest buffer after structure format conversion.
305 * Otherwise we emulate getdents with getdents if the host has it.
306 */
307#if defined(__NR_getdents) && HOST_LONG_BITS >= TARGET_ABI_BITS
308#define EMULATE_GETDENTS_WITH_GETDENTS
309#endif
310
311#if defined(TARGET_NR_getdents) && defined(EMULATE_GETDENTS_WITH_GETDENTS)
Juan Quintelaac42f442023-07-09 18:34:30 +0100312_syscall3(int, sys_getdents, unsigned int, fd, struct linux_dirent *, dirp, unsigned int, count);
Peter Maydell3307e232013-06-12 16:20:21 +0100313#endif
Peter Maydell2b3f64c2018-04-19 13:57:40 +0100314#if (defined(TARGET_NR_getdents) && \
315 !defined(EMULATE_GETDENTS_WITH_GETDENTS)) || \
Peter Maydell3307e232013-06-12 16:20:21 +0100316 (defined(TARGET_NR_getdents64) && defined(__NR_getdents64))
Juan Quintelaac42f442023-07-09 18:34:30 +0100317_syscall3(int, sys_getdents64, unsigned int, fd, struct linux_dirent64 *, dirp, unsigned int, count);
aurel323b3f24a2009-04-15 16:12:13 +0000318#endif
Richard Hendersond35b2612010-06-04 12:14:10 -0700319#if defined(TARGET_NR__llseek) && defined(__NR_llseek)
Juan Quintelaac42f442023-07-09 18:34:30 +0100320_syscall5(int, _llseek, unsigned int, fd, unsigned long, hi, unsigned long, lo,
321 loff_t *, res, unsigned int, wh);
aurel323b3f24a2009-04-15 16:12:13 +0000322#endif
Miloš Stojanovićc1a402a2017-05-15 16:59:45 +0200323_syscall3(int, sys_rt_sigqueueinfo, pid_t, pid, int, sig, siginfo_t *, uinfo)
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +0200324_syscall4(int, sys_rt_tgsigqueueinfo, pid_t, pid, pid_t, tid, int, sig,
325 siginfo_t *, uinfo)
aurel323b3f24a2009-04-15 16:12:13 +0000326_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
aurel323b3f24a2009-04-15 16:12:13 +0000327#ifdef __NR_exit_group
328_syscall1(int,exit_group,int,error_code)
329#endif
Helge Delleraf804f32022-10-25 04:34:14 +0200330#if defined(__NR_close_range) && defined(TARGET_NR_close_range)
331#define __NR_sys_close_range __NR_close_range
332_syscall3(int,sys_close_range,int,first,int,last,int,flags)
333#ifndef CLOSE_RANGE_CLOEXEC
334#define CLOSE_RANGE_CLOEXEC (1U << 2)
335#endif
336#endif
Alistair Francis14690292020-03-18 15:47:01 -0700337#if defined(__NR_futex)
aurel323b3f24a2009-04-15 16:12:13 +0000338_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
339 const struct timespec *,timeout,int *,uaddr2,int,val3)
340#endif
Alistair Francis14690292020-03-18 15:47:01 -0700341#if defined(__NR_futex_time64)
342_syscall6(int,sys_futex_time64,int *,uaddr,int,op,int,val,
343 const struct timespec *,timeout,int *,uaddr2,int,val3)
344#endif
Helge Dellercc054c62022-09-18 21:45:46 +0200345#if defined(__NR_pidfd_open) && defined(TARGET_NR_pidfd_open)
346_syscall2(int, pidfd_open, pid_t, pid, unsigned int, flags);
347#endif
348#if defined(__NR_pidfd_send_signal) && defined(TARGET_NR_pidfd_send_signal)
349_syscall4(int, pidfd_send_signal, int, pidfd, int, sig, siginfo_t *, info,
350 unsigned int, flags);
351#endif
352#if defined(__NR_pidfd_getfd) && defined(TARGET_NR_pidfd_getfd)
353_syscall3(int, pidfd_getfd, int, pidfd, int, targetfd, unsigned int, flags);
354#endif
Mike Frysinger737de1d2011-02-07 01:05:55 -0500355#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
356_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
357 unsigned long *, user_mask_ptr);
358#define __NR_sys_sched_setaffinity __NR_sched_setaffinity
359_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
360 unsigned long *, user_mask_ptr);
Tonis Tiigi45ad7612022-01-04 20:18:18 -0800361/* sched_attr is not defined in glibc */
362struct sched_attr {
363 uint32_t size;
364 uint32_t sched_policy;
365 uint64_t sched_flags;
366 int32_t sched_nice;
367 uint32_t sched_priority;
368 uint64_t sched_runtime;
369 uint64_t sched_deadline;
370 uint64_t sched_period;
371 uint32_t sched_util_min;
372 uint32_t sched_util_max;
373};
374#define __NR_sys_sched_getattr __NR_sched_getattr
375_syscall4(int, sys_sched_getattr, pid_t, pid, struct sched_attr *, attr,
376 unsigned int, size, unsigned int, flags);
377#define __NR_sys_sched_setattr __NR_sched_setattr
378_syscall3(int, sys_sched_setattr, pid_t, pid, struct sched_attr *, attr,
379 unsigned int, flags);
Tonis Tiigi407a1192022-01-04 20:18:19 -0800380#define __NR_sys_sched_getscheduler __NR_sched_getscheduler
381_syscall1(int, sys_sched_getscheduler, pid_t, pid);
382#define __NR_sys_sched_setscheduler __NR_sched_setscheduler
383_syscall3(int, sys_sched_setscheduler, pid_t, pid, int, policy,
384 const struct sched_param *, param);
385#define __NR_sys_sched_getparam __NR_sched_getparam
386_syscall2(int, sys_sched_getparam, pid_t, pid,
387 struct sched_param *, param);
388#define __NR_sys_sched_setparam __NR_sched_setparam
389_syscall2(int, sys_sched_setparam, pid_t, pid,
390 const struct sched_param *, param);
Samuel Thibaultb827c3e2018-01-12 09:14:35 +0100391#define __NR_sys_getcpu __NR_getcpu
392_syscall3(int, sys_getcpu, unsigned *, cpu, unsigned *, node, void *, tcache);
Alexander Graf0f6b4d22011-09-27 14:39:42 +0200393_syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd,
394 void *, arg);
Peter Maydelle0eb2102014-03-17 12:15:35 +0000395_syscall2(int, capget, struct __user_cap_header_struct *, header,
396 struct __user_cap_data_struct *, data);
397_syscall2(int, capset, struct __user_cap_header_struct *, header,
398 struct __user_cap_data_struct *, data);
Paul Burtonab31cda2014-06-22 11:25:43 +0100399#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
400_syscall2(int, ioprio_get, int, which, int, who)
401#endif
402#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
403_syscall3(int, ioprio_set, int, which, int, who, int, ioprio)
404#endif
Laurent Vivierf894efd2016-02-21 10:56:23 +0100405#if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
406_syscall3(int, getrandom, void *, buf, size_t, buflen, unsigned int, flags)
407#endif
aurel323b3f24a2009-04-15 16:12:13 +0000408
Laurent Vivier2f147882016-09-25 22:20:20 +0200409#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
410_syscall5(int, kcmp, pid_t, pid1, pid_t, pid2, int, type,
411 unsigned long, idx1, unsigned long, idx2)
412#endif
413
Aleksandar Rikaloefa92182019-06-28 12:43:34 +0200414/*
415 * It is assumed that struct statx is architecture independent.
416 */
417#if defined(TARGET_NR_statx) && defined(__NR_statx)
418_syscall5(int, sys_statx, int, dirfd, const char *, pathname, int, flags,
419 unsigned int, mask, struct target_statx *, statxbuf)
420#endif
Andreas Schwab85004762019-05-13 11:02:53 +0200421#if defined(TARGET_NR_membarrier) && defined(__NR_membarrier)
422_syscall2(int, membarrier, int, cmd, int, flags)
423#endif
Aleksandar Rikaloefa92182019-06-28 12:43:34 +0200424
Philippe Mathieu-Daudé180d4ef2021-05-17 07:52:43 +0200425static const bitmask_transtbl fcntl_flags_tbl[] = {
aurel323b3f24a2009-04-15 16:12:13 +0000426 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
427 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
428 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
429 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
430 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
431 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
432 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
433 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
Richard Hendersonafc87632012-07-25 14:30:34 -0700434 { TARGET_O_SYNC, TARGET_O_DSYNC, O_SYNC, O_DSYNC, },
aurel323b3f24a2009-04-15 16:12:13 +0000435 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
436 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
437 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
438 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
aurel323b3f24a2009-04-15 16:12:13 +0000439#if defined(O_DIRECT)
440 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
441#endif
Richard Hendersonafc87632012-07-25 14:30:34 -0700442#if defined(O_NOATIME)
443 { TARGET_O_NOATIME, TARGET_O_NOATIME, O_NOATIME, O_NOATIME },
444#endif
445#if defined(O_CLOEXEC)
446 { TARGET_O_CLOEXEC, TARGET_O_CLOEXEC, O_CLOEXEC, O_CLOEXEC },
447#endif
448#if defined(O_PATH)
449 { TARGET_O_PATH, TARGET_O_PATH, O_PATH, O_PATH },
450#endif
Riku Voipio5f9cee42017-08-08 16:01:19 +0300451#if defined(O_TMPFILE)
452 { TARGET_O_TMPFILE, TARGET_O_TMPFILE, O_TMPFILE, O_TMPFILE },
453#endif
Richard Hendersonafc87632012-07-25 14:30:34 -0700454 /* Don't terminate the list prematurely on 64-bit host+guest. */
455#if TARGET_O_LARGEFILE != 0 || O_LARGEFILE != 0
456 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
457#endif
aurel323b3f24a2009-04-15 16:12:13 +0000458 { 0, 0, 0, 0 }
459};
460
Andreas Schwab0f6bb192020-07-23 12:27:13 +0200461_syscall2(int, sys_getcwd1, char *, buf, size_t, size)
aurel323b3f24a2009-04-15 16:12:13 +0000462
Filip Bozutacac46eb2020-08-25 00:30:50 +0200463#if defined(TARGET_NR_utimensat) || defined(TARGET_NR_utimensat_time64)
Peter Maydell700fa582016-07-18 11:47:55 +0100464#if defined(__NR_utimensat)
Peter Maydell1acae9f2013-07-02 14:04:12 +0100465#define __NR_sys_utimensat __NR_utimensat
ths9007f0e2007-09-25 17:50:37 +0000466_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
467 const struct timespec *,tsp,int,flags)
Peter Maydell1acae9f2013-07-02 14:04:12 +0100468#else
469static int sys_utimensat(int dirfd, const char *pathname,
470 const struct timespec times[2], int flags)
471{
472 errno = ENOSYS;
473 return -1;
474}
ths9007f0e2007-09-25 17:50:37 +0000475#endif
Peter Maydell1acae9f2013-07-02 14:04:12 +0100476#endif /* TARGET_NR_utimensat */
aurel323b3f24a2009-04-15 16:12:13 +0000477
Andreas Schwab95d03072018-01-23 11:53:31 +0100478#ifdef TARGET_NR_renameat2
479#if defined(__NR_renameat2)
480#define __NR_sys_renameat2 __NR_renameat2
481_syscall5(int, sys_renameat2, int, oldfd, const char *, old, int, newfd,
482 const char *, new, unsigned int, flags)
483#else
484static int sys_renameat2(int oldfd, const char *old,
485 int newfd, const char *new, int flags)
486{
487 if (flags == 0) {
488 return renameat(oldfd, old, newfd, new);
489 }
490 errno = ENOSYS;
491 return -1;
492}
493#endif
494#endif /* TARGET_NR_renameat2 */
495
aurel323b3f24a2009-04-15 16:12:13 +0000496#ifdef CONFIG_INOTIFY
aurel328690e422009-04-17 13:50:32 +0000497#include <sys/inotify.h>
aurel323b3f24a2009-04-15 16:12:13 +0000498#else
499/* Userspace can usually survive runtime without inotify */
500#undef TARGET_NR_inotify_init
Riku Voipioc05c7a72010-03-26 15:25:11 +0000501#undef TARGET_NR_inotify_init1
aurel323b3f24a2009-04-15 16:12:13 +0000502#undef TARGET_NR_inotify_add_watch
503#undef TARGET_NR_inotify_rm_watch
504#endif /* CONFIG_INOTIFY */
505
Peter Maydell163a05a2011-06-27 17:44:52 +0100506#if defined(TARGET_NR_prlimit64)
507#ifndef __NR_prlimit64
508# define __NR_prlimit64 -1
509#endif
510#define __NR_sys_prlimit64 __NR_prlimit64
511/* The glibc rlimit structure may not be that used by the underlying syscall */
512struct host_rlimit64 {
513 uint64_t rlim_cur;
514 uint64_t rlim_max;
515};
516_syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
517 const struct host_rlimit64 *, new_limit,
518 struct host_rlimit64 *, old_limit)
519#endif
520
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +1100521
522#if defined(TARGET_NR_timer_create)
zhaolichang6f9ff552020-09-17 15:50:25 +0800523/* Maximum of 32 active POSIX timers allowed at any one time. */
Peter Maydell9e598992022-07-25 12:00:35 +0100524#define GUEST_TIMER_MAX 32
525static timer_t g_posix_timers[GUEST_TIMER_MAX];
526static int g_posix_timer_allocated[GUEST_TIMER_MAX];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +1100527
528static inline int next_free_host_timer(void)
529{
Peter Maydell9e598992022-07-25 12:00:35 +0100530 int k;
531 for (k = 0; k < ARRAY_SIZE(g_posix_timer_allocated); k++) {
532 if (qatomic_xchg(g_posix_timer_allocated + k, 1) == 0) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +1100533 return k;
534 }
535 }
536 return -1;
537}
Peter Maydell9e598992022-07-25 12:00:35 +0100538
539static inline void free_host_timer_slot(int id)
540{
541 qatomic_store_release(g_posix_timer_allocated + id, 0);
542}
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +1100543#endif
544
Philippe Mathieu-Daudé3ffe3262021-07-08 19:05:49 +0200545static inline int host_to_target_errno(int host_errno)
ths637947f2007-06-01 12:09:19 +0000546{
Philippe Mathieu-Daudé3ffe3262021-07-08 19:05:49 +0200547 switch (host_errno) {
548#define E(X) case X: return TARGET_##X;
549#include "errnos.c.inc"
550#undef E
551 default:
552 return host_errno;
Timothy E Baldwin24661192016-05-12 18:47:25 +0100553 }
ths637947f2007-06-01 12:09:19 +0000554}
555
Philippe Mathieu-Daudé3ffe3262021-07-08 19:05:49 +0200556static inline int target_to_host_errno(int target_errno)
thsb92c47c2007-11-01 00:07:38 +0000557{
Philippe Mathieu-Daudé3ffe3262021-07-08 19:05:49 +0200558 switch (target_errno) {
559#define E(X) case TARGET_##X: return X;
560#include "errnos.c.inc"
561#undef E
562 default:
563 return target_errno;
Timothy E Baldwin24661192016-05-12 18:47:25 +0100564 }
thsb92c47c2007-11-01 00:07:38 +0000565}
566
Ilya Leoshkevich892a4f62022-06-21 16:42:05 +0200567abi_long get_errno(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000568{
569 if (ret == -1)
ths637947f2007-06-01 12:09:19 +0000570 return -host_to_target_errno(errno);
bellard31e31b82003-02-18 22:55:36 +0000571 else
572 return ret;
573}
574
Peter Maydell7dcdaea2016-06-06 19:58:18 +0100575const char *target_strerror(int err)
thsb92c47c2007-11-01 00:07:38 +0000576{
Richard Hendersonaf254a22021-11-22 19:47:33 +0100577 if (err == QEMU_ERESTARTSYS) {
Peter Maydellda2a34f2016-06-06 19:58:19 +0100578 return "To be restarted";
579 }
Richard Henderson57a0c932021-11-17 05:14:52 -0800580 if (err == QEMU_ESIGRETURN) {
Peter Maydellda2a34f2016-06-06 19:58:19 +0100581 return "Successful exit from sigreturn";
582 }
583
thsb92c47c2007-11-01 00:07:38 +0000584 return strerror(target_to_host_errno(err));
585}
586
Tonis Tiigi45ad7612022-01-04 20:18:18 -0800587static int check_zeroed_user(abi_long addr, size_t ksize, size_t usize)
588{
589 int i;
590 uint8_t b;
591 if (usize <= ksize) {
592 return 1;
593 }
594 for (i = ksize; i < usize; i++) {
595 if (get_user_u8(b, addr + i)) {
596 return -TARGET_EFAULT;
597 }
598 if (b != 0) {
599 return 0;
600 }
601 }
602 return 1;
603}
604
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100605#define safe_syscall0(type, name) \
606static type safe_##name(void) \
607{ \
608 return safe_syscall(__NR_##name); \
609}
610
611#define safe_syscall1(type, name, type1, arg1) \
612static type safe_##name(type1 arg1) \
613{ \
614 return safe_syscall(__NR_##name, arg1); \
615}
616
617#define safe_syscall2(type, name, type1, arg1, type2, arg2) \
618static type safe_##name(type1 arg1, type2 arg2) \
619{ \
620 return safe_syscall(__NR_##name, arg1, arg2); \
621}
622
623#define safe_syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
624static type safe_##name(type1 arg1, type2 arg2, type3 arg3) \
625{ \
626 return safe_syscall(__NR_##name, arg1, arg2, arg3); \
627}
628
629#define safe_syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
630 type4, arg4) \
631static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
632{ \
633 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4); \
634}
635
636#define safe_syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \
637 type4, arg4, type5, arg5) \
638static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
639 type5 arg5) \
640{ \
641 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
642}
643
644#define safe_syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \
645 type4, arg4, type5, arg5, type6, arg6) \
646static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
647 type5 arg5, type6 arg6) \
648{ \
649 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
650}
651
Timothy E Baldwin50afd022016-05-12 18:47:47 +0100652safe_syscall3(ssize_t, read, int, fd, void *, buff, size_t, count)
653safe_syscall3(ssize_t, write, int, fd, const void *, buff, size_t, count)
Timothy E Baldwinc10a0732016-05-12 18:47:48 +0100654safe_syscall4(int, openat, int, dirfd, const char *, pathname, \
655 int, flags, mode_t, mode)
Alistair Francis859e8a82020-03-12 15:13:49 -0700656#if defined(TARGET_NR_wait4) || defined(TARGET_NR_waitpid)
Timothy E Baldwin4af80a32016-05-12 18:47:49 +0100657safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \
658 struct rusage *, rusage)
Alistair Francis859e8a82020-03-12 15:13:49 -0700659#endif
Timothy E Baldwin4af80a32016-05-12 18:47:49 +0100660safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \
661 int, options, struct rusage *, rusage)
Pierrick Bouvier7a8d9f32023-07-05 14:10:23 +0200662safe_syscall3(int, execve, const char *, filename, char **, argv, char **, envp)
Drew DeVault55bbe4d2022-11-04 18:36:32 +0100663safe_syscall5(int, execveat, int, dirfd, const char *, filename,
664 char **, argv, char **, envp, int, flags)
Alistair Francis859e8a82020-03-12 15:13:49 -0700665#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \
Filip Bozutae5ce9682020-08-25 00:30:49 +0200666 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
Peter Maydell6df9d382016-05-12 18:47:51 +0100667safe_syscall6(int, pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, \
668 fd_set *, exceptfds, struct timespec *, timeout, void *, sig)
Alistair Francis859e8a82020-03-12 15:13:49 -0700669#endif
Filip Bozutae5ce9682020-08-25 00:30:49 +0200670#if defined(TARGET_NR_ppoll) || defined(TARGET_NR_ppoll_time64)
Peter Maydella6130232016-06-06 19:58:10 +0100671safe_syscall5(int, ppoll, struct pollfd *, ufds, unsigned int, nfds,
672 struct timespec *, tsp, const sigset_t *, sigmask,
673 size_t, sigsetsize)
Alistair Francis859e8a82020-03-12 15:13:49 -0700674#endif
Peter Maydell227f0212016-06-06 19:58:11 +0100675safe_syscall6(int, epoll_pwait, int, epfd, struct epoll_event *, events,
676 int, maxevents, int, timeout, const sigset_t *, sigmask,
677 size_t, sigsetsize)
Alistair Francis14690292020-03-18 15:47:01 -0700678#if defined(__NR_futex)
Peter Maydelld509eeb2016-05-12 18:47:52 +0100679safe_syscall6(int,futex,int *,uaddr,int,op,int,val, \
680 const struct timespec *,timeout,int *,uaddr2,int,val3)
Alistair Francis859e8a82020-03-12 15:13:49 -0700681#endif
Alistair Francis14690292020-03-18 15:47:01 -0700682#if defined(__NR_futex_time64)
683safe_syscall6(int,futex_time64,int *,uaddr,int,op,int,val, \
684 const struct timespec *,timeout,int *,uaddr2,int,val3)
685#endif
Peter Maydell2fe4fba2016-05-27 15:51:48 +0100686safe_syscall2(int, rt_sigsuspend, sigset_t *, newset, size_t, sigsetsize)
Peter Maydellbef653d2016-05-27 15:51:57 +0100687safe_syscall2(int, kill, pid_t, pid, int, sig)
688safe_syscall2(int, tkill, int, tid, int, sig)
689safe_syscall3(int, tgkill, int, tgid, int, pid, int, sig)
Peter Maydell918c03e2016-06-06 19:58:02 +0100690safe_syscall3(ssize_t, readv, int, fd, const struct iovec *, iov, int, iovcnt)
691safe_syscall3(ssize_t, writev, int, fd, const struct iovec *, iov, int, iovcnt)
Dejan Jovicevic0f263862016-10-11 11:52:46 +0200692safe_syscall5(ssize_t, preadv, int, fd, const struct iovec *, iov, int, iovcnt,
693 unsigned long, pos_l, unsigned long, pos_h)
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +0200694safe_syscall5(ssize_t, pwritev, int, fd, const struct iovec *, iov, int, iovcnt,
695 unsigned long, pos_l, unsigned long, pos_h)
Peter Maydell2a3c7612016-06-06 19:58:03 +0100696safe_syscall3(int, connect, int, fd, const struct sockaddr *, addr,
697 socklen_t, addrlen)
Peter Maydell66687532016-06-06 19:58:04 +0100698safe_syscall6(ssize_t, sendto, int, fd, const void *, buf, size_t, len,
699 int, flags, const struct sockaddr *, addr, socklen_t, addrlen)
700safe_syscall6(ssize_t, recvfrom, int, fd, void *, buf, size_t, len,
701 int, flags, struct sockaddr *, addr, socklen_t *, addrlen)
702safe_syscall3(ssize_t, sendmsg, int, fd, const struct msghdr *, msg, int, flags)
703safe_syscall3(ssize_t, recvmsg, int, fd, struct msghdr *, msg, int, flags)
Peter Maydell2a845982016-06-06 19:58:07 +0100704safe_syscall2(int, flock, int, fd, int, operation)
Filip Bozutaddcbde12020-08-24 21:21:16 +0200705#if defined(TARGET_NR_rt_sigtimedwait) || defined(TARGET_NR_rt_sigtimedwait_time64)
Peter Maydellb3f82332016-06-06 19:58:08 +0100706safe_syscall4(int, rt_sigtimedwait, const sigset_t *, these, siginfo_t *, uinfo,
707 const struct timespec *, uts, size_t, sigsetsize)
Alistair Francis859e8a82020-03-12 15:13:49 -0700708#endif
Peter Maydellff6dc132016-06-06 19:58:13 +0100709safe_syscall4(int, accept4, int, fd, struct sockaddr *, addr, socklen_t *, len,
710 int, flags)
Alistair Francis859e8a82020-03-12 15:13:49 -0700711#if defined(TARGET_NR_nanosleep)
Peter Maydell9e518222016-06-06 19:58:09 +0100712safe_syscall2(int, nanosleep, const struct timespec *, req,
713 struct timespec *, rem)
Alistair Francis859e8a82020-03-12 15:13:49 -0700714#endif
Filip Bozuta6ac03b22020-08-24 21:21:15 +0200715#if defined(TARGET_NR_clock_nanosleep) || \
716 defined(TARGET_NR_clock_nanosleep_time64)
Peter Maydell9e518222016-06-06 19:58:09 +0100717safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags,
718 const struct timespec *, req, struct timespec *, rem)
719#endif
Laurent Vivier524fa342019-05-29 10:48:04 +0200720#ifdef __NR_ipc
Matus Kyseld8c08b12020-06-26 14:46:11 +0200721#ifdef __s390x__
722safe_syscall5(int, ipc, int, call, long, first, long, second, long, third,
723 void *, ptr)
724#else
Peter Maydell89f9fe42016-06-06 19:58:05 +0100725safe_syscall6(int, ipc, int, call, long, first, long, second, long, third,
726 void *, ptr, long, fifth)
Laurent Vivier86e63692019-05-23 19:54:13 +0200727#endif
Matus Kyseld8c08b12020-06-26 14:46:11 +0200728#endif
Laurent Vivier86e63692019-05-23 19:54:13 +0200729#ifdef __NR_msgsnd
730safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz,
731 int, flags)
Laurent Vivier86e63692019-05-23 19:54:13 +0200732#endif
733#ifdef __NR_msgrcv
734safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz,
735 long, msgtype, int, flags)
Laurent Vivier86e63692019-05-23 19:54:13 +0200736#endif
737#ifdef __NR_semtimedop
738safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops,
739 unsigned, nsops, const struct timespec *, timeout)
Peter Maydell89f9fe42016-06-06 19:58:05 +0100740#endif
Filip Bozutad107e372020-08-24 21:37:52 +0200741#if defined(TARGET_NR_mq_timedsend) || \
742 defined(TARGET_NR_mq_timedsend_time64)
Peter Maydelld40ecd62016-06-06 19:58:06 +0100743safe_syscall5(int, mq_timedsend, int, mqdes, const char *, msg_ptr,
744 size_t, len, unsigned, prio, const struct timespec *, timeout)
Alistair Francis859e8a82020-03-12 15:13:49 -0700745#endif
Filip Bozutad107e372020-08-24 21:37:52 +0200746#if defined(TARGET_NR_mq_timedreceive) || \
747 defined(TARGET_NR_mq_timedreceive_time64)
Peter Maydelld40ecd62016-06-06 19:58:06 +0100748safe_syscall5(int, mq_timedreceive, int, mqdes, char *, msg_ptr,
749 size_t, len, unsigned *, prio, const struct timespec *, timeout)
750#endif
Andreas Schwab84946452020-11-12 12:45:16 +0100751#if defined(TARGET_NR_copy_file_range) && defined(__NR_copy_file_range)
752safe_syscall6(ssize_t, copy_file_range, int, infd, loff_t *, pinoff,
753 int, outfd, loff_t *, poutoff, size_t, length,
754 unsigned int, flags)
755#endif
756
Peter Maydell49ca6f32016-06-06 19:58:14 +0100757/* We do ioctl like this rather than via safe_syscall3 to preserve the
758 * "third argument might be integer or pointer or not present" behaviour of
759 * the libc function.
760 */
761#define safe_ioctl(...) safe_syscall(__NR_ioctl, __VA_ARGS__)
Peter Maydell435da5e2016-06-13 11:22:05 +0100762/* Similarly for fcntl. Note that callers must always:
763 * pass the F_GETLK64 etc constants rather than the unsuffixed F_GETLK
764 * use the flock64 struct rather than unsuffixed flock
765 * This will then work and use a 64-bit offset for both 32-bit and 64-bit hosts.
766 */
767#ifdef __NR_fcntl64
768#define safe_fcntl(...) safe_syscall(__NR_fcntl64, __VA_ARGS__)
769#else
770#define safe_fcntl(...) safe_syscall(__NR_fcntl, __VA_ARGS__)
771#endif
Timothy E Baldwin50afd022016-05-12 18:47:47 +0100772
Paul Burton8289d112014-06-22 11:25:33 +0100773static inline int host_to_target_sock_type(int host_type)
774{
775 int target_type;
776
777 switch (host_type & 0xf /* SOCK_TYPE_MASK */) {
778 case SOCK_DGRAM:
779 target_type = TARGET_SOCK_DGRAM;
780 break;
781 case SOCK_STREAM:
782 target_type = TARGET_SOCK_STREAM;
783 break;
784 default:
785 target_type = host_type & 0xf /* SOCK_TYPE_MASK */;
786 break;
787 }
788
789#if defined(SOCK_CLOEXEC)
790 if (host_type & SOCK_CLOEXEC) {
791 target_type |= TARGET_SOCK_CLOEXEC;
792 }
793#endif
794
795#if defined(SOCK_NONBLOCK)
796 if (host_type & SOCK_NONBLOCK) {
797 target_type |= TARGET_SOCK_NONBLOCK;
798 }
799#endif
800
801 return target_type;
802}
803
Helge Dellerdfe49862023-07-17 12:27:13 +0200804static abi_ulong target_brk, initial_target_brk;
vincent4d1de872011-06-14 21:56:33 +0000805static abi_ulong brk_page;
bellard31e31b82003-02-18 22:55:36 +0000806
blueswir1992f48a2007-10-14 16:27:31 +0000807void target_set_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000808{
Andreas Schwabd28b3c92023-07-06 13:34:19 +0200809 target_brk = TARGET_PAGE_ALIGN(new_brk);
Helge Dellerdfe49862023-07-17 12:27:13 +0200810 initial_target_brk = target_brk;
vincent4d1de872011-06-14 21:56:33 +0000811 brk_page = HOST_PAGE_ALIGN(target_brk);
bellard31e31b82003-02-18 22:55:36 +0000812}
813
ths0da46a62007-10-20 20:23:07 +0000814/* do_brk() must return target values and target errnos. */
Helge Deller86f04732022-12-25 09:23:19 +0100815abi_long do_brk(abi_ulong brk_val)
bellard31e31b82003-02-18 22:55:36 +0000816{
blueswir1992f48a2007-10-14 16:27:31 +0000817 abi_long mapped_addr;
Peter Maydellef4330c2016-07-22 13:41:52 +0100818 abi_ulong new_alloc_size;
Helge Deller86f04732022-12-25 09:23:19 +0100819 abi_ulong new_brk, new_host_brk_page;
bellard31e31b82003-02-18 22:55:36 +0000820
Richard Hendersonee1bf832021-02-12 10:48:44 -0800821 /* brk pointers are always untagged */
822
Helge Deller86f04732022-12-25 09:23:19 +0100823 /* return old brk value if brk_val unchanged or zero */
824 if (!brk_val || brk_val == target_brk) {
vincent4d1de872011-06-14 21:56:33 +0000825 return target_brk;
826 }
bellard31e31b82003-02-18 22:55:36 +0000827
Helge Dellerdfe49862023-07-17 12:27:13 +0200828 /* do not allow to shrink below initial brk value */
829 if (brk_val < initial_target_brk) {
830 brk_val = initial_target_brk;
831 }
832
Helge Deller86f04732022-12-25 09:23:19 +0100833 new_brk = TARGET_PAGE_ALIGN(brk_val);
834 new_host_brk_page = HOST_PAGE_ALIGN(brk_val);
835
836 /* brk_val and old target_brk might be on the same page */
837 if (new_brk == TARGET_PAGE_ALIGN(target_brk)) {
Helge Deller15ad9852023-07-17 08:37:17 +0200838 /* empty remaining bytes in (possibly larger) host page */
839 memset(g2h_untagged(new_brk), 0, new_host_brk_page - new_brk);
Helge Deller86f04732022-12-25 09:23:19 +0100840 target_brk = brk_val;
841 return target_brk;
842 }
843
844 /* Release heap if necesary */
845 if (new_brk < target_brk) {
846 /* empty remaining bytes in (possibly larger) host page */
Helge Deller15ad9852023-07-17 08:37:17 +0200847 memset(g2h_untagged(new_brk), 0, new_host_brk_page - new_brk);
Helge Deller86f04732022-12-25 09:23:19 +0100848
849 /* free unused host pages and set new brk_page */
850 target_munmap(new_host_brk_page, brk_page - new_host_brk_page);
851 brk_page = new_host_brk_page;
852
853 target_brk = brk_val;
854 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000855 }
856
Peter Maydell00faf082011-04-18 16:34:24 +0100857 /* We need to allocate more memory after the brk... Note that
858 * we don't use MAP_FIXED because that will map over the top of
859 * any existing mapping (like the one with the host libc or qemu
860 * itself); instead we treat "mapped but at wrong address" as
861 * a failure and unmap again.
862 */
Helge Deller86f04732022-12-25 09:23:19 +0100863 new_alloc_size = new_host_brk_page - brk_page;
864 if (new_alloc_size) {
865 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
bellard54936002003-05-13 00:25:15 +0000866 PROT_READ|PROT_WRITE,
Peter Maydell00faf082011-04-18 16:34:24 +0100867 MAP_ANON|MAP_PRIVATE, 0, 0));
Helge Deller86f04732022-12-25 09:23:19 +0100868 } else {
869 mapped_addr = brk_page;
870 }
Peter Maydell00faf082011-04-18 16:34:24 +0100871
872 if (mapped_addr == brk_page) {
Cédric VINCENT70afc342011-08-26 10:56:50 +0200873 /* Heap contents are initialized to zero, as for anonymous
874 * mapped pages. Technically the new pages are already
875 * initialized to zero since they *are* anonymous mapped
876 * pages, however we have to take care with the contents that
877 * come from the remaining part of the previous page: it may
878 * contains garbage data due to a previous heap usage (grown
879 * then shrunken). */
Helge Deller15ad9852023-07-17 08:37:17 +0200880 memset(g2h_untagged(brk_page), 0, HOST_PAGE_ALIGN(brk_page) - brk_page);
Cédric VINCENT70afc342011-08-26 10:56:50 +0200881
Helge Deller86f04732022-12-25 09:23:19 +0100882 target_brk = brk_val;
883 brk_page = new_host_brk_page;
Peter Maydell00faf082011-04-18 16:34:24 +0100884 return target_brk;
885 } else if (mapped_addr != -1) {
886 /* Mapped but at wrong address, meaning there wasn't actually
887 * enough space for this brk.
888 */
889 target_munmap(mapped_addr, new_alloc_size);
890 mapped_addr = -1;
891 }
balrog7ab240a2008-04-26 12:17:34 +0000892
Richard Henderson7dd46c02010-05-03 10:07:49 -0700893#if defined(TARGET_ALPHA)
894 /* We (partially) emulate OSF/1 on Alpha, which requires we
895 return a proper errno, not an unchanged brk value. */
Peter Maydell00faf082011-04-18 16:34:24 +0100896 return -TARGET_ENOMEM;
Richard Henderson7dd46c02010-05-03 10:07:49 -0700897#endif
Peter Maydell00faf082011-04-18 16:34:24 +0100898 /* For everything else, return the previous break. */
balrog7ab240a2008-04-26 12:17:34 +0000899 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000900}
901
Alistair Francis859e8a82020-03-12 15:13:49 -0700902#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \
Filip Bozutae5ce9682020-08-25 00:30:49 +0200903 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
ths26edcf42007-12-09 02:25:24 +0000904static inline abi_long copy_from_user_fdset(fd_set *fds,
905 abi_ulong target_fds_addr,
906 int n)
bellard31e31b82003-02-18 22:55:36 +0000907{
ths26edcf42007-12-09 02:25:24 +0000908 int i, nw, j, k;
909 abi_ulong b, *target_fds;
910
Laurent Vivierb1b2db22016-05-31 18:36:02 +0200911 nw = DIV_ROUND_UP(n, TARGET_ABI_BITS);
ths26edcf42007-12-09 02:25:24 +0000912 if (!(target_fds = lock_user(VERIFY_READ,
913 target_fds_addr,
914 sizeof(abi_ulong) * nw,
915 1)))
916 return -TARGET_EFAULT;
917
918 FD_ZERO(fds);
919 k = 0;
920 for (i = 0; i < nw; i++) {
921 /* grab the abi_ulong */
922 __get_user(b, &target_fds[i]);
923 for (j = 0; j < TARGET_ABI_BITS; j++) {
924 /* check the bit inside the abi_ulong */
925 if ((b >> j) & 1)
926 FD_SET(k, fds);
927 k++;
bellard31e31b82003-02-18 22:55:36 +0000928 }
bellard31e31b82003-02-18 22:55:36 +0000929 }
ths26edcf42007-12-09 02:25:24 +0000930
931 unlock_user(target_fds, target_fds_addr, 0);
932
933 return 0;
bellard31e31b82003-02-18 22:55:36 +0000934}
935
Mike Frysinger055e0902011-06-03 17:01:49 -0400936static inline abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr,
937 abi_ulong target_fds_addr,
938 int n)
939{
940 if (target_fds_addr) {
941 if (copy_from_user_fdset(fds, target_fds_addr, n))
942 return -TARGET_EFAULT;
943 *fds_ptr = fds;
944 } else {
945 *fds_ptr = NULL;
946 }
947 return 0;
948}
949
ths26edcf42007-12-09 02:25:24 +0000950static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
951 const fd_set *fds,
952 int n)
bellard31e31b82003-02-18 22:55:36 +0000953{
bellard31e31b82003-02-18 22:55:36 +0000954 int i, nw, j, k;
blueswir1992f48a2007-10-14 16:27:31 +0000955 abi_long v;
ths26edcf42007-12-09 02:25:24 +0000956 abi_ulong *target_fds;
bellard31e31b82003-02-18 22:55:36 +0000957
Laurent Vivierb1b2db22016-05-31 18:36:02 +0200958 nw = DIV_ROUND_UP(n, TARGET_ABI_BITS);
ths26edcf42007-12-09 02:25:24 +0000959 if (!(target_fds = lock_user(VERIFY_WRITE,
960 target_fds_addr,
961 sizeof(abi_ulong) * nw,
962 0)))
963 return -TARGET_EFAULT;
964
965 k = 0;
966 for (i = 0; i < nw; i++) {
967 v = 0;
968 for (j = 0; j < TARGET_ABI_BITS; j++) {
Andreas Schwab9ab709b2013-04-09 01:02:34 +0000969 v |= ((abi_ulong)(FD_ISSET(k, fds) != 0) << j);
ths26edcf42007-12-09 02:25:24 +0000970 k++;
bellard31e31b82003-02-18 22:55:36 +0000971 }
ths26edcf42007-12-09 02:25:24 +0000972 __put_user(v, &target_fds[i]);
bellard31e31b82003-02-18 22:55:36 +0000973 }
ths26edcf42007-12-09 02:25:24 +0000974
975 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
976
977 return 0;
bellard31e31b82003-02-18 22:55:36 +0000978}
Alistair Francis859e8a82020-03-12 15:13:49 -0700979#endif
bellard31e31b82003-02-18 22:55:36 +0000980
bellardc596ed12003-07-13 17:32:31 +0000981#if defined(__alpha__)
982#define HOST_HZ 1024
983#else
984#define HOST_HZ 100
985#endif
986
blueswir1992f48a2007-10-14 16:27:31 +0000987static inline abi_long host_to_target_clock_t(long ticks)
bellardc596ed12003-07-13 17:32:31 +0000988{
989#if HOST_HZ == TARGET_HZ
990 return ticks;
991#else
992 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
993#endif
994}
995
bellard579a97f2007-11-11 14:26:47 +0000996static inline abi_long host_to_target_rusage(abi_ulong target_addr,
997 const struct rusage *rusage)
bellardb4091862003-05-16 15:39:34 +0000998{
pbrook53a59602006-03-25 19:31:22 +0000999 struct target_rusage *target_rusage;
1000
bellard579a97f2007-11-11 14:26:47 +00001001 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
1002 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001003 target_rusage->ru_utime.tv_sec = tswapal(rusage->ru_utime.tv_sec);
1004 target_rusage->ru_utime.tv_usec = tswapal(rusage->ru_utime.tv_usec);
1005 target_rusage->ru_stime.tv_sec = tswapal(rusage->ru_stime.tv_sec);
1006 target_rusage->ru_stime.tv_usec = tswapal(rusage->ru_stime.tv_usec);
1007 target_rusage->ru_maxrss = tswapal(rusage->ru_maxrss);
1008 target_rusage->ru_ixrss = tswapal(rusage->ru_ixrss);
1009 target_rusage->ru_idrss = tswapal(rusage->ru_idrss);
1010 target_rusage->ru_isrss = tswapal(rusage->ru_isrss);
1011 target_rusage->ru_minflt = tswapal(rusage->ru_minflt);
1012 target_rusage->ru_majflt = tswapal(rusage->ru_majflt);
1013 target_rusage->ru_nswap = tswapal(rusage->ru_nswap);
1014 target_rusage->ru_inblock = tswapal(rusage->ru_inblock);
1015 target_rusage->ru_oublock = tswapal(rusage->ru_oublock);
1016 target_rusage->ru_msgsnd = tswapal(rusage->ru_msgsnd);
1017 target_rusage->ru_msgrcv = tswapal(rusage->ru_msgrcv);
1018 target_rusage->ru_nsignals = tswapal(rusage->ru_nsignals);
1019 target_rusage->ru_nvcsw = tswapal(rusage->ru_nvcsw);
1020 target_rusage->ru_nivcsw = tswapal(rusage->ru_nivcsw);
pbrook53a59602006-03-25 19:31:22 +00001021 unlock_user_struct(target_rusage, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001022
1023 return 0;
bellardb4091862003-05-16 15:39:34 +00001024}
1025
Alistair Francis859e8a82020-03-12 15:13:49 -07001026#ifdef TARGET_NR_setrlimit
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001027static inline rlim_t target_to_host_rlim(abi_ulong target_rlim)
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001028{
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001029 abi_ulong target_rlim_swap;
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001030 rlim_t result;
1031
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001032 target_rlim_swap = tswapal(target_rlim);
1033 if (target_rlim_swap == TARGET_RLIM_INFINITY)
1034 return RLIM_INFINITY;
1035
1036 result = target_rlim_swap;
1037 if (target_rlim_swap != (rlim_t)result)
1038 return RLIM_INFINITY;
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001039
1040 return result;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001041}
Alistair Francis859e8a82020-03-12 15:13:49 -07001042#endif
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001043
Alistair Francis859e8a82020-03-12 15:13:49 -07001044#if defined(TARGET_NR_getrlimit) || defined(TARGET_NR_ugetrlimit)
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001045static inline abi_ulong host_to_target_rlim(rlim_t rlim)
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001046{
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001047 abi_ulong target_rlim_swap;
1048 abi_ulong result;
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001049
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001050 if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim)
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001051 target_rlim_swap = TARGET_RLIM_INFINITY;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001052 else
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001053 target_rlim_swap = rlim;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001054 result = tswapal(target_rlim_swap);
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001055
1056 return result;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001057}
Alistair Francis859e8a82020-03-12 15:13:49 -07001058#endif
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001059
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03001060static inline int target_to_host_resource(int code)
1061{
1062 switch (code) {
1063 case TARGET_RLIMIT_AS:
1064 return RLIMIT_AS;
1065 case TARGET_RLIMIT_CORE:
1066 return RLIMIT_CORE;
1067 case TARGET_RLIMIT_CPU:
1068 return RLIMIT_CPU;
1069 case TARGET_RLIMIT_DATA:
1070 return RLIMIT_DATA;
1071 case TARGET_RLIMIT_FSIZE:
1072 return RLIMIT_FSIZE;
1073 case TARGET_RLIMIT_LOCKS:
1074 return RLIMIT_LOCKS;
1075 case TARGET_RLIMIT_MEMLOCK:
1076 return RLIMIT_MEMLOCK;
1077 case TARGET_RLIMIT_MSGQUEUE:
1078 return RLIMIT_MSGQUEUE;
1079 case TARGET_RLIMIT_NICE:
1080 return RLIMIT_NICE;
1081 case TARGET_RLIMIT_NOFILE:
1082 return RLIMIT_NOFILE;
1083 case TARGET_RLIMIT_NPROC:
1084 return RLIMIT_NPROC;
1085 case TARGET_RLIMIT_RSS:
1086 return RLIMIT_RSS;
1087 case TARGET_RLIMIT_RTPRIO:
1088 return RLIMIT_RTPRIO;
Fabrice Fontainec3a28d72022-05-23 12:52:39 +02001089#ifdef RLIMIT_RTTIME
Serge Belyshev244fd082022-01-29 22:48:23 +03001090 case TARGET_RLIMIT_RTTIME:
1091 return RLIMIT_RTTIME;
Fabrice Fontainec3a28d72022-05-23 12:52:39 +02001092#endif
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03001093 case TARGET_RLIMIT_SIGPENDING:
1094 return RLIMIT_SIGPENDING;
1095 case TARGET_RLIMIT_STACK:
1096 return RLIMIT_STACK;
1097 default:
1098 return code;
1099 }
1100}
1101
ths788f5ec2007-12-09 02:37:05 +00001102static inline abi_long copy_from_user_timeval(struct timeval *tv,
1103 abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +00001104{
pbrook53a59602006-03-25 19:31:22 +00001105 struct target_timeval *target_tv;
1106
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001107 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) {
bellard579a97f2007-11-11 14:26:47 +00001108 return -TARGET_EFAULT;
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001109 }
ths788f5ec2007-12-09 02:37:05 +00001110
1111 __get_user(tv->tv_sec, &target_tv->tv_sec);
1112 __get_user(tv->tv_usec, &target_tv->tv_usec);
1113
1114 unlock_user_struct(target_tv, target_tv_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001115
1116 return 0;
bellard31e31b82003-02-18 22:55:36 +00001117}
1118
ths788f5ec2007-12-09 02:37:05 +00001119static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
1120 const struct timeval *tv)
bellard31e31b82003-02-18 22:55:36 +00001121{
pbrook53a59602006-03-25 19:31:22 +00001122 struct target_timeval *target_tv;
1123
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001124 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
bellard579a97f2007-11-11 14:26:47 +00001125 return -TARGET_EFAULT;
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001126 }
ths788f5ec2007-12-09 02:37:05 +00001127
1128 __put_user(tv->tv_sec, &target_tv->tv_sec);
1129 __put_user(tv->tv_usec, &target_tv->tv_usec);
1130
1131 unlock_user_struct(target_tv, target_tv_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001132
1133 return 0;
bellard31e31b82003-02-18 22:55:36 +00001134}
1135
Filip Bozuta6ac03b22020-08-24 21:21:15 +02001136#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
1137static inline abi_long copy_from_user_timeval64(struct timeval *tv,
1138 abi_ulong target_tv_addr)
1139{
1140 struct target__kernel_sock_timeval *target_tv;
1141
1142 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) {
1143 return -TARGET_EFAULT;
1144 }
1145
1146 __get_user(tv->tv_sec, &target_tv->tv_sec);
1147 __get_user(tv->tv_usec, &target_tv->tv_usec);
1148
1149 unlock_user_struct(target_tv, target_tv_addr, 0);
1150
1151 return 0;
1152}
1153#endif
1154
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001155static inline abi_long copy_to_user_timeval64(abi_ulong target_tv_addr,
Filip Bozuta6ac03b22020-08-24 21:21:15 +02001156 const struct timeval *tv)
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001157{
1158 struct target__kernel_sock_timeval *target_tv;
1159
1160 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
1161 return -TARGET_EFAULT;
1162 }
1163
1164 __put_user(tv->tv_sec, &target_tv->tv_sec);
1165 __put_user(tv->tv_usec, &target_tv->tv_usec);
1166
1167 unlock_user_struct(target_tv, target_tv_addr, 1);
1168
1169 return 0;
1170}
1171
Alistair Francis859e8a82020-03-12 15:13:49 -07001172#if defined(TARGET_NR_futex) || \
1173 defined(TARGET_NR_rt_sigtimedwait) || \
1174 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6) || \
1175 defined(TARGET_NR_nanosleep) || defined(TARGET_NR_clock_settime) || \
1176 defined(TARGET_NR_utimensat) || defined(TARGET_NR_mq_timedsend) || \
Matus Kyseld8c08b12020-06-26 14:46:11 +02001177 defined(TARGET_NR_mq_timedreceive) || defined(TARGET_NR_ipc) || \
Filip Bozuta2c86c902020-07-22 17:34:20 +02001178 defined(TARGET_NR_semop) || defined(TARGET_NR_semtimedop) || \
1179 defined(TARGET_NR_timer_settime) || \
1180 (defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD))
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001181static inline abi_long target_to_host_timespec(struct timespec *host_ts,
1182 abi_ulong target_addr)
1183{
1184 struct target_timespec *target_ts;
1185
1186 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) {
1187 return -TARGET_EFAULT;
1188 }
1189 __get_user(host_ts->tv_sec, &target_ts->tv_sec);
1190 __get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1191 unlock_user_struct(target_ts, target_addr, 0);
1192 return 0;
1193}
Alistair Francis859e8a82020-03-12 15:13:49 -07001194#endif
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001195
Filip Bozuta828cb3a2020-07-22 17:34:21 +02001196#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) || \
1197 defined(TARGET_NR_timer_settime64) || \
Filip Bozutad107e372020-08-24 21:37:52 +02001198 defined(TARGET_NR_mq_timedsend_time64) || \
1199 defined(TARGET_NR_mq_timedreceive_time64) || \
Filip Bozuta6ac03b22020-08-24 21:21:15 +02001200 (defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)) || \
Filip Bozutaddcbde12020-08-24 21:21:16 +02001201 defined(TARGET_NR_clock_nanosleep_time64) || \
Filip Bozutacac46eb2020-08-25 00:30:50 +02001202 defined(TARGET_NR_rt_sigtimedwait_time64) || \
1203 defined(TARGET_NR_utimensat) || \
1204 defined(TARGET_NR_utimensat_time64) || \
Filip Bozutae5ce9682020-08-25 00:30:49 +02001205 defined(TARGET_NR_semtimedop_time64) || \
1206 defined(TARGET_NR_pselect6_time64) || defined(TARGET_NR_ppoll_time64)
Alistair Francisc6c8d102020-03-12 15:13:53 -07001207static inline abi_long target_to_host_timespec64(struct timespec *host_ts,
1208 abi_ulong target_addr)
1209{
1210 struct target__kernel_timespec *target_ts;
1211
1212 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) {
1213 return -TARGET_EFAULT;
1214 }
1215 __get_user(host_ts->tv_sec, &target_ts->tv_sec);
1216 __get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
Laurent Vivier00576752020-08-27 09:04:49 +02001217 /* in 32bit mode, this drops the padding */
1218 host_ts->tv_nsec = (long)(abi_long)host_ts->tv_nsec;
Alistair Francisc6c8d102020-03-12 15:13:53 -07001219 unlock_user_struct(target_ts, target_addr, 0);
1220 return 0;
1221}
1222#endif
1223
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001224static inline abi_long host_to_target_timespec(abi_ulong target_addr,
1225 struct timespec *host_ts)
1226{
1227 struct target_timespec *target_ts;
1228
1229 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) {
1230 return -TARGET_EFAULT;
1231 }
1232 __put_user(host_ts->tv_sec, &target_ts->tv_sec);
1233 __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1234 unlock_user_struct(target_ts, target_addr, 1);
1235 return 0;
1236}
1237
1238static inline abi_long host_to_target_timespec64(abi_ulong target_addr,
1239 struct timespec *host_ts)
1240{
1241 struct target__kernel_timespec *target_ts;
1242
1243 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) {
1244 return -TARGET_EFAULT;
1245 }
1246 __put_user(host_ts->tv_sec, &target_ts->tv_sec);
1247 __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1248 unlock_user_struct(target_ts, target_addr, 1);
1249 return 0;
1250}
1251
Richard Hendersona52f5f82020-02-12 19:22:23 -08001252#if defined(TARGET_NR_gettimeofday)
1253static inline abi_long copy_to_user_timezone(abi_ulong target_tz_addr,
1254 struct timezone *tz)
1255{
1256 struct target_timezone *target_tz;
1257
1258 if (!lock_user_struct(VERIFY_WRITE, target_tz, target_tz_addr, 1)) {
1259 return -TARGET_EFAULT;
1260 }
1261
1262 __put_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
1263 __put_user(tz->tz_dsttime, &target_tz->tz_dsttime);
1264
1265 unlock_user_struct(target_tz, target_tz_addr, 1);
1266
1267 return 0;
1268}
1269#endif
1270
Alistair Francis859e8a82020-03-12 15:13:49 -07001271#if defined(TARGET_NR_settimeofday)
Paul Burtonef4467e2014-06-22 11:25:40 +01001272static inline abi_long copy_from_user_timezone(struct timezone *tz,
1273 abi_ulong target_tz_addr)
1274{
1275 struct target_timezone *target_tz;
1276
1277 if (!lock_user_struct(VERIFY_READ, target_tz, target_tz_addr, 1)) {
1278 return -TARGET_EFAULT;
1279 }
1280
1281 __get_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
1282 __get_user(tz->tz_dsttime, &target_tz->tz_dsttime);
1283
1284 unlock_user_struct(target_tz, target_tz_addr, 0);
1285
1286 return 0;
1287}
Alistair Francis859e8a82020-03-12 15:13:49 -07001288#endif
Paul Burtonef4467e2014-06-22 11:25:40 +01001289
Nathan Froyd8ec9cf82009-07-22 09:14:36 -07001290#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
1291#include <mqueue.h>
1292
aurel3224e10032009-04-15 16:11:43 +00001293static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr,
1294 abi_ulong target_mq_attr_addr)
1295{
1296 struct target_mq_attr *target_mq_attr;
1297
1298 if (!lock_user_struct(VERIFY_READ, target_mq_attr,
1299 target_mq_attr_addr, 1))
1300 return -TARGET_EFAULT;
1301
1302 __get_user(attr->mq_flags, &target_mq_attr->mq_flags);
1303 __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
1304 __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
1305 __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
1306
1307 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0);
1308
1309 return 0;
1310}
1311
1312static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
1313 const struct mq_attr *attr)
1314{
1315 struct target_mq_attr *target_mq_attr;
1316
1317 if (!lock_user_struct(VERIFY_WRITE, target_mq_attr,
1318 target_mq_attr_addr, 0))
1319 return -TARGET_EFAULT;
1320
1321 __put_user(attr->mq_flags, &target_mq_attr->mq_flags);
1322 __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
1323 __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
1324 __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
1325
1326 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1);
1327
1328 return 0;
1329}
Nathan Froyd8ec9cf82009-07-22 09:14:36 -07001330#endif
bellard31e31b82003-02-18 22:55:36 +00001331
Mike Frysinger055e0902011-06-03 17:01:49 -04001332#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect)
ths0da46a62007-10-20 20:23:07 +00001333/* do_select() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001334static abi_long do_select(int n,
ths26edcf42007-12-09 02:25:24 +00001335 abi_ulong rfd_addr, abi_ulong wfd_addr,
1336 abi_ulong efd_addr, abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +00001337{
1338 fd_set rfds, wfds, efds;
1339 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
Peter Maydell6df9d382016-05-12 18:47:51 +01001340 struct timeval tv;
1341 struct timespec ts, *ts_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00001342 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00001343
Mike Frysinger055e0902011-06-03 17:01:49 -04001344 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
1345 if (ret) {
1346 return ret;
pbrook53a59602006-03-25 19:31:22 +00001347 }
Mike Frysinger055e0902011-06-03 17:01:49 -04001348 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
1349 if (ret) {
1350 return ret;
pbrook53a59602006-03-25 19:31:22 +00001351 }
Mike Frysinger055e0902011-06-03 17:01:49 -04001352 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
1353 if (ret) {
1354 return ret;
pbrook53a59602006-03-25 19:31:22 +00001355 }
ths3b46e622007-09-17 08:09:54 +00001356
ths26edcf42007-12-09 02:25:24 +00001357 if (target_tv_addr) {
ths788f5ec2007-12-09 02:37:05 +00001358 if (copy_from_user_timeval(&tv, target_tv_addr))
1359 return -TARGET_EFAULT;
Peter Maydell6df9d382016-05-12 18:47:51 +01001360 ts.tv_sec = tv.tv_sec;
1361 ts.tv_nsec = tv.tv_usec * 1000;
1362 ts_ptr = &ts;
bellard31e31b82003-02-18 22:55:36 +00001363 } else {
Peter Maydell6df9d382016-05-12 18:47:51 +01001364 ts_ptr = NULL;
bellard31e31b82003-02-18 22:55:36 +00001365 }
ths26edcf42007-12-09 02:25:24 +00001366
Peter Maydell6df9d382016-05-12 18:47:51 +01001367 ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
1368 ts_ptr, NULL));
pbrook53a59602006-03-25 19:31:22 +00001369
ths26edcf42007-12-09 02:25:24 +00001370 if (!is_error(ret)) {
1371 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
1372 return -TARGET_EFAULT;
1373 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
1374 return -TARGET_EFAULT;
1375 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
1376 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00001377
Peter Maydell6df9d382016-05-12 18:47:51 +01001378 if (target_tv_addr) {
1379 tv.tv_sec = ts.tv_sec;
1380 tv.tv_usec = ts.tv_nsec / 1000;
1381 if (copy_to_user_timeval(target_tv_addr, &tv)) {
1382 return -TARGET_EFAULT;
1383 }
1384 }
bellard31e31b82003-02-18 22:55:36 +00001385 }
bellard579a97f2007-11-11 14:26:47 +00001386
bellard31e31b82003-02-18 22:55:36 +00001387 return ret;
1388}
Laurent Vivier5457dc92016-07-08 01:17:27 +02001389
1390#if defined(TARGET_WANT_OLD_SYS_SELECT)
1391static abi_long do_old_select(abi_ulong arg1)
1392{
1393 struct target_sel_arg_struct *sel;
1394 abi_ulong inp, outp, exp, tvp;
1395 long nsel;
1396
1397 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1)) {
1398 return -TARGET_EFAULT;
1399 }
1400
1401 nsel = tswapal(sel->n);
1402 inp = tswapal(sel->inp);
1403 outp = tswapal(sel->outp);
1404 exp = tswapal(sel->exp);
1405 tvp = tswapal(sel->tvp);
1406
1407 unlock_user_struct(sel, arg1, 0);
1408
1409 return do_select(nsel, inp, outp, exp, tvp);
1410}
1411#endif
Mike Frysinger055e0902011-06-03 17:01:49 -04001412#endif
bellard31e31b82003-02-18 22:55:36 +00001413
Filip Bozutae5ce9682020-08-25 00:30:49 +02001414#if defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
1415static abi_long do_pselect6(abi_long arg1, abi_long arg2, abi_long arg3,
1416 abi_long arg4, abi_long arg5, abi_long arg6,
1417 bool time64)
1418{
1419 abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr;
1420 fd_set rfds, wfds, efds;
1421 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
1422 struct timespec ts, *ts_ptr;
1423 abi_long ret;
1424
1425 /*
1426 * The 6th arg is actually two args smashed together,
1427 * so we cannot use the C library.
1428 */
Filip Bozutae5ce9682020-08-25 00:30:49 +02001429 struct {
1430 sigset_t *set;
1431 size_t size;
1432 } sig, *sig_ptr;
1433
1434 abi_ulong arg_sigset, arg_sigsize, *arg7;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001435
1436 n = arg1;
1437 rfd_addr = arg2;
1438 wfd_addr = arg3;
1439 efd_addr = arg4;
1440 ts_addr = arg5;
1441
1442 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
1443 if (ret) {
1444 return ret;
1445 }
1446 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
1447 if (ret) {
1448 return ret;
1449 }
1450 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
1451 if (ret) {
1452 return ret;
1453 }
1454
1455 /*
1456 * This takes a timespec, and not a timeval, so we cannot
1457 * use the do_select() helper ...
1458 */
1459 if (ts_addr) {
1460 if (time64) {
1461 if (target_to_host_timespec64(&ts, ts_addr)) {
1462 return -TARGET_EFAULT;
1463 }
1464 } else {
1465 if (target_to_host_timespec(&ts, ts_addr)) {
1466 return -TARGET_EFAULT;
1467 }
1468 }
1469 ts_ptr = &ts;
1470 } else {
1471 ts_ptr = NULL;
1472 }
1473
1474 /* Extract the two packed args for the sigset */
Richard Hendersoncb226032022-03-15 01:43:06 -07001475 sig_ptr = NULL;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001476 if (arg6) {
Filip Bozutae5ce9682020-08-25 00:30:49 +02001477 arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1);
1478 if (!arg7) {
1479 return -TARGET_EFAULT;
1480 }
1481 arg_sigset = tswapal(arg7[0]);
1482 arg_sigsize = tswapal(arg7[1]);
1483 unlock_user(arg7, arg6, 0);
1484
1485 if (arg_sigset) {
Richard Hendersoncb226032022-03-15 01:43:06 -07001486 ret = process_sigsuspend_mask(&sig.set, arg_sigset, arg_sigsize);
1487 if (ret != 0) {
1488 return ret;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001489 }
Richard Hendersoncb226032022-03-15 01:43:06 -07001490 sig_ptr = &sig;
1491 sig.size = SIGSET_T_SIZE;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001492 }
Filip Bozutae5ce9682020-08-25 00:30:49 +02001493 }
1494
1495 ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
1496 ts_ptr, sig_ptr));
1497
Richard Hendersoncb226032022-03-15 01:43:06 -07001498 if (sig_ptr) {
1499 finish_sigsuspend_mask(ret);
1500 }
1501
Filip Bozutae5ce9682020-08-25 00:30:49 +02001502 if (!is_error(ret)) {
1503 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n)) {
1504 return -TARGET_EFAULT;
1505 }
1506 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n)) {
1507 return -TARGET_EFAULT;
1508 }
1509 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n)) {
1510 return -TARGET_EFAULT;
1511 }
1512 if (time64) {
1513 if (ts_addr && host_to_target_timespec64(ts_addr, &ts)) {
1514 return -TARGET_EFAULT;
1515 }
1516 } else {
1517 if (ts_addr && host_to_target_timespec(ts_addr, &ts)) {
1518 return -TARGET_EFAULT;
1519 }
1520 }
1521 }
1522 return ret;
1523}
1524#endif
1525
1526#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll) || \
1527 defined(TARGET_NR_ppoll_time64)
1528static abi_long do_ppoll(abi_long arg1, abi_long arg2, abi_long arg3,
1529 abi_long arg4, abi_long arg5, bool ppoll, bool time64)
1530{
1531 struct target_pollfd *target_pfd;
1532 unsigned int nfds = arg2;
1533 struct pollfd *pfd;
1534 unsigned int i;
1535 abi_long ret;
1536
1537 pfd = NULL;
1538 target_pfd = NULL;
1539 if (nfds) {
1540 if (nfds > (INT_MAX / sizeof(struct target_pollfd))) {
1541 return -TARGET_EINVAL;
1542 }
1543 target_pfd = lock_user(VERIFY_WRITE, arg1,
1544 sizeof(struct target_pollfd) * nfds, 1);
1545 if (!target_pfd) {
1546 return -TARGET_EFAULT;
1547 }
1548
1549 pfd = alloca(sizeof(struct pollfd) * nfds);
1550 for (i = 0; i < nfds; i++) {
1551 pfd[i].fd = tswap32(target_pfd[i].fd);
1552 pfd[i].events = tswap16(target_pfd[i].events);
1553 }
1554 }
1555 if (ppoll) {
1556 struct timespec _timeout_ts, *timeout_ts = &_timeout_ts;
Richard Hendersondb36aa72022-03-15 01:43:08 -07001557 sigset_t *set = NULL;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001558
1559 if (arg3) {
1560 if (time64) {
1561 if (target_to_host_timespec64(timeout_ts, arg3)) {
1562 unlock_user(target_pfd, arg1, 0);
1563 return -TARGET_EFAULT;
1564 }
1565 } else {
1566 if (target_to_host_timespec(timeout_ts, arg3)) {
1567 unlock_user(target_pfd, arg1, 0);
1568 return -TARGET_EFAULT;
1569 }
1570 }
1571 } else {
1572 timeout_ts = NULL;
1573 }
1574
1575 if (arg4) {
Richard Hendersondb36aa72022-03-15 01:43:08 -07001576 ret = process_sigsuspend_mask(&set, arg4, arg5);
1577 if (ret != 0) {
Filip Bozutae5ce9682020-08-25 00:30:49 +02001578 unlock_user(target_pfd, arg1, 0);
Richard Hendersondb36aa72022-03-15 01:43:08 -07001579 return ret;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001580 }
Filip Bozutae5ce9682020-08-25 00:30:49 +02001581 }
1582
1583 ret = get_errno(safe_ppoll(pfd, nfds, timeout_ts,
1584 set, SIGSET_T_SIZE));
1585
Richard Hendersondb36aa72022-03-15 01:43:08 -07001586 if (set) {
1587 finish_sigsuspend_mask(ret);
1588 }
Filip Bozutae5ce9682020-08-25 00:30:49 +02001589 if (!is_error(ret) && arg3) {
1590 if (time64) {
1591 if (host_to_target_timespec64(arg3, timeout_ts)) {
1592 return -TARGET_EFAULT;
1593 }
1594 } else {
1595 if (host_to_target_timespec(arg3, timeout_ts)) {
1596 return -TARGET_EFAULT;
1597 }
1598 }
1599 }
Filip Bozutae5ce9682020-08-25 00:30:49 +02001600 } else {
1601 struct timespec ts, *pts;
1602
1603 if (arg3 >= 0) {
1604 /* Convert ms to secs, ns */
1605 ts.tv_sec = arg3 / 1000;
1606 ts.tv_nsec = (arg3 % 1000) * 1000000LL;
1607 pts = &ts;
1608 } else {
1609 /* -ve poll() timeout means "infinite" */
1610 pts = NULL;
1611 }
1612 ret = get_errno(safe_ppoll(pfd, nfds, pts, NULL, 0));
1613 }
1614
1615 if (!is_error(ret)) {
1616 for (i = 0; i < nfds; i++) {
1617 target_pfd[i].revents = tswap16(pfd[i].revents);
1618 }
1619 }
1620 unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds);
1621 return ret;
1622}
1623#endif
1624
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02001625static abi_long do_pipe(CPUArchState *cpu_env, abi_ulong pipedes,
Richard Hendersonfb41a662010-05-03 10:07:52 -07001626 int flags, int is_pipe2)
Riku Voipio099d6b02009-05-05 12:10:04 +03001627{
1628 int host_pipe[2];
1629 abi_long ret;
Helge Deller499d8052022-07-19 18:20:42 +02001630 ret = pipe2(host_pipe, flags);
Riku Voipio099d6b02009-05-05 12:10:04 +03001631
1632 if (is_error(ret))
1633 return get_errno(ret);
Richard Hendersonfb41a662010-05-03 10:07:52 -07001634
1635 /* Several targets have special calling conventions for the original
1636 pipe syscall, but didn't replicate this into the pipe2 syscall. */
1637 if (!is_pipe2) {
1638#if defined(TARGET_ALPHA)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02001639 cpu_env->ir[IR_A4] = host_pipe[1];
Richard Hendersonfb41a662010-05-03 10:07:52 -07001640 return host_pipe[0];
1641#elif defined(TARGET_MIPS)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02001642 cpu_env->active_tc.gpr[3] = host_pipe[1];
Richard Hendersonfb41a662010-05-03 10:07:52 -07001643 return host_pipe[0];
1644#elif defined(TARGET_SH4)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02001645 cpu_env->gregs[1] = host_pipe[1];
Richard Hendersonfb41a662010-05-03 10:07:52 -07001646 return host_pipe[0];
Peter Maydell82f05b62013-07-06 17:39:48 +01001647#elif defined(TARGET_SPARC)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02001648 cpu_env->regwptr[1] = host_pipe[1];
Peter Maydell82f05b62013-07-06 17:39:48 +01001649 return host_pipe[0];
takasi-y@ops.dti.ne.jp597c0212010-02-18 00:35:03 +09001650#endif
Richard Hendersonfb41a662010-05-03 10:07:52 -07001651 }
1652
Riku Voipio099d6b02009-05-05 12:10:04 +03001653 if (put_user_s32(host_pipe[0], pipedes)
Helge Deller6f200f52022-07-17 18:21:53 +02001654 || put_user_s32(host_pipe[1], pipedes + sizeof(abi_int)))
Riku Voipio099d6b02009-05-05 12:10:04 +03001655 return -TARGET_EFAULT;
Riku Voipio099d6b02009-05-05 12:10:04 +03001656 return get_errno(ret);
1657}
1658
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001659static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
1660 abi_ulong target_addr,
1661 socklen_t len)
1662{
1663 struct target_ip_mreqn *target_smreqn;
1664
1665 target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
1666 if (!target_smreqn)
1667 return -TARGET_EFAULT;
1668 mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
1669 mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
1670 if (len == sizeof(struct target_ip_mreqn))
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001671 mreqn->imr_ifindex = tswapal(target_smreqn->imr_ifindex);
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001672 unlock_user(target_smreqn, target_addr, 0);
1673
1674 return 0;
1675}
1676
Laurent Vivier7b36f782015-10-28 21:40:44 +01001677static inline abi_long target_to_host_sockaddr(int fd, struct sockaddr *addr,
bellard579a97f2007-11-11 14:26:47 +00001678 abi_ulong target_addr,
1679 socklen_t len)
bellard7854b052003-03-29 17:22:23 +00001680{
aurel32607175e2009-04-15 16:11:59 +00001681 const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
1682 sa_family_t sa_family;
pbrook53a59602006-03-25 19:31:22 +00001683 struct target_sockaddr *target_saddr;
1684
Laurent Vivier7b36f782015-10-28 21:40:44 +01001685 if (fd_trans_target_to_host_addr(fd)) {
1686 return fd_trans_target_to_host_addr(fd)(addr, target_addr, len);
1687 }
1688
bellard579a97f2007-11-11 14:26:47 +00001689 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
1690 if (!target_saddr)
1691 return -TARGET_EFAULT;
aurel32607175e2009-04-15 16:11:59 +00001692
1693 sa_family = tswap16(target_saddr->sa_family);
1694
1695 /* Oops. The caller might send a incomplete sun_path; sun_path
1696 * must be terminated by \0 (see the manual page), but
1697 * unfortunately it is quite common to specify sockaddr_un
1698 * length as "strlen(x->sun_path)" while it should be
1699 * "strlen(...) + 1". We'll fix that here if needed.
1700 * Linux kernel has a similar feature.
1701 */
1702
1703 if (sa_family == AF_UNIX) {
1704 if (len < unix_maxlen && len > 0) {
1705 char *cp = (char*)target_saddr;
1706
1707 if ( cp[len-1] && !cp[len] )
1708 len++;
1709 }
1710 if (len > unix_maxlen)
1711 len = unix_maxlen;
1712 }
1713
pbrook53a59602006-03-25 19:31:22 +00001714 memcpy(addr, target_saddr, len);
aurel32607175e2009-04-15 16:11:59 +00001715 addr->sa_family = sa_family;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02001716 if (sa_family == AF_NETLINK) {
1717 struct sockaddr_nl *nladdr;
1718
1719 nladdr = (struct sockaddr_nl *)addr;
1720 nladdr->nl_pid = tswap32(nladdr->nl_pid);
1721 nladdr->nl_groups = tswap32(nladdr->nl_groups);
1722 } else if (sa_family == AF_PACKET) {
Joakim Tjernlund33a29b52014-07-12 15:47:07 +02001723 struct target_sockaddr_ll *lladdr;
1724
1725 lladdr = (struct target_sockaddr_ll *)addr;
1726 lladdr->sll_ifindex = tswap32(lladdr->sll_ifindex);
1727 lladdr->sll_hatype = tswap16(lladdr->sll_hatype);
Mathis Marion44cf6732023-03-07 16:42:55 +01001728 } else if (sa_family == AF_INET6) {
1729 struct sockaddr_in6 *in6addr;
1730
1731 in6addr = (struct sockaddr_in6 *)addr;
1732 in6addr->sin6_scope_id = tswap32(in6addr->sin6_scope_id);
Joakim Tjernlund33a29b52014-07-12 15:47:07 +02001733 }
pbrook53a59602006-03-25 19:31:22 +00001734 unlock_user(target_saddr, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001735
1736 return 0;
bellard7854b052003-03-29 17:22:23 +00001737}
1738
bellard579a97f2007-11-11 14:26:47 +00001739static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
1740 struct sockaddr *addr,
1741 socklen_t len)
bellard7854b052003-03-29 17:22:23 +00001742{
pbrook53a59602006-03-25 19:31:22 +00001743 struct target_sockaddr *target_saddr;
1744
Peter Maydella1e22192016-07-07 15:44:43 +01001745 if (len == 0) {
1746 return 0;
1747 }
Philippe Mathieu-Daudé68607102017-07-26 23:42:18 -03001748 assert(addr);
Peter Maydella1e22192016-07-07 15:44:43 +01001749
bellard579a97f2007-11-11 14:26:47 +00001750 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
1751 if (!target_saddr)
1752 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001753 memcpy(target_saddr, addr, len);
Peter Maydella1e22192016-07-07 15:44:43 +01001754 if (len >= offsetof(struct target_sockaddr, sa_family) +
1755 sizeof(target_saddr->sa_family)) {
1756 target_saddr->sa_family = tswap16(addr->sa_family);
1757 }
Philippe Mathieu-Daudéa47401b2019-10-21 13:48:52 +02001758 if (addr->sa_family == AF_NETLINK &&
1759 len >= sizeof(struct target_sockaddr_nl)) {
1760 struct target_sockaddr_nl *target_nl =
1761 (struct target_sockaddr_nl *)target_saddr;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02001762 target_nl->nl_pid = tswap32(target_nl->nl_pid);
1763 target_nl->nl_groups = tswap32(target_nl->nl_groups);
Laurent Viviera82ea932016-06-27 00:18:22 +02001764 } else if (addr->sa_family == AF_PACKET) {
1765 struct sockaddr_ll *target_ll = (struct sockaddr_ll *)target_saddr;
1766 target_ll->sll_ifindex = tswap32(target_ll->sll_ifindex);
1767 target_ll->sll_hatype = tswap16(target_ll->sll_hatype);
Helge Delleree1ac3a2017-02-18 23:31:30 +01001768 } else if (addr->sa_family == AF_INET6 &&
1769 len >= sizeof(struct target_sockaddr_in6)) {
1770 struct target_sockaddr_in6 *target_in6 =
1771 (struct target_sockaddr_in6 *)target_saddr;
1772 target_in6->sin6_scope_id = tswap16(target_in6->sin6_scope_id);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02001773 }
pbrook53a59602006-03-25 19:31:22 +00001774 unlock_user(target_saddr, target_addr, len);
bellard579a97f2007-11-11 14:26:47 +00001775
1776 return 0;
bellard7854b052003-03-29 17:22:23 +00001777}
1778
bellard5a4a8982007-11-11 17:39:18 +00001779static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
1780 struct target_msghdr *target_msgh)
bellard7854b052003-03-29 17:22:23 +00001781{
1782 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001783 abi_long msg_controllen;
1784 abi_ulong target_cmsg_addr;
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001785 struct target_cmsghdr *target_cmsg, *target_cmsg_start;
bellard7854b052003-03-29 17:22:23 +00001786 socklen_t space = 0;
bellard5a4a8982007-11-11 17:39:18 +00001787
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001788 msg_controllen = tswapal(target_msgh->msg_controllen);
bellard5a4a8982007-11-11 17:39:18 +00001789 if (msg_controllen < sizeof (struct target_cmsghdr))
1790 goto the_end;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001791 target_cmsg_addr = tswapal(target_msgh->msg_control);
bellard5a4a8982007-11-11 17:39:18 +00001792 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001793 target_cmsg_start = target_cmsg;
bellard5a4a8982007-11-11 17:39:18 +00001794 if (!target_cmsg)
1795 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001796
1797 while (cmsg && target_cmsg) {
1798 void *data = CMSG_DATA(cmsg);
1799 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1800
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001801 int len = tswapal(target_cmsg->cmsg_len)
Peter Maydellad762b92017-12-15 13:52:56 +00001802 - sizeof(struct target_cmsghdr);
bellard7854b052003-03-29 17:22:23 +00001803
1804 space += CMSG_SPACE(len);
1805 if (space > msgh->msg_controllen) {
1806 space -= CMSG_SPACE(len);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001807 /* This is a QEMU bug, since we allocated the payload
1808 * area ourselves (unlike overflow in host-to-target
1809 * conversion, which is just the guest giving us a buffer
1810 * that's too small). It can't happen for the payload types
1811 * we currently support; if it becomes an issue in future
1812 * we would need to improve our allocation strategy to
1813 * something more intelligent than "twice the size of the
1814 * target buffer we're reading from".
1815 */
Josh Kunz39be5352020-02-03 18:54:13 -08001816 qemu_log_mask(LOG_UNIMP,
1817 ("Unsupported ancillary data %d/%d: "
1818 "unhandled msg size\n"),
1819 tswap32(target_cmsg->cmsg_level),
1820 tswap32(target_cmsg->cmsg_type));
bellard7854b052003-03-29 17:22:23 +00001821 break;
1822 }
1823
Petar Jovanovicdbf4f792013-09-13 19:27:29 +02001824 if (tswap32(target_cmsg->cmsg_level) == TARGET_SOL_SOCKET) {
1825 cmsg->cmsg_level = SOL_SOCKET;
1826 } else {
1827 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
1828 }
bellard7854b052003-03-29 17:22:23 +00001829 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
1830 cmsg->cmsg_len = CMSG_LEN(len);
1831
Alex Suykov30b8b682014-12-23 07:52:58 +02001832 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +00001833 int *fd = (int *)data;
1834 int *target_fd = (int *)target_data;
1835 int i, numfds = len / sizeof(int);
1836
Peter Maydell876e23c2015-05-26 19:46:32 +01001837 for (i = 0; i < numfds; i++) {
1838 __get_user(fd[i], target_fd + i);
1839 }
Alex Suykov30b8b682014-12-23 07:52:58 +02001840 } else if (cmsg->cmsg_level == SOL_SOCKET
1841 && cmsg->cmsg_type == SCM_CREDENTIALS) {
1842 struct ucred *cred = (struct ucred *)data;
1843 struct target_ucred *target_cred =
1844 (struct target_ucred *)target_data;
1845
Peter Maydell876e23c2015-05-26 19:46:32 +01001846 __get_user(cred->pid, &target_cred->pid);
1847 __get_user(cred->uid, &target_cred->uid);
1848 __get_user(cred->gid, &target_cred->gid);
Helge Deller27404b62022-12-12 18:34:15 +01001849 } else if (cmsg->cmsg_level == SOL_ALG) {
1850 uint32_t *dst = (uint32_t *)data;
1851
1852 memcpy(dst, target_data, len);
1853 /* fix endianess of first 32-bit word */
1854 if (len >= sizeof(uint32_t)) {
1855 *dst = tswap32(*dst);
1856 }
Alex Suykov30b8b682014-12-23 07:52:58 +02001857 } else {
Josh Kunz39be5352020-02-03 18:54:13 -08001858 qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n",
1859 cmsg->cmsg_level, cmsg->cmsg_type);
Alex Suykov30b8b682014-12-23 07:52:58 +02001860 memcpy(data, target_data, len);
bellard7854b052003-03-29 17:22:23 +00001861 }
1862
1863 cmsg = CMSG_NXTHDR(msgh, cmsg);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001864 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg,
1865 target_cmsg_start);
bellard7854b052003-03-29 17:22:23 +00001866 }
bellard5a4a8982007-11-11 17:39:18 +00001867 unlock_user(target_cmsg, target_cmsg_addr, 0);
1868 the_end:
bellard7854b052003-03-29 17:22:23 +00001869 msgh->msg_controllen = space;
bellard5a4a8982007-11-11 17:39:18 +00001870 return 0;
bellard7854b052003-03-29 17:22:23 +00001871}
1872
bellard5a4a8982007-11-11 17:39:18 +00001873static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
1874 struct msghdr *msgh)
bellard7854b052003-03-29 17:22:23 +00001875{
1876 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001877 abi_long msg_controllen;
1878 abi_ulong target_cmsg_addr;
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001879 struct target_cmsghdr *target_cmsg, *target_cmsg_start;
bellard7854b052003-03-29 17:22:23 +00001880 socklen_t space = 0;
1881
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001882 msg_controllen = tswapal(target_msgh->msg_controllen);
bellard5a4a8982007-11-11 17:39:18 +00001883 if (msg_controllen < sizeof (struct target_cmsghdr))
1884 goto the_end;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001885 target_cmsg_addr = tswapal(target_msgh->msg_control);
bellard5a4a8982007-11-11 17:39:18 +00001886 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001887 target_cmsg_start = target_cmsg;
bellard5a4a8982007-11-11 17:39:18 +00001888 if (!target_cmsg)
1889 return -TARGET_EFAULT;
1890
bellard7854b052003-03-29 17:22:23 +00001891 while (cmsg && target_cmsg) {
1892 void *data = CMSG_DATA(cmsg);
1893 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1894
Peter Maydellad762b92017-12-15 13:52:56 +00001895 int len = cmsg->cmsg_len - sizeof(struct cmsghdr);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001896 int tgt_len, tgt_space;
bellard7854b052003-03-29 17:22:23 +00001897
Peter Maydellc2aeb252015-05-26 19:46:31 +01001898 /* We never copy a half-header but may copy half-data;
1899 * this is Linux's behaviour in put_cmsg(). Note that
1900 * truncation here is a guest problem (which we report
1901 * to the guest via the CTRUNC bit), unlike truncation
1902 * in target_to_host_cmsg, which is a QEMU bug.
1903 */
Peter Maydell71749702017-12-15 13:52:55 +00001904 if (msg_controllen < sizeof(struct target_cmsghdr)) {
Peter Maydellc2aeb252015-05-26 19:46:31 +01001905 target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
bellard7854b052003-03-29 17:22:23 +00001906 break;
1907 }
1908
Petar Jovanovicdbf4f792013-09-13 19:27:29 +02001909 if (cmsg->cmsg_level == SOL_SOCKET) {
1910 target_cmsg->cmsg_level = tswap32(TARGET_SOL_SOCKET);
1911 } else {
1912 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
1913 }
bellard7854b052003-03-29 17:22:23 +00001914 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
bellard7854b052003-03-29 17:22:23 +00001915
Peter Maydellc2aeb252015-05-26 19:46:31 +01001916 /* Payload types which need a different size of payload on
1917 * the target must adjust tgt_len here.
1918 */
Peter Maydell309786c2018-05-18 19:47:15 +01001919 tgt_len = len;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001920 switch (cmsg->cmsg_level) {
1921 case SOL_SOCKET:
1922 switch (cmsg->cmsg_type) {
1923 case SO_TIMESTAMP:
1924 tgt_len = sizeof(struct target_timeval);
1925 break;
1926 default:
1927 break;
1928 }
Peter Maydell309786c2018-05-18 19:47:15 +01001929 break;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001930 default:
1931 break;
1932 }
1933
Peter Maydell71749702017-12-15 13:52:55 +00001934 if (msg_controllen < TARGET_CMSG_LEN(tgt_len)) {
Peter Maydellc2aeb252015-05-26 19:46:31 +01001935 target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
Peter Maydell71749702017-12-15 13:52:55 +00001936 tgt_len = msg_controllen - sizeof(struct target_cmsghdr);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001937 }
1938
1939 /* We must now copy-and-convert len bytes of payload
1940 * into tgt_len bytes of destination space. Bear in mind
1941 * that in both source and destination we may be dealing
1942 * with a truncated value!
1943 */
Huw Davies52b65492014-04-17 14:02:47 +01001944 switch (cmsg->cmsg_level) {
1945 case SOL_SOCKET:
1946 switch (cmsg->cmsg_type) {
1947 case SCM_RIGHTS:
1948 {
1949 int *fd = (int *)data;
1950 int *target_fd = (int *)target_data;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001951 int i, numfds = tgt_len / sizeof(int);
bellard7854b052003-03-29 17:22:23 +00001952
Peter Maydell876e23c2015-05-26 19:46:32 +01001953 for (i = 0; i < numfds; i++) {
1954 __put_user(fd[i], target_fd + i);
1955 }
Huw Davies52b65492014-04-17 14:02:47 +01001956 break;
1957 }
1958 case SO_TIMESTAMP:
1959 {
1960 struct timeval *tv = (struct timeval *)data;
1961 struct target_timeval *target_tv =
1962 (struct target_timeval *)target_data;
Jing Huangaebf5bc2012-07-24 14:01:42 +00001963
Peter Maydellc2aeb252015-05-26 19:46:31 +01001964 if (len != sizeof(struct timeval) ||
1965 tgt_len != sizeof(struct target_timeval)) {
Huw Davies52b65492014-04-17 14:02:47 +01001966 goto unimplemented;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001967 }
Huw Davies52b65492014-04-17 14:02:47 +01001968
1969 /* copy struct timeval to target */
Peter Maydell876e23c2015-05-26 19:46:32 +01001970 __put_user(tv->tv_sec, &target_tv->tv_sec);
1971 __put_user(tv->tv_usec, &target_tv->tv_usec);
Huw Davies52b65492014-04-17 14:02:47 +01001972 break;
1973 }
Huw Davies4bc29752014-04-17 14:02:48 +01001974 case SCM_CREDENTIALS:
1975 {
1976 struct ucred *cred = (struct ucred *)data;
1977 struct target_ucred *target_cred =
1978 (struct target_ucred *)target_data;
1979
1980 __put_user(cred->pid, &target_cred->pid);
1981 __put_user(cred->uid, &target_cred->uid);
1982 __put_user(cred->gid, &target_cred->gid);
1983 break;
1984 }
Huw Davies52b65492014-04-17 14:02:47 +01001985 default:
1986 goto unimplemented;
1987 }
1988 break;
1989
Helge Delleree1ac3a2017-02-18 23:31:30 +01001990 case SOL_IP:
1991 switch (cmsg->cmsg_type) {
1992 case IP_TTL:
1993 {
1994 uint32_t *v = (uint32_t *)data;
1995 uint32_t *t_int = (uint32_t *)target_data;
1996
Peter Maydell71749702017-12-15 13:52:55 +00001997 if (len != sizeof(uint32_t) ||
1998 tgt_len != sizeof(uint32_t)) {
1999 goto unimplemented;
2000 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01002001 __put_user(*v, t_int);
2002 break;
2003 }
2004 case IP_RECVERR:
2005 {
2006 struct errhdr_t {
2007 struct sock_extended_err ee;
2008 struct sockaddr_in offender;
2009 };
2010 struct errhdr_t *errh = (struct errhdr_t *)data;
2011 struct errhdr_t *target_errh =
2012 (struct errhdr_t *)target_data;
2013
Peter Maydell71749702017-12-15 13:52:55 +00002014 if (len != sizeof(struct errhdr_t) ||
2015 tgt_len != sizeof(struct errhdr_t)) {
2016 goto unimplemented;
2017 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01002018 __put_user(errh->ee.ee_errno, &target_errh->ee.ee_errno);
2019 __put_user(errh->ee.ee_origin, &target_errh->ee.ee_origin);
2020 __put_user(errh->ee.ee_type, &target_errh->ee.ee_type);
2021 __put_user(errh->ee.ee_code, &target_errh->ee.ee_code);
2022 __put_user(errh->ee.ee_pad, &target_errh->ee.ee_pad);
2023 __put_user(errh->ee.ee_info, &target_errh->ee.ee_info);
2024 __put_user(errh->ee.ee_data, &target_errh->ee.ee_data);
2025 host_to_target_sockaddr((unsigned long) &target_errh->offender,
2026 (void *) &errh->offender, sizeof(errh->offender));
2027 break;
2028 }
2029 default:
2030 goto unimplemented;
2031 }
2032 break;
2033
2034 case SOL_IPV6:
2035 switch (cmsg->cmsg_type) {
2036 case IPV6_HOPLIMIT:
2037 {
2038 uint32_t *v = (uint32_t *)data;
2039 uint32_t *t_int = (uint32_t *)target_data;
2040
Peter Maydell71749702017-12-15 13:52:55 +00002041 if (len != sizeof(uint32_t) ||
2042 tgt_len != sizeof(uint32_t)) {
2043 goto unimplemented;
2044 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01002045 __put_user(*v, t_int);
2046 break;
2047 }
2048 case IPV6_RECVERR:
2049 {
2050 struct errhdr6_t {
2051 struct sock_extended_err ee;
2052 struct sockaddr_in6 offender;
2053 };
2054 struct errhdr6_t *errh = (struct errhdr6_t *)data;
2055 struct errhdr6_t *target_errh =
2056 (struct errhdr6_t *)target_data;
2057
Peter Maydell71749702017-12-15 13:52:55 +00002058 if (len != sizeof(struct errhdr6_t) ||
2059 tgt_len != sizeof(struct errhdr6_t)) {
2060 goto unimplemented;
2061 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01002062 __put_user(errh->ee.ee_errno, &target_errh->ee.ee_errno);
2063 __put_user(errh->ee.ee_origin, &target_errh->ee.ee_origin);
2064 __put_user(errh->ee.ee_type, &target_errh->ee.ee_type);
2065 __put_user(errh->ee.ee_code, &target_errh->ee.ee_code);
2066 __put_user(errh->ee.ee_pad, &target_errh->ee.ee_pad);
2067 __put_user(errh->ee.ee_info, &target_errh->ee.ee_info);
2068 __put_user(errh->ee.ee_data, &target_errh->ee.ee_data);
2069 host_to_target_sockaddr((unsigned long) &target_errh->offender,
2070 (void *) &errh->offender, sizeof(errh->offender));
2071 break;
2072 }
2073 default:
2074 goto unimplemented;
2075 }
2076 break;
2077
Huw Davies52b65492014-04-17 14:02:47 +01002078 default:
2079 unimplemented:
Josh Kunz39be5352020-02-03 18:54:13 -08002080 qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n",
2081 cmsg->cmsg_level, cmsg->cmsg_type);
Peter Maydellc2aeb252015-05-26 19:46:31 +01002082 memcpy(target_data, data, MIN(len, tgt_len));
2083 if (tgt_len > len) {
2084 memset(target_data + len, 0, tgt_len - len);
2085 }
bellard7854b052003-03-29 17:22:23 +00002086 }
2087
Peter Maydell71749702017-12-15 13:52:55 +00002088 target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(tgt_len));
2089 tgt_space = TARGET_CMSG_SPACE(tgt_len);
Peter Maydellc2aeb252015-05-26 19:46:31 +01002090 if (msg_controllen < tgt_space) {
2091 tgt_space = msg_controllen;
2092 }
2093 msg_controllen -= tgt_space;
2094 space += tgt_space;
bellard7854b052003-03-29 17:22:23 +00002095 cmsg = CMSG_NXTHDR(msgh, cmsg);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02002096 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg,
2097 target_cmsg_start);
bellard7854b052003-03-29 17:22:23 +00002098 }
bellard5a4a8982007-11-11 17:39:18 +00002099 unlock_user(target_cmsg, target_cmsg_addr, space);
2100 the_end:
Matthias Brauncbb21ee2011-08-12 19:57:41 +02002101 target_msgh->msg_controllen = tswapal(space);
bellard5a4a8982007-11-11 17:39:18 +00002102 return 0;
bellard7854b052003-03-29 17:22:23 +00002103}
2104
ths0da46a62007-10-20 20:23:07 +00002105/* do_setsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002106static abi_long do_setsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00002107 abi_ulong optval_addr, socklen_t optlen)
bellard7854b052003-03-29 17:22:23 +00002108{
blueswir1992f48a2007-10-14 16:27:31 +00002109 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +00002110 int val;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02002111 struct ip_mreqn *ip_mreq;
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02002112 struct ip_mreq_source *ip_mreq_source;
ths3b46e622007-09-17 08:09:54 +00002113
bellard8853f862004-02-22 14:57:26 +00002114 switch(level) {
2115 case SOL_TCP:
Shu-Chun Wengfe51b0a2020-12-18 11:32:11 -08002116 case SOL_UDP:
2117 /* TCP and UDP options all take an 'int' value. */
bellard7854b052003-03-29 17:22:23 +00002118 if (optlen < sizeof(uint32_t))
ths0da46a62007-10-20 20:23:07 +00002119 return -TARGET_EINVAL;
ths3b46e622007-09-17 08:09:54 +00002120
bellard2f619692007-11-16 10:46:05 +00002121 if (get_user_u32(val, optval_addr))
2122 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00002123 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
2124 break;
2125 case SOL_IP:
2126 switch(optname) {
bellard2efbe912005-07-23 15:10:20 +00002127 case IP_TOS:
2128 case IP_TTL:
bellard8853f862004-02-22 14:57:26 +00002129 case IP_HDRINCL:
bellard2efbe912005-07-23 15:10:20 +00002130 case IP_ROUTER_ALERT:
2131 case IP_RECVOPTS:
2132 case IP_RETOPTS:
2133 case IP_PKTINFO:
2134 case IP_MTU_DISCOVER:
2135 case IP_RECVERR:
Helge Delleree1ac3a2017-02-18 23:31:30 +01002136 case IP_RECVTTL:
bellard2efbe912005-07-23 15:10:20 +00002137 case IP_RECVTOS:
2138#ifdef IP_FREEBIND
2139 case IP_FREEBIND:
2140#endif
2141 case IP_MULTICAST_TTL:
2142 case IP_MULTICAST_LOOP:
bellard8853f862004-02-22 14:57:26 +00002143 val = 0;
2144 if (optlen >= sizeof(uint32_t)) {
bellard2f619692007-11-16 10:46:05 +00002145 if (get_user_u32(val, optval_addr))
2146 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00002147 } else if (optlen >= 1) {
bellard2f619692007-11-16 10:46:05 +00002148 if (get_user_u8(val, optval_addr))
2149 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00002150 }
2151 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
2152 break;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02002153 case IP_ADD_MEMBERSHIP:
2154 case IP_DROP_MEMBERSHIP:
2155 if (optlen < sizeof (struct target_ip_mreq) ||
2156 optlen > sizeof (struct target_ip_mreqn))
2157 return -TARGET_EINVAL;
2158
2159 ip_mreq = (struct ip_mreqn *) alloca(optlen);
2160 target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
2161 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen));
2162 break;
2163
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02002164 case IP_BLOCK_SOURCE:
2165 case IP_UNBLOCK_SOURCE:
2166 case IP_ADD_SOURCE_MEMBERSHIP:
2167 case IP_DROP_SOURCE_MEMBERSHIP:
2168 if (optlen != sizeof (struct target_ip_mreq_source))
2169 return -TARGET_EINVAL;
2170
2171 ip_mreq_source = lock_user(VERIFY_READ, optval_addr, optlen, 1);
Peter Maydell74e43b02021-08-09 16:54:24 +01002172 if (!ip_mreq_source) {
2173 return -TARGET_EFAULT;
2174 }
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02002175 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen));
2176 unlock_user (ip_mreq_source, optval_addr, 0);
2177 break;
2178
bellard8853f862004-02-22 14:57:26 +00002179 default:
2180 goto unimplemented;
2181 }
2182 break;
Laurent Vivier0d78b3b2013-08-30 01:46:43 +02002183 case SOL_IPV6:
2184 switch (optname) {
2185 case IPV6_MTU_DISCOVER:
2186 case IPV6_MTU:
2187 case IPV6_V6ONLY:
2188 case IPV6_RECVPKTINFO:
Helge Delleree1ac3a2017-02-18 23:31:30 +01002189 case IPV6_UNICAST_HOPS:
Laurent Vivier21749c42018-06-27 23:21:52 +02002190 case IPV6_MULTICAST_HOPS:
2191 case IPV6_MULTICAST_LOOP:
Helge Delleree1ac3a2017-02-18 23:31:30 +01002192 case IPV6_RECVERR:
2193 case IPV6_RECVHOPLIMIT:
2194 case IPV6_2292HOPLIMIT:
2195 case IPV6_CHECKSUM:
Helge Dellerb9cce6d2019-03-10 12:12:16 +01002196 case IPV6_ADDRFORM:
2197 case IPV6_2292PKTINFO:
2198 case IPV6_RECVTCLASS:
2199 case IPV6_RECVRTHDR:
2200 case IPV6_2292RTHDR:
2201 case IPV6_RECVHOPOPTS:
2202 case IPV6_2292HOPOPTS:
2203 case IPV6_RECVDSTOPTS:
2204 case IPV6_2292DSTOPTS:
2205 case IPV6_TCLASS:
Shu-Chun Weng22db1212020-12-18 11:32:12 -08002206 case IPV6_ADDR_PREFERENCES:
Helge Dellerb9cce6d2019-03-10 12:12:16 +01002207#ifdef IPV6_RECVPATHMTU
2208 case IPV6_RECVPATHMTU:
2209#endif
2210#ifdef IPV6_TRANSPARENT
2211 case IPV6_TRANSPARENT:
2212#endif
2213#ifdef IPV6_FREEBIND
2214 case IPV6_FREEBIND:
2215#endif
2216#ifdef IPV6_RECVORIGDSTADDR
2217 case IPV6_RECVORIGDSTADDR:
2218#endif
Laurent Vivier0d78b3b2013-08-30 01:46:43 +02002219 val = 0;
2220 if (optlen < sizeof(uint32_t)) {
2221 return -TARGET_EINVAL;
2222 }
2223 if (get_user_u32(val, optval_addr)) {
2224 return -TARGET_EFAULT;
2225 }
2226 ret = get_errno(setsockopt(sockfd, level, optname,
2227 &val, sizeof(val)));
2228 break;
Helge Delleree1ac3a2017-02-18 23:31:30 +01002229 case IPV6_PKTINFO:
2230 {
2231 struct in6_pktinfo pki;
2232
2233 if (optlen < sizeof(pki)) {
2234 return -TARGET_EINVAL;
2235 }
2236
2237 if (copy_from_user(&pki, optval_addr, sizeof(pki))) {
2238 return -TARGET_EFAULT;
2239 }
2240
2241 pki.ipi6_ifindex = tswap32(pki.ipi6_ifindex);
2242
2243 ret = get_errno(setsockopt(sockfd, level, optname,
2244 &pki, sizeof(pki)));
2245 break;
2246 }
Neng Chen22bf4ee2019-06-19 16:17:10 +02002247 case IPV6_ADD_MEMBERSHIP:
2248 case IPV6_DROP_MEMBERSHIP:
2249 {
2250 struct ipv6_mreq ipv6mreq;
2251
2252 if (optlen < sizeof(ipv6mreq)) {
2253 return -TARGET_EINVAL;
2254 }
2255
2256 if (copy_from_user(&ipv6mreq, optval_addr, sizeof(ipv6mreq))) {
2257 return -TARGET_EFAULT;
2258 }
2259
2260 ipv6mreq.ipv6mr_interface = tswap32(ipv6mreq.ipv6mr_interface);
2261
2262 ret = get_errno(setsockopt(sockfd, level, optname,
2263 &ipv6mreq, sizeof(ipv6mreq)));
2264 break;
2265 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01002266 default:
2267 goto unimplemented;
2268 }
2269 break;
2270 case SOL_ICMPV6:
2271 switch (optname) {
2272 case ICMPV6_FILTER:
2273 {
2274 struct icmp6_filter icmp6f;
2275
2276 if (optlen > sizeof(icmp6f)) {
2277 optlen = sizeof(icmp6f);
2278 }
2279
2280 if (copy_from_user(&icmp6f, optval_addr, optlen)) {
2281 return -TARGET_EFAULT;
2282 }
2283
2284 for (val = 0; val < 8; val++) {
2285 icmp6f.data[val] = tswap32(icmp6f.data[val]);
2286 }
2287
2288 ret = get_errno(setsockopt(sockfd, level, optname,
2289 &icmp6f, optlen));
2290 break;
2291 }
Laurent Vivier0d78b3b2013-08-30 01:46:43 +02002292 default:
2293 goto unimplemented;
2294 }
2295 break;
Jing Huang920394d2012-07-24 13:59:23 +00002296 case SOL_RAW:
2297 switch (optname) {
2298 case ICMP_FILTER:
Helge Delleree1ac3a2017-02-18 23:31:30 +01002299 case IPV6_CHECKSUM:
2300 /* those take an u32 value */
Jing Huang920394d2012-07-24 13:59:23 +00002301 if (optlen < sizeof(uint32_t)) {
2302 return -TARGET_EINVAL;
2303 }
2304
2305 if (get_user_u32(val, optval_addr)) {
2306 return -TARGET_EFAULT;
2307 }
2308 ret = get_errno(setsockopt(sockfd, level, optname,
2309 &val, sizeof(val)));
2310 break;
2311
2312 default:
2313 goto unimplemented;
2314 }
2315 break;
Yunqiang Suf31dddd2019-06-19 16:17:11 +02002316#if defined(SOL_ALG) && defined(ALG_SET_KEY) && defined(ALG_SET_AEAD_AUTHSIZE)
2317 case SOL_ALG:
2318 switch (optname) {
2319 case ALG_SET_KEY:
2320 {
2321 char *alg_key = g_malloc(optlen);
2322
2323 if (!alg_key) {
2324 return -TARGET_ENOMEM;
2325 }
2326 if (copy_from_user(alg_key, optval_addr, optlen)) {
2327 g_free(alg_key);
2328 return -TARGET_EFAULT;
2329 }
2330 ret = get_errno(setsockopt(sockfd, level, optname,
2331 alg_key, optlen));
2332 g_free(alg_key);
2333 break;
2334 }
2335 case ALG_SET_AEAD_AUTHSIZE:
2336 {
2337 ret = get_errno(setsockopt(sockfd, level, optname,
2338 NULL, optlen));
2339 break;
2340 }
2341 default:
2342 goto unimplemented;
2343 }
2344 break;
2345#endif
bellard3532fa72006-06-24 15:06:03 +00002346 case TARGET_SOL_SOCKET:
bellard8853f862004-02-22 14:57:26 +00002347 switch (optname) {
Laurent Vivier1b09aeb2013-01-01 08:24:11 +00002348 case TARGET_SO_RCVTIMEO:
2349 {
2350 struct timeval tv;
2351
2352 optname = SO_RCVTIMEO;
2353
2354set_timeout:
2355 if (optlen != sizeof(struct target_timeval)) {
2356 return -TARGET_EINVAL;
2357 }
2358
2359 if (copy_from_user_timeval(&tv, optval_addr)) {
2360 return -TARGET_EFAULT;
2361 }
2362
2363 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
2364 &tv, sizeof(tv)));
2365 return ret;
2366 }
2367 case TARGET_SO_SNDTIMEO:
2368 optname = SO_SNDTIMEO;
2369 goto set_timeout;
Laurent Vivierf57d4192013-08-30 01:46:41 +02002370 case TARGET_SO_ATTACH_FILTER:
2371 {
2372 struct target_sock_fprog *tfprog;
2373 struct target_sock_filter *tfilter;
2374 struct sock_fprog fprog;
2375 struct sock_filter *filter;
2376 int i;
2377
2378 if (optlen != sizeof(*tfprog)) {
2379 return -TARGET_EINVAL;
2380 }
2381 if (!lock_user_struct(VERIFY_READ, tfprog, optval_addr, 0)) {
2382 return -TARGET_EFAULT;
2383 }
2384 if (!lock_user_struct(VERIFY_READ, tfilter,
2385 tswapal(tfprog->filter), 0)) {
2386 unlock_user_struct(tfprog, optval_addr, 1);
2387 return -TARGET_EFAULT;
2388 }
2389
2390 fprog.len = tswap16(tfprog->len);
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05302391 filter = g_try_new(struct sock_filter, fprog.len);
Laurent Vivierf57d4192013-08-30 01:46:41 +02002392 if (filter == NULL) {
2393 unlock_user_struct(tfilter, tfprog->filter, 1);
2394 unlock_user_struct(tfprog, optval_addr, 1);
2395 return -TARGET_ENOMEM;
2396 }
2397 for (i = 0; i < fprog.len; i++) {
2398 filter[i].code = tswap16(tfilter[i].code);
2399 filter[i].jt = tfilter[i].jt;
2400 filter[i].jf = tfilter[i].jf;
2401 filter[i].k = tswap32(tfilter[i].k);
2402 }
2403 fprog.filter = filter;
2404
2405 ret = get_errno(setsockopt(sockfd, SOL_SOCKET,
2406 SO_ATTACH_FILTER, &fprog, sizeof(fprog)));
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05302407 g_free(filter);
Laurent Vivierf57d4192013-08-30 01:46:41 +02002408
2409 unlock_user_struct(tfilter, tfprog->filter, 1);
2410 unlock_user_struct(tfprog, optval_addr, 1);
2411 return ret;
2412 }
Joakim Tjernlund451aaf62014-07-12 15:47:06 +02002413 case TARGET_SO_BINDTODEVICE:
2414 {
2415 char *dev_ifname, *addr_ifname;
2416
2417 if (optlen > IFNAMSIZ - 1) {
2418 optlen = IFNAMSIZ - 1;
2419 }
2420 dev_ifname = lock_user(VERIFY_READ, optval_addr, optlen, 1);
2421 if (!dev_ifname) {
2422 return -TARGET_EFAULT;
2423 }
2424 optname = SO_BINDTODEVICE;
2425 addr_ifname = alloca(IFNAMSIZ);
2426 memcpy(addr_ifname, dev_ifname, optlen);
2427 addr_ifname[optlen] = 0;
Chen Gangfad6c582016-01-11 13:58:50 +08002428 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
2429 addr_ifname, optlen));
Joakim Tjernlund451aaf62014-07-12 15:47:06 +02002430 unlock_user (dev_ifname, optval_addr, 0);
2431 return ret;
2432 }
Carlo Marcelo Arenas Belón83eb6e52018-08-24 01:56:01 -07002433 case TARGET_SO_LINGER:
2434 {
2435 struct linger lg;
2436 struct target_linger *tlg;
2437
2438 if (optlen != sizeof(struct target_linger)) {
2439 return -TARGET_EINVAL;
2440 }
2441 if (!lock_user_struct(VERIFY_READ, tlg, optval_addr, 1)) {
2442 return -TARGET_EFAULT;
2443 }
2444 __get_user(lg.l_onoff, &tlg->l_onoff);
2445 __get_user(lg.l_linger, &tlg->l_linger);
2446 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, SO_LINGER,
2447 &lg, sizeof(lg)));
2448 unlock_user_struct(tlg, optval_addr, 0);
2449 return ret;
2450 }
bellard8853f862004-02-22 14:57:26 +00002451 /* Options with 'int' argument. */
bellard3532fa72006-06-24 15:06:03 +00002452 case TARGET_SO_DEBUG:
2453 optname = SO_DEBUG;
2454 break;
2455 case TARGET_SO_REUSEADDR:
2456 optname = SO_REUSEADDR;
2457 break;
Yunqiang Su113a9dd2018-10-30 13:55:08 +01002458#ifdef SO_REUSEPORT
2459 case TARGET_SO_REUSEPORT:
2460 optname = SO_REUSEPORT;
2461 break;
2462#endif
bellard3532fa72006-06-24 15:06:03 +00002463 case TARGET_SO_TYPE:
2464 optname = SO_TYPE;
2465 break;
2466 case TARGET_SO_ERROR:
2467 optname = SO_ERROR;
2468 break;
2469 case TARGET_SO_DONTROUTE:
2470 optname = SO_DONTROUTE;
2471 break;
2472 case TARGET_SO_BROADCAST:
2473 optname = SO_BROADCAST;
2474 break;
2475 case TARGET_SO_SNDBUF:
2476 optname = SO_SNDBUF;
2477 break;
Paul Burtond79b6cc2014-06-22 11:25:35 +01002478 case TARGET_SO_SNDBUFFORCE:
2479 optname = SO_SNDBUFFORCE;
2480 break;
bellard3532fa72006-06-24 15:06:03 +00002481 case TARGET_SO_RCVBUF:
2482 optname = SO_RCVBUF;
2483 break;
Paul Burtond79b6cc2014-06-22 11:25:35 +01002484 case TARGET_SO_RCVBUFFORCE:
2485 optname = SO_RCVBUFFORCE;
2486 break;
bellard3532fa72006-06-24 15:06:03 +00002487 case TARGET_SO_KEEPALIVE:
2488 optname = SO_KEEPALIVE;
2489 break;
2490 case TARGET_SO_OOBINLINE:
2491 optname = SO_OOBINLINE;
2492 break;
2493 case TARGET_SO_NO_CHECK:
2494 optname = SO_NO_CHECK;
2495 break;
2496 case TARGET_SO_PRIORITY:
2497 optname = SO_PRIORITY;
2498 break;
bellard5e83e8e2005-03-01 22:32:06 +00002499#ifdef SO_BSDCOMPAT
bellard3532fa72006-06-24 15:06:03 +00002500 case TARGET_SO_BSDCOMPAT:
2501 optname = SO_BSDCOMPAT;
2502 break;
bellard5e83e8e2005-03-01 22:32:06 +00002503#endif
bellard3532fa72006-06-24 15:06:03 +00002504 case TARGET_SO_PASSCRED:
2505 optname = SO_PASSCRED;
2506 break;
Paul Burton82d0fe62014-06-22 11:25:36 +01002507 case TARGET_SO_PASSSEC:
2508 optname = SO_PASSSEC;
2509 break;
bellard3532fa72006-06-24 15:06:03 +00002510 case TARGET_SO_TIMESTAMP:
2511 optname = SO_TIMESTAMP;
2512 break;
2513 case TARGET_SO_RCVLOWAT:
2514 optname = SO_RCVLOWAT;
2515 break;
bellard8853f862004-02-22 14:57:26 +00002516 default:
2517 goto unimplemented;
2518 }
bellard3532fa72006-06-24 15:06:03 +00002519 if (optlen < sizeof(uint32_t))
bellard2f619692007-11-16 10:46:05 +00002520 return -TARGET_EINVAL;
bellard3532fa72006-06-24 15:06:03 +00002521
bellard2f619692007-11-16 10:46:05 +00002522 if (get_user_u32(val, optval_addr))
2523 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00002524 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
bellard8853f862004-02-22 14:57:26 +00002525 break;
Josh Kunza2d86682019-10-29 15:43:10 -07002526#ifdef SOL_NETLINK
2527 case SOL_NETLINK:
2528 switch (optname) {
2529 case NETLINK_PKTINFO:
2530 case NETLINK_ADD_MEMBERSHIP:
2531 case NETLINK_DROP_MEMBERSHIP:
2532 case NETLINK_BROADCAST_ERROR:
2533 case NETLINK_NO_ENOBUFS:
2534#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2535 case NETLINK_LISTEN_ALL_NSID:
2536 case NETLINK_CAP_ACK:
2537#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2538#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
2539 case NETLINK_EXT_ACK:
2540#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2541#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
2542 case NETLINK_GET_STRICT_CHK:
2543#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2544 break;
2545 default:
2546 goto unimplemented;
2547 }
2548 val = 0;
2549 if (optlen < sizeof(uint32_t)) {
2550 return -TARGET_EINVAL;
2551 }
2552 if (get_user_u32(val, optval_addr)) {
2553 return -TARGET_EFAULT;
2554 }
2555 ret = get_errno(setsockopt(sockfd, SOL_NETLINK, optname, &val,
2556 sizeof(val)));
2557 break;
2558#endif /* SOL_NETLINK */
bellard7854b052003-03-29 17:22:23 +00002559 default:
bellard8853f862004-02-22 14:57:26 +00002560 unimplemented:
Josh Kunz39be5352020-02-03 18:54:13 -08002561 qemu_log_mask(LOG_UNIMP, "Unsupported setsockopt level=%d optname=%d\n",
2562 level, optname);
ths6fa13c12007-12-18 02:41:04 +00002563 ret = -TARGET_ENOPROTOOPT;
bellard7854b052003-03-29 17:22:23 +00002564 }
bellard8853f862004-02-22 14:57:26 +00002565 return ret;
bellard7854b052003-03-29 17:22:23 +00002566}
2567
ths0da46a62007-10-20 20:23:07 +00002568/* do_getsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002569static abi_long do_getsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00002570 abi_ulong optval_addr, abi_ulong optlen)
bellard7854b052003-03-29 17:22:23 +00002571{
blueswir1992f48a2007-10-14 16:27:31 +00002572 abi_long ret;
blueswir1b55266b2008-09-20 08:07:15 +00002573 int len, val;
2574 socklen_t lv;
bellard8853f862004-02-22 14:57:26 +00002575
2576 switch(level) {
bellard3532fa72006-06-24 15:06:03 +00002577 case TARGET_SOL_SOCKET:
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002578 level = SOL_SOCKET;
2579 switch (optname) {
2580 /* These don't just return a single integer */
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002581 case TARGET_SO_PEERNAME:
2582 goto unimplemented;
Andreas Schwab405dc4c2019-05-13 11:06:26 +02002583 case TARGET_SO_RCVTIMEO: {
2584 struct timeval tv;
2585 socklen_t tvlen;
2586
2587 optname = SO_RCVTIMEO;
2588
2589get_timeout:
2590 if (get_user_u32(len, optlen)) {
2591 return -TARGET_EFAULT;
2592 }
2593 if (len < 0) {
2594 return -TARGET_EINVAL;
2595 }
2596
2597 tvlen = sizeof(tv);
2598 ret = get_errno(getsockopt(sockfd, level, optname,
2599 &tv, &tvlen));
2600 if (ret < 0) {
2601 return ret;
2602 }
2603 if (len > sizeof(struct target_timeval)) {
2604 len = sizeof(struct target_timeval);
2605 }
2606 if (copy_to_user_timeval(optval_addr, &tv)) {
2607 return -TARGET_EFAULT;
2608 }
2609 if (put_user_u32(len, optlen)) {
2610 return -TARGET_EFAULT;
2611 }
2612 break;
2613 }
2614 case TARGET_SO_SNDTIMEO:
2615 optname = SO_SNDTIMEO;
2616 goto get_timeout;
Akos PASZTORY583359a2011-11-14 15:09:49 +02002617 case TARGET_SO_PEERCRED: {
2618 struct ucred cr;
2619 socklen_t crlen;
2620 struct target_ucred *tcr;
2621
2622 if (get_user_u32(len, optlen)) {
2623 return -TARGET_EFAULT;
2624 }
2625 if (len < 0) {
2626 return -TARGET_EINVAL;
2627 }
2628
2629 crlen = sizeof(cr);
2630 ret = get_errno(getsockopt(sockfd, level, SO_PEERCRED,
2631 &cr, &crlen));
2632 if (ret < 0) {
2633 return ret;
2634 }
2635 if (len > crlen) {
2636 len = crlen;
2637 }
2638 if (!lock_user_struct(VERIFY_WRITE, tcr, optval_addr, 0)) {
2639 return -TARGET_EFAULT;
2640 }
2641 __put_user(cr.pid, &tcr->pid);
2642 __put_user(cr.uid, &tcr->uid);
2643 __put_user(cr.gid, &tcr->gid);
2644 unlock_user_struct(tcr, optval_addr, 1);
2645 if (put_user_u32(len, optlen)) {
2646 return -TARGET_EFAULT;
2647 }
2648 break;
2649 }
Laurent Vivier6d485a52020-02-04 22:19:01 +01002650 case TARGET_SO_PEERSEC: {
2651 char *name;
2652
2653 if (get_user_u32(len, optlen)) {
2654 return -TARGET_EFAULT;
2655 }
2656 if (len < 0) {
2657 return -TARGET_EINVAL;
2658 }
2659 name = lock_user(VERIFY_WRITE, optval_addr, len, 0);
2660 if (!name) {
2661 return -TARGET_EFAULT;
2662 }
2663 lv = len;
2664 ret = get_errno(getsockopt(sockfd, level, SO_PEERSEC,
2665 name, &lv));
2666 if (put_user_u32(lv, optlen)) {
2667 ret = -TARGET_EFAULT;
2668 }
2669 unlock_user(name, optval_addr, lv);
2670 break;
2671 }
Carlo Marcelo Arenas Belón83eb6e52018-08-24 01:56:01 -07002672 case TARGET_SO_LINGER:
2673 {
2674 struct linger lg;
2675 socklen_t lglen;
2676 struct target_linger *tlg;
2677
2678 if (get_user_u32(len, optlen)) {
2679 return -TARGET_EFAULT;
2680 }
2681 if (len < 0) {
2682 return -TARGET_EINVAL;
2683 }
2684
2685 lglen = sizeof(lg);
2686 ret = get_errno(getsockopt(sockfd, level, SO_LINGER,
2687 &lg, &lglen));
2688 if (ret < 0) {
2689 return ret;
2690 }
2691 if (len > lglen) {
2692 len = lglen;
2693 }
2694 if (!lock_user_struct(VERIFY_WRITE, tlg, optval_addr, 0)) {
2695 return -TARGET_EFAULT;
2696 }
2697 __put_user(lg.l_onoff, &tlg->l_onoff);
2698 __put_user(lg.l_linger, &tlg->l_linger);
2699 unlock_user_struct(tlg, optval_addr, 1);
2700 if (put_user_u32(len, optlen)) {
2701 return -TARGET_EFAULT;
2702 }
2703 break;
2704 }
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002705 /* Options with 'int' argument. */
2706 case TARGET_SO_DEBUG:
2707 optname = SO_DEBUG;
2708 goto int_case;
2709 case TARGET_SO_REUSEADDR:
2710 optname = SO_REUSEADDR;
2711 goto int_case;
Yunqiang Su113a9dd2018-10-30 13:55:08 +01002712#ifdef SO_REUSEPORT
2713 case TARGET_SO_REUSEPORT:
2714 optname = SO_REUSEPORT;
2715 goto int_case;
2716#endif
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002717 case TARGET_SO_TYPE:
2718 optname = SO_TYPE;
2719 goto int_case;
2720 case TARGET_SO_ERROR:
2721 optname = SO_ERROR;
2722 goto int_case;
2723 case TARGET_SO_DONTROUTE:
2724 optname = SO_DONTROUTE;
2725 goto int_case;
2726 case TARGET_SO_BROADCAST:
2727 optname = SO_BROADCAST;
2728 goto int_case;
2729 case TARGET_SO_SNDBUF:
2730 optname = SO_SNDBUF;
2731 goto int_case;
2732 case TARGET_SO_RCVBUF:
2733 optname = SO_RCVBUF;
2734 goto int_case;
2735 case TARGET_SO_KEEPALIVE:
2736 optname = SO_KEEPALIVE;
2737 goto int_case;
2738 case TARGET_SO_OOBINLINE:
2739 optname = SO_OOBINLINE;
2740 goto int_case;
2741 case TARGET_SO_NO_CHECK:
2742 optname = SO_NO_CHECK;
2743 goto int_case;
2744 case TARGET_SO_PRIORITY:
2745 optname = SO_PRIORITY;
2746 goto int_case;
2747#ifdef SO_BSDCOMPAT
2748 case TARGET_SO_BSDCOMPAT:
2749 optname = SO_BSDCOMPAT;
2750 goto int_case;
2751#endif
2752 case TARGET_SO_PASSCRED:
2753 optname = SO_PASSCRED;
2754 goto int_case;
2755 case TARGET_SO_TIMESTAMP:
2756 optname = SO_TIMESTAMP;
2757 goto int_case;
2758 case TARGET_SO_RCVLOWAT:
2759 optname = SO_RCVLOWAT;
2760 goto int_case;
Paul Burtonaec1ca42014-06-22 11:25:34 +01002761 case TARGET_SO_ACCEPTCONN:
2762 optname = SO_ACCEPTCONN;
2763 goto int_case;
Jason A. Donenfeldec63e062021-02-04 16:39:25 +01002764 case TARGET_SO_PROTOCOL:
2765 optname = SO_PROTOCOL;
2766 goto int_case;
2767 case TARGET_SO_DOMAIN:
2768 optname = SO_DOMAIN;
2769 goto int_case;
bellard8853f862004-02-22 14:57:26 +00002770 default:
bellard2efbe912005-07-23 15:10:20 +00002771 goto int_case;
2772 }
2773 break;
2774 case SOL_TCP:
Shu-Chun Wengfe51b0a2020-12-18 11:32:11 -08002775 case SOL_UDP:
2776 /* TCP and UDP options all take an 'int' value. */
bellard2efbe912005-07-23 15:10:20 +00002777 int_case:
bellard2f619692007-11-16 10:46:05 +00002778 if (get_user_u32(len, optlen))
2779 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002780 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00002781 return -TARGET_EINVAL;
Mike Frysinger73160d92011-02-07 01:05:49 -05002782 lv = sizeof(lv);
bellard2efbe912005-07-23 15:10:20 +00002783 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2784 if (ret < 0)
2785 return ret;
Helge Dellercb88b7c2023-01-27 21:25:27 +01002786 switch (optname) {
2787 case SO_TYPE:
Paul Burton8289d112014-06-22 11:25:33 +01002788 val = host_to_target_sock_type(val);
Helge Dellercb88b7c2023-01-27 21:25:27 +01002789 break;
2790 case SO_ERROR:
2791 val = host_to_target_errno(val);
2792 break;
Paul Burton8289d112014-06-22 11:25:33 +01002793 }
bellard2efbe912005-07-23 15:10:20 +00002794 if (len > lv)
2795 len = lv;
bellard2f619692007-11-16 10:46:05 +00002796 if (len == 4) {
2797 if (put_user_u32(val, optval_addr))
2798 return -TARGET_EFAULT;
2799 } else {
2800 if (put_user_u8(val, optval_addr))
2801 return -TARGET_EFAULT;
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002802 }
bellard2f619692007-11-16 10:46:05 +00002803 if (put_user_u32(len, optlen))
2804 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002805 break;
2806 case SOL_IP:
2807 switch(optname) {
2808 case IP_TOS:
2809 case IP_TTL:
2810 case IP_HDRINCL:
2811 case IP_ROUTER_ALERT:
2812 case IP_RECVOPTS:
2813 case IP_RETOPTS:
2814 case IP_PKTINFO:
2815 case IP_MTU_DISCOVER:
2816 case IP_RECVERR:
2817 case IP_RECVTOS:
2818#ifdef IP_FREEBIND
2819 case IP_FREEBIND:
2820#endif
2821 case IP_MULTICAST_TTL:
2822 case IP_MULTICAST_LOOP:
bellard2f619692007-11-16 10:46:05 +00002823 if (get_user_u32(len, optlen))
2824 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00002825 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00002826 return -TARGET_EINVAL;
Mike Frysinger73160d92011-02-07 01:05:49 -05002827 lv = sizeof(lv);
bellard8853f862004-02-22 14:57:26 +00002828 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2829 if (ret < 0)
2830 return ret;
bellard2efbe912005-07-23 15:10:20 +00002831 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
bellard2efbe912005-07-23 15:10:20 +00002832 len = 1;
bellard2f619692007-11-16 10:46:05 +00002833 if (put_user_u32(len, optlen)
2834 || put_user_u8(val, optval_addr))
2835 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002836 } else {
bellard2efbe912005-07-23 15:10:20 +00002837 if (len > sizeof(int))
2838 len = sizeof(int);
bellard2f619692007-11-16 10:46:05 +00002839 if (put_user_u32(len, optlen)
2840 || put_user_u32(val, optval_addr))
2841 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002842 }
bellard8853f862004-02-22 14:57:26 +00002843 break;
bellard2efbe912005-07-23 15:10:20 +00002844 default:
thsc02f4992007-12-18 02:39:59 +00002845 ret = -TARGET_ENOPROTOOPT;
2846 break;
bellard8853f862004-02-22 14:57:26 +00002847 }
2848 break;
Tom Deseynbd8ed482018-12-13 14:06:11 +01002849 case SOL_IPV6:
2850 switch (optname) {
2851 case IPV6_MTU_DISCOVER:
2852 case IPV6_MTU:
2853 case IPV6_V6ONLY:
2854 case IPV6_RECVPKTINFO:
2855 case IPV6_UNICAST_HOPS:
2856 case IPV6_MULTICAST_HOPS:
2857 case IPV6_MULTICAST_LOOP:
2858 case IPV6_RECVERR:
2859 case IPV6_RECVHOPLIMIT:
2860 case IPV6_2292HOPLIMIT:
2861 case IPV6_CHECKSUM:
Helge Dellerb9cce6d2019-03-10 12:12:16 +01002862 case IPV6_ADDRFORM:
2863 case IPV6_2292PKTINFO:
2864 case IPV6_RECVTCLASS:
2865 case IPV6_RECVRTHDR:
2866 case IPV6_2292RTHDR:
2867 case IPV6_RECVHOPOPTS:
2868 case IPV6_2292HOPOPTS:
2869 case IPV6_RECVDSTOPTS:
2870 case IPV6_2292DSTOPTS:
2871 case IPV6_TCLASS:
Shu-Chun Weng22db1212020-12-18 11:32:12 -08002872 case IPV6_ADDR_PREFERENCES:
Helge Dellerb9cce6d2019-03-10 12:12:16 +01002873#ifdef IPV6_RECVPATHMTU
2874 case IPV6_RECVPATHMTU:
2875#endif
2876#ifdef IPV6_TRANSPARENT
2877 case IPV6_TRANSPARENT:
2878#endif
2879#ifdef IPV6_FREEBIND
2880 case IPV6_FREEBIND:
2881#endif
2882#ifdef IPV6_RECVORIGDSTADDR
2883 case IPV6_RECVORIGDSTADDR:
2884#endif
Tom Deseynbd8ed482018-12-13 14:06:11 +01002885 if (get_user_u32(len, optlen))
2886 return -TARGET_EFAULT;
2887 if (len < 0)
2888 return -TARGET_EINVAL;
2889 lv = sizeof(lv);
2890 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2891 if (ret < 0)
2892 return ret;
2893 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
2894 len = 1;
2895 if (put_user_u32(len, optlen)
2896 || put_user_u8(val, optval_addr))
2897 return -TARGET_EFAULT;
2898 } else {
2899 if (len > sizeof(int))
2900 len = sizeof(int);
2901 if (put_user_u32(len, optlen)
2902 || put_user_u32(val, optval_addr))
2903 return -TARGET_EFAULT;
2904 }
2905 break;
2906 default:
2907 ret = -TARGET_ENOPROTOOPT;
2908 break;
2909 }
2910 break;
Josh Kunza2d86682019-10-29 15:43:10 -07002911#ifdef SOL_NETLINK
2912 case SOL_NETLINK:
2913 switch (optname) {
2914 case NETLINK_PKTINFO:
2915 case NETLINK_BROADCAST_ERROR:
2916 case NETLINK_NO_ENOBUFS:
2917#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2918 case NETLINK_LISTEN_ALL_NSID:
2919 case NETLINK_CAP_ACK:
2920#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2921#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
2922 case NETLINK_EXT_ACK:
2923#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2924#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
2925 case NETLINK_GET_STRICT_CHK:
2926#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2927 if (get_user_u32(len, optlen)) {
2928 return -TARGET_EFAULT;
2929 }
2930 if (len != sizeof(val)) {
2931 return -TARGET_EINVAL;
2932 }
2933 lv = len;
2934 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2935 if (ret < 0) {
2936 return ret;
2937 }
2938 if (put_user_u32(lv, optlen)
2939 || put_user_u32(val, optval_addr)) {
2940 return -TARGET_EFAULT;
2941 }
2942 break;
2943#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2944 case NETLINK_LIST_MEMBERSHIPS:
2945 {
2946 uint32_t *results;
2947 int i;
2948 if (get_user_u32(len, optlen)) {
2949 return -TARGET_EFAULT;
2950 }
2951 if (len < 0) {
2952 return -TARGET_EINVAL;
2953 }
2954 results = lock_user(VERIFY_WRITE, optval_addr, len, 1);
Frédéric Fortier13e340c2021-03-28 14:01:35 -04002955 if (!results && len > 0) {
Josh Kunza2d86682019-10-29 15:43:10 -07002956 return -TARGET_EFAULT;
2957 }
2958 lv = len;
2959 ret = get_errno(getsockopt(sockfd, level, optname, results, &lv));
2960 if (ret < 0) {
2961 unlock_user(results, optval_addr, 0);
2962 return ret;
2963 }
2964 /* swap host endianess to target endianess. */
2965 for (i = 0; i < (len / sizeof(uint32_t)); i++) {
2966 results[i] = tswap32(results[i]);
2967 }
2968 if (put_user_u32(lv, optlen)) {
2969 return -TARGET_EFAULT;
2970 }
2971 unlock_user(results, optval_addr, 0);
2972 break;
2973 }
2974#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2975 default:
2976 goto unimplemented;
2977 }
Laurent Vivierc0cb8802019-11-12 11:50:55 +01002978 break;
Josh Kunza2d86682019-10-29 15:43:10 -07002979#endif /* SOL_NETLINK */
bellard8853f862004-02-22 14:57:26 +00002980 default:
2981 unimplemented:
Josh Kunz39be5352020-02-03 18:54:13 -08002982 qemu_log_mask(LOG_UNIMP,
2983 "getsockopt level=%d optname=%d not yet supported\n",
2984 level, optname);
thsc02f4992007-12-18 02:39:59 +00002985 ret = -TARGET_EOPNOTSUPP;
bellard8853f862004-02-22 14:57:26 +00002986 break;
2987 }
2988 return ret;
bellard7854b052003-03-29 17:22:23 +00002989}
2990
Max Filippov9ac22512018-04-04 17:30:41 -07002991/* Convert target low/high pair representing file offset into the host
2992 * low/high pair. This function doesn't handle offsets bigger than 64 bits
2993 * as the kernel doesn't handle them either.
2994 */
2995static void target_to_host_low_high(abi_ulong tlow,
2996 abi_ulong thigh,
2997 unsigned long *hlow,
2998 unsigned long *hhigh)
2999{
3000 uint64_t off = tlow |
3001 ((unsigned long long)thigh << TARGET_LONG_BITS / 2) <<
3002 TARGET_LONG_BITS / 2;
3003
3004 *hlow = off;
3005 *hhigh = (off >> HOST_LONG_BITS / 2) >> HOST_LONG_BITS / 2;
3006}
3007
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003008static struct iovec *lock_iovec(int type, abi_ulong target_addr,
Peter Maydelldab32b32016-07-15 14:57:26 +01003009 abi_ulong count, int copy)
pbrook53a59602006-03-25 19:31:22 +00003010{
3011 struct target_iovec *target_vec;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003012 struct iovec *vec;
3013 abi_ulong total_len, max_len;
balrogd732dcb2008-10-28 10:21:03 +00003014 int i;
Peter Maydell501bb4b2014-02-17 18:55:33 +00003015 int err = 0;
Tom Musta29560a62014-08-12 13:53:43 -05003016 bool bad_address = false;
pbrook53a59602006-03-25 19:31:22 +00003017
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003018 if (count == 0) {
3019 errno = 0;
3020 return NULL;
pbrook53a59602006-03-25 19:31:22 +00003021 }
Peter Maydelldab32b32016-07-15 14:57:26 +01003022 if (count > IOV_MAX) {
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003023 errno = EINVAL;
3024 return NULL;
3025 }
3026
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303027 vec = g_try_new0(struct iovec, count);
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003028 if (vec == NULL) {
3029 errno = ENOMEM;
3030 return NULL;
3031 }
3032
3033 target_vec = lock_user(VERIFY_READ, target_addr,
3034 count * sizeof(struct target_iovec), 1);
3035 if (target_vec == NULL) {
Peter Maydell501bb4b2014-02-17 18:55:33 +00003036 err = EFAULT;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003037 goto fail2;
3038 }
3039
3040 /* ??? If host page size > target page size, this will result in a
3041 value larger than what we can actually support. */
3042 max_len = 0x7fffffff & TARGET_PAGE_MASK;
3043 total_len = 0;
3044
3045 for (i = 0; i < count; i++) {
3046 abi_ulong base = tswapal(target_vec[i].iov_base);
3047 abi_long len = tswapal(target_vec[i].iov_len);
3048
3049 if (len < 0) {
Peter Maydell501bb4b2014-02-17 18:55:33 +00003050 err = EINVAL;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003051 goto fail;
3052 } else if (len == 0) {
3053 /* Zero length pointer is ignored. */
3054 vec[i].iov_base = 0;
3055 } else {
3056 vec[i].iov_base = lock_user(type, base, len, copy);
Tom Musta29560a62014-08-12 13:53:43 -05003057 /* If the first buffer pointer is bad, this is a fault. But
3058 * subsequent bad buffers will result in a partial write; this
3059 * is realized by filling the vector with null pointers and
3060 * zero lengths. */
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003061 if (!vec[i].iov_base) {
Tom Musta29560a62014-08-12 13:53:43 -05003062 if (i == 0) {
3063 err = EFAULT;
3064 goto fail;
3065 } else {
3066 bad_address = true;
3067 }
3068 }
3069 if (bad_address) {
3070 len = 0;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003071 }
3072 if (len > max_len - total_len) {
3073 len = max_len - total_len;
3074 }
3075 }
3076 vec[i].iov_len = len;
3077 total_len += len;
3078 }
3079
3080 unlock_user(target_vec, target_addr, 0);
3081 return vec;
3082
3083 fail:
Chen Gang S7eff5182015-01-23 18:01:09 +08003084 while (--i >= 0) {
3085 if (tswapal(target_vec[i].iov_len) > 0) {
3086 unlock_user(vec[i].iov_base, tswapal(target_vec[i].iov_base), 0);
3087 }
3088 }
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003089 unlock_user(target_vec, target_addr, 0);
Peter Maydell501bb4b2014-02-17 18:55:33 +00003090 fail2:
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303091 g_free(vec);
Peter Maydell501bb4b2014-02-17 18:55:33 +00003092 errno = err;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003093 return NULL;
pbrook53a59602006-03-25 19:31:22 +00003094}
3095
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003096static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
Peter Maydelldab32b32016-07-15 14:57:26 +01003097 abi_ulong count, int copy)
pbrook53a59602006-03-25 19:31:22 +00003098{
3099 struct target_iovec *target_vec;
pbrook53a59602006-03-25 19:31:22 +00003100 int i;
3101
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003102 target_vec = lock_user(VERIFY_READ, target_addr,
3103 count * sizeof(struct target_iovec), 1);
3104 if (target_vec) {
3105 for (i = 0; i < count; i++) {
3106 abi_ulong base = tswapal(target_vec[i].iov_base);
Chen Gang S71ec7ce2015-01-23 18:07:50 +08003107 abi_long len = tswapal(target_vec[i].iov_len);
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003108 if (len < 0) {
3109 break;
3110 }
balrogd732dcb2008-10-28 10:21:03 +00003111 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
3112 }
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003113 unlock_user(target_vec, target_addr, 0);
pbrook53a59602006-03-25 19:31:22 +00003114 }
bellard579a97f2007-11-11 14:26:47 +00003115
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303116 g_free(vec);
pbrook53a59602006-03-25 19:31:22 +00003117}
3118
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003119static inline int target_to_host_sock_type(int *type)
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003120{
3121 int host_type = 0;
3122 int target_type = *type;
3123
3124 switch (target_type & TARGET_SOCK_TYPE_MASK) {
3125 case TARGET_SOCK_DGRAM:
3126 host_type = SOCK_DGRAM;
3127 break;
3128 case TARGET_SOCK_STREAM:
3129 host_type = SOCK_STREAM;
3130 break;
3131 default:
3132 host_type = target_type & TARGET_SOCK_TYPE_MASK;
3133 break;
3134 }
3135 if (target_type & TARGET_SOCK_CLOEXEC) {
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003136#if defined(SOCK_CLOEXEC)
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003137 host_type |= SOCK_CLOEXEC;
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003138#else
3139 return -TARGET_EINVAL;
3140#endif
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003141 }
3142 if (target_type & TARGET_SOCK_NONBLOCK) {
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003143#if defined(SOCK_NONBLOCK)
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003144 host_type |= SOCK_NONBLOCK;
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003145#elif !defined(O_NONBLOCK)
3146 return -TARGET_EINVAL;
3147#endif
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003148 }
3149 *type = host_type;
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003150 return 0;
3151}
3152
3153/* Try to emulate socket type flags after socket creation. */
3154static int sock_flags_fixup(int fd, int target_type)
3155{
3156#if !defined(SOCK_NONBLOCK) && defined(O_NONBLOCK)
3157 if (target_type & TARGET_SOCK_NONBLOCK) {
3158 int flags = fcntl(fd, F_GETFL);
3159 if (fcntl(fd, F_SETFL, O_NONBLOCK | flags) == -1) {
3160 close(fd);
3161 return -TARGET_EINVAL;
3162 }
3163 }
3164#endif
3165 return fd;
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003166}
3167
ths0da46a62007-10-20 20:23:07 +00003168/* do_socket() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003169static abi_long do_socket(int domain, int type, int protocol)
bellard3532fa72006-06-24 15:06:03 +00003170{
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003171 int target_type = type;
3172 int ret;
3173
3174 ret = target_to_host_sock_type(&type);
3175 if (ret) {
3176 return ret;
3177 }
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003178
Laurent Vivier575b22b2016-06-02 22:14:15 +02003179 if (domain == PF_NETLINK && !(
3180#ifdef CONFIG_RTNETLINK
3181 protocol == NETLINK_ROUTE ||
3182#endif
3183 protocol == NETLINK_KOBJECT_UEVENT ||
3184 protocol == NETLINK_AUDIT)) {
Josh Kunz71e24432020-07-06 17:10:36 -07003185 return -TARGET_EPROTONOSUPPORT;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003186 }
Laurent Vivierff626f22015-10-28 21:40:42 +01003187
3188 if (domain == AF_PACKET ||
3189 (domain == AF_INET && type == SOCK_PACKET)) {
3190 protocol = tswap16(protocol);
3191 }
3192
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003193 ret = get_errno(socket(domain, type, protocol));
3194 if (ret >= 0) {
3195 ret = sock_flags_fixup(ret, target_type);
Laurent Vivier0cf22722015-10-28 21:40:45 +01003196 if (type == SOCK_PACKET) {
3197 /* Manage an obsolete case :
3198 * if socket type is SOCK_PACKET, bind by name
3199 */
3200 fd_trans_register(ret, &target_packet_trans);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003201 } else if (domain == PF_NETLINK) {
3202 switch (protocol) {
Laurent Vivier575b22b2016-06-02 22:14:15 +02003203#ifdef CONFIG_RTNETLINK
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003204 case NETLINK_ROUTE:
3205 fd_trans_register(ret, &target_netlink_route_trans);
3206 break;
Laurent Vivier575b22b2016-06-02 22:14:15 +02003207#endif
Laurent Vivierb2656202016-05-22 18:56:20 +02003208 case NETLINK_KOBJECT_UEVENT:
3209 /* nothing to do: messages are strings */
3210 break;
Laurent Vivier5ce9bb52016-05-22 18:56:21 +02003211 case NETLINK_AUDIT:
3212 fd_trans_register(ret, &target_netlink_audit_trans);
3213 break;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003214 default:
3215 g_assert_not_reached();
3216 }
Laurent Vivier0cf22722015-10-28 21:40:45 +01003217 }
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003218 }
3219 return ret;
bellard3532fa72006-06-24 15:06:03 +00003220}
3221
ths0da46a62007-10-20 20:23:07 +00003222/* do_bind() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003223static abi_long do_bind(int sockfd, abi_ulong target_addr,
3224 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00003225{
aurel328f7aeaf2009-01-30 19:47:57 +00003226 void *addr;
Arnaud Patard917507b2009-06-19 10:44:45 +03003227 abi_long ret;
aurel328f7aeaf2009-01-30 19:47:57 +00003228
Blue Swirl38724252010-09-18 05:53:14 +00003229 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003230 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003231 }
aurel328f7aeaf2009-01-30 19:47:57 +00003232
aurel32607175e2009-04-15 16:11:59 +00003233 addr = alloca(addrlen+1);
ths3b46e622007-09-17 08:09:54 +00003234
Laurent Vivier7b36f782015-10-28 21:40:44 +01003235 ret = target_to_host_sockaddr(sockfd, addr, target_addr, addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03003236 if (ret)
3237 return ret;
3238
bellard3532fa72006-06-24 15:06:03 +00003239 return get_errno(bind(sockfd, addr, addrlen));
3240}
3241
ths0da46a62007-10-20 20:23:07 +00003242/* do_connect() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003243static abi_long do_connect(int sockfd, abi_ulong target_addr,
3244 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00003245{
aurel328f7aeaf2009-01-30 19:47:57 +00003246 void *addr;
Arnaud Patard917507b2009-06-19 10:44:45 +03003247 abi_long ret;
aurel328f7aeaf2009-01-30 19:47:57 +00003248
Blue Swirl38724252010-09-18 05:53:14 +00003249 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003250 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003251 }
aurel328f7aeaf2009-01-30 19:47:57 +00003252
Joakim Tjernlund2dd08df2014-07-11 17:18:03 +02003253 addr = alloca(addrlen+1);
ths3b46e622007-09-17 08:09:54 +00003254
Laurent Vivier7b36f782015-10-28 21:40:44 +01003255 ret = target_to_host_sockaddr(sockfd, addr, target_addr, addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03003256 if (ret)
3257 return ret;
3258
Peter Maydell2a3c7612016-06-06 19:58:03 +01003259 return get_errno(safe_connect(sockfd, addr, addrlen));
bellard3532fa72006-06-24 15:06:03 +00003260}
3261
Alexander Graff19e00d2014-03-02 19:36:42 +00003262/* do_sendrecvmsg_locked() Must return target values and target errnos. */
3263static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
3264 int flags, int send)
bellard3532fa72006-06-24 15:06:03 +00003265{
balrog6de645c2008-10-28 10:26:29 +00003266 abi_long ret, len;
bellard3532fa72006-06-24 15:06:03 +00003267 struct msghdr msg;
Peter Maydelldab32b32016-07-15 14:57:26 +01003268 abi_ulong count;
bellard3532fa72006-06-24 15:06:03 +00003269 struct iovec *vec;
blueswir1992f48a2007-10-14 16:27:31 +00003270 abi_ulong target_vec;
bellard3532fa72006-06-24 15:06:03 +00003271
bellard3532fa72006-06-24 15:06:03 +00003272 if (msgp->msg_name) {
3273 msg.msg_namelen = tswap32(msgp->msg_namelen);
Joakim Tjernlund2dd08df2014-07-11 17:18:03 +02003274 msg.msg_name = alloca(msg.msg_namelen+1);
Laurent Vivier7b36f782015-10-28 21:40:44 +01003275 ret = target_to_host_sockaddr(fd, msg.msg_name,
3276 tswapal(msgp->msg_name),
3277 msg.msg_namelen);
Peter Maydell26a6fc92016-07-15 14:57:28 +01003278 if (ret == -TARGET_EFAULT) {
3279 /* For connected sockets msg_name and msg_namelen must
3280 * be ignored, so returning EFAULT immediately is wrong.
3281 * Instead, pass a bad msg_name to the host kernel, and
3282 * let it decide whether to return EFAULT or not.
3283 */
3284 msg.msg_name = (void *)-1;
3285 } else if (ret) {
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003286 goto out2;
Arnaud Patard917507b2009-06-19 10:44:45 +03003287 }
bellard3532fa72006-06-24 15:06:03 +00003288 } else {
3289 msg.msg_name = NULL;
3290 msg.msg_namelen = 0;
3291 }
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003292 msg.msg_controllen = 2 * tswapal(msgp->msg_controllen);
bellard3532fa72006-06-24 15:06:03 +00003293 msg.msg_control = alloca(msg.msg_controllen);
Jonas Schievink1d3d1b22018-07-12 00:12:44 +02003294 memset(msg.msg_control, 0, msg.msg_controllen);
3295
bellard3532fa72006-06-24 15:06:03 +00003296 msg.msg_flags = tswap32(msgp->msg_flags);
ths3b46e622007-09-17 08:09:54 +00003297
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003298 count = tswapal(msgp->msg_iovlen);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003299 target_vec = tswapal(msgp->msg_iov);
Peter Maydell97b07972016-07-15 14:57:27 +01003300
3301 if (count > IOV_MAX) {
3302 /* sendrcvmsg returns a different errno for this condition than
3303 * readv/writev, so we must catch it here before lock_iovec() does.
3304 */
3305 ret = -TARGET_EMSGSIZE;
3306 goto out2;
3307 }
3308
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003309 vec = lock_iovec(send ? VERIFY_READ : VERIFY_WRITE,
3310 target_vec, count, send);
3311 if (vec == NULL) {
3312 ret = -host_to_target_errno(errno);
Helge Deller3f0744f2022-12-12 18:34:16 +01003313 /* allow sending packet without any iov, e.g. with MSG_MORE flag */
3314 if (!send || ret) {
3315 goto out2;
3316 }
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003317 }
bellard3532fa72006-06-24 15:06:03 +00003318 msg.msg_iovlen = count;
3319 msg.msg_iov = vec;
ths3b46e622007-09-17 08:09:54 +00003320
bellard3532fa72006-06-24 15:06:03 +00003321 if (send) {
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003322 if (fd_trans_target_to_host_data(fd)) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003323 void *host_msg;
3324
3325 host_msg = g_malloc(msg.msg_iov->iov_len);
3326 memcpy(host_msg, msg.msg_iov->iov_base, msg.msg_iov->iov_len);
3327 ret = fd_trans_target_to_host_data(fd)(host_msg,
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003328 msg.msg_iov->iov_len);
Laurent Vivier7d61d892016-06-21 19:51:14 +02003329 if (ret >= 0) {
3330 msg.msg_iov->iov_base = host_msg;
3331 ret = get_errno(safe_sendmsg(fd, &msg, flags));
3332 }
3333 g_free(host_msg);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003334 } else {
3335 ret = target_to_host_cmsg(&msg, msgp);
Laurent Vivier7d61d892016-06-21 19:51:14 +02003336 if (ret == 0) {
3337 ret = get_errno(safe_sendmsg(fd, &msg, flags));
3338 }
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003339 }
bellard3532fa72006-06-24 15:06:03 +00003340 } else {
Peter Maydell66687532016-06-06 19:58:04 +01003341 ret = get_errno(safe_recvmsg(fd, &msg, flags));
balrog6de645c2008-10-28 10:26:29 +00003342 if (!is_error(ret)) {
3343 len = ret;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003344 if (fd_trans_host_to_target_data(fd)) {
3345 ret = fd_trans_host_to_target_data(fd)(msg.msg_iov->iov_base,
Laurent Vivier2a03d3e2018-08-20 19:15:54 +02003346 MIN(msg.msg_iov->iov_len, len));
Icenowy Zheng16c81dd2022-10-28 16:12:20 +08003347 }
3348 if (!is_error(ret)) {
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003349 ret = host_to_target_cmsg(msgp, &msg);
3350 }
Jing Huangca619062012-07-24 13:58:02 +00003351 if (!is_error(ret)) {
3352 msgp->msg_namelen = tswap32(msg.msg_namelen);
Andreas Schwab24894f32019-02-12 17:34:35 +01003353 msgp->msg_flags = tswap32(msg.msg_flags);
Peter Maydell26a6fc92016-07-15 14:57:28 +01003354 if (msg.msg_name != NULL && msg.msg_name != (void *)-1) {
Jing Huangca619062012-07-24 13:58:02 +00003355 ret = host_to_target_sockaddr(tswapal(msgp->msg_name),
3356 msg.msg_name, msg.msg_namelen);
3357 if (ret) {
3358 goto out;
3359 }
3360 }
3361
balrog6de645c2008-10-28 10:26:29 +00003362 ret = len;
Jing Huangca619062012-07-24 13:58:02 +00003363 }
balrog6de645c2008-10-28 10:26:29 +00003364 }
bellard3532fa72006-06-24 15:06:03 +00003365 }
Jing Huangca619062012-07-24 13:58:02 +00003366
3367out:
Helge Deller3f0744f2022-12-12 18:34:16 +01003368 if (vec) {
3369 unlock_iovec(vec, target_vec, count, !send);
3370 }
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003371out2:
Alexander Graff19e00d2014-03-02 19:36:42 +00003372 return ret;
3373}
3374
3375static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
3376 int flags, int send)
3377{
3378 abi_long ret;
3379 struct target_msghdr *msgp;
3380
3381 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
3382 msgp,
3383 target_msg,
3384 send ? 1 : 0)) {
3385 return -TARGET_EFAULT;
3386 }
3387 ret = do_sendrecvmsg_locked(fd, msgp, flags, send);
bellard579a97f2007-11-11 14:26:47 +00003388 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
bellard3532fa72006-06-24 15:06:03 +00003389 return ret;
3390}
3391
Alexander Graff19e00d2014-03-02 19:36:42 +00003392/* We don't rely on the C library to have sendmmsg/recvmmsg support,
3393 * so it might not have this *mmsg-specific flag either.
3394 */
3395#ifndef MSG_WAITFORONE
3396#define MSG_WAITFORONE 0x10000
3397#endif
3398
3399static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec,
3400 unsigned int vlen, unsigned int flags,
3401 int send)
3402{
3403 struct target_mmsghdr *mmsgp;
3404 abi_long ret = 0;
3405 int i;
3406
3407 if (vlen > UIO_MAXIOV) {
3408 vlen = UIO_MAXIOV;
3409 }
3410
3411 mmsgp = lock_user(VERIFY_WRITE, target_msgvec, sizeof(*mmsgp) * vlen, 1);
3412 if (!mmsgp) {
3413 return -TARGET_EFAULT;
3414 }
3415
3416 for (i = 0; i < vlen; i++) {
3417 ret = do_sendrecvmsg_locked(fd, &mmsgp[i].msg_hdr, flags, send);
3418 if (is_error(ret)) {
3419 break;
3420 }
3421 mmsgp[i].msg_len = tswap32(ret);
3422 /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
3423 if (flags & MSG_WAITFORONE) {
3424 flags |= MSG_DONTWAIT;
3425 }
3426 }
3427
3428 unlock_user(mmsgp, target_msgvec, sizeof(*mmsgp) * i);
3429
3430 /* Return number of datagrams sent if we sent any at all;
3431 * otherwise return the error.
3432 */
3433 if (i) {
3434 return i;
3435 }
3436 return ret;
3437}
Alexander Graff19e00d2014-03-02 19:36:42 +00003438
Peter Maydella94b4982013-02-08 04:35:04 +00003439/* do_accept4() Must return target values and target errnos. */
3440static abi_long do_accept4(int fd, abi_ulong target_addr,
3441 abi_ulong target_addrlen_addr, int flags)
pbrook1be9e1d2006-11-19 15:26:04 +00003442{
Andreas Schwabcd813362019-02-14 12:43:40 +01003443 socklen_t addrlen, ret_addrlen;
bellard2f619692007-11-16 10:46:05 +00003444 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00003445 abi_long ret;
Petar Jovanovicd25295d2014-03-31 17:41:23 +02003446 int host_flags;
3447
Helge Dellerdca4c832023-07-08 07:24:00 +02003448 if (flags & ~(TARGET_SOCK_CLOEXEC | TARGET_SOCK_NONBLOCK)) {
3449 return -TARGET_EINVAL;
3450 }
3451
3452 host_flags = 0;
3453 if (flags & TARGET_SOCK_NONBLOCK) {
3454 host_flags |= SOCK_NONBLOCK;
3455 }
3456 if (flags & TARGET_SOCK_CLOEXEC) {
3457 host_flags |= SOCK_CLOEXEC;
3458 }
pbrook1be9e1d2006-11-19 15:26:04 +00003459
Peter Maydella94b4982013-02-08 04:35:04 +00003460 if (target_addr == 0) {
Peter Maydellff6dc132016-06-06 19:58:13 +01003461 return get_errno(safe_accept4(fd, NULL, NULL, host_flags));
Peter Maydella94b4982013-02-08 04:35:04 +00003462 }
Arnaud Patard917507b2009-06-19 10:44:45 +03003463
Matus Kysele554eb42020-09-30 17:16:16 +02003464 /* linux returns EFAULT if addrlen pointer is invalid */
bellard2f619692007-11-16 10:46:05 +00003465 if (get_user_u32(addrlen, target_addrlen_addr))
Matus Kysele554eb42020-09-30 17:16:16 +02003466 return -TARGET_EFAULT;
bellard2f619692007-11-16 10:46:05 +00003467
Blue Swirl38724252010-09-18 05:53:14 +00003468 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003469 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003470 }
aurel328f7aeaf2009-01-30 19:47:57 +00003471
Richard Hendersonc7169b02021-02-12 10:48:47 -08003472 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
Matus Kysele554eb42020-09-30 17:16:16 +02003473 return -TARGET_EFAULT;
Richard Hendersonc7169b02021-02-12 10:48:47 -08003474 }
Arnaud Patard917507b2009-06-19 10:44:45 +03003475
bellard2f619692007-11-16 10:46:05 +00003476 addr = alloca(addrlen);
3477
Andreas Schwabcd813362019-02-14 12:43:40 +01003478 ret_addrlen = addrlen;
3479 ret = get_errno(safe_accept4(fd, addr, &ret_addrlen, host_flags));
pbrook1be9e1d2006-11-19 15:26:04 +00003480 if (!is_error(ret)) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003481 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3482 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
bellard2f619692007-11-16 10:46:05 +00003483 ret = -TARGET_EFAULT;
Andreas Schwabcd813362019-02-14 12:43:40 +01003484 }
pbrook1be9e1d2006-11-19 15:26:04 +00003485 }
3486 return ret;
3487}
3488
ths0da46a62007-10-20 20:23:07 +00003489/* do_getpeername() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003490static abi_long do_getpeername(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00003491 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00003492{
Andreas Schwabcd813362019-02-14 12:43:40 +01003493 socklen_t addrlen, ret_addrlen;
bellard2f619692007-11-16 10:46:05 +00003494 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00003495 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003496
bellard2f619692007-11-16 10:46:05 +00003497 if (get_user_u32(addrlen, target_addrlen_addr))
3498 return -TARGET_EFAULT;
3499
Blue Swirl38724252010-09-18 05:53:14 +00003500 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003501 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003502 }
aurel328f7aeaf2009-01-30 19:47:57 +00003503
Richard Hendersonc7169b02021-02-12 10:48:47 -08003504 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
Arnaud Patard917507b2009-06-19 10:44:45 +03003505 return -TARGET_EFAULT;
Richard Hendersonc7169b02021-02-12 10:48:47 -08003506 }
Arnaud Patard917507b2009-06-19 10:44:45 +03003507
bellard2f619692007-11-16 10:46:05 +00003508 addr = alloca(addrlen);
3509
Andreas Schwabcd813362019-02-14 12:43:40 +01003510 ret_addrlen = addrlen;
3511 ret = get_errno(getpeername(fd, addr, &ret_addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003512 if (!is_error(ret)) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003513 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3514 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
bellard2f619692007-11-16 10:46:05 +00003515 ret = -TARGET_EFAULT;
Andreas Schwabcd813362019-02-14 12:43:40 +01003516 }
pbrook1be9e1d2006-11-19 15:26:04 +00003517 }
3518 return ret;
3519}
3520
ths0da46a62007-10-20 20:23:07 +00003521/* do_getsockname() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003522static abi_long do_getsockname(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00003523 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00003524{
Andreas Schwabcd813362019-02-14 12:43:40 +01003525 socklen_t addrlen, ret_addrlen;
bellard2f619692007-11-16 10:46:05 +00003526 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00003527 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003528
bellard2f619692007-11-16 10:46:05 +00003529 if (get_user_u32(addrlen, target_addrlen_addr))
3530 return -TARGET_EFAULT;
3531
Blue Swirl38724252010-09-18 05:53:14 +00003532 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003533 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003534 }
aurel328f7aeaf2009-01-30 19:47:57 +00003535
Richard Hendersonc7169b02021-02-12 10:48:47 -08003536 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
Arnaud Patard917507b2009-06-19 10:44:45 +03003537 return -TARGET_EFAULT;
Richard Hendersonc7169b02021-02-12 10:48:47 -08003538 }
Arnaud Patard917507b2009-06-19 10:44:45 +03003539
bellard2f619692007-11-16 10:46:05 +00003540 addr = alloca(addrlen);
3541
Andreas Schwabcd813362019-02-14 12:43:40 +01003542 ret_addrlen = addrlen;
3543 ret = get_errno(getsockname(fd, addr, &ret_addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003544 if (!is_error(ret)) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003545 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3546 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
bellard2f619692007-11-16 10:46:05 +00003547 ret = -TARGET_EFAULT;
Andreas Schwabcd813362019-02-14 12:43:40 +01003548 }
pbrook1be9e1d2006-11-19 15:26:04 +00003549 }
3550 return ret;
3551}
3552
ths0da46a62007-10-20 20:23:07 +00003553/* do_socketpair() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003554static abi_long do_socketpair(int domain, int type, int protocol,
bellard2f619692007-11-16 10:46:05 +00003555 abi_ulong target_tab_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00003556{
3557 int tab[2];
blueswir1992f48a2007-10-14 16:27:31 +00003558 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003559
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003560 target_to_host_sock_type(&type);
3561
pbrook1be9e1d2006-11-19 15:26:04 +00003562 ret = get_errno(socketpair(domain, type, protocol, tab));
3563 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00003564 if (put_user_s32(tab[0], target_tab_addr)
3565 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
3566 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00003567 }
3568 return ret;
3569}
3570
ths0da46a62007-10-20 20:23:07 +00003571/* do_sendto() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003572static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
3573 abi_ulong target_addr, socklen_t addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00003574{
3575 void *addr;
3576 void *host_msg;
Laurent Vivier7d61d892016-06-21 19:51:14 +02003577 void *copy_msg = NULL;
blueswir1992f48a2007-10-14 16:27:31 +00003578 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003579
Blue Swirl38724252010-09-18 05:53:14 +00003580 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003581 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003582 }
aurel328f7aeaf2009-01-30 19:47:57 +00003583
bellard579a97f2007-11-11 14:26:47 +00003584 host_msg = lock_user(VERIFY_READ, msg, len, 1);
3585 if (!host_msg)
3586 return -TARGET_EFAULT;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003587 if (fd_trans_target_to_host_data(fd)) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003588 copy_msg = host_msg;
3589 host_msg = g_malloc(len);
3590 memcpy(host_msg, copy_msg, len);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003591 ret = fd_trans_target_to_host_data(fd)(host_msg, len);
3592 if (ret < 0) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003593 goto fail;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003594 }
3595 }
pbrook1be9e1d2006-11-19 15:26:04 +00003596 if (target_addr) {
Joakim Tjernlund2dd08df2014-07-11 17:18:03 +02003597 addr = alloca(addrlen+1);
Laurent Vivier7b36f782015-10-28 21:40:44 +01003598 ret = target_to_host_sockaddr(fd, addr, target_addr, addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03003599 if (ret) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003600 goto fail;
Arnaud Patard917507b2009-06-19 10:44:45 +03003601 }
Peter Maydell66687532016-06-06 19:58:04 +01003602 ret = get_errno(safe_sendto(fd, host_msg, len, flags, addr, addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003603 } else {
Peter Maydell66687532016-06-06 19:58:04 +01003604 ret = get_errno(safe_sendto(fd, host_msg, len, flags, NULL, 0));
pbrook1be9e1d2006-11-19 15:26:04 +00003605 }
Laurent Vivier7d61d892016-06-21 19:51:14 +02003606fail:
3607 if (copy_msg) {
3608 g_free(host_msg);
3609 host_msg = copy_msg;
3610 }
pbrook1be9e1d2006-11-19 15:26:04 +00003611 unlock_user(host_msg, msg, 0);
3612 return ret;
3613}
3614
ths0da46a62007-10-20 20:23:07 +00003615/* do_recvfrom() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003616static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
3617 abi_ulong target_addr,
3618 abi_ulong target_addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00003619{
Andreas Schwabcd813362019-02-14 12:43:40 +01003620 socklen_t addrlen, ret_addrlen;
pbrook1be9e1d2006-11-19 15:26:04 +00003621 void *addr;
3622 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00003623 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003624
Zach Reizner4a1e6bc2021-03-26 22:11:16 -04003625 if (!msg) {
3626 host_msg = NULL;
3627 } else {
3628 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
3629 if (!host_msg) {
3630 return -TARGET_EFAULT;
3631 }
3632 }
pbrook1be9e1d2006-11-19 15:26:04 +00003633 if (target_addr) {
bellard2f619692007-11-16 10:46:05 +00003634 if (get_user_u32(addrlen, target_addrlen)) {
3635 ret = -TARGET_EFAULT;
3636 goto fail;
3637 }
Blue Swirl38724252010-09-18 05:53:14 +00003638 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003639 ret = -TARGET_EINVAL;
3640 goto fail;
3641 }
pbrook1be9e1d2006-11-19 15:26:04 +00003642 addr = alloca(addrlen);
Andreas Schwabcd813362019-02-14 12:43:40 +01003643 ret_addrlen = addrlen;
Peter Maydell66687532016-06-06 19:58:04 +01003644 ret = get_errno(safe_recvfrom(fd, host_msg, len, flags,
Andreas Schwabcd813362019-02-14 12:43:40 +01003645 addr, &ret_addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003646 } else {
3647 addr = NULL; /* To keep compiler quiet. */
Andreas Schwabcd813362019-02-14 12:43:40 +01003648 addrlen = 0; /* To keep compiler quiet. */
Peter Maydell66687532016-06-06 19:58:04 +01003649 ret = get_errno(safe_recvfrom(fd, host_msg, len, flags, NULL, 0));
pbrook1be9e1d2006-11-19 15:26:04 +00003650 }
3651 if (!is_error(ret)) {
Laurent Vivierc35e1f92016-06-21 19:51:15 +02003652 if (fd_trans_host_to_target_data(fd)) {
Laurent Vivier2a03d3e2018-08-20 19:15:54 +02003653 abi_long trans;
3654 trans = fd_trans_host_to_target_data(fd)(host_msg, MIN(ret, len));
3655 if (is_error(trans)) {
3656 ret = trans;
3657 goto fail;
3658 }
Laurent Vivierc35e1f92016-06-21 19:51:15 +02003659 }
pbrook1be9e1d2006-11-19 15:26:04 +00003660 if (target_addr) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003661 host_to_target_sockaddr(target_addr, addr,
3662 MIN(addrlen, ret_addrlen));
3663 if (put_user_u32(ret_addrlen, target_addrlen)) {
bellard2f619692007-11-16 10:46:05 +00003664 ret = -TARGET_EFAULT;
3665 goto fail;
3666 }
pbrook1be9e1d2006-11-19 15:26:04 +00003667 }
3668 unlock_user(host_msg, msg, len);
3669 } else {
bellard2f619692007-11-16 10:46:05 +00003670fail:
pbrook1be9e1d2006-11-19 15:26:04 +00003671 unlock_user(host_msg, msg, 0);
3672 }
3673 return ret;
3674}
3675
j_mayer32407102007-09-26 23:01:49 +00003676#ifdef TARGET_NR_socketcall
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003677/* do_socketcall() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003678static abi_long do_socketcall(int num, abi_ulong vptr)
bellard31e31b82003-02-18 22:55:36 +00003679{
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003680 static const unsigned nargs[] = { /* number of arguments per operation */
3681 [TARGET_SYS_SOCKET] = 3, /* domain, type, protocol */
3682 [TARGET_SYS_BIND] = 3, /* fd, addr, addrlen */
3683 [TARGET_SYS_CONNECT] = 3, /* fd, addr, addrlen */
3684 [TARGET_SYS_LISTEN] = 2, /* fd, backlog */
3685 [TARGET_SYS_ACCEPT] = 3, /* fd, addr, addrlen */
3686 [TARGET_SYS_GETSOCKNAME] = 3, /* fd, addr, addrlen */
3687 [TARGET_SYS_GETPEERNAME] = 3, /* fd, addr, addrlen */
3688 [TARGET_SYS_SOCKETPAIR] = 4, /* domain, type, protocol, tab */
3689 [TARGET_SYS_SEND] = 4, /* fd, msg, len, flags */
3690 [TARGET_SYS_RECV] = 4, /* fd, msg, len, flags */
3691 [TARGET_SYS_SENDTO] = 6, /* fd, msg, len, flags, addr, addrlen */
3692 [TARGET_SYS_RECVFROM] = 6, /* fd, msg, len, flags, addr, addrlen */
3693 [TARGET_SYS_SHUTDOWN] = 2, /* fd, how */
3694 [TARGET_SYS_SETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
3695 [TARGET_SYS_GETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
3696 [TARGET_SYS_SENDMSG] = 3, /* fd, msg, flags */
3697 [TARGET_SYS_RECVMSG] = 3, /* fd, msg, flags */
3698 [TARGET_SYS_ACCEPT4] = 4, /* fd, addr, addrlen, flags */
3699 [TARGET_SYS_RECVMMSG] = 4, /* fd, msgvec, vlen, flags */
3700 [TARGET_SYS_SENDMMSG] = 4, /* fd, msgvec, vlen, flags */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003701 };
3702 abi_long a[6]; /* max 6 args */
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003703 unsigned i;
bellard31e31b82003-02-18 22:55:36 +00003704
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003705 /* check the range of the first argument num */
3706 /* (TARGET_SYS_SENDMMSG is the highest among TARGET_SYS_xxx) */
3707 if (num < 1 || num > TARGET_SYS_SENDMMSG) {
3708 return -TARGET_EINVAL;
3709 }
3710 /* ensure we have space for args */
3711 if (nargs[num] > ARRAY_SIZE(a)) {
3712 return -TARGET_EINVAL;
3713 }
3714 /* collect the arguments in a[] according to nargs[] */
3715 for (i = 0; i < nargs[num]; ++i) {
3716 if (get_user_ual(a[i], vptr + i * sizeof(abi_long)) != 0) {
3717 return -TARGET_EFAULT;
André Hentschelb9d36eb2014-01-06 20:18:52 +01003718 }
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003719 }
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003720 /* now when we have the args, invoke the appropriate underlying function */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003721 switch (num) {
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003722 case TARGET_SYS_SOCKET: /* domain, type, protocol */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003723 return do_socket(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003724 case TARGET_SYS_BIND: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003725 return do_bind(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003726 case TARGET_SYS_CONNECT: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003727 return do_connect(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003728 case TARGET_SYS_LISTEN: /* sockfd, backlog */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003729 return get_errno(listen(a[0], a[1]));
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003730 case TARGET_SYS_ACCEPT: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003731 return do_accept4(a[0], a[1], a[2], 0);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003732 case TARGET_SYS_GETSOCKNAME: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003733 return do_getsockname(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003734 case TARGET_SYS_GETPEERNAME: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003735 return do_getpeername(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003736 case TARGET_SYS_SOCKETPAIR: /* domain, type, protocol, tab */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003737 return do_socketpair(a[0], a[1], a[2], a[3]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003738 case TARGET_SYS_SEND: /* sockfd, msg, len, flags */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003739 return do_sendto(a[0], a[1], a[2], a[3], 0, 0);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003740 case TARGET_SYS_RECV: /* sockfd, msg, len, flags */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003741 return do_recvfrom(a[0], a[1], a[2], a[3], 0, 0);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003742 case TARGET_SYS_SENDTO: /* sockfd, msg, len, flags, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003743 return do_sendto(a[0], a[1], a[2], a[3], a[4], a[5]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003744 case TARGET_SYS_RECVFROM: /* sockfd, msg, len, flags, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003745 return do_recvfrom(a[0], a[1], a[2], a[3], a[4], a[5]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003746 case TARGET_SYS_SHUTDOWN: /* sockfd, how */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003747 return get_errno(shutdown(a[0], a[1]));
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003748 case TARGET_SYS_SETSOCKOPT: /* sockfd, level, optname, optval, optlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003749 return do_setsockopt(a[0], a[1], a[2], a[3], a[4]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003750 case TARGET_SYS_GETSOCKOPT: /* sockfd, level, optname, optval, optlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003751 return do_getsockopt(a[0], a[1], a[2], a[3], a[4]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003752 case TARGET_SYS_SENDMSG: /* sockfd, msg, flags */
3753 return do_sendrecvmsg(a[0], a[1], a[2], 1);
3754 case TARGET_SYS_RECVMSG: /* sockfd, msg, flags */
3755 return do_sendrecvmsg(a[0], a[1], a[2], 0);
3756 case TARGET_SYS_ACCEPT4: /* sockfd, addr, addrlen, flags */
3757 return do_accept4(a[0], a[1], a[2], a[3]);
3758 case TARGET_SYS_RECVMMSG: /* sockfd, msgvec, vlen, flags */
3759 return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0);
3760 case TARGET_SYS_SENDMMSG: /* sockfd, msgvec, vlen, flags */
3761 return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 1);
bellard31e31b82003-02-18 22:55:36 +00003762 default:
Josh Kunz39be5352020-02-03 18:54:13 -08003763 qemu_log_mask(LOG_UNIMP, "Unsupported socketcall: %d\n", num);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003764 return -TARGET_EINVAL;
bellard31e31b82003-02-18 22:55:36 +00003765 }
bellard31e31b82003-02-18 22:55:36 +00003766}
j_mayer32407102007-09-26 23:01:49 +00003767#endif
bellard31e31b82003-02-18 22:55:36 +00003768
bellard8853f862004-02-22 14:57:26 +00003769#define N_SHM_REGIONS 32
3770
3771static struct shm_region {
Peter Maydellb6e17872016-02-09 15:57:11 +00003772 abi_ulong start;
3773 abi_ulong size;
3774 bool in_use;
bellard8853f862004-02-22 14:57:26 +00003775} shm_regions[N_SHM_REGIONS];
3776
Peter Maydell005eb2a2016-07-15 16:50:47 +01003777#ifndef TARGET_SEMID64_DS
3778/* asm-generic version of this struct */
3779struct target_semid64_ds
ths3eb6b042007-06-03 14:26:27 +00003780{
3781 struct target_ipc_perm sem_perm;
blueswir1992f48a2007-10-14 16:27:31 +00003782 abi_ulong sem_otime;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003783#if TARGET_ABI_BITS == 32
blueswir1992f48a2007-10-14 16:27:31 +00003784 abi_ulong __unused1;
Tom Musta03527342014-08-12 13:53:32 -05003785#endif
blueswir1992f48a2007-10-14 16:27:31 +00003786 abi_ulong sem_ctime;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003787#if TARGET_ABI_BITS == 32
blueswir1992f48a2007-10-14 16:27:31 +00003788 abi_ulong __unused2;
Tom Musta03527342014-08-12 13:53:32 -05003789#endif
blueswir1992f48a2007-10-14 16:27:31 +00003790 abi_ulong sem_nsems;
3791 abi_ulong __unused3;
3792 abi_ulong __unused4;
ths3eb6b042007-06-03 14:26:27 +00003793};
Peter Maydell005eb2a2016-07-15 16:50:47 +01003794#endif
ths3eb6b042007-06-03 14:26:27 +00003795
bellard579a97f2007-11-11 14:26:47 +00003796static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
3797 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00003798{
3799 struct target_ipc_perm *target_ip;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003800 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003801
bellard579a97f2007-11-11 14:26:47 +00003802 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
3803 return -TARGET_EFAULT;
Michael S. Tsirkine8bbe362009-09-30 18:56:44 +00003804 target_ip = &(target_sd->sem_perm);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003805 host_ip->__key = tswap32(target_ip->__key);
3806 host_ip->uid = tswap32(target_ip->uid);
3807 host_ip->gid = tswap32(target_ip->gid);
3808 host_ip->cuid = tswap32(target_ip->cuid);
3809 host_ip->cgid = tswap32(target_ip->cgid);
3810#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
3811 host_ip->mode = tswap32(target_ip->mode);
3812#else
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003813 host_ip->mode = tswap16(target_ip->mode);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003814#endif
3815#if defined(TARGET_PPC)
3816 host_ip->__seq = tswap32(target_ip->__seq);
3817#else
3818 host_ip->__seq = tswap16(target_ip->__seq);
3819#endif
ths3eb6b042007-06-03 14:26:27 +00003820 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00003821 return 0;
ths3eb6b042007-06-03 14:26:27 +00003822}
3823
bellard579a97f2007-11-11 14:26:47 +00003824static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
3825 struct ipc_perm *host_ip)
ths3eb6b042007-06-03 14:26:27 +00003826{
3827 struct target_ipc_perm *target_ip;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003828 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003829
bellard579a97f2007-11-11 14:26:47 +00003830 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3831 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00003832 target_ip = &(target_sd->sem_perm);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003833 target_ip->__key = tswap32(host_ip->__key);
3834 target_ip->uid = tswap32(host_ip->uid);
3835 target_ip->gid = tswap32(host_ip->gid);
3836 target_ip->cuid = tswap32(host_ip->cuid);
3837 target_ip->cgid = tswap32(host_ip->cgid);
3838#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
3839 target_ip->mode = tswap32(host_ip->mode);
3840#else
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003841 target_ip->mode = tswap16(host_ip->mode);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003842#endif
3843#if defined(TARGET_PPC)
3844 target_ip->__seq = tswap32(host_ip->__seq);
3845#else
3846 target_ip->__seq = tswap16(host_ip->__seq);
3847#endif
ths3eb6b042007-06-03 14:26:27 +00003848 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00003849 return 0;
ths3eb6b042007-06-03 14:26:27 +00003850}
3851
bellard579a97f2007-11-11 14:26:47 +00003852static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
3853 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00003854{
Peter Maydell005eb2a2016-07-15 16:50:47 +01003855 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003856
bellard579a97f2007-11-11 14:26:47 +00003857 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
3858 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00003859 if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
3860 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003861 host_sd->sem_nsems = tswapal(target_sd->sem_nsems);
3862 host_sd->sem_otime = tswapal(target_sd->sem_otime);
3863 host_sd->sem_ctime = tswapal(target_sd->sem_ctime);
ths3eb6b042007-06-03 14:26:27 +00003864 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00003865 return 0;
ths3eb6b042007-06-03 14:26:27 +00003866}
3867
bellard579a97f2007-11-11 14:26:47 +00003868static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
3869 struct semid_ds *host_sd)
ths3eb6b042007-06-03 14:26:27 +00003870{
Peter Maydell005eb2a2016-07-15 16:50:47 +01003871 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003872
bellard579a97f2007-11-11 14:26:47 +00003873 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3874 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00003875 if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
Dong Xu Wang3a931132011-11-29 16:52:38 +08003876 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003877 target_sd->sem_nsems = tswapal(host_sd->sem_nsems);
3878 target_sd->sem_otime = tswapal(host_sd->sem_otime);
3879 target_sd->sem_ctime = tswapal(host_sd->sem_ctime);
ths3eb6b042007-06-03 14:26:27 +00003880 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00003881 return 0;
ths3eb6b042007-06-03 14:26:27 +00003882}
3883
aurel32e5289082009-04-18 16:16:12 +00003884struct target_seminfo {
3885 int semmap;
3886 int semmni;
3887 int semmns;
3888 int semmnu;
3889 int semmsl;
3890 int semopm;
3891 int semume;
3892 int semusz;
3893 int semvmx;
3894 int semaem;
3895};
3896
3897static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
3898 struct seminfo *host_seminfo)
3899{
3900 struct target_seminfo *target_seminfo;
3901 if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
3902 return -TARGET_EFAULT;
3903 __put_user(host_seminfo->semmap, &target_seminfo->semmap);
3904 __put_user(host_seminfo->semmni, &target_seminfo->semmni);
3905 __put_user(host_seminfo->semmns, &target_seminfo->semmns);
3906 __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
3907 __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
3908 __put_user(host_seminfo->semopm, &target_seminfo->semopm);
3909 __put_user(host_seminfo->semume, &target_seminfo->semume);
3910 __put_user(host_seminfo->semusz, &target_seminfo->semusz);
3911 __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
3912 __put_user(host_seminfo->semaem, &target_seminfo->semaem);
3913 unlock_user_struct(target_seminfo, target_addr, 1);
3914 return 0;
3915}
3916
thsfa294812007-02-02 22:05:00 +00003917union semun {
3918 int val;
ths3eb6b042007-06-03 14:26:27 +00003919 struct semid_ds *buf;
thsfa294812007-02-02 22:05:00 +00003920 unsigned short *array;
aurel32e5289082009-04-18 16:16:12 +00003921 struct seminfo *__buf;
thsfa294812007-02-02 22:05:00 +00003922};
3923
ths3eb6b042007-06-03 14:26:27 +00003924union target_semun {
3925 int val;
aurel32e5289082009-04-18 16:16:12 +00003926 abi_ulong buf;
3927 abi_ulong array;
3928 abi_ulong __buf;
ths3eb6b042007-06-03 14:26:27 +00003929};
3930
aurel32e5289082009-04-18 16:16:12 +00003931static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
3932 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00003933{
aurel32e5289082009-04-18 16:16:12 +00003934 int nsems;
3935 unsigned short *array;
3936 union semun semun;
3937 struct semid_ds semid_ds;
3938 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00003939
aurel32e5289082009-04-18 16:16:12 +00003940 semun.buf = &semid_ds;
3941
3942 ret = semctl(semid, 0, IPC_STAT, semun);
3943 if (ret == -1)
3944 return get_errno(ret);
3945
3946 nsems = semid_ds.sem_nsems;
3947
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303948 *host_array = g_try_new(unsigned short, nsems);
Peter Maydell69d4c702014-02-17 18:55:34 +00003949 if (!*host_array) {
3950 return -TARGET_ENOMEM;
3951 }
aurel32e5289082009-04-18 16:16:12 +00003952 array = lock_user(VERIFY_READ, target_addr,
3953 nsems*sizeof(unsigned short), 1);
Peter Maydell69d4c702014-02-17 18:55:34 +00003954 if (!array) {
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303955 g_free(*host_array);
aurel32e5289082009-04-18 16:16:12 +00003956 return -TARGET_EFAULT;
Peter Maydell69d4c702014-02-17 18:55:34 +00003957 }
aurel32e5289082009-04-18 16:16:12 +00003958
3959 for(i=0; i<nsems; i++) {
3960 __get_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00003961 }
aurel32e5289082009-04-18 16:16:12 +00003962 unlock_user(array, target_addr, 0);
3963
bellard579a97f2007-11-11 14:26:47 +00003964 return 0;
ths3eb6b042007-06-03 14:26:27 +00003965}
3966
aurel32e5289082009-04-18 16:16:12 +00003967static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
3968 unsigned short **host_array)
ths3eb6b042007-06-03 14:26:27 +00003969{
aurel32e5289082009-04-18 16:16:12 +00003970 int nsems;
3971 unsigned short *array;
3972 union semun semun;
3973 struct semid_ds semid_ds;
3974 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00003975
aurel32e5289082009-04-18 16:16:12 +00003976 semun.buf = &semid_ds;
3977
3978 ret = semctl(semid, 0, IPC_STAT, semun);
3979 if (ret == -1)
3980 return get_errno(ret);
3981
3982 nsems = semid_ds.sem_nsems;
3983
3984 array = lock_user(VERIFY_WRITE, target_addr,
3985 nsems*sizeof(unsigned short), 0);
3986 if (!array)
3987 return -TARGET_EFAULT;
3988
3989 for(i=0; i<nsems; i++) {
3990 __put_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00003991 }
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303992 g_free(*host_array);
aurel32e5289082009-04-18 16:16:12 +00003993 unlock_user(array, target_addr, 1);
3994
bellard579a97f2007-11-11 14:26:47 +00003995 return 0;
ths3eb6b042007-06-03 14:26:27 +00003996}
3997
aurel32e5289082009-04-18 16:16:12 +00003998static inline abi_long do_semctl(int semid, int semnum, int cmd,
Stefan Weild1c002b2015-02-08 15:40:58 +01003999 abi_ulong target_arg)
ths3eb6b042007-06-03 14:26:27 +00004000{
Stefan Weild1c002b2015-02-08 15:40:58 +01004001 union target_semun target_su = { .buf = target_arg };
ths3eb6b042007-06-03 14:26:27 +00004002 union semun arg;
4003 struct semid_ds dsarg;
vibi sreenivasan7b8118e2009-06-19 13:34:39 +05304004 unsigned short *array = NULL;
aurel32e5289082009-04-18 16:16:12 +00004005 struct seminfo seminfo;
4006 abi_long ret = -TARGET_EINVAL;
4007 abi_long err;
4008 cmd &= 0xff;
ths3eb6b042007-06-03 14:26:27 +00004009
4010 switch( cmd ) {
4011 case GETVAL:
ths3eb6b042007-06-03 14:26:27 +00004012 case SETVAL:
Tom Musta5464bae2014-08-12 13:53:34 -05004013 /* In 64 bit cross-endian situations, we will erroneously pick up
4014 * the wrong half of the union for the "val" element. To rectify
4015 * this, the entire 8-byte structure is byteswapped, followed by
4016 * a swap of the 4 byte val field. In other cases, the data is
4017 * already in proper host byte order. */
4018 if (sizeof(target_su.val) != (sizeof(target_su.buf))) {
4019 target_su.buf = tswapal(target_su.buf);
4020 arg.val = tswap32(target_su.val);
4021 } else {
4022 arg.val = target_su.val;
4023 }
aurel32e5289082009-04-18 16:16:12 +00004024 ret = get_errno(semctl(semid, semnum, cmd, arg));
ths3eb6b042007-06-03 14:26:27 +00004025 break;
4026 case GETALL:
ths3eb6b042007-06-03 14:26:27 +00004027 case SETALL:
aurel32e5289082009-04-18 16:16:12 +00004028 err = target_to_host_semarray(semid, &array, target_su.array);
4029 if (err)
4030 return err;
4031 arg.array = array;
4032 ret = get_errno(semctl(semid, semnum, cmd, arg));
4033 err = host_to_target_semarray(semid, target_su.array, &array);
4034 if (err)
4035 return err;
ths3eb6b042007-06-03 14:26:27 +00004036 break;
4037 case IPC_STAT:
ths3eb6b042007-06-03 14:26:27 +00004038 case IPC_SET:
aurel32e5289082009-04-18 16:16:12 +00004039 case SEM_STAT:
4040 err = target_to_host_semid_ds(&dsarg, target_su.buf);
4041 if (err)
4042 return err;
4043 arg.buf = &dsarg;
4044 ret = get_errno(semctl(semid, semnum, cmd, arg));
4045 err = host_to_target_semid_ds(target_su.buf, &dsarg);
4046 if (err)
4047 return err;
ths3eb6b042007-06-03 14:26:27 +00004048 break;
aurel32e5289082009-04-18 16:16:12 +00004049 case IPC_INFO:
4050 case SEM_INFO:
4051 arg.__buf = &seminfo;
4052 ret = get_errno(semctl(semid, semnum, cmd, arg));
4053 err = host_to_target_seminfo(target_su.__buf, &seminfo);
4054 if (err)
4055 return err;
4056 break;
4057 case IPC_RMID:
4058 case GETPID:
4059 case GETNCNT:
4060 case GETZCNT:
4061 ret = get_errno(semctl(semid, semnum, cmd, NULL));
4062 break;
ths3eb6b042007-06-03 14:26:27 +00004063 }
4064
4065 return ret;
4066}
4067
aurel32e5289082009-04-18 16:16:12 +00004068struct target_sembuf {
4069 unsigned short sem_num;
4070 short sem_op;
4071 short sem_flg;
4072};
4073
4074static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
4075 abi_ulong target_addr,
4076 unsigned nsops)
4077{
4078 struct target_sembuf *target_sembuf;
4079 int i;
4080
4081 target_sembuf = lock_user(VERIFY_READ, target_addr,
4082 nsops*sizeof(struct target_sembuf), 1);
4083 if (!target_sembuf)
4084 return -TARGET_EFAULT;
4085
4086 for(i=0; i<nsops; i++) {
4087 __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
4088 __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
4089 __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
4090 }
4091
4092 unlock_user(target_sembuf, target_addr, 0);
4093
4094 return 0;
4095}
4096
Matus Kyseld8c08b12020-06-26 14:46:11 +02004097#if defined(TARGET_NR_ipc) || defined(TARGET_NR_semop) || \
Filip Bozutacac46eb2020-08-25 00:30:50 +02004098 defined(TARGET_NR_semtimedop) || defined(TARGET_NR_semtimedop_time64)
Matus Kyseld8c08b12020-06-26 14:46:11 +02004099
4100/*
4101 * This macro is required to handle the s390 variants, which passes the
4102 * arguments in a different order than default.
4103 */
4104#ifdef __s390x__
4105#define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
4106 (__nsops), (__timeout), (__sops)
4107#else
4108#define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
4109 (__nsops), 0, (__sops), (__timeout)
4110#endif
4111
4112static inline abi_long do_semtimedop(int semid,
4113 abi_long ptr,
4114 unsigned nsops,
Filip Bozutacac46eb2020-08-25 00:30:50 +02004115 abi_long timeout, bool time64)
aurel32e5289082009-04-18 16:16:12 +00004116{
Filip Bozuta0a7ec842020-08-18 20:07:22 +02004117 struct sembuf *sops;
Matus Kyseld8c08b12020-06-26 14:46:11 +02004118 struct timespec ts, *pts = NULL;
Laurent Vivier524fa342019-05-29 10:48:04 +02004119 abi_long ret;
aurel32e5289082009-04-18 16:16:12 +00004120
Matus Kyseld8c08b12020-06-26 14:46:11 +02004121 if (timeout) {
4122 pts = &ts;
Filip Bozutacac46eb2020-08-25 00:30:50 +02004123 if (time64) {
4124 if (target_to_host_timespec64(pts, timeout)) {
4125 return -TARGET_EFAULT;
4126 }
4127 } else {
4128 if (target_to_host_timespec(pts, timeout)) {
4129 return -TARGET_EFAULT;
4130 }
Matus Kyseld8c08b12020-06-26 14:46:11 +02004131 }
4132 }
4133
Filip Bozuta0a7ec842020-08-18 20:07:22 +02004134 if (nsops > TARGET_SEMOPM) {
4135 return -TARGET_E2BIG;
4136 }
4137
4138 sops = g_new(struct sembuf, nsops);
4139
4140 if (target_to_host_sembuf(sops, ptr, nsops)) {
4141 g_free(sops);
aurel32e5289082009-04-18 16:16:12 +00004142 return -TARGET_EFAULT;
Filip Bozuta0a7ec842020-08-18 20:07:22 +02004143 }
aurel32e5289082009-04-18 16:16:12 +00004144
Laurent Vivier524fa342019-05-29 10:48:04 +02004145 ret = -TARGET_ENOSYS;
4146#ifdef __NR_semtimedop
Matus Kyseld8c08b12020-06-26 14:46:11 +02004147 ret = get_errno(safe_semtimedop(semid, sops, nsops, pts));
Laurent Vivier524fa342019-05-29 10:48:04 +02004148#endif
4149#ifdef __NR_ipc
4150 if (ret == -TARGET_ENOSYS) {
Matus Kyseld8c08b12020-06-26 14:46:11 +02004151 ret = get_errno(safe_ipc(IPCOP_semtimedop, semid,
4152 SEMTIMEDOP_IPC_ARGS(nsops, sops, (long)pts)));
Laurent Vivier524fa342019-05-29 10:48:04 +02004153 }
4154#endif
Filip Bozuta0a7ec842020-08-18 20:07:22 +02004155 g_free(sops);
Laurent Vivier524fa342019-05-29 10:48:04 +02004156 return ret;
aurel32e5289082009-04-18 16:16:12 +00004157}
Matus Kyseld8c08b12020-06-26 14:46:11 +02004158#endif
aurel32e5289082009-04-18 16:16:12 +00004159
ths1bc012f2007-06-03 14:27:49 +00004160struct target_msqid_ds
4161{
aurel321c54ff92008-10-13 21:08:44 +00004162 struct target_ipc_perm msg_perm;
4163 abi_ulong msg_stime;
4164#if TARGET_ABI_BITS == 32
4165 abi_ulong __unused1;
4166#endif
4167 abi_ulong msg_rtime;
4168#if TARGET_ABI_BITS == 32
4169 abi_ulong __unused2;
4170#endif
4171 abi_ulong msg_ctime;
4172#if TARGET_ABI_BITS == 32
4173 abi_ulong __unused3;
4174#endif
4175 abi_ulong __msg_cbytes;
4176 abi_ulong msg_qnum;
4177 abi_ulong msg_qbytes;
4178 abi_ulong msg_lspid;
4179 abi_ulong msg_lrpid;
4180 abi_ulong __unused4;
4181 abi_ulong __unused5;
ths1bc012f2007-06-03 14:27:49 +00004182};
4183
bellard579a97f2007-11-11 14:26:47 +00004184static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
4185 abi_ulong target_addr)
ths1bc012f2007-06-03 14:27:49 +00004186{
4187 struct target_msqid_ds *target_md;
4188
bellard579a97f2007-11-11 14:26:47 +00004189 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
4190 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00004191 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
4192 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02004193 host_md->msg_stime = tswapal(target_md->msg_stime);
4194 host_md->msg_rtime = tswapal(target_md->msg_rtime);
4195 host_md->msg_ctime = tswapal(target_md->msg_ctime);
4196 host_md->__msg_cbytes = tswapal(target_md->__msg_cbytes);
4197 host_md->msg_qnum = tswapal(target_md->msg_qnum);
4198 host_md->msg_qbytes = tswapal(target_md->msg_qbytes);
4199 host_md->msg_lspid = tswapal(target_md->msg_lspid);
4200 host_md->msg_lrpid = tswapal(target_md->msg_lrpid);
ths1bc012f2007-06-03 14:27:49 +00004201 unlock_user_struct(target_md, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00004202 return 0;
ths1bc012f2007-06-03 14:27:49 +00004203}
4204
bellard579a97f2007-11-11 14:26:47 +00004205static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
4206 struct msqid_ds *host_md)
ths1bc012f2007-06-03 14:27:49 +00004207{
4208 struct target_msqid_ds *target_md;
4209
bellard579a97f2007-11-11 14:26:47 +00004210 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
4211 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00004212 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
4213 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02004214 target_md->msg_stime = tswapal(host_md->msg_stime);
4215 target_md->msg_rtime = tswapal(host_md->msg_rtime);
4216 target_md->msg_ctime = tswapal(host_md->msg_ctime);
4217 target_md->__msg_cbytes = tswapal(host_md->__msg_cbytes);
4218 target_md->msg_qnum = tswapal(host_md->msg_qnum);
4219 target_md->msg_qbytes = tswapal(host_md->msg_qbytes);
4220 target_md->msg_lspid = tswapal(host_md->msg_lspid);
4221 target_md->msg_lrpid = tswapal(host_md->msg_lrpid);
ths1bc012f2007-06-03 14:27:49 +00004222 unlock_user_struct(target_md, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00004223 return 0;
ths1bc012f2007-06-03 14:27:49 +00004224}
4225
aurel321c54ff92008-10-13 21:08:44 +00004226struct target_msginfo {
4227 int msgpool;
4228 int msgmap;
4229 int msgmax;
4230 int msgmnb;
4231 int msgmni;
4232 int msgssz;
4233 int msgtql;
4234 unsigned short int msgseg;
4235};
4236
4237static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
4238 struct msginfo *host_msginfo)
4239{
4240 struct target_msginfo *target_msginfo;
4241 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
4242 return -TARGET_EFAULT;
4243 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
4244 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
4245 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
4246 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
4247 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
4248 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
4249 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
4250 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
4251 unlock_user_struct(target_msginfo, target_addr, 1);
aurel3200b229a2008-10-24 13:12:52 +00004252 return 0;
aurel321c54ff92008-10-13 21:08:44 +00004253}
4254
4255static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
ths1bc012f2007-06-03 14:27:49 +00004256{
4257 struct msqid_ds dsarg;
aurel321c54ff92008-10-13 21:08:44 +00004258 struct msginfo msginfo;
4259 abi_long ret = -TARGET_EINVAL;
4260
4261 cmd &= 0xff;
4262
4263 switch (cmd) {
ths1bc012f2007-06-03 14:27:49 +00004264 case IPC_STAT:
4265 case IPC_SET:
aurel321c54ff92008-10-13 21:08:44 +00004266 case MSG_STAT:
4267 if (target_to_host_msqid_ds(&dsarg,ptr))
4268 return -TARGET_EFAULT;
4269 ret = get_errno(msgctl(msgid, cmd, &dsarg));
4270 if (host_to_target_msqid_ds(ptr,&dsarg))
4271 return -TARGET_EFAULT;
4272 break;
4273 case IPC_RMID:
4274 ret = get_errno(msgctl(msgid, cmd, NULL));
4275 break;
4276 case IPC_INFO:
4277 case MSG_INFO:
4278 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
4279 if (host_to_target_msginfo(ptr, &msginfo))
4280 return -TARGET_EFAULT;
4281 break;
ths1bc012f2007-06-03 14:27:49 +00004282 }
aurel321c54ff92008-10-13 21:08:44 +00004283
ths1bc012f2007-06-03 14:27:49 +00004284 return ret;
4285}
4286
4287struct target_msgbuf {
aurel321c54ff92008-10-13 21:08:44 +00004288 abi_long mtype;
4289 char mtext[1];
ths1bc012f2007-06-03 14:27:49 +00004290};
4291
blueswir1992f48a2007-10-14 16:27:31 +00004292static inline abi_long do_msgsnd(int msqid, abi_long msgp,
Tom Mustaedcc5f92014-08-12 13:53:37 -05004293 ssize_t msgsz, int msgflg)
ths1bc012f2007-06-03 14:27:49 +00004294{
4295 struct target_msgbuf *target_mb;
4296 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00004297 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00004298
Tom Mustaedcc5f92014-08-12 13:53:37 -05004299 if (msgsz < 0) {
4300 return -TARGET_EINVAL;
4301 }
4302
bellard579a97f2007-11-11 14:26:47 +00004303 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
4304 return -TARGET_EFAULT;
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304305 host_mb = g_try_malloc(msgsz + sizeof(long));
zhanghailiang29e03fc2014-08-14 15:29:18 +08004306 if (!host_mb) {
4307 unlock_user_struct(target_mb, msgp, 0);
4308 return -TARGET_ENOMEM;
4309 }
Matthias Brauncbb21ee2011-08-12 19:57:41 +02004310 host_mb->mtype = (abi_long) tswapal(target_mb->mtype);
aurel321c54ff92008-10-13 21:08:44 +00004311 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
Laurent Vivier524fa342019-05-29 10:48:04 +02004312 ret = -TARGET_ENOSYS;
4313#ifdef __NR_msgsnd
Peter Maydell89f9fe42016-06-06 19:58:05 +01004314 ret = get_errno(safe_msgsnd(msqid, host_mb, msgsz, msgflg));
Laurent Vivier524fa342019-05-29 10:48:04 +02004315#endif
4316#ifdef __NR_ipc
4317 if (ret == -TARGET_ENOSYS) {
Matus Kyseld8c08b12020-06-26 14:46:11 +02004318#ifdef __s390x__
4319 ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg,
4320 host_mb));
4321#else
Laurent Vivier524fa342019-05-29 10:48:04 +02004322 ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg,
4323 host_mb, 0));
Matus Kyseld8c08b12020-06-26 14:46:11 +02004324#endif
Laurent Vivier524fa342019-05-29 10:48:04 +02004325 }
4326#endif
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304327 g_free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00004328 unlock_user_struct(target_mb, msgp, 0);
4329
4330 return ret;
4331}
4332
Matus Kyseld8c08b12020-06-26 14:46:11 +02004333#ifdef __NR_ipc
4334#if defined(__sparc__)
4335/* SPARC for msgrcv it does not use the kludge on final 2 arguments. */
4336#define MSGRCV_ARGS(__msgp, __msgtyp) __msgp, __msgtyp
4337#elif defined(__s390x__)
4338/* The s390 sys_ipc variant has only five parameters. */
4339#define MSGRCV_ARGS(__msgp, __msgtyp) \
4340 ((long int[]){(long int)__msgp, __msgtyp})
4341#else
4342#define MSGRCV_ARGS(__msgp, __msgtyp) \
4343 ((long int[]){(long int)__msgp, __msgtyp}), 0
4344#endif
4345#endif
4346
blueswir1992f48a2007-10-14 16:27:31 +00004347static inline abi_long do_msgrcv(int msqid, abi_long msgp,
Peter Maydell99874f62016-05-20 19:00:56 +01004348 ssize_t msgsz, abi_long msgtyp,
blueswir1992f48a2007-10-14 16:27:31 +00004349 int msgflg)
ths1bc012f2007-06-03 14:27:49 +00004350{
4351 struct target_msgbuf *target_mb;
bellard579a97f2007-11-11 14:26:47 +00004352 char *target_mtext;
ths1bc012f2007-06-03 14:27:49 +00004353 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00004354 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00004355
Peter Maydell99874f62016-05-20 19:00:56 +01004356 if (msgsz < 0) {
4357 return -TARGET_EINVAL;
4358 }
4359
bellard579a97f2007-11-11 14:26:47 +00004360 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
4361 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00004362
Peter Maydell415d8472016-05-20 19:00:57 +01004363 host_mb = g_try_malloc(msgsz + sizeof(long));
4364 if (!host_mb) {
4365 ret = -TARGET_ENOMEM;
4366 goto end;
4367 }
Laurent Vivier524fa342019-05-29 10:48:04 +02004368 ret = -TARGET_ENOSYS;
4369#ifdef __NR_msgrcv
Peter Maydell89f9fe42016-06-06 19:58:05 +01004370 ret = get_errno(safe_msgrcv(msqid, host_mb, msgsz, msgtyp, msgflg));
Laurent Vivier524fa342019-05-29 10:48:04 +02004371#endif
4372#ifdef __NR_ipc
4373 if (ret == -TARGET_ENOSYS) {
4374 ret = get_errno(safe_ipc(IPCOP_CALL(1, IPCOP_msgrcv), msqid, msgsz,
Matus Kyseld8c08b12020-06-26 14:46:11 +02004375 msgflg, MSGRCV_ARGS(host_mb, msgtyp)));
Laurent Vivier524fa342019-05-29 10:48:04 +02004376 }
4377#endif
aurel321c54ff92008-10-13 21:08:44 +00004378
bellard579a97f2007-11-11 14:26:47 +00004379 if (ret > 0) {
4380 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
4381 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
4382 if (!target_mtext) {
4383 ret = -TARGET_EFAULT;
4384 goto end;
4385 }
aurel321c54ff92008-10-13 21:08:44 +00004386 memcpy(target_mb->mtext, host_mb->mtext, ret);
bellard579a97f2007-11-11 14:26:47 +00004387 unlock_user(target_mtext, target_mtext_addr, ret);
4388 }
aurel321c54ff92008-10-13 21:08:44 +00004389
Matthias Brauncbb21ee2011-08-12 19:57:41 +02004390 target_mb->mtype = tswapal(host_mb->mtype);
ths1bc012f2007-06-03 14:27:49 +00004391
bellard579a97f2007-11-11 14:26:47 +00004392end:
4393 if (target_mb)
4394 unlock_user_struct(target_mb, msgp, 1);
Jim Meyering0d07fe42012-08-22 13:55:53 +02004395 g_free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00004396 return ret;
4397}
4398
Riku Voipio88a8c982009-04-03 10:42:00 +03004399static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
4400 abi_ulong target_addr)
4401{
4402 struct target_shmid_ds *target_sd;
4403
4404 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
4405 return -TARGET_EFAULT;
4406 if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
4407 return -TARGET_EFAULT;
4408 __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
4409 __get_user(host_sd->shm_atime, &target_sd->shm_atime);
4410 __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
4411 __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
4412 __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
4413 __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
4414 __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
4415 unlock_user_struct(target_sd, target_addr, 0);
4416 return 0;
4417}
4418
4419static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
4420 struct shmid_ds *host_sd)
4421{
4422 struct target_shmid_ds *target_sd;
4423
4424 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
4425 return -TARGET_EFAULT;
4426 if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
4427 return -TARGET_EFAULT;
4428 __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
4429 __put_user(host_sd->shm_atime, &target_sd->shm_atime);
4430 __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
4431 __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
4432 __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
4433 __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
4434 __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
4435 unlock_user_struct(target_sd, target_addr, 1);
4436 return 0;
4437}
4438
4439struct target_shminfo {
4440 abi_ulong shmmax;
4441 abi_ulong shmmin;
4442 abi_ulong shmmni;
4443 abi_ulong shmseg;
4444 abi_ulong shmall;
4445};
4446
4447static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
4448 struct shminfo *host_shminfo)
4449{
4450 struct target_shminfo *target_shminfo;
4451 if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
4452 return -TARGET_EFAULT;
4453 __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
4454 __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
4455 __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
4456 __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
4457 __put_user(host_shminfo->shmall, &target_shminfo->shmall);
4458 unlock_user_struct(target_shminfo, target_addr, 1);
4459 return 0;
4460}
4461
4462struct target_shm_info {
4463 int used_ids;
4464 abi_ulong shm_tot;
4465 abi_ulong shm_rss;
4466 abi_ulong shm_swp;
4467 abi_ulong swap_attempts;
4468 abi_ulong swap_successes;
4469};
4470
4471static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
4472 struct shm_info *host_shm_info)
4473{
4474 struct target_shm_info *target_shm_info;
4475 if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
4476 return -TARGET_EFAULT;
4477 __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
4478 __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
4479 __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
4480 __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
4481 __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
4482 __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
4483 unlock_user_struct(target_shm_info, target_addr, 1);
4484 return 0;
4485}
4486
4487static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
4488{
4489 struct shmid_ds dsarg;
4490 struct shminfo shminfo;
4491 struct shm_info shm_info;
4492 abi_long ret = -TARGET_EINVAL;
4493
4494 cmd &= 0xff;
4495
4496 switch(cmd) {
4497 case IPC_STAT:
4498 case IPC_SET:
4499 case SHM_STAT:
4500 if (target_to_host_shmid_ds(&dsarg, buf))
4501 return -TARGET_EFAULT;
4502 ret = get_errno(shmctl(shmid, cmd, &dsarg));
4503 if (host_to_target_shmid_ds(buf, &dsarg))
4504 return -TARGET_EFAULT;
4505 break;
4506 case IPC_INFO:
4507 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
4508 if (host_to_target_shminfo(buf, &shminfo))
4509 return -TARGET_EFAULT;
4510 break;
4511 case SHM_INFO:
4512 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
4513 if (host_to_target_shm_info(buf, &shm_info))
4514 return -TARGET_EFAULT;
4515 break;
4516 case IPC_RMID:
4517 case SHM_LOCK:
4518 case SHM_UNLOCK:
4519 ret = get_errno(shmctl(shmid, cmd, NULL));
4520 break;
4521 }
4522
4523 return ret;
4524}
4525
Peter Maydellee8e7612016-07-11 16:48:11 +01004526#ifndef TARGET_FORCE_SHMLBA
4527/* For most architectures, SHMLBA is the same as the page size;
4528 * some architectures have larger values, in which case they should
4529 * define TARGET_FORCE_SHMLBA and provide a target_shmlba() function.
4530 * This corresponds to the kernel arch code defining __ARCH_FORCE_SHMLBA
4531 * and defining its own value for SHMLBA.
4532 *
4533 * The kernel also permits SHMLBA to be set by the architecture to a
4534 * value larger than the page size without setting __ARCH_FORCE_SHMLBA;
4535 * this means that addresses are rounded to the large size if
4536 * SHM_RND is set but addresses not aligned to that size are not rejected
4537 * as long as they are at least page-aligned. Since the only architecture
4538 * which uses this is ia64 this code doesn't provide for that oddity.
4539 */
4540static inline abi_ulong target_shmlba(CPUArchState *cpu_env)
4541{
4542 return TARGET_PAGE_SIZE;
4543}
4544#endif
4545
Richard Henderson9b61f772023-06-26 16:02:50 +02004546static abi_ulong do_shmat(CPUArchState *cpu_env, int shmid,
4547 abi_ulong shmaddr, int shmflg)
Riku Voipio88a8c982009-04-03 10:42:00 +03004548{
Richard Henderson228168c2021-06-11 23:08:28 -07004549 CPUState *cpu = env_cpu(cpu_env);
Richard Henderson9b61f772023-06-26 16:02:50 +02004550 abi_ulong raddr;
Riku Voipio88a8c982009-04-03 10:42:00 +03004551 void *host_raddr;
4552 struct shmid_ds shm_info;
Richard Henderson9b61f772023-06-26 16:02:50 +02004553 int i, ret;
Peter Maydellee8e7612016-07-11 16:48:11 +01004554 abi_ulong shmlba;
Riku Voipio88a8c982009-04-03 10:42:00 +03004555
Richard Hendersonee1bf832021-02-12 10:48:44 -08004556 /* shmat pointers are always untagged */
4557
Riku Voipio88a8c982009-04-03 10:42:00 +03004558 /* find out the length of the shared memory segment */
4559 ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
4560 if (is_error(ret)) {
4561 /* can't get length, bail out */
4562 return ret;
4563 }
4564
Peter Maydellee8e7612016-07-11 16:48:11 +01004565 shmlba = target_shmlba(cpu_env);
4566
4567 if (shmaddr & (shmlba - 1)) {
4568 if (shmflg & SHM_RND) {
4569 shmaddr &= ~(shmlba - 1);
4570 } else {
4571 return -TARGET_EINVAL;
4572 }
4573 }
Richard Henderson46b12f42021-02-12 10:48:46 -08004574 if (!guest_range_valid_untagged(shmaddr, shm_info.shm_segsz)) {
Max Filippovebf9a362018-03-07 13:50:10 -08004575 return -TARGET_EINVAL;
4576 }
Peter Maydellee8e7612016-07-11 16:48:11 +01004577
Riku Voipio88a8c982009-04-03 10:42:00 +03004578 mmap_lock();
4579
Richard Henderson228168c2021-06-11 23:08:28 -07004580 /*
4581 * We're mapping shared memory, so ensure we generate code for parallel
4582 * execution and flush old translations. This will work up to the level
4583 * supported by the host -- anything that requires EXCP_ATOMIC will not
4584 * be atomic with respect to an external process.
4585 */
4586 if (!(cpu->tcg_cflags & CF_PARALLEL)) {
4587 cpu->tcg_cflags |= CF_PARALLEL;
4588 tb_flush(cpu);
4589 }
4590
Riku Voipio88a8c982009-04-03 10:42:00 +03004591 if (shmaddr)
Richard Henderson3e8f1622021-02-12 10:48:43 -08004592 host_raddr = shmat(shmid, (void *)g2h_untagged(shmaddr), shmflg);
Riku Voipio88a8c982009-04-03 10:42:00 +03004593 else {
4594 abi_ulong mmap_start;
4595
Richard Henderson30ab9ef2019-05-19 13:19:52 -07004596 /* In order to use the host shmat, we need to honor host SHMLBA. */
4597 mmap_start = mmap_find_vma(0, shm_info.shm_segsz, MAX(SHMLBA, shmlba));
Riku Voipio88a8c982009-04-03 10:42:00 +03004598
4599 if (mmap_start == -1) {
4600 errno = ENOMEM;
4601 host_raddr = (void *)-1;
4602 } else
Richard Henderson3e8f1622021-02-12 10:48:43 -08004603 host_raddr = shmat(shmid, g2h_untagged(mmap_start),
4604 shmflg | SHM_REMAP);
Riku Voipio88a8c982009-04-03 10:42:00 +03004605 }
4606
4607 if (host_raddr == (void *)-1) {
4608 mmap_unlock();
Richard Henderson9b61f772023-06-26 16:02:50 +02004609 return get_errno((intptr_t)host_raddr);
Riku Voipio88a8c982009-04-03 10:42:00 +03004610 }
Richard Henderson9b61f772023-06-26 16:02:50 +02004611 raddr = h2g((uintptr_t)host_raddr);
Riku Voipio88a8c982009-04-03 10:42:00 +03004612
Richard Henderson49840a42023-03-06 01:51:09 +03004613 page_set_flags(raddr, raddr + shm_info.shm_segsz - 1,
Richard Hendersond9c58582021-02-12 10:48:32 -08004614 PAGE_VALID | PAGE_RESET | PAGE_READ |
4615 (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
Riku Voipio88a8c982009-04-03 10:42:00 +03004616
4617 for (i = 0; i < N_SHM_REGIONS; i++) {
Peter Maydellb6e17872016-02-09 15:57:11 +00004618 if (!shm_regions[i].in_use) {
4619 shm_regions[i].in_use = true;
Riku Voipio88a8c982009-04-03 10:42:00 +03004620 shm_regions[i].start = raddr;
4621 shm_regions[i].size = shm_info.shm_segsz;
4622 break;
4623 }
4624 }
4625
4626 mmap_unlock();
4627 return raddr;
Riku Voipio88a8c982009-04-03 10:42:00 +03004628}
4629
4630static inline abi_long do_shmdt(abi_ulong shmaddr)
4631{
4632 int i;
Max Filippov3c5f6a52018-02-28 14:16:04 -08004633 abi_long rv;
4634
Richard Hendersonee1bf832021-02-12 10:48:44 -08004635 /* shmdt pointers are always untagged */
4636
Max Filippov3c5f6a52018-02-28 14:16:04 -08004637 mmap_lock();
Riku Voipio88a8c982009-04-03 10:42:00 +03004638
4639 for (i = 0; i < N_SHM_REGIONS; ++i) {
Peter Maydellb6e17872016-02-09 15:57:11 +00004640 if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
4641 shm_regions[i].in_use = false;
Richard Henderson49840a42023-03-06 01:51:09 +03004642 page_set_flags(shmaddr, shmaddr + shm_regions[i].size - 1, 0);
Riku Voipio88a8c982009-04-03 10:42:00 +03004643 break;
4644 }
4645 }
Richard Henderson3e8f1622021-02-12 10:48:43 -08004646 rv = get_errno(shmdt(g2h_untagged(shmaddr)));
Riku Voipio88a8c982009-04-03 10:42:00 +03004647
Max Filippov3c5f6a52018-02-28 14:16:04 -08004648 mmap_unlock();
4649
4650 return rv;
Riku Voipio88a8c982009-04-03 10:42:00 +03004651}
4652
aurel321c54ff92008-10-13 21:08:44 +00004653#ifdef TARGET_NR_ipc
pbrook53a59602006-03-25 19:31:22 +00004654/* ??? This only works with linear mappings. */
ths0da46a62007-10-20 20:23:07 +00004655/* do_ipc() must return target values and target errnos. */
Peter Maydellee8e7612016-07-11 16:48:11 +01004656static abi_long do_ipc(CPUArchState *cpu_env,
4657 unsigned int call, abi_long first,
Tom Musta37ed0952014-08-12 13:53:35 -05004658 abi_long second, abi_long third,
blueswir1992f48a2007-10-14 16:27:31 +00004659 abi_long ptr, abi_long fifth)
bellard8853f862004-02-22 14:57:26 +00004660{
4661 int version;
blueswir1992f48a2007-10-14 16:27:31 +00004662 abi_long ret = 0;
bellard8853f862004-02-22 14:57:26 +00004663
4664 version = call >> 16;
4665 call &= 0xffff;
4666
4667 switch (call) {
thsfa294812007-02-02 22:05:00 +00004668 case IPCOP_semop:
Filip Bozutacac46eb2020-08-25 00:30:50 +02004669 ret = do_semtimedop(first, ptr, second, 0, false);
Matus Kyseld8c08b12020-06-26 14:46:11 +02004670 break;
4671 case IPCOP_semtimedop:
4672 /*
4673 * The s390 sys_ipc variant has only five parameters instead of six
4674 * (as for default variant) and the only difference is the handling of
4675 * SEMTIMEDOP where on s390 the third parameter is used as a pointer
4676 * to a struct timespec where the generic variant uses fifth parameter.
4677 */
4678#if defined(TARGET_S390X)
Filip Bozutacac46eb2020-08-25 00:30:50 +02004679 ret = do_semtimedop(first, ptr, second, third, TARGET_ABI_BITS == 64);
Matus Kyseld8c08b12020-06-26 14:46:11 +02004680#else
Filip Bozutacac46eb2020-08-25 00:30:50 +02004681 ret = do_semtimedop(first, ptr, second, fifth, TARGET_ABI_BITS == 64);
Matus Kyseld8c08b12020-06-26 14:46:11 +02004682#endif
thsfa294812007-02-02 22:05:00 +00004683 break;
4684
4685 case IPCOP_semget:
4686 ret = get_errno(semget(first, second, third));
4687 break;
4688
Tom Musta5d2fa8e2014-08-12 13:53:33 -05004689 case IPCOP_semctl: {
4690 /* The semun argument to semctl is passed by value, so dereference the
4691 * ptr argument. */
4692 abi_ulong atptr;
Tom Musta37ed0952014-08-12 13:53:35 -05004693 get_user_ual(atptr, ptr);
Stefan Weild1c002b2015-02-08 15:40:58 +01004694 ret = do_semctl(first, second, third, atptr);
thsfa294812007-02-02 22:05:00 +00004695 break;
Tom Musta5d2fa8e2014-08-12 13:53:33 -05004696 }
thsd96372e2007-02-02 22:05:44 +00004697
aurel321c54ff92008-10-13 21:08:44 +00004698 case IPCOP_msgget:
4699 ret = get_errno(msgget(first, second));
4700 break;
thsd96372e2007-02-02 22:05:44 +00004701
aurel321c54ff92008-10-13 21:08:44 +00004702 case IPCOP_msgsnd:
4703 ret = do_msgsnd(first, ptr, second, third);
4704 break;
thsd96372e2007-02-02 22:05:44 +00004705
aurel321c54ff92008-10-13 21:08:44 +00004706 case IPCOP_msgctl:
4707 ret = do_msgctl(first, second, ptr);
4708 break;
thsd96372e2007-02-02 22:05:44 +00004709
aurel321c54ff92008-10-13 21:08:44 +00004710 case IPCOP_msgrcv:
4711 switch (version) {
4712 case 0:
4713 {
4714 struct target_ipc_kludge {
4715 abi_long msgp;
4716 abi_long msgtyp;
4717 } *tmp;
thsd96372e2007-02-02 22:05:44 +00004718
aurel321c54ff92008-10-13 21:08:44 +00004719 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
4720 ret = -TARGET_EFAULT;
4721 break;
ths1bc012f2007-06-03 14:27:49 +00004722 }
aurel321c54ff92008-10-13 21:08:44 +00004723
Laurent Vivier79dd77d2012-12-20 11:00:11 +00004724 ret = do_msgrcv(first, tswapal(tmp->msgp), second, tswapal(tmp->msgtyp), third);
aurel321c54ff92008-10-13 21:08:44 +00004725
4726 unlock_user_struct(tmp, ptr, 0);
4727 break;
4728 }
4729 default:
4730 ret = do_msgrcv(first, ptr, second, fifth, third);
4731 }
4732 break;
thsd96372e2007-02-02 22:05:44 +00004733
bellard8853f862004-02-22 14:57:26 +00004734 case IPCOP_shmat:
Riku Voipio88a8c982009-04-03 10:42:00 +03004735 switch (version) {
4736 default:
bellard5a4a8982007-11-11 17:39:18 +00004737 {
4738 abi_ulong raddr;
Peter Maydellee8e7612016-07-11 16:48:11 +01004739 raddr = do_shmat(cpu_env, first, ptr, second);
Riku Voipio88a8c982009-04-03 10:42:00 +03004740 if (is_error(raddr))
4741 return get_errno(raddr);
bellard2f619692007-11-16 10:46:05 +00004742 if (put_user_ual(raddr, third))
bellard5a4a8982007-11-11 17:39:18 +00004743 return -TARGET_EFAULT;
Riku Voipio88a8c982009-04-03 10:42:00 +03004744 break;
4745 }
4746 case 1:
4747 ret = -TARGET_EINVAL;
4748 break;
bellard5a4a8982007-11-11 17:39:18 +00004749 }
bellard8853f862004-02-22 14:57:26 +00004750 break;
4751 case IPCOP_shmdt:
Riku Voipio88a8c982009-04-03 10:42:00 +03004752 ret = do_shmdt(ptr);
bellard8853f862004-02-22 14:57:26 +00004753 break;
4754
4755 case IPCOP_shmget:
4756 /* IPC_* flag values are the same on all linux platforms */
4757 ret = get_errno(shmget(first, second, third));
4758 break;
4759
4760 /* IPC_* and SHM_* command values are the same on all linux platforms */
4761 case IPCOP_shmctl:
Petar Jovanovica2926782013-10-30 14:46:32 +01004762 ret = do_shmctl(first, second, ptr);
bellard8853f862004-02-22 14:57:26 +00004763 break;
4764 default:
Josh Kunz39be5352020-02-03 18:54:13 -08004765 qemu_log_mask(LOG_UNIMP, "Unsupported ipc call: %d (version %d)\n",
4766 call, version);
ths0da46a62007-10-20 20:23:07 +00004767 ret = -TARGET_ENOSYS;
bellard8853f862004-02-22 14:57:26 +00004768 break;
4769 }
4770 return ret;
4771}
j_mayer32407102007-09-26 23:01:49 +00004772#endif
bellard8853f862004-02-22 14:57:26 +00004773
bellard31e31b82003-02-18 22:55:36 +00004774/* kernel structure types definitions */
bellard31e31b82003-02-18 22:55:36 +00004775
Blue Swirl001faf32009-05-13 17:53:17 +00004776#define STRUCT(name, ...) STRUCT_ ## name,
bellard31e31b82003-02-18 22:55:36 +00004777#define STRUCT_SPECIAL(name) STRUCT_ ## name,
4778enum {
4779#include "syscall_types.h"
Alexander Graf8be656b2015-05-06 23:47:32 +02004780STRUCT_MAX
bellard31e31b82003-02-18 22:55:36 +00004781};
4782#undef STRUCT
4783#undef STRUCT_SPECIAL
4784
Blue Swirl001faf32009-05-13 17:53:17 +00004785#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
bellard31e31b82003-02-18 22:55:36 +00004786#define STRUCT_SPECIAL(name)
4787#include "syscall_types.h"
4788#undef STRUCT
4789#undef STRUCT_SPECIAL
4790
bellard31e31b82003-02-18 22:55:36 +00004791#define MAX_STRUCT_SIZE 4096
4792
Peter Maydelldace20d2011-01-10 13:11:24 +00004793#ifdef CONFIG_FIEMAP
Peter Maydell285da2b2011-01-06 15:04:18 +00004794/* So fiemap access checks don't overflow on 32 bit systems.
4795 * This is very slightly smaller than the limit imposed by
4796 * the underlying kernel.
4797 */
4798#define FIEMAP_MAX_EXTENTS ((UINT_MAX - sizeof(struct fiemap)) \
4799 / sizeof(struct fiemap_extent))
4800
4801static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004802 int fd, int cmd, abi_long arg)
Peter Maydell285da2b2011-01-06 15:04:18 +00004803{
4804 /* The parameter for this ioctl is a struct fiemap followed
4805 * by an array of struct fiemap_extent whose size is set
4806 * in fiemap->fm_extent_count. The array is filled in by the
4807 * ioctl.
4808 */
4809 int target_size_in, target_size_out;
4810 struct fiemap *fm;
4811 const argtype *arg_type = ie->arg_type;
4812 const argtype extent_arg_type[] = { MK_STRUCT(STRUCT_fiemap_extent) };
4813 void *argptr, *p;
4814 abi_long ret;
4815 int i, extent_size = thunk_type_size(extent_arg_type, 0);
4816 uint32_t outbufsz;
4817 int free_fm = 0;
4818
4819 assert(arg_type[0] == TYPE_PTR);
4820 assert(ie->access == IOC_RW);
4821 arg_type++;
4822 target_size_in = thunk_type_size(arg_type, 0);
4823 argptr = lock_user(VERIFY_READ, arg, target_size_in, 1);
4824 if (!argptr) {
4825 return -TARGET_EFAULT;
4826 }
4827 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4828 unlock_user(argptr, arg, 0);
4829 fm = (struct fiemap *)buf_temp;
4830 if (fm->fm_extent_count > FIEMAP_MAX_EXTENTS) {
4831 return -TARGET_EINVAL;
4832 }
4833
4834 outbufsz = sizeof (*fm) +
4835 (sizeof(struct fiemap_extent) * fm->fm_extent_count);
4836
4837 if (outbufsz > MAX_STRUCT_SIZE) {
4838 /* We can't fit all the extents into the fixed size buffer.
4839 * Allocate one that is large enough and use it instead.
4840 */
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304841 fm = g_try_malloc(outbufsz);
Peter Maydell285da2b2011-01-06 15:04:18 +00004842 if (!fm) {
4843 return -TARGET_ENOMEM;
4844 }
4845 memcpy(fm, buf_temp, sizeof(struct fiemap));
4846 free_fm = 1;
4847 }
Peter Maydell49ca6f32016-06-06 19:58:14 +01004848 ret = get_errno(safe_ioctl(fd, ie->host_cmd, fm));
Peter Maydell285da2b2011-01-06 15:04:18 +00004849 if (!is_error(ret)) {
4850 target_size_out = target_size_in;
4851 /* An extent_count of 0 means we were only counting the extents
4852 * so there are no structs to copy
4853 */
4854 if (fm->fm_extent_count != 0) {
4855 target_size_out += fm->fm_mapped_extents * extent_size;
4856 }
4857 argptr = lock_user(VERIFY_WRITE, arg, target_size_out, 0);
4858 if (!argptr) {
4859 ret = -TARGET_EFAULT;
4860 } else {
4861 /* Convert the struct fiemap */
4862 thunk_convert(argptr, fm, arg_type, THUNK_TARGET);
4863 if (fm->fm_extent_count != 0) {
4864 p = argptr + target_size_in;
4865 /* ...and then all the struct fiemap_extents */
4866 for (i = 0; i < fm->fm_mapped_extents; i++) {
4867 thunk_convert(p, &fm->fm_extents[i], extent_arg_type,
4868 THUNK_TARGET);
4869 p += extent_size;
4870 }
4871 }
4872 unlock_user(argptr, arg, target_size_out);
4873 }
4874 }
4875 if (free_fm) {
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304876 g_free(fm);
Peter Maydell285da2b2011-01-06 15:04:18 +00004877 }
4878 return ret;
4879}
Peter Maydelldace20d2011-01-10 13:11:24 +00004880#endif
Peter Maydell285da2b2011-01-06 15:04:18 +00004881
Laurent Vivier059c2f22011-03-30 00:12:12 +02004882static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004883 int fd, int cmd, abi_long arg)
Laurent Vivier059c2f22011-03-30 00:12:12 +02004884{
4885 const argtype *arg_type = ie->arg_type;
4886 int target_size;
4887 void *argptr;
4888 int ret;
4889 struct ifconf *host_ifconf;
4890 uint32_t outbufsz;
4891 const argtype ifreq_arg_type[] = { MK_STRUCT(STRUCT_sockaddr_ifreq) };
Stefan4df7b7f2021-01-09 19:59:42 +01004892 const argtype ifreq_max_type[] = { MK_STRUCT(STRUCT_ifmap_ifreq) };
Laurent Vivier059c2f22011-03-30 00:12:12 +02004893 int target_ifreq_size;
4894 int nb_ifreq;
4895 int free_buf = 0;
4896 int i;
4897 int target_ifc_len;
4898 abi_long target_ifc_buf;
4899 int host_ifc_len;
4900 char *host_ifc_buf;
4901
4902 assert(arg_type[0] == TYPE_PTR);
4903 assert(ie->access == IOC_RW);
4904
4905 arg_type++;
4906 target_size = thunk_type_size(arg_type, 0);
4907
4908 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4909 if (!argptr)
4910 return -TARGET_EFAULT;
4911 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4912 unlock_user(argptr, arg, 0);
4913
4914 host_ifconf = (struct ifconf *)(unsigned long)buf_temp;
Laurent Vivier059c2f22011-03-30 00:12:12 +02004915 target_ifc_buf = (abi_long)(unsigned long)host_ifconf->ifc_buf;
Stefan4df7b7f2021-01-09 19:59:42 +01004916 target_ifreq_size = thunk_type_size(ifreq_max_type, 0);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004917
Kan Li22e4a2672018-10-24 20:13:03 +00004918 if (target_ifc_buf != 0) {
4919 target_ifc_len = host_ifconf->ifc_len;
4920 nb_ifreq = target_ifc_len / target_ifreq_size;
4921 host_ifc_len = nb_ifreq * sizeof(struct ifreq);
4922
4923 outbufsz = sizeof(*host_ifconf) + host_ifc_len;
4924 if (outbufsz > MAX_STRUCT_SIZE) {
4925 /*
4926 * We can't fit all the extents into the fixed size buffer.
4927 * Allocate one that is large enough and use it instead.
4928 */
Ahmed Abouzied7a5626a2022-01-04 16:38:41 +02004929 host_ifconf = g_try_malloc(outbufsz);
Kan Li22e4a2672018-10-24 20:13:03 +00004930 if (!host_ifconf) {
4931 return -TARGET_ENOMEM;
4932 }
4933 memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf));
4934 free_buf = 1;
Laurent Vivier059c2f22011-03-30 00:12:12 +02004935 }
Kan Li22e4a2672018-10-24 20:13:03 +00004936 host_ifc_buf = (char *)host_ifconf + sizeof(*host_ifconf);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004937
Kan Li22e4a2672018-10-24 20:13:03 +00004938 host_ifconf->ifc_len = host_ifc_len;
4939 } else {
4940 host_ifc_buf = NULL;
4941 }
Laurent Vivier059c2f22011-03-30 00:12:12 +02004942 host_ifconf->ifc_buf = host_ifc_buf;
4943
Peter Maydell49ca6f32016-06-06 19:58:14 +01004944 ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_ifconf));
Laurent Vivier059c2f22011-03-30 00:12:12 +02004945 if (!is_error(ret)) {
4946 /* convert host ifc_len to target ifc_len */
4947
4948 nb_ifreq = host_ifconf->ifc_len / sizeof(struct ifreq);
4949 target_ifc_len = nb_ifreq * target_ifreq_size;
4950 host_ifconf->ifc_len = target_ifc_len;
4951
4952 /* restore target ifc_buf */
4953
4954 host_ifconf->ifc_buf = (char *)(unsigned long)target_ifc_buf;
4955
4956 /* copy struct ifconf to target user */
4957
4958 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
4959 if (!argptr)
4960 return -TARGET_EFAULT;
4961 thunk_convert(argptr, host_ifconf, arg_type, THUNK_TARGET);
4962 unlock_user(argptr, arg, target_size);
4963
Kan Li22e4a2672018-10-24 20:13:03 +00004964 if (target_ifc_buf != 0) {
4965 /* copy ifreq[] to target user */
4966 argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0);
4967 for (i = 0; i < nb_ifreq ; i++) {
4968 thunk_convert(argptr + i * target_ifreq_size,
4969 host_ifc_buf + i * sizeof(struct ifreq),
4970 ifreq_arg_type, THUNK_TARGET);
4971 }
4972 unlock_user(argptr, target_ifc_buf, target_ifc_len);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004973 }
Laurent Vivier059c2f22011-03-30 00:12:12 +02004974 }
4975
4976 if (free_buf) {
Ahmed Abouzied7a5626a2022-01-04 16:38:41 +02004977 g_free(host_ifconf);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004978 }
4979
4980 return ret;
4981}
4982
Cortland Tölvaa1333672018-10-08 09:35:21 -07004983#if defined(CONFIG_USBFS)
4984#if HOST_LONG_BITS > 64
4985#error USBDEVFS thunks do not support >64 bit hosts yet.
4986#endif
4987struct live_urb {
4988 uint64_t target_urb_adr;
4989 uint64_t target_buf_adr;
4990 char *target_buf_ptr;
4991 struct usbdevfs_urb host_urb;
4992};
4993
4994static GHashTable *usbdevfs_urb_hashtable(void)
4995{
4996 static GHashTable *urb_hashtable;
4997
4998 if (!urb_hashtable) {
4999 urb_hashtable = g_hash_table_new(g_int64_hash, g_int64_equal);
5000 }
5001 return urb_hashtable;
5002}
5003
5004static void urb_hashtable_insert(struct live_urb *urb)
5005{
5006 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
5007 g_hash_table_insert(urb_hashtable, urb, urb);
5008}
5009
5010static struct live_urb *urb_hashtable_lookup(uint64_t target_urb_adr)
5011{
5012 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
5013 return g_hash_table_lookup(urb_hashtable, &target_urb_adr);
5014}
5015
5016static void urb_hashtable_remove(struct live_urb *urb)
5017{
5018 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
5019 g_hash_table_remove(urb_hashtable, urb);
5020}
5021
5022static abi_long
5023do_ioctl_usbdevfs_reapurb(const IOCTLEntry *ie, uint8_t *buf_temp,
5024 int fd, int cmd, abi_long arg)
5025{
5026 const argtype usbfsurb_arg_type[] = { MK_STRUCT(STRUCT_usbdevfs_urb) };
5027 const argtype ptrvoid_arg_type[] = { TYPE_PTRVOID, 0, 0 };
5028 struct live_urb *lurb;
5029 void *argptr;
5030 uint64_t hurb;
5031 int target_size;
5032 uintptr_t target_urb_adr;
5033 abi_long ret;
5034
5035 target_size = thunk_type_size(usbfsurb_arg_type, THUNK_TARGET);
5036
5037 memset(buf_temp, 0, sizeof(uint64_t));
5038 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
5039 if (is_error(ret)) {
5040 return ret;
5041 }
5042
5043 memcpy(&hurb, buf_temp, sizeof(uint64_t));
5044 lurb = (void *)((uintptr_t)hurb - offsetof(struct live_urb, host_urb));
5045 if (!lurb->target_urb_adr) {
5046 return -TARGET_EFAULT;
5047 }
5048 urb_hashtable_remove(lurb);
5049 unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr,
5050 lurb->host_urb.buffer_length);
5051 lurb->target_buf_ptr = NULL;
5052
5053 /* restore the guest buffer pointer */
5054 lurb->host_urb.buffer = (void *)(uintptr_t)lurb->target_buf_adr;
5055
5056 /* update the guest urb struct */
5057 argptr = lock_user(VERIFY_WRITE, lurb->target_urb_adr, target_size, 0);
5058 if (!argptr) {
5059 g_free(lurb);
5060 return -TARGET_EFAULT;
5061 }
5062 thunk_convert(argptr, &lurb->host_urb, usbfsurb_arg_type, THUNK_TARGET);
5063 unlock_user(argptr, lurb->target_urb_adr, target_size);
5064
5065 target_size = thunk_type_size(ptrvoid_arg_type, THUNK_TARGET);
5066 /* write back the urb handle */
5067 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5068 if (!argptr) {
5069 g_free(lurb);
5070 return -TARGET_EFAULT;
5071 }
5072
5073 /* GHashTable uses 64-bit keys but thunk_convert expects uintptr_t */
5074 target_urb_adr = lurb->target_urb_adr;
5075 thunk_convert(argptr, &target_urb_adr, ptrvoid_arg_type, THUNK_TARGET);
5076 unlock_user(argptr, arg, target_size);
5077
5078 g_free(lurb);
5079 return ret;
5080}
5081
5082static abi_long
5083do_ioctl_usbdevfs_discardurb(const IOCTLEntry *ie,
5084 uint8_t *buf_temp __attribute__((unused)),
5085 int fd, int cmd, abi_long arg)
5086{
5087 struct live_urb *lurb;
5088
5089 /* map target address back to host URB with metadata. */
5090 lurb = urb_hashtable_lookup(arg);
5091 if (!lurb) {
5092 return -TARGET_EFAULT;
5093 }
5094 return get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
5095}
5096
5097static abi_long
5098do_ioctl_usbdevfs_submiturb(const IOCTLEntry *ie, uint8_t *buf_temp,
5099 int fd, int cmd, abi_long arg)
5100{
5101 const argtype *arg_type = ie->arg_type;
5102 int target_size;
5103 abi_long ret;
5104 void *argptr;
5105 int rw_dir;
5106 struct live_urb *lurb;
5107
5108 /*
5109 * each submitted URB needs to map to a unique ID for the
5110 * kernel, and that unique ID needs to be a pointer to
5111 * host memory. hence, we need to malloc for each URB.
5112 * isochronous transfers have a variable length struct.
5113 */
5114 arg_type++;
5115 target_size = thunk_type_size(arg_type, THUNK_TARGET);
5116
5117 /* construct host copy of urb and metadata */
Markus Armbrusterb21e2382022-03-15 15:41:56 +01005118 lurb = g_try_new0(struct live_urb, 1);
Cortland Tölvaa1333672018-10-08 09:35:21 -07005119 if (!lurb) {
5120 return -TARGET_ENOMEM;
5121 }
5122
5123 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5124 if (!argptr) {
5125 g_free(lurb);
5126 return -TARGET_EFAULT;
5127 }
5128 thunk_convert(&lurb->host_urb, argptr, arg_type, THUNK_HOST);
5129 unlock_user(argptr, arg, 0);
5130
5131 lurb->target_urb_adr = arg;
5132 lurb->target_buf_adr = (uintptr_t)lurb->host_urb.buffer;
5133
5134 /* buffer space used depends on endpoint type so lock the entire buffer */
5135 /* control type urbs should check the buffer contents for true direction */
5136 rw_dir = lurb->host_urb.endpoint & USB_DIR_IN ? VERIFY_WRITE : VERIFY_READ;
5137 lurb->target_buf_ptr = lock_user(rw_dir, lurb->target_buf_adr,
5138 lurb->host_urb.buffer_length, 1);
5139 if (lurb->target_buf_ptr == NULL) {
5140 g_free(lurb);
5141 return -TARGET_EFAULT;
5142 }
5143
5144 /* update buffer pointer in host copy */
5145 lurb->host_urb.buffer = lurb->target_buf_ptr;
5146
5147 ret = get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
5148 if (is_error(ret)) {
5149 unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr, 0);
5150 g_free(lurb);
5151 } else {
5152 urb_hashtable_insert(lurb);
5153 }
5154
5155 return ret;
5156}
5157#endif /* CONFIG_USBFS */
5158
Alexander Graf56e904e2012-01-31 18:42:06 +01005159static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
Laurent Vivier45c874e2015-06-16 00:35:28 +02005160 int cmd, abi_long arg)
Alexander Graf56e904e2012-01-31 18:42:06 +01005161{
5162 void *argptr;
5163 struct dm_ioctl *host_dm;
5164 abi_long guest_data;
5165 uint32_t guest_data_size;
5166 int target_size;
5167 const argtype *arg_type = ie->arg_type;
5168 abi_long ret;
5169 void *big_buf = NULL;
5170 char *host_data;
5171
5172 arg_type++;
5173 target_size = thunk_type_size(arg_type, 0);
5174 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5175 if (!argptr) {
5176 ret = -TARGET_EFAULT;
5177 goto out;
5178 }
5179 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5180 unlock_user(argptr, arg, 0);
5181
5182 /* buf_temp is too small, so fetch things into a bigger buffer */
5183 big_buf = g_malloc0(((struct dm_ioctl*)buf_temp)->data_size * 2);
5184 memcpy(big_buf, buf_temp, target_size);
5185 buf_temp = big_buf;
5186 host_dm = big_buf;
5187
5188 guest_data = arg + host_dm->data_start;
5189 if ((guest_data - arg) < 0) {
Peter Maydellf9757b12016-07-12 13:02:14 +01005190 ret = -TARGET_EINVAL;
Alexander Graf56e904e2012-01-31 18:42:06 +01005191 goto out;
5192 }
5193 guest_data_size = host_dm->data_size - host_dm->data_start;
5194 host_data = (char*)host_dm + host_dm->data_start;
5195
5196 argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1);
Peter Maydell32112152016-07-12 13:02:13 +01005197 if (!argptr) {
5198 ret = -TARGET_EFAULT;
5199 goto out;
5200 }
5201
Alexander Graf56e904e2012-01-31 18:42:06 +01005202 switch (ie->host_cmd) {
5203 case DM_REMOVE_ALL:
5204 case DM_LIST_DEVICES:
5205 case DM_DEV_CREATE:
5206 case DM_DEV_REMOVE:
5207 case DM_DEV_SUSPEND:
5208 case DM_DEV_STATUS:
5209 case DM_DEV_WAIT:
5210 case DM_TABLE_STATUS:
5211 case DM_TABLE_CLEAR:
5212 case DM_TABLE_DEPS:
5213 case DM_LIST_VERSIONS:
5214 /* no input data */
5215 break;
5216 case DM_DEV_RENAME:
5217 case DM_DEV_SET_GEOMETRY:
5218 /* data contains only strings */
5219 memcpy(host_data, argptr, guest_data_size);
5220 break;
5221 case DM_TARGET_MSG:
5222 memcpy(host_data, argptr, guest_data_size);
5223 *(uint64_t*)host_data = tswap64(*(uint64_t*)argptr);
5224 break;
5225 case DM_TABLE_LOAD:
5226 {
5227 void *gspec = argptr;
5228 void *cur_data = host_data;
5229 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
5230 int spec_size = thunk_type_size(arg_type, 0);
5231 int i;
5232
5233 for (i = 0; i < host_dm->target_count; i++) {
5234 struct dm_target_spec *spec = cur_data;
5235 uint32_t next;
5236 int slen;
5237
5238 thunk_convert(spec, gspec, arg_type, THUNK_HOST);
5239 slen = strlen((char*)gspec + spec_size) + 1;
5240 next = spec->next;
5241 spec->next = sizeof(*spec) + slen;
5242 strcpy((char*)&spec[1], gspec + spec_size);
5243 gspec += next;
5244 cur_data += spec->next;
5245 }
5246 break;
5247 }
5248 default:
5249 ret = -TARGET_EINVAL;
Chen Gang Sdec04732015-01-25 08:00:42 +08005250 unlock_user(argptr, guest_data, 0);
Alexander Graf56e904e2012-01-31 18:42:06 +01005251 goto out;
5252 }
5253 unlock_user(argptr, guest_data, 0);
5254
Peter Maydell49ca6f32016-06-06 19:58:14 +01005255 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
Alexander Graf56e904e2012-01-31 18:42:06 +01005256 if (!is_error(ret)) {
5257 guest_data = arg + host_dm->data_start;
5258 guest_data_size = host_dm->data_size - host_dm->data_start;
5259 argptr = lock_user(VERIFY_WRITE, guest_data, guest_data_size, 0);
5260 switch (ie->host_cmd) {
5261 case DM_REMOVE_ALL:
5262 case DM_DEV_CREATE:
5263 case DM_DEV_REMOVE:
5264 case DM_DEV_RENAME:
5265 case DM_DEV_SUSPEND:
5266 case DM_DEV_STATUS:
5267 case DM_TABLE_LOAD:
5268 case DM_TABLE_CLEAR:
5269 case DM_TARGET_MSG:
5270 case DM_DEV_SET_GEOMETRY:
5271 /* no return data */
5272 break;
5273 case DM_LIST_DEVICES:
5274 {
5275 struct dm_name_list *nl = (void*)host_dm + host_dm->data_start;
5276 uint32_t remaining_data = guest_data_size;
5277 void *cur_data = argptr;
5278 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
5279 int nl_size = 12; /* can't use thunk_size due to alignment */
5280
5281 while (1) {
5282 uint32_t next = nl->next;
5283 if (next) {
5284 nl->next = nl_size + (strlen(nl->name) + 1);
5285 }
5286 if (remaining_data < nl->next) {
5287 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5288 break;
5289 }
5290 thunk_convert(cur_data, nl, arg_type, THUNK_TARGET);
5291 strcpy(cur_data + nl_size, nl->name);
5292 cur_data += nl->next;
5293 remaining_data -= nl->next;
5294 if (!next) {
5295 break;
5296 }
5297 nl = (void*)nl + next;
5298 }
5299 break;
5300 }
5301 case DM_DEV_WAIT:
5302 case DM_TABLE_STATUS:
5303 {
5304 struct dm_target_spec *spec = (void*)host_dm + host_dm->data_start;
5305 void *cur_data = argptr;
5306 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
5307 int spec_size = thunk_type_size(arg_type, 0);
5308 int i;
5309
5310 for (i = 0; i < host_dm->target_count; i++) {
5311 uint32_t next = spec->next;
5312 int slen = strlen((char*)&spec[1]) + 1;
5313 spec->next = (cur_data - argptr) + spec_size + slen;
5314 if (guest_data_size < spec->next) {
5315 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5316 break;
5317 }
5318 thunk_convert(cur_data, spec, arg_type, THUNK_TARGET);
5319 strcpy(cur_data + spec_size, (char*)&spec[1]);
5320 cur_data = argptr + spec->next;
5321 spec = (void*)host_dm + host_dm->data_start + next;
5322 }
5323 break;
5324 }
5325 case DM_TABLE_DEPS:
5326 {
5327 void *hdata = (void*)host_dm + host_dm->data_start;
5328 int count = *(uint32_t*)hdata;
5329 uint64_t *hdev = hdata + 8;
5330 uint64_t *gdev = argptr + 8;
5331 int i;
5332
5333 *(uint32_t*)argptr = tswap32(count);
5334 for (i = 0; i < count; i++) {
5335 *gdev = tswap64(*hdev);
5336 gdev++;
5337 hdev++;
5338 }
5339 break;
5340 }
5341 case DM_LIST_VERSIONS:
5342 {
5343 struct dm_target_versions *vers = (void*)host_dm + host_dm->data_start;
5344 uint32_t remaining_data = guest_data_size;
5345 void *cur_data = argptr;
5346 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_versions) };
5347 int vers_size = thunk_type_size(arg_type, 0);
5348
5349 while (1) {
5350 uint32_t next = vers->next;
5351 if (next) {
5352 vers->next = vers_size + (strlen(vers->name) + 1);
5353 }
5354 if (remaining_data < vers->next) {
5355 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5356 break;
5357 }
5358 thunk_convert(cur_data, vers, arg_type, THUNK_TARGET);
5359 strcpy(cur_data + vers_size, vers->name);
5360 cur_data += vers->next;
5361 remaining_data -= vers->next;
5362 if (!next) {
5363 break;
5364 }
5365 vers = (void*)vers + next;
5366 }
5367 break;
5368 }
5369 default:
Chen Gang Sdec04732015-01-25 08:00:42 +08005370 unlock_user(argptr, guest_data, 0);
Alexander Graf56e904e2012-01-31 18:42:06 +01005371 ret = -TARGET_EINVAL;
5372 goto out;
5373 }
5374 unlock_user(argptr, guest_data, guest_data_size);
5375
5376 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5377 if (!argptr) {
5378 ret = -TARGET_EFAULT;
5379 goto out;
5380 }
5381 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5382 unlock_user(argptr, arg, target_size);
5383 }
5384out:
Stefan Weilad11ad72012-09-04 22:14:19 +02005385 g_free(big_buf);
Alexander Graf56e904e2012-01-31 18:42:06 +01005386 return ret;
5387}
5388
Alexander Grafa59b5e32014-08-22 13:15:50 +02005389static abi_long do_ioctl_blkpg(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
Laurent Vivier45c874e2015-06-16 00:35:28 +02005390 int cmd, abi_long arg)
Alexander Grafa59b5e32014-08-22 13:15:50 +02005391{
5392 void *argptr;
5393 int target_size;
5394 const argtype *arg_type = ie->arg_type;
5395 const argtype part_arg_type[] = { MK_STRUCT(STRUCT_blkpg_partition) };
5396 abi_long ret;
5397
5398 struct blkpg_ioctl_arg *host_blkpg = (void*)buf_temp;
5399 struct blkpg_partition host_part;
5400
5401 /* Read and convert blkpg */
5402 arg_type++;
5403 target_size = thunk_type_size(arg_type, 0);
5404 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5405 if (!argptr) {
5406 ret = -TARGET_EFAULT;
5407 goto out;
5408 }
5409 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5410 unlock_user(argptr, arg, 0);
5411
5412 switch (host_blkpg->op) {
5413 case BLKPG_ADD_PARTITION:
5414 case BLKPG_DEL_PARTITION:
5415 /* payload is struct blkpg_partition */
5416 break;
5417 default:
5418 /* Unknown opcode */
5419 ret = -TARGET_EINVAL;
5420 goto out;
5421 }
5422
5423 /* Read and convert blkpg->data */
5424 arg = (abi_long)(uintptr_t)host_blkpg->data;
5425 target_size = thunk_type_size(part_arg_type, 0);
5426 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5427 if (!argptr) {
5428 ret = -TARGET_EFAULT;
5429 goto out;
5430 }
5431 thunk_convert(&host_part, argptr, part_arg_type, THUNK_HOST);
5432 unlock_user(argptr, arg, 0);
5433
5434 /* Swizzle the data pointer to our local copy and call! */
5435 host_blkpg->data = &host_part;
Peter Maydell49ca6f32016-06-06 19:58:14 +01005436 ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_blkpg));
Alexander Grafa59b5e32014-08-22 13:15:50 +02005437
5438out:
5439 return ret;
5440}
5441
Laurent Vivier7ff7b662013-07-02 14:04:12 +01005442static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02005443 int fd, int cmd, abi_long arg)
Laurent Vivier7ff7b662013-07-02 14:04:12 +01005444{
5445 const argtype *arg_type = ie->arg_type;
5446 const StructEntry *se;
5447 const argtype *field_types;
5448 const int *dst_offsets, *src_offsets;
5449 int target_size;
5450 void *argptr;
Marc-André Lureaub78c5222019-03-05 16:15:00 +01005451 abi_ulong *target_rt_dev_ptr = NULL;
5452 unsigned long *host_rt_dev_ptr = NULL;
Laurent Vivier7ff7b662013-07-02 14:04:12 +01005453 abi_long ret;
5454 int i;
5455
5456 assert(ie->access == IOC_W);
5457 assert(*arg_type == TYPE_PTR);
5458 arg_type++;
5459 assert(*arg_type == TYPE_STRUCT);
5460 target_size = thunk_type_size(arg_type, 0);
5461 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5462 if (!argptr) {
5463 return -TARGET_EFAULT;
5464 }
5465 arg_type++;
5466 assert(*arg_type == (int)STRUCT_rtentry);
5467 se = struct_entries + *arg_type++;
5468 assert(se->convert[0] == NULL);
5469 /* convert struct here to be able to catch rt_dev string */
5470 field_types = se->field_types;
5471 dst_offsets = se->field_offsets[THUNK_HOST];
5472 src_offsets = se->field_offsets[THUNK_TARGET];
5473 for (i = 0; i < se->nb_fields; i++) {
5474 if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) {
5475 assert(*field_types == TYPE_PTRVOID);
Markus Armbruster3d558332022-11-23 14:38:11 +01005476 target_rt_dev_ptr = argptr + src_offsets[i];
Laurent Vivier7ff7b662013-07-02 14:04:12 +01005477 host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]);
5478 if (*target_rt_dev_ptr != 0) {
5479 *host_rt_dev_ptr = (unsigned long)lock_user_string(
5480 tswapal(*target_rt_dev_ptr));
5481 if (!*host_rt_dev_ptr) {
5482 unlock_user(argptr, arg, 0);
5483 return -TARGET_EFAULT;
5484 }
5485 } else {
5486 *host_rt_dev_ptr = 0;
5487 }
5488 field_types++;
5489 continue;
5490 }
5491 field_types = thunk_convert(buf_temp + dst_offsets[i],
5492 argptr + src_offsets[i],
5493 field_types, THUNK_HOST);
5494 }
5495 unlock_user(argptr, arg, 0);
5496
Peter Maydell49ca6f32016-06-06 19:58:14 +01005497 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
Marc-André Lureaub78c5222019-03-05 16:15:00 +01005498
5499 assert(host_rt_dev_ptr != NULL);
5500 assert(target_rt_dev_ptr != NULL);
Laurent Vivier7ff7b662013-07-02 14:04:12 +01005501 if (*host_rt_dev_ptr != 0) {
5502 unlock_user((void *)*host_rt_dev_ptr,
5503 *target_rt_dev_ptr, 0);
5504 }
5505 return ret;
5506}
5507
Paul Burtonca56f5b2014-06-22 11:25:47 +01005508static abi_long do_ioctl_kdsigaccept(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02005509 int fd, int cmd, abi_long arg)
Paul Burtonca56f5b2014-06-22 11:25:47 +01005510{
5511 int sig = target_to_host_signal(arg);
Peter Maydell49ca6f32016-06-06 19:58:14 +01005512 return get_errno(safe_ioctl(fd, ie->host_cmd, sig));
Paul Burtonca56f5b2014-06-22 11:25:47 +01005513}
5514
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02005515static abi_long do_ioctl_SIOCGSTAMP(const IOCTLEntry *ie, uint8_t *buf_temp,
5516 int fd, int cmd, abi_long arg)
5517{
5518 struct timeval tv;
5519 abi_long ret;
5520
5521 ret = get_errno(safe_ioctl(fd, SIOCGSTAMP, &tv));
5522 if (is_error(ret)) {
5523 return ret;
5524 }
5525
5526 if (cmd == (int)TARGET_SIOCGSTAMP_OLD) {
5527 if (copy_to_user_timeval(arg, &tv)) {
5528 return -TARGET_EFAULT;
5529 }
5530 } else {
5531 if (copy_to_user_timeval64(arg, &tv)) {
5532 return -TARGET_EFAULT;
5533 }
5534 }
5535
5536 return ret;
5537}
5538
5539static abi_long do_ioctl_SIOCGSTAMPNS(const IOCTLEntry *ie, uint8_t *buf_temp,
5540 int fd, int cmd, abi_long arg)
5541{
5542 struct timespec ts;
5543 abi_long ret;
5544
5545 ret = get_errno(safe_ioctl(fd, SIOCGSTAMPNS, &ts));
5546 if (is_error(ret)) {
5547 return ret;
5548 }
5549
5550 if (cmd == (int)TARGET_SIOCGSTAMPNS_OLD) {
5551 if (host_to_target_timespec(arg, &ts)) {
5552 return -TARGET_EFAULT;
5553 }
5554 } else{
5555 if (host_to_target_timespec64(arg, &ts)) {
5556 return -TARGET_EFAULT;
5557 }
5558 }
5559
5560 return ret;
5561}
5562
Andreas Schwab2b74f622018-01-29 11:47:06 +01005563#ifdef TIOCGPTPEER
5564static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry *ie, uint8_t *buf_temp,
5565 int fd, int cmd, abi_long arg)
5566{
5567 int flags = target_to_host_bitmask(arg, fcntl_flags_tbl);
5568 return get_errno(safe_ioctl(fd, ie->host_cmd, flags));
5569}
5570#endif
5571
Chen Gange865b972020-06-05 09:32:21 +08005572#ifdef HAVE_DRM_H
5573
5574static void unlock_drm_version(struct drm_version *host_ver,
5575 struct target_drm_version *target_ver,
5576 bool copy)
5577{
5578 unlock_user(host_ver->name, target_ver->name,
5579 copy ? host_ver->name_len : 0);
5580 unlock_user(host_ver->date, target_ver->date,
5581 copy ? host_ver->date_len : 0);
5582 unlock_user(host_ver->desc, target_ver->desc,
5583 copy ? host_ver->desc_len : 0);
5584}
5585
5586static inline abi_long target_to_host_drmversion(struct drm_version *host_ver,
5587 struct target_drm_version *target_ver)
5588{
5589 memset(host_ver, 0, sizeof(*host_ver));
5590
5591 __get_user(host_ver->name_len, &target_ver->name_len);
5592 if (host_ver->name_len) {
5593 host_ver->name = lock_user(VERIFY_WRITE, target_ver->name,
5594 target_ver->name_len, 0);
5595 if (!host_ver->name) {
5596 return -EFAULT;
5597 }
5598 }
5599
5600 __get_user(host_ver->date_len, &target_ver->date_len);
5601 if (host_ver->date_len) {
5602 host_ver->date = lock_user(VERIFY_WRITE, target_ver->date,
5603 target_ver->date_len, 0);
5604 if (!host_ver->date) {
5605 goto err;
5606 }
5607 }
5608
5609 __get_user(host_ver->desc_len, &target_ver->desc_len);
5610 if (host_ver->desc_len) {
5611 host_ver->desc = lock_user(VERIFY_WRITE, target_ver->desc,
5612 target_ver->desc_len, 0);
5613 if (!host_ver->desc) {
5614 goto err;
5615 }
5616 }
5617
5618 return 0;
5619err:
5620 unlock_drm_version(host_ver, target_ver, false);
5621 return -EFAULT;
5622}
5623
5624static inline void host_to_target_drmversion(
5625 struct target_drm_version *target_ver,
5626 struct drm_version *host_ver)
5627{
5628 __put_user(host_ver->version_major, &target_ver->version_major);
5629 __put_user(host_ver->version_minor, &target_ver->version_minor);
5630 __put_user(host_ver->version_patchlevel, &target_ver->version_patchlevel);
5631 __put_user(host_ver->name_len, &target_ver->name_len);
5632 __put_user(host_ver->date_len, &target_ver->date_len);
5633 __put_user(host_ver->desc_len, &target_ver->desc_len);
5634 unlock_drm_version(host_ver, target_ver, true);
5635}
5636
5637static abi_long do_ioctl_drm(const IOCTLEntry *ie, uint8_t *buf_temp,
5638 int fd, int cmd, abi_long arg)
5639{
5640 struct drm_version *ver;
5641 struct target_drm_version *target_ver;
5642 abi_long ret;
5643
5644 switch (ie->host_cmd) {
5645 case DRM_IOCTL_VERSION:
5646 if (!lock_user_struct(VERIFY_WRITE, target_ver, arg, 0)) {
5647 return -TARGET_EFAULT;
5648 }
5649 ver = (struct drm_version *)buf_temp;
5650 ret = target_to_host_drmversion(ver, target_ver);
5651 if (!is_error(ret)) {
5652 ret = get_errno(safe_ioctl(fd, ie->host_cmd, ver));
5653 if (is_error(ret)) {
5654 unlock_drm_version(ver, target_ver, false);
5655 } else {
5656 host_to_target_drmversion(target_ver, ver);
5657 }
5658 }
5659 unlock_user_struct(target_ver, arg, 0);
5660 return ret;
5661 }
5662 return -TARGET_ENOSYS;
5663}
5664
Chen Gang913b03c2020-08-02 21:39:38 +08005665static abi_long do_ioctl_drm_i915_getparam(const IOCTLEntry *ie,
5666 struct drm_i915_getparam *gparam,
5667 int fd, abi_long arg)
5668{
5669 abi_long ret;
5670 int value;
5671 struct target_drm_i915_getparam *target_gparam;
5672
5673 if (!lock_user_struct(VERIFY_READ, target_gparam, arg, 0)) {
5674 return -TARGET_EFAULT;
5675 }
5676
5677 __get_user(gparam->param, &target_gparam->param);
5678 gparam->value = &value;
5679 ret = get_errno(safe_ioctl(fd, ie->host_cmd, gparam));
5680 put_user_s32(value, target_gparam->value);
5681
5682 unlock_user_struct(target_gparam, arg, 0);
5683 return ret;
5684}
5685
5686static abi_long do_ioctl_drm_i915(const IOCTLEntry *ie, uint8_t *buf_temp,
5687 int fd, int cmd, abi_long arg)
5688{
5689 switch (ie->host_cmd) {
5690 case DRM_IOCTL_I915_GETPARAM:
5691 return do_ioctl_drm_i915_getparam(ie,
5692 (struct drm_i915_getparam *)buf_temp,
5693 fd, arg);
5694 default:
5695 return -TARGET_ENOSYS;
5696 }
5697}
5698
Chen Gange865b972020-06-05 09:32:21 +08005699#endif
5700
Shu-Chun Weng6addf062020-09-28 18:48:01 -07005701static abi_long do_ioctl_TUNSETTXFILTER(const IOCTLEntry *ie, uint8_t *buf_temp,
5702 int fd, int cmd, abi_long arg)
5703{
5704 struct tun_filter *filter = (struct tun_filter *)buf_temp;
5705 struct tun_filter *target_filter;
5706 char *target_addr;
5707
5708 assert(ie->access == IOC_W);
5709
5710 target_filter = lock_user(VERIFY_READ, arg, sizeof(*target_filter), 1);
5711 if (!target_filter) {
5712 return -TARGET_EFAULT;
5713 }
5714 filter->flags = tswap16(target_filter->flags);
5715 filter->count = tswap16(target_filter->count);
5716 unlock_user(target_filter, arg, 0);
5717
5718 if (filter->count) {
5719 if (offsetof(struct tun_filter, addr) + filter->count * ETH_ALEN >
5720 MAX_STRUCT_SIZE) {
5721 return -TARGET_EFAULT;
5722 }
5723
5724 target_addr = lock_user(VERIFY_READ,
5725 arg + offsetof(struct tun_filter, addr),
5726 filter->count * ETH_ALEN, 1);
5727 if (!target_addr) {
5728 return -TARGET_EFAULT;
5729 }
5730 memcpy(filter->addr, target_addr, filter->count * ETH_ALEN);
5731 unlock_user(target_addr, arg + offsetof(struct tun_filter, addr), 0);
5732 }
5733
5734 return get_errno(safe_ioctl(fd, ie->host_cmd, filter));
5735}
5736
Filip Bozuta79482e592020-06-19 14:47:27 +02005737IOCTLEntry ioctl_entries[] = {
Blue Swirl001faf32009-05-13 17:53:17 +00005738#define IOCTL(cmd, access, ...) \
Peter Maydelld2ef05b2011-01-06 15:04:17 +00005739 { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
5740#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
5741 { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
Helge Deller8cb762f2016-12-06 16:24:03 +01005742#define IOCTL_IGNORE(cmd) \
5743 { TARGET_ ## cmd, 0, #cmd },
bellard31e31b82003-02-18 22:55:36 +00005744#include "ioctls.h"
5745 { 0, 0, },
5746};
5747
pbrook53a59602006-03-25 19:31:22 +00005748/* ??? Implement proper locking for ioctls. */
ths0da46a62007-10-20 20:23:07 +00005749/* do_ioctl() Must return target values and target errnos. */
Laurent Vivier45c874e2015-06-16 00:35:28 +02005750static abi_long do_ioctl(int fd, int cmd, abi_long arg)
bellard31e31b82003-02-18 22:55:36 +00005751{
5752 const IOCTLEntry *ie;
5753 const argtype *arg_type;
blueswir1992f48a2007-10-14 16:27:31 +00005754 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00005755 uint8_t buf_temp[MAX_STRUCT_SIZE];
pbrook53a59602006-03-25 19:31:22 +00005756 int target_size;
5757 void *argptr;
bellard31e31b82003-02-18 22:55:36 +00005758
5759 ie = ioctl_entries;
5760 for(;;) {
5761 if (ie->target_cmd == 0) {
Josh Kunz39be5352020-02-03 18:54:13 -08005762 qemu_log_mask(
5763 LOG_UNIMP, "Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
Thomas Weißschuh59d11722023-04-26 09:06:59 +02005764 return -TARGET_ENOTTY;
bellard31e31b82003-02-18 22:55:36 +00005765 }
5766 if (ie->target_cmd == cmd)
5767 break;
5768 ie++;
5769 }
5770 arg_type = ie->arg_type;
Peter Maydelld2ef05b2011-01-06 15:04:17 +00005771 if (ie->do_ioctl) {
5772 return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
Helge Deller8cb762f2016-12-06 16:24:03 +01005773 } else if (!ie->host_cmd) {
5774 /* Some architectures define BSD ioctls in their headers
5775 that are not implemented in Linux. */
Thomas Weißschuh59d11722023-04-26 09:06:59 +02005776 return -TARGET_ENOTTY;
Peter Maydelld2ef05b2011-01-06 15:04:17 +00005777 }
5778
bellard31e31b82003-02-18 22:55:36 +00005779 switch(arg_type[0]) {
5780 case TYPE_NULL:
5781 /* no argument */
Peter Maydell49ca6f32016-06-06 19:58:14 +01005782 ret = get_errno(safe_ioctl(fd, ie->host_cmd));
bellard31e31b82003-02-18 22:55:36 +00005783 break;
5784 case TYPE_PTRVOID:
5785 case TYPE_INT:
Filip Bozutac858e532020-01-15 20:36:47 +01005786 case TYPE_LONG:
5787 case TYPE_ULONG:
Peter Maydell49ca6f32016-06-06 19:58:14 +01005788 ret = get_errno(safe_ioctl(fd, ie->host_cmd, arg));
bellard31e31b82003-02-18 22:55:36 +00005789 break;
5790 case TYPE_PTR:
5791 arg_type++;
pbrook53a59602006-03-25 19:31:22 +00005792 target_size = thunk_type_size(arg_type, 0);
bellard31e31b82003-02-18 22:55:36 +00005793 switch(ie->access) {
5794 case IOC_R:
Peter Maydell49ca6f32016-06-06 19:58:14 +01005795 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
bellard31e31b82003-02-18 22:55:36 +00005796 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005797 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5798 if (!argptr)
5799 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005800 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5801 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00005802 }
5803 break;
5804 case IOC_W:
bellard579a97f2007-11-11 14:26:47 +00005805 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5806 if (!argptr)
5807 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005808 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5809 unlock_user(argptr, arg, 0);
Peter Maydell49ca6f32016-06-06 19:58:14 +01005810 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
bellard31e31b82003-02-18 22:55:36 +00005811 break;
5812 default:
5813 case IOC_RW:
bellard579a97f2007-11-11 14:26:47 +00005814 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5815 if (!argptr)
5816 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005817 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5818 unlock_user(argptr, arg, 0);
Peter Maydell49ca6f32016-06-06 19:58:14 +01005819 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
bellard31e31b82003-02-18 22:55:36 +00005820 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005821 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5822 if (!argptr)
5823 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005824 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5825 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00005826 }
5827 break;
5828 }
5829 break;
5830 default:
Josh Kunz39be5352020-02-03 18:54:13 -08005831 qemu_log_mask(LOG_UNIMP,
5832 "Unsupported ioctl type: cmd=0x%04lx type=%d\n",
5833 (long)cmd, arg_type[0]);
Thomas Weißschuh59d11722023-04-26 09:06:59 +02005834 ret = -TARGET_ENOTTY;
bellard31e31b82003-02-18 22:55:36 +00005835 break;
5836 }
5837 return ret;
5838}
5839
blueswir1b39bc502008-10-05 10:51:10 +00005840static const bitmask_transtbl iflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00005841 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
5842 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
5843 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
5844 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
5845 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
5846 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
5847 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
5848 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
5849 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
5850 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
5851 { TARGET_IXON, TARGET_IXON, IXON, IXON },
5852 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
5853 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
5854 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
Filip Bozutac218b4e2020-07-23 23:02:32 +02005855 { TARGET_IUTF8, TARGET_IUTF8, IUTF8, IUTF8},
bellard31e31b82003-02-18 22:55:36 +00005856 { 0, 0, 0, 0 }
5857};
5858
blueswir1b39bc502008-10-05 10:51:10 +00005859static const bitmask_transtbl oflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00005860 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
5861 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
5862 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
5863 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
5864 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
5865 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
5866 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
5867 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
5868 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
5869 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
5870 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
5871 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
5872 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
5873 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
5874 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
5875 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
5876 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
5877 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
5878 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
5879 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
5880 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
5881 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
5882 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
5883 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
5884 { 0, 0, 0, 0 }
5885};
5886
blueswir1b39bc502008-10-05 10:51:10 +00005887static const bitmask_transtbl cflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00005888 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
5889 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
5890 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
5891 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
5892 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
5893 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
5894 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
5895 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
5896 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
5897 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
5898 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
5899 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
5900 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
5901 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
5902 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
5903 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
5904 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
5905 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
5906 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
5907 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
5908 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
5909 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
5910 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
5911 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
5912 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
5913 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
5914 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
5915 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
5916 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
5917 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
5918 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
5919 { 0, 0, 0, 0 }
5920};
5921
blueswir1b39bc502008-10-05 10:51:10 +00005922static const bitmask_transtbl lflag_tbl[] = {
Filip Bozutac218b4e2020-07-23 23:02:32 +02005923 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
5924 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
5925 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
5926 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
5927 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
5928 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
5929 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
5930 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
5931 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
5932 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
5933 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
5934 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
5935 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
5936 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
5937 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
5938 { TARGET_EXTPROC, TARGET_EXTPROC, EXTPROC, EXTPROC},
5939 { 0, 0, 0, 0 }
bellard31e31b82003-02-18 22:55:36 +00005940};
5941
5942static void target_to_host_termios (void *dst, const void *src)
5943{
5944 struct host_termios *host = dst;
5945 const struct target_termios *target = src;
ths3b46e622007-09-17 08:09:54 +00005946
ths5fafdf22007-09-16 21:08:06 +00005947 host->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00005948 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00005949 host->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00005950 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00005951 host->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00005952 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00005953 host->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00005954 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
5955 host->c_line = target->c_line;
ths3b46e622007-09-17 08:09:54 +00005956
Arnaud Patard44607122009-04-21 17:39:08 +03005957 memset(host->c_cc, 0, sizeof(host->c_cc));
ths5fafdf22007-09-16 21:08:06 +00005958 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
5959 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
ths3b46e622007-09-17 08:09:54 +00005960 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
ths5fafdf22007-09-16 21:08:06 +00005961 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
ths3b46e622007-09-17 08:09:54 +00005962 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
ths5fafdf22007-09-16 21:08:06 +00005963 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
ths3b46e622007-09-17 08:09:54 +00005964 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
ths5fafdf22007-09-16 21:08:06 +00005965 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
ths3b46e622007-09-17 08:09:54 +00005966 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
ths5fafdf22007-09-16 21:08:06 +00005967 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
5968 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
ths3b46e622007-09-17 08:09:54 +00005969 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
5970 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
5971 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
5972 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
5973 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
ths5fafdf22007-09-16 21:08:06 +00005974 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
bellard31e31b82003-02-18 22:55:36 +00005975}
ths3b46e622007-09-17 08:09:54 +00005976
bellard31e31b82003-02-18 22:55:36 +00005977static void host_to_target_termios (void *dst, const void *src)
5978{
5979 struct target_termios *target = dst;
5980 const struct host_termios *host = src;
5981
ths5fafdf22007-09-16 21:08:06 +00005982 target->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00005983 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00005984 target->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00005985 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00005986 target->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00005987 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00005988 target->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00005989 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
5990 target->c_line = host->c_line;
ths3b46e622007-09-17 08:09:54 +00005991
Arnaud Patard44607122009-04-21 17:39:08 +03005992 memset(target->c_cc, 0, sizeof(target->c_cc));
bellard31e31b82003-02-18 22:55:36 +00005993 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
5994 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
5995 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
5996 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
5997 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
5998 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
5999 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
6000 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
6001 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
6002 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
6003 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
6004 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
6005 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
6006 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
6007 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
6008 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
6009 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
6010}
6011
blueswir18e853dc2008-10-05 10:49:32 +00006012static const StructEntry struct_termios_def = {
bellard31e31b82003-02-18 22:55:36 +00006013 .convert = { host_to_target_termios, target_to_host_termios },
6014 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
6015 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
Filip Bozuta888468d2020-07-23 23:02:33 +02006016 .print = print_termios,
bellard31e31b82003-02-18 22:55:36 +00006017};
6018
Richard Henderson4b840f92023-07-07 21:40:36 +01006019/* If the host does not provide these bits, they may be safely discarded. */
6020#ifndef MAP_SYNC
6021#define MAP_SYNC 0
6022#endif
6023#ifndef MAP_UNINITIALIZED
6024#define MAP_UNINITIALIZED 0
6025#endif
6026
Philippe Mathieu-Daudé180d4ef2021-05-17 07:52:43 +02006027static const bitmask_transtbl mmap_flags_tbl[] = {
Richard Henderson4b840f92023-07-07 21:40:36 +01006028 { TARGET_MAP_TYPE, TARGET_MAP_SHARED, MAP_TYPE, MAP_SHARED },
6029 { TARGET_MAP_TYPE, TARGET_MAP_PRIVATE, MAP_TYPE, MAP_PRIVATE },
6030 { TARGET_MAP_TYPE, TARGET_MAP_SHARED_VALIDATE,
6031 MAP_TYPE, MAP_SHARED_VALIDATE },
Helge Deller541e1692017-10-31 13:53:58 +01006032 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
6033 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS,
6034 MAP_ANONYMOUS, MAP_ANONYMOUS },
6035 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN,
6036 MAP_GROWSDOWN, MAP_GROWSDOWN },
6037 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE,
6038 MAP_DENYWRITE, MAP_DENYWRITE },
6039 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE,
6040 MAP_EXECUTABLE, MAP_EXECUTABLE },
6041 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
6042 { TARGET_MAP_NORESERVE, TARGET_MAP_NORESERVE,
6043 MAP_NORESERVE, MAP_NORESERVE },
6044 { TARGET_MAP_HUGETLB, TARGET_MAP_HUGETLB, MAP_HUGETLB, MAP_HUGETLB },
6045 /* MAP_STACK had been ignored by the kernel for quite some time.
6046 Recognize it for the target insofar as we do not want to pass
6047 it through to the host. */
6048 { TARGET_MAP_STACK, TARGET_MAP_STACK, 0, 0 },
Richard Henderson4b840f92023-07-07 21:40:36 +01006049 { TARGET_MAP_SYNC, TARGET_MAP_SYNC, MAP_SYNC, MAP_SYNC },
6050 { TARGET_MAP_NONBLOCK, TARGET_MAP_NONBLOCK, MAP_NONBLOCK, MAP_NONBLOCK },
6051 { TARGET_MAP_POPULATE, TARGET_MAP_POPULATE, MAP_POPULATE, MAP_POPULATE },
6052 { TARGET_MAP_FIXED_NOREPLACE, TARGET_MAP_FIXED_NOREPLACE,
6053 MAP_FIXED_NOREPLACE, MAP_FIXED_NOREPLACE },
6054 { TARGET_MAP_UNINITIALIZED, TARGET_MAP_UNINITIALIZED,
6055 MAP_UNINITIALIZED, MAP_UNINITIALIZED },
Helge Deller541e1692017-10-31 13:53:58 +01006056 { 0, 0, 0, 0 }
bellard5286db72003-06-05 00:57:30 +00006057};
6058
Laurent Vivier9d12f792020-03-10 11:33:55 +01006059/*
6060 * NOTE: TARGET_ABI32 is defined for TARGET_I386 (but not for TARGET_X86_64)
6061 * TARGET_I386 is defined if TARGET_X86_64 is defined
6062 */
bellard2ab83ea2003-06-15 19:56:46 +00006063#if defined(TARGET_I386)
bellard6dbad632003-03-16 18:05:05 +00006064
6065/* NOTE: there is really one LDT for all the threads */
blueswir1b1d8e522008-10-26 13:43:07 +00006066static uint8_t *ldt_table;
bellard6dbad632003-03-16 18:05:05 +00006067
bellard03acab62007-11-11 14:57:14 +00006068static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00006069{
6070 int size;
pbrook53a59602006-03-25 19:31:22 +00006071 void *p;
bellard6dbad632003-03-16 18:05:05 +00006072
6073 if (!ldt_table)
6074 return 0;
6075 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
6076 if (size > bytecount)
6077 size = bytecount;
bellard579a97f2007-11-11 14:26:47 +00006078 p = lock_user(VERIFY_WRITE, ptr, size, 0);
6079 if (!p)
bellard03acab62007-11-11 14:57:14 +00006080 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00006081 /* ??? Should this by byteswapped? */
pbrook53a59602006-03-25 19:31:22 +00006082 memcpy(p, ldt_table, size);
6083 unlock_user(p, ptr, size);
bellard6dbad632003-03-16 18:05:05 +00006084 return size;
6085}
6086
6087/* XXX: add locking support */
bellard03acab62007-11-11 14:57:14 +00006088static abi_long write_ldt(CPUX86State *env,
6089 abi_ulong ptr, unsigned long bytecount, int oldmode)
bellard6dbad632003-03-16 18:05:05 +00006090{
6091 struct target_modify_ldt_ldt_s ldt_info;
pbrook53a59602006-03-25 19:31:22 +00006092 struct target_modify_ldt_ldt_s *target_ldt_info;
bellard6dbad632003-03-16 18:05:05 +00006093 int seg_32bit, contents, read_exec_only, limit_in_pages;
bellard8d18e892007-11-14 15:18:40 +00006094 int seg_not_present, useable, lm;
bellard6dbad632003-03-16 18:05:05 +00006095 uint32_t *lp, entry_1, entry_2;
6096
6097 if (bytecount != sizeof(ldt_info))
bellard03acab62007-11-11 14:57:14 +00006098 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +00006099 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
bellard03acab62007-11-11 14:57:14 +00006100 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00006101 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02006102 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
pbrook53a59602006-03-25 19:31:22 +00006103 ldt_info.limit = tswap32(target_ldt_info->limit);
6104 ldt_info.flags = tswap32(target_ldt_info->flags);
6105 unlock_user_struct(target_ldt_info, ptr, 0);
ths3b46e622007-09-17 08:09:54 +00006106
bellard6dbad632003-03-16 18:05:05 +00006107 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
bellard03acab62007-11-11 14:57:14 +00006108 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00006109 seg_32bit = ldt_info.flags & 1;
6110 contents = (ldt_info.flags >> 1) & 3;
6111 read_exec_only = (ldt_info.flags >> 3) & 1;
6112 limit_in_pages = (ldt_info.flags >> 4) & 1;
6113 seg_not_present = (ldt_info.flags >> 5) & 1;
6114 useable = (ldt_info.flags >> 6) & 1;
bellard8d18e892007-11-14 15:18:40 +00006115#ifdef TARGET_ABI32
6116 lm = 0;
6117#else
6118 lm = (ldt_info.flags >> 7) & 1;
6119#endif
bellard6dbad632003-03-16 18:05:05 +00006120 if (contents == 3) {
6121 if (oldmode)
bellard03acab62007-11-11 14:57:14 +00006122 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00006123 if (seg_not_present == 0)
bellard03acab62007-11-11 14:57:14 +00006124 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00006125 }
6126 /* allocate the LDT */
6127 if (!ldt_table) {
balroge4415702008-11-10 02:55:33 +00006128 env->ldt.base = target_mmap(0,
6129 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
6130 PROT_READ|PROT_WRITE,
6131 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
6132 if (env->ldt.base == -1)
bellard03acab62007-11-11 14:57:14 +00006133 return -TARGET_ENOMEM;
Richard Henderson3e8f1622021-02-12 10:48:43 -08006134 memset(g2h_untagged(env->ldt.base), 0,
balroge4415702008-11-10 02:55:33 +00006135 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
bellard6dbad632003-03-16 18:05:05 +00006136 env->ldt.limit = 0xffff;
Richard Henderson3e8f1622021-02-12 10:48:43 -08006137 ldt_table = g2h_untagged(env->ldt.base);
bellard6dbad632003-03-16 18:05:05 +00006138 }
6139
6140 /* NOTE: same code as Linux kernel */
6141 /* Allow LDTs to be cleared by the user. */
6142 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
6143 if (oldmode ||
6144 (contents == 0 &&
6145 read_exec_only == 1 &&
6146 seg_32bit == 0 &&
6147 limit_in_pages == 0 &&
6148 seg_not_present == 1 &&
6149 useable == 0 )) {
6150 entry_1 = 0;
6151 entry_2 = 0;
6152 goto install;
6153 }
6154 }
ths3b46e622007-09-17 08:09:54 +00006155
bellard6dbad632003-03-16 18:05:05 +00006156 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
6157 (ldt_info.limit & 0x0ffff);
6158 entry_2 = (ldt_info.base_addr & 0xff000000) |
6159 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
6160 (ldt_info.limit & 0xf0000) |
6161 ((read_exec_only ^ 1) << 9) |
6162 (contents << 10) |
6163 ((seg_not_present ^ 1) << 15) |
6164 (seg_32bit << 22) |
6165 (limit_in_pages << 23) |
bellard8d18e892007-11-14 15:18:40 +00006166 (lm << 21) |
bellard6dbad632003-03-16 18:05:05 +00006167 0x7000;
6168 if (!oldmode)
6169 entry_2 |= (useable << 20);
bellard14ae3ba2003-05-27 23:25:06 +00006170
bellard6dbad632003-03-16 18:05:05 +00006171 /* Install the new entry ... */
6172install:
6173 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
6174 lp[0] = tswap32(entry_1);
6175 lp[1] = tswap32(entry_2);
6176 return 0;
6177}
6178
6179/* specific and weird i386 syscalls */
blueswir18fcd3692008-08-17 20:26:25 +00006180static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
6181 unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00006182{
bellard03acab62007-11-11 14:57:14 +00006183 abi_long ret;
ths3b46e622007-09-17 08:09:54 +00006184
bellard6dbad632003-03-16 18:05:05 +00006185 switch (func) {
6186 case 0:
6187 ret = read_ldt(ptr, bytecount);
6188 break;
6189 case 1:
6190 ret = write_ldt(env, ptr, bytecount, 1);
6191 break;
6192 case 0x11:
6193 ret = write_ldt(env, ptr, bytecount, 0);
6194 break;
bellard03acab62007-11-11 14:57:14 +00006195 default:
6196 ret = -TARGET_ENOSYS;
6197 break;
bellard6dbad632003-03-16 18:05:05 +00006198 }
6199 return ret;
6200}
bellard1b6b0292003-03-22 17:31:38 +00006201
Laurent Vivier9d12f792020-03-10 11:33:55 +01006202#if defined(TARGET_ABI32)
Alexander Grafbc22eb42013-07-16 18:44:58 +01006203abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00006204{
Richard Henderson3e8f1622021-02-12 10:48:43 -08006205 uint64_t *gdt_table = g2h_untagged(env->gdt.base);
bellard8d18e892007-11-14 15:18:40 +00006206 struct target_modify_ldt_ldt_s ldt_info;
6207 struct target_modify_ldt_ldt_s *target_ldt_info;
6208 int seg_32bit, contents, read_exec_only, limit_in_pages;
6209 int seg_not_present, useable, lm;
6210 uint32_t *lp, entry_1, entry_2;
6211 int i;
6212
6213 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
6214 if (!target_ldt_info)
6215 return -TARGET_EFAULT;
6216 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02006217 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
bellard8d18e892007-11-14 15:18:40 +00006218 ldt_info.limit = tswap32(target_ldt_info->limit);
6219 ldt_info.flags = tswap32(target_ldt_info->flags);
6220 if (ldt_info.entry_number == -1) {
6221 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
6222 if (gdt_table[i] == 0) {
6223 ldt_info.entry_number = i;
6224 target_ldt_info->entry_number = tswap32(i);
6225 break;
6226 }
6227 }
6228 }
6229 unlock_user_struct(target_ldt_info, ptr, 1);
6230
6231 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
6232 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
6233 return -TARGET_EINVAL;
6234 seg_32bit = ldt_info.flags & 1;
6235 contents = (ldt_info.flags >> 1) & 3;
6236 read_exec_only = (ldt_info.flags >> 3) & 1;
6237 limit_in_pages = (ldt_info.flags >> 4) & 1;
6238 seg_not_present = (ldt_info.flags >> 5) & 1;
6239 useable = (ldt_info.flags >> 6) & 1;
6240#ifdef TARGET_ABI32
6241 lm = 0;
6242#else
6243 lm = (ldt_info.flags >> 7) & 1;
6244#endif
6245
6246 if (contents == 3) {
6247 if (seg_not_present == 0)
6248 return -TARGET_EINVAL;
6249 }
6250
6251 /* NOTE: same code as Linux kernel */
6252 /* Allow LDTs to be cleared by the user. */
6253 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
6254 if ((contents == 0 &&
6255 read_exec_only == 1 &&
6256 seg_32bit == 0 &&
6257 limit_in_pages == 0 &&
6258 seg_not_present == 1 &&
6259 useable == 0 )) {
6260 entry_1 = 0;
6261 entry_2 = 0;
6262 goto install;
6263 }
6264 }
6265
6266 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
6267 (ldt_info.limit & 0x0ffff);
6268 entry_2 = (ldt_info.base_addr & 0xff000000) |
6269 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
6270 (ldt_info.limit & 0xf0000) |
6271 ((read_exec_only ^ 1) << 9) |
6272 (contents << 10) |
6273 ((seg_not_present ^ 1) << 15) |
6274 (seg_32bit << 22) |
6275 (limit_in_pages << 23) |
6276 (useable << 20) |
6277 (lm << 21) |
6278 0x7000;
6279
6280 /* Install the new entry ... */
6281install:
6282 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
6283 lp[0] = tswap32(entry_1);
6284 lp[1] = tswap32(entry_2);
6285 return 0;
6286}
6287
blueswir18fcd3692008-08-17 20:26:25 +00006288static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00006289{
6290 struct target_modify_ldt_ldt_s *target_ldt_info;
Richard Henderson3e8f1622021-02-12 10:48:43 -08006291 uint64_t *gdt_table = g2h_untagged(env->gdt.base);
bellard8d18e892007-11-14 15:18:40 +00006292 uint32_t base_addr, limit, flags;
6293 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
6294 int seg_not_present, useable, lm;
6295 uint32_t *lp, entry_1, entry_2;
6296
6297 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
6298 if (!target_ldt_info)
6299 return -TARGET_EFAULT;
6300 idx = tswap32(target_ldt_info->entry_number);
6301 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
6302 idx > TARGET_GDT_ENTRY_TLS_MAX) {
6303 unlock_user_struct(target_ldt_info, ptr, 1);
6304 return -TARGET_EINVAL;
6305 }
6306 lp = (uint32_t *)(gdt_table + idx);
6307 entry_1 = tswap32(lp[0]);
6308 entry_2 = tswap32(lp[1]);
6309
6310 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
6311 contents = (entry_2 >> 10) & 3;
6312 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
6313 seg_32bit = (entry_2 >> 22) & 1;
6314 limit_in_pages = (entry_2 >> 23) & 1;
6315 useable = (entry_2 >> 20) & 1;
6316#ifdef TARGET_ABI32
6317 lm = 0;
6318#else
6319 lm = (entry_2 >> 21) & 1;
6320#endif
6321 flags = (seg_32bit << 0) | (contents << 1) |
6322 (read_exec_only << 3) | (limit_in_pages << 4) |
6323 (seg_not_present << 5) | (useable << 6) | (lm << 7);
6324 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
6325 base_addr = (entry_1 >> 16) |
6326 (entry_2 & 0xff000000) |
6327 ((entry_2 & 0xff) << 16);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02006328 target_ldt_info->base_addr = tswapal(base_addr);
bellard8d18e892007-11-14 15:18:40 +00006329 target_ldt_info->limit = tswap32(limit);
6330 target_ldt_info->flags = tswap32(flags);
6331 unlock_user_struct(target_ldt_info, ptr, 1);
6332 return 0;
6333}
6334
Laurent Vivier9d12f792020-03-10 11:33:55 +01006335abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
6336{
Helge Deller538fabc2020-04-25 00:00:33 +02006337 return -TARGET_ENOSYS;
Laurent Vivier9d12f792020-03-10 11:33:55 +01006338}
6339#else
Peter Maydell2667e712013-07-16 18:44:59 +01006340abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
bellardd2fd1af2007-11-14 18:08:56 +00006341{
Juan Quintela1add8692011-06-16 17:37:09 +01006342 abi_long ret = 0;
bellardd2fd1af2007-11-14 18:08:56 +00006343 abi_ulong val;
6344 int idx;
Juan Quintela1add8692011-06-16 17:37:09 +01006345
bellardd2fd1af2007-11-14 18:08:56 +00006346 switch(code) {
6347 case TARGET_ARCH_SET_GS:
6348 case TARGET_ARCH_SET_FS:
6349 if (code == TARGET_ARCH_SET_GS)
6350 idx = R_GS;
6351 else
6352 idx = R_FS;
6353 cpu_x86_load_seg(env, idx, 0);
6354 env->segs[idx].base = addr;
6355 break;
6356 case TARGET_ARCH_GET_GS:
6357 case TARGET_ARCH_GET_FS:
6358 if (code == TARGET_ARCH_GET_GS)
6359 idx = R_GS;
6360 else
6361 idx = R_FS;
6362 val = env->segs[idx].base;
6363 if (put_user(val, addr, abi_ulong))
Juan Quintela1add8692011-06-16 17:37:09 +01006364 ret = -TARGET_EFAULT;
bellardd2fd1af2007-11-14 18:08:56 +00006365 break;
6366 default:
6367 ret = -TARGET_EINVAL;
6368 break;
6369 }
Juan Quintela1add8692011-06-16 17:37:09 +01006370 return ret;
bellardd2fd1af2007-11-14 18:08:56 +00006371}
Laurent Vivier9d12f792020-03-10 11:33:55 +01006372#endif /* defined(TARGET_ABI32 */
bellard2ab83ea2003-06-15 19:56:46 +00006373#endif /* defined(TARGET_I386) */
6374
Richard Henderson87e9bf22021-12-27 07:01:22 -08006375/*
6376 * These constants are generic. Supply any that are missing from the host.
6377 */
6378#ifndef PR_SET_NAME
6379# define PR_SET_NAME 15
6380# define PR_GET_NAME 16
6381#endif
6382#ifndef PR_SET_FP_MODE
6383# define PR_SET_FP_MODE 45
6384# define PR_GET_FP_MODE 46
6385# define PR_FP_MODE_FR (1 << 0)
6386# define PR_FP_MODE_FRE (1 << 1)
6387#endif
6388#ifndef PR_SVE_SET_VL
6389# define PR_SVE_SET_VL 50
6390# define PR_SVE_GET_VL 51
6391# define PR_SVE_VL_LEN_MASK 0xffff
6392# define PR_SVE_VL_INHERIT (1 << 17)
6393#endif
6394#ifndef PR_PAC_RESET_KEYS
6395# define PR_PAC_RESET_KEYS 54
6396# define PR_PAC_APIAKEY (1 << 0)
6397# define PR_PAC_APIBKEY (1 << 1)
6398# define PR_PAC_APDAKEY (1 << 2)
6399# define PR_PAC_APDBKEY (1 << 3)
6400# define PR_PAC_APGAKEY (1 << 4)
6401#endif
6402#ifndef PR_SET_TAGGED_ADDR_CTRL
6403# define PR_SET_TAGGED_ADDR_CTRL 55
6404# define PR_GET_TAGGED_ADDR_CTRL 56
6405# define PR_TAGGED_ADDR_ENABLE (1UL << 0)
6406#endif
6407#ifndef PR_MTE_TCF_SHIFT
6408# define PR_MTE_TCF_SHIFT 1
6409# define PR_MTE_TCF_NONE (0UL << PR_MTE_TCF_SHIFT)
6410# define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT)
6411# define PR_MTE_TCF_ASYNC (2UL << PR_MTE_TCF_SHIFT)
6412# define PR_MTE_TCF_MASK (3UL << PR_MTE_TCF_SHIFT)
6413# define PR_MTE_TAG_SHIFT 3
6414# define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT)
6415#endif
Richard Henderson220717a2021-12-27 07:01:23 -08006416#ifndef PR_SET_IO_FLUSHER
6417# define PR_SET_IO_FLUSHER 57
6418# define PR_GET_IO_FLUSHER 58
6419#endif
6420#ifndef PR_SET_SYSCALL_USER_DISPATCH
6421# define PR_SET_SYSCALL_USER_DISPATCH 59
6422#endif
Richard Henderson24d87c12022-07-08 20:45:37 +05306423#ifndef PR_SME_SET_VL
6424# define PR_SME_SET_VL 63
6425# define PR_SME_GET_VL 64
6426# define PR_SME_VL_LEN_MASK 0xffff
6427# define PR_SME_VL_INHERIT (1 << 17)
6428#endif
Richard Henderson87e9bf22021-12-27 07:01:22 -08006429
6430#include "target_prctl.h"
6431
6432static abi_long do_prctl_inval0(CPUArchState *env)
6433{
6434 return -TARGET_EINVAL;
6435}
6436
6437static abi_long do_prctl_inval1(CPUArchState *env, abi_long arg2)
6438{
6439 return -TARGET_EINVAL;
6440}
6441
6442#ifndef do_prctl_get_fp_mode
6443#define do_prctl_get_fp_mode do_prctl_inval0
6444#endif
6445#ifndef do_prctl_set_fp_mode
6446#define do_prctl_set_fp_mode do_prctl_inval1
6447#endif
Richard Hendersonfd72f5d2022-07-08 20:45:36 +05306448#ifndef do_prctl_sve_get_vl
6449#define do_prctl_sve_get_vl do_prctl_inval0
Richard Henderson87e9bf22021-12-27 07:01:22 -08006450#endif
Richard Hendersonfd72f5d2022-07-08 20:45:36 +05306451#ifndef do_prctl_sve_set_vl
6452#define do_prctl_sve_set_vl do_prctl_inval1
Richard Henderson87e9bf22021-12-27 07:01:22 -08006453#endif
6454#ifndef do_prctl_reset_keys
6455#define do_prctl_reset_keys do_prctl_inval1
6456#endif
6457#ifndef do_prctl_set_tagged_addr_ctrl
6458#define do_prctl_set_tagged_addr_ctrl do_prctl_inval1
6459#endif
6460#ifndef do_prctl_get_tagged_addr_ctrl
6461#define do_prctl_get_tagged_addr_ctrl do_prctl_inval0
6462#endif
Richard Henderson6e8dcac2021-12-27 07:01:24 -08006463#ifndef do_prctl_get_unalign
6464#define do_prctl_get_unalign do_prctl_inval1
6465#endif
6466#ifndef do_prctl_set_unalign
6467#define do_prctl_set_unalign do_prctl_inval1
6468#endif
Richard Henderson24d87c12022-07-08 20:45:37 +05306469#ifndef do_prctl_sme_get_vl
6470#define do_prctl_sme_get_vl do_prctl_inval0
6471#endif
6472#ifndef do_prctl_sme_set_vl
6473#define do_prctl_sme_set_vl do_prctl_inval1
6474#endif
Richard Henderson87e9bf22021-12-27 07:01:22 -08006475
6476static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
6477 abi_long arg3, abi_long arg4, abi_long arg5)
6478{
6479 abi_long ret;
6480
6481 switch (option) {
6482 case PR_GET_PDEATHSIG:
6483 {
6484 int deathsig;
6485 ret = get_errno(prctl(PR_GET_PDEATHSIG, &deathsig,
6486 arg3, arg4, arg5));
Richard Henderson1edebb32022-01-06 14:57:36 -08006487 if (!is_error(ret) &&
6488 put_user_s32(host_to_target_signal(deathsig), arg2)) {
Richard Henderson87e9bf22021-12-27 07:01:22 -08006489 return -TARGET_EFAULT;
6490 }
6491 return ret;
6492 }
Richard Hendersonf746c652022-01-06 14:57:37 -08006493 case PR_SET_PDEATHSIG:
6494 return get_errno(prctl(PR_SET_PDEATHSIG, target_to_host_signal(arg2),
6495 arg3, arg4, arg5));
Richard Henderson87e9bf22021-12-27 07:01:22 -08006496 case PR_GET_NAME:
6497 {
6498 void *name = lock_user(VERIFY_WRITE, arg2, 16, 1);
6499 if (!name) {
6500 return -TARGET_EFAULT;
6501 }
6502 ret = get_errno(prctl(PR_GET_NAME, (uintptr_t)name,
6503 arg3, arg4, arg5));
6504 unlock_user(name, arg2, 16);
6505 return ret;
6506 }
6507 case PR_SET_NAME:
6508 {
6509 void *name = lock_user(VERIFY_READ, arg2, 16, 1);
6510 if (!name) {
6511 return -TARGET_EFAULT;
6512 }
6513 ret = get_errno(prctl(PR_SET_NAME, (uintptr_t)name,
6514 arg3, arg4, arg5));
6515 unlock_user(name, arg2, 0);
6516 return ret;
6517 }
6518 case PR_GET_FP_MODE:
6519 return do_prctl_get_fp_mode(env);
6520 case PR_SET_FP_MODE:
6521 return do_prctl_set_fp_mode(env, arg2);
6522 case PR_SVE_GET_VL:
Richard Hendersonfd72f5d2022-07-08 20:45:36 +05306523 return do_prctl_sve_get_vl(env);
Richard Henderson87e9bf22021-12-27 07:01:22 -08006524 case PR_SVE_SET_VL:
Richard Hendersonfd72f5d2022-07-08 20:45:36 +05306525 return do_prctl_sve_set_vl(env, arg2);
Richard Henderson24d87c12022-07-08 20:45:37 +05306526 case PR_SME_GET_VL:
6527 return do_prctl_sme_get_vl(env);
6528 case PR_SME_SET_VL:
6529 return do_prctl_sme_set_vl(env, arg2);
Richard Henderson87e9bf22021-12-27 07:01:22 -08006530 case PR_PAC_RESET_KEYS:
6531 if (arg3 || arg4 || arg5) {
6532 return -TARGET_EINVAL;
6533 }
6534 return do_prctl_reset_keys(env, arg2);
6535 case PR_SET_TAGGED_ADDR_CTRL:
6536 if (arg3 || arg4 || arg5) {
6537 return -TARGET_EINVAL;
6538 }
6539 return do_prctl_set_tagged_addr_ctrl(env, arg2);
6540 case PR_GET_TAGGED_ADDR_CTRL:
6541 if (arg2 || arg3 || arg4 || arg5) {
6542 return -TARGET_EINVAL;
6543 }
6544 return do_prctl_get_tagged_addr_ctrl(env);
Richard Henderson220717a2021-12-27 07:01:23 -08006545
Richard Henderson6e8dcac2021-12-27 07:01:24 -08006546 case PR_GET_UNALIGN:
6547 return do_prctl_get_unalign(env, arg2);
6548 case PR_SET_UNALIGN:
6549 return do_prctl_set_unalign(env, arg2);
6550
Richard Henderson4f4e5562022-01-06 14:57:38 -08006551 case PR_CAP_AMBIENT:
6552 case PR_CAPBSET_READ:
6553 case PR_CAPBSET_DROP:
Richard Henderson220717a2021-12-27 07:01:23 -08006554 case PR_GET_DUMPABLE:
6555 case PR_SET_DUMPABLE:
6556 case PR_GET_KEEPCAPS:
6557 case PR_SET_KEEPCAPS:
Richard Henderson4f4e5562022-01-06 14:57:38 -08006558 case PR_GET_SECUREBITS:
6559 case PR_SET_SECUREBITS:
Richard Henderson220717a2021-12-27 07:01:23 -08006560 case PR_GET_TIMING:
6561 case PR_SET_TIMING:
6562 case PR_GET_TIMERSLACK:
6563 case PR_SET_TIMERSLACK:
6564 case PR_MCE_KILL:
6565 case PR_MCE_KILL_GET:
6566 case PR_GET_NO_NEW_PRIVS:
6567 case PR_SET_NO_NEW_PRIVS:
6568 case PR_GET_IO_FLUSHER:
6569 case PR_SET_IO_FLUSHER:
6570 /* Some prctl options have no pointer arguments and we can pass on. */
6571 return get_errno(prctl(option, arg2, arg3, arg4, arg5));
6572
6573 case PR_GET_CHILD_SUBREAPER:
6574 case PR_SET_CHILD_SUBREAPER:
6575 case PR_GET_SPECULATION_CTRL:
6576 case PR_SET_SPECULATION_CTRL:
6577 case PR_GET_TID_ADDRESS:
6578 /* TODO */
6579 return -TARGET_EINVAL;
6580
6581 case PR_GET_FPEXC:
6582 case PR_SET_FPEXC:
6583 /* Was used for SPE on PowerPC. */
6584 return -TARGET_EINVAL;
6585
6586 case PR_GET_ENDIAN:
6587 case PR_SET_ENDIAN:
6588 case PR_GET_FPEMU:
6589 case PR_SET_FPEMU:
6590 case PR_SET_MM:
Richard Henderson87e9bf22021-12-27 07:01:22 -08006591 case PR_GET_SECCOMP:
6592 case PR_SET_SECCOMP:
Richard Henderson220717a2021-12-27 07:01:23 -08006593 case PR_SET_SYSCALL_USER_DISPATCH:
6594 case PR_GET_THP_DISABLE:
6595 case PR_SET_THP_DISABLE:
6596 case PR_GET_TSC:
6597 case PR_SET_TSC:
Richard Henderson220717a2021-12-27 07:01:23 -08006598 /* Disable to prevent the target disabling stuff we need. */
Richard Henderson87e9bf22021-12-27 07:01:22 -08006599 return -TARGET_EINVAL;
Richard Henderson220717a2021-12-27 07:01:23 -08006600
Richard Henderson87e9bf22021-12-27 07:01:22 -08006601 default:
Richard Henderson220717a2021-12-27 07:01:23 -08006602 qemu_log_mask(LOG_UNIMP, "Unsupported prctl: " TARGET_ABI_FMT_ld "\n",
6603 option);
6604 return -TARGET_EINVAL;
Richard Henderson87e9bf22021-12-27 07:01:22 -08006605 }
6606}
6607
Riku Voipio05098a92011-03-04 15:27:29 +02006608#define NEW_STACK_SIZE 0x40000
pbrookd865bab2008-06-07 22:12:17 +00006609
pbrookd865bab2008-06-07 22:12:17 +00006610
6611static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
6612typedef struct {
Andreas Färber9349b4f2012-03-14 01:38:32 +01006613 CPUArchState *env;
pbrookd865bab2008-06-07 22:12:17 +00006614 pthread_mutex_t mutex;
6615 pthread_cond_t cond;
6616 pthread_t thread;
6617 uint32_t tid;
6618 abi_ulong child_tidptr;
6619 abi_ulong parent_tidptr;
6620 sigset_t sigmask;
6621} new_thread_info;
6622
6623static void *clone_func(void *arg)
6624{
6625 new_thread_info *info = arg;
Andreas Färber9349b4f2012-03-14 01:38:32 +01006626 CPUArchState *env;
Andreas Färber0d342822012-12-17 07:12:13 +01006627 CPUState *cpu;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03006628 TaskState *ts;
pbrookd865bab2008-06-07 22:12:17 +00006629
Emilio G. Cota70903762015-08-23 20:23:41 -04006630 rcu_register_thread();
Emilio G. Cota3468b592017-07-19 18:57:58 -04006631 tcg_register_thread();
pbrookd865bab2008-06-07 22:12:17 +00006632 env = info->env;
Richard Henderson29a0af62019-03-22 16:07:18 -07006633 cpu = env_cpu(env);
Andreas Färbera2247f82013-06-09 19:47:04 +02006634 thread_cpu = cpu;
Andreas Färber0429a972013-08-26 18:14:44 +02006635 ts = (TaskState *)cpu->opaque;
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +00006636 info->tid = sys_gettid();
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03006637 task_settid(ts);
pbrookd865bab2008-06-07 22:12:17 +00006638 if (info->child_tidptr)
6639 put_user_u32(info->tid, info->child_tidptr);
6640 if (info->parent_tidptr)
6641 put_user_u32(info->tid, info->parent_tidptr);
Richard Henderson5ebdd772019-03-14 13:10:53 -07006642 qemu_guest_random_seed_thread_part2(cpu->random_seed);
pbrookd865bab2008-06-07 22:12:17 +00006643 /* Enable signals. */
6644 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
6645 /* Signal to the parent that we're ready. */
6646 pthread_mutex_lock(&info->mutex);
6647 pthread_cond_broadcast(&info->cond);
6648 pthread_mutex_unlock(&info->mutex);
Emilio G. Cotaa4dd3d52017-10-18 18:01:41 -04006649 /* Wait until the parent has finished initializing the tls state. */
pbrookd865bab2008-06-07 22:12:17 +00006650 pthread_mutex_lock(&clone_lock);
6651 pthread_mutex_unlock(&clone_lock);
6652 cpu_loop(env);
6653 /* never exits */
6654 return NULL;
6655}
bellard1b6b0292003-03-22 17:31:38 +00006656
ths0da46a62007-10-20 20:23:07 +00006657/* do_fork() Must return host values and target errnos (unlike most
6658 do_*() functions). */
Andreas Färber9349b4f2012-03-14 01:38:32 +01006659static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
pbrookd865bab2008-06-07 22:12:17 +00006660 abi_ulong parent_tidptr, target_ulong newtls,
6661 abi_ulong child_tidptr)
bellard1b6b0292003-03-22 17:31:38 +00006662{
Richard Henderson29a0af62019-03-22 16:07:18 -07006663 CPUState *cpu = env_cpu(env);
bellard1b6b0292003-03-22 17:31:38 +00006664 int ret;
bellard5cd43932003-03-29 16:54:36 +00006665 TaskState *ts;
Andreas Färber0429a972013-08-26 18:14:44 +02006666 CPUState *new_cpu;
Andreas Färber9349b4f2012-03-14 01:38:32 +01006667 CPUArchState *new_env;
pbrookd865bab2008-06-07 22:12:17 +00006668 sigset_t sigmask;
ths3b46e622007-09-17 08:09:54 +00006669
Peter Maydell5ea2fc82016-08-02 18:41:27 +01006670 flags &= ~CLONE_IGNORED_FLAGS;
6671
balrog436d1242008-09-21 02:39:45 +00006672 /* Emulate vfork() with fork() */
6673 if (flags & CLONE_VFORK)
6674 flags &= ~(CLONE_VFORK | CLONE_VM);
6675
bellard1b6b0292003-03-22 17:31:38 +00006676 if (flags & CLONE_VM) {
Andreas Färber0429a972013-08-26 18:14:44 +02006677 TaskState *parent_ts = (TaskState *)cpu->opaque;
pbrookd865bab2008-06-07 22:12:17 +00006678 new_thread_info info;
6679 pthread_attr_t attr;
Peter Maydell24cb36a2013-07-16 18:45:00 +01006680
Peter Maydell5ea2fc82016-08-02 18:41:27 +01006681 if (((flags & CLONE_THREAD_FLAGS) != CLONE_THREAD_FLAGS) ||
6682 (flags & CLONE_INVALID_THREAD_FLAGS)) {
6683 return -TARGET_EINVAL;
6684 }
6685
Markus Armbrusterc78d65e2015-09-14 13:53:03 +02006686 ts = g_new0(TaskState, 1);
pbrook624f7972008-05-31 16:11:38 +00006687 init_task_state(ts);
Max Filippov73a988d2018-03-30 06:19:58 -07006688
6689 /* Grab a mutex so that thread setup appears atomic. */
6690 pthread_mutex_lock(&clone_lock);
6691
Richard Henderson6cc9d672021-03-01 19:21:08 -08006692 /*
6693 * If this is our first additional thread, we need to ensure we
6694 * generate code for parallel execution and flush old translations.
6695 * Do this now so that the copy gets CF_PARALLEL too.
6696 */
6697 if (!(cpu->tcg_cflags & CF_PARALLEL)) {
6698 cpu->tcg_cflags |= CF_PARALLEL;
6699 tb_flush(cpu);
6700 }
6701
bellard1b6b0292003-03-22 17:31:38 +00006702 /* we create a new CPU instance. */
thsc5be9f02007-02-28 20:20:53 +00006703 new_env = cpu_copy(env);
pbrook6e68e072008-05-30 17:22:15 +00006704 /* Init regs that differ from the parent. */
Richard Henderson608999d2019-11-06 12:33:15 +01006705 cpu_clone_regs_child(new_env, newsp, flags);
Richard Henderson07a6ecf2019-11-06 12:33:16 +01006706 cpu_clone_regs_parent(env, flags);
Richard Henderson29a0af62019-03-22 16:07:18 -07006707 new_cpu = env_cpu(new_env);
Andreas Färber0429a972013-08-26 18:14:44 +02006708 new_cpu->opaque = ts;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03006709 ts->bprm = parent_ts->bprm;
6710 ts->info = parent_ts->info;
Peter Maydell3d3efba2016-05-27 15:51:49 +01006711 ts->signal_mask = parent_ts->signal_mask;
pbrookd865bab2008-06-07 22:12:17 +00006712
Peter Maydell7cfbd382016-08-02 18:41:26 +01006713 if (flags & CLONE_CHILD_CLEARTID) {
pbrookc2764712009-03-07 15:24:59 +00006714 ts->child_tidptr = child_tidptr;
6715 }
6716
Peter Maydell7cfbd382016-08-02 18:41:26 +01006717 if (flags & CLONE_SETTLS) {
pbrookd865bab2008-06-07 22:12:17 +00006718 cpu_set_tls (new_env, newtls);
Peter Maydell7cfbd382016-08-02 18:41:26 +01006719 }
pbrookd865bab2008-06-07 22:12:17 +00006720
pbrookd865bab2008-06-07 22:12:17 +00006721 memset(&info, 0, sizeof(info));
6722 pthread_mutex_init(&info.mutex, NULL);
6723 pthread_mutex_lock(&info.mutex);
6724 pthread_cond_init(&info.cond, NULL);
6725 info.env = new_env;
Peter Maydell7cfbd382016-08-02 18:41:26 +01006726 if (flags & CLONE_CHILD_SETTID) {
pbrookd865bab2008-06-07 22:12:17 +00006727 info.child_tidptr = child_tidptr;
Peter Maydell7cfbd382016-08-02 18:41:26 +01006728 }
6729 if (flags & CLONE_PARENT_SETTID) {
pbrookd865bab2008-06-07 22:12:17 +00006730 info.parent_tidptr = parent_tidptr;
Peter Maydell7cfbd382016-08-02 18:41:26 +01006731 }
pbrookd865bab2008-06-07 22:12:17 +00006732
6733 ret = pthread_attr_init(&attr);
Nathan Froyd48e15fc2010-10-29 07:48:57 -07006734 ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE);
6735 ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pbrookd865bab2008-06-07 22:12:17 +00006736 /* It is not safe to deliver signals until the child has finished
6737 initializing, so temporarily block all signals. */
6738 sigfillset(&sigmask);
6739 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
Richard Henderson5ebdd772019-03-14 13:10:53 -07006740 cpu->random_seed = qemu_guest_random_seed_thread_part1();
pbrookd865bab2008-06-07 22:12:17 +00006741
6742 ret = pthread_create(&info.thread, &attr, clone_func, &info);
pbrookc2764712009-03-07 15:24:59 +00006743 /* TODO: Free new CPU state if thread creation failed. */
pbrookd865bab2008-06-07 22:12:17 +00006744
6745 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
6746 pthread_attr_destroy(&attr);
6747 if (ret == 0) {
6748 /* Wait for the child to initialize. */
6749 pthread_cond_wait(&info.cond, &info.mutex);
6750 ret = info.tid;
pbrookd865bab2008-06-07 22:12:17 +00006751 } else {
6752 ret = -1;
6753 }
6754 pthread_mutex_unlock(&info.mutex);
6755 pthread_cond_destroy(&info.cond);
6756 pthread_mutex_destroy(&info.mutex);
6757 pthread_mutex_unlock(&clone_lock);
bellard1b6b0292003-03-22 17:31:38 +00006758 } else {
6759 /* if no CLONE_VM, we consider it is a fork */
Peter Maydell5ea2fc82016-08-02 18:41:27 +01006760 if (flags & CLONE_INVALID_FORK_FLAGS) {
6761 return -TARGET_EINVAL;
6762 }
6763
6764 /* We can't support custom termination signals */
6765 if ((flags & CSIGNAL) != TARGET_SIGCHLD) {
Timothy E Baldwin93b4eff2015-08-31 00:26:21 +01006766 return -TARGET_EINVAL;
6767 }
Timothy E Baldwin7d92d342016-05-27 15:51:58 +01006768
Helge Deller895ce8b2022-11-29 12:08:20 +01006769#if !defined(__NR_pidfd_open) || !defined(TARGET_NR_pidfd_open)
6770 if (flags & CLONE_PIDFD) {
6771 return -TARGET_EINVAL;
6772 }
6773#endif
6774
6775 /* Can not allow CLONE_PIDFD with CLONE_PARENT_SETTID */
6776 if ((flags & CLONE_PIDFD) && (flags & CLONE_PARENT_SETTID)) {
6777 return -TARGET_EINVAL;
6778 }
6779
Timothy E Baldwin7d92d342016-05-27 15:51:58 +01006780 if (block_signals()) {
Richard Hendersonaf254a22021-11-22 19:47:33 +01006781 return -QEMU_ERESTARTSYS;
Timothy E Baldwin7d92d342016-05-27 15:51:58 +01006782 }
6783
pbrookd865bab2008-06-07 22:12:17 +00006784 fork_start();
bellard1b6b0292003-03-22 17:31:38 +00006785 ret = fork();
pbrookd865bab2008-06-07 22:12:17 +00006786 if (ret == 0) {
aurel322b1319c2008-12-18 22:44:04 +00006787 /* Child Process. */
Richard Henderson608999d2019-11-06 12:33:15 +01006788 cpu_clone_regs_child(env, newsp, flags);
pbrookd865bab2008-06-07 22:12:17 +00006789 fork_end(1);
aurel322b1319c2008-12-18 22:44:04 +00006790 /* There is a race condition here. The parent process could
6791 theoretically read the TID in the child process before the child
6792 tid is set. This would require using either ptrace
6793 (not implemented) or having *_tidptr to point at a shared memory
6794 mapping. We can't repeat the spinlock hack used above because
6795 the child process gets its own copy of the lock. */
pbrookd865bab2008-06-07 22:12:17 +00006796 if (flags & CLONE_CHILD_SETTID)
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +00006797 put_user_u32(sys_gettid(), child_tidptr);
pbrookd865bab2008-06-07 22:12:17 +00006798 if (flags & CLONE_PARENT_SETTID)
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +00006799 put_user_u32(sys_gettid(), parent_tidptr);
Andreas Färber0429a972013-08-26 18:14:44 +02006800 ts = (TaskState *)cpu->opaque;
pbrookd865bab2008-06-07 22:12:17 +00006801 if (flags & CLONE_SETTLS)
6802 cpu_set_tls (env, newtls);
pbrookc2764712009-03-07 15:24:59 +00006803 if (flags & CLONE_CHILD_CLEARTID)
6804 ts->child_tidptr = child_tidptr;
pbrookd865bab2008-06-07 22:12:17 +00006805 } else {
Richard Henderson07a6ecf2019-11-06 12:33:16 +01006806 cpu_clone_regs_parent(env, flags);
Helge Deller895ce8b2022-11-29 12:08:20 +01006807 if (flags & CLONE_PIDFD) {
6808 int pid_fd = 0;
6809#if defined(__NR_pidfd_open) && defined(TARGET_NR_pidfd_open)
6810 int pid_child = ret;
6811 pid_fd = pidfd_open(pid_child, 0);
6812 if (pid_fd >= 0) {
6813 fcntl(pid_fd, F_SETFD, fcntl(pid_fd, F_GETFL)
6814 | FD_CLOEXEC);
6815 } else {
6816 pid_fd = 0;
6817 }
6818#endif
6819 put_user_u32(pid_fd, parent_tidptr);
6820 }
pbrookd865bab2008-06-07 22:12:17 +00006821 fork_end(0);
6822 }
Ilya Leoshkevich7de08162023-02-14 15:08:26 +01006823 g_assert(!cpu_in_exclusive_context(cpu));
bellard1b6b0292003-03-22 17:31:38 +00006824 }
6825 return ret;
6826}
6827
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006828/* warning : doesn't handle linux specific flags... */
6829static int target_to_host_fcntl_cmd(int cmd)
6830{
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006831 int ret;
6832
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006833 switch(cmd) {
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006834 case TARGET_F_DUPFD:
6835 case TARGET_F_GETFD:
6836 case TARGET_F_SETFD:
6837 case TARGET_F_GETFL:
6838 case TARGET_F_SETFL:
Andreas Schwab2d92c682020-05-25 09:59:28 +02006839 case TARGET_F_OFD_GETLK:
6840 case TARGET_F_OFD_SETLK:
6841 case TARGET_F_OFD_SETLKW:
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006842 ret = cmd;
6843 break;
6844 case TARGET_F_GETLK:
6845 ret = F_GETLK64;
6846 break;
6847 case TARGET_F_SETLK:
6848 ret = F_SETLK64;
6849 break;
6850 case TARGET_F_SETLKW:
6851 ret = F_SETLKW64;
6852 break;
6853 case TARGET_F_GETOWN:
6854 ret = F_GETOWN;
6855 break;
6856 case TARGET_F_SETOWN:
6857 ret = F_SETOWN;
6858 break;
6859 case TARGET_F_GETSIG:
6860 ret = F_GETSIG;
6861 break;
6862 case TARGET_F_SETSIG:
6863 ret = F_SETSIG;
6864 break;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006865#if TARGET_ABI_BITS == 32
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006866 case TARGET_F_GETLK64:
6867 ret = F_GETLK64;
6868 break;
6869 case TARGET_F_SETLK64:
6870 ret = F_SETLK64;
6871 break;
6872 case TARGET_F_SETLKW64:
6873 ret = F_SETLKW64;
6874 break;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006875#endif
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006876 case TARGET_F_SETLEASE:
6877 ret = F_SETLEASE;
6878 break;
6879 case TARGET_F_GETLEASE:
6880 ret = F_GETLEASE;
6881 break;
malcfbd5de92009-09-06 06:31:59 +04006882#ifdef F_DUPFD_CLOEXEC
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006883 case TARGET_F_DUPFD_CLOEXEC:
6884 ret = F_DUPFD_CLOEXEC;
6885 break;
malcfbd5de92009-09-06 06:31:59 +04006886#endif
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006887 case TARGET_F_NOTIFY:
6888 ret = F_NOTIFY;
6889 break;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006890#ifdef F_GETOWN_EX
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006891 case TARGET_F_GETOWN_EX:
6892 ret = F_GETOWN_EX;
6893 break;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006894#endif
6895#ifdef F_SETOWN_EX
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006896 case TARGET_F_SETOWN_EX:
6897 ret = F_SETOWN_EX;
6898 break;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006899#endif
Peter Maydellddf31aa2016-06-30 17:33:49 +01006900#ifdef F_SETPIPE_SZ
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006901 case TARGET_F_SETPIPE_SZ:
6902 ret = F_SETPIPE_SZ;
6903 break;
6904 case TARGET_F_GETPIPE_SZ:
6905 ret = F_GETPIPE_SZ;
6906 break;
Peter Maydellddf31aa2016-06-30 17:33:49 +01006907#endif
Shu-Chun Weng2bb963f2020-12-18 11:32:10 -08006908#ifdef F_ADD_SEALS
6909 case TARGET_F_ADD_SEALS:
6910 ret = F_ADD_SEALS;
6911 break;
6912 case TARGET_F_GET_SEALS:
6913 ret = F_GET_SEALS;
6914 break;
6915#endif
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006916 default:
6917 ret = -TARGET_EINVAL;
6918 break;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006919 }
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006920
6921#if defined(__powerpc64__)
6922 /* On PPC64, glibc headers has the F_*LK* defined to 12, 13 and 14 and
6923 * is not supported by kernel. The glibc fcntl call actually adjusts
6924 * them to 5, 6 and 7 before making the syscall(). Since we make the
6925 * syscall directly, adjust to what is supported by the kernel.
6926 */
6927 if (ret >= F_GETLK64 && ret <= F_SETLKW64) {
6928 ret -= F_GETLK64 - 5;
6929 }
6930#endif
6931
6932 return ret;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006933}
6934
Laurent Vivierae68ad92018-05-10 01:11:21 +02006935#define FLOCK_TRANSTBL \
6936 switch (type) { \
6937 TRANSTBL_CONVERT(F_RDLCK); \
6938 TRANSTBL_CONVERT(F_WRLCK); \
6939 TRANSTBL_CONVERT(F_UNLCK); \
Laurent Vivierae68ad92018-05-10 01:11:21 +02006940 }
6941
6942static int target_to_host_flock(int type)
6943{
6944#define TRANSTBL_CONVERT(a) case TARGET_##a: return a
6945 FLOCK_TRANSTBL
6946#undef TRANSTBL_CONVERT
6947 return -TARGET_EINVAL;
6948}
6949
6950static int host_to_target_flock(int type)
6951{
6952#define TRANSTBL_CONVERT(a) case a: return TARGET_##a
6953 FLOCK_TRANSTBL
6954#undef TRANSTBL_CONVERT
6955 /* if we don't know how to convert the value coming
6956 * from the host we copy to the target field as-is
6957 */
6958 return type;
6959}
Laurent Vivier2ba7f732013-01-10 21:42:48 +01006960
Peter Maydell213d3e92016-06-13 11:22:05 +01006961static inline abi_long copy_from_user_flock(struct flock64 *fl,
6962 abi_ulong target_flock_addr)
6963{
6964 struct target_flock *target_fl;
Laurent Vivierae68ad92018-05-10 01:11:21 +02006965 int l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006966
6967 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
6968 return -TARGET_EFAULT;
6969 }
6970
6971 __get_user(l_type, &target_fl->l_type);
Laurent Vivierae68ad92018-05-10 01:11:21 +02006972 l_type = target_to_host_flock(l_type);
6973 if (l_type < 0) {
6974 return l_type;
6975 }
6976 fl->l_type = l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006977 __get_user(fl->l_whence, &target_fl->l_whence);
6978 __get_user(fl->l_start, &target_fl->l_start);
6979 __get_user(fl->l_len, &target_fl->l_len);
6980 __get_user(fl->l_pid, &target_fl->l_pid);
6981 unlock_user_struct(target_fl, target_flock_addr, 0);
6982 return 0;
6983}
6984
6985static inline abi_long copy_to_user_flock(abi_ulong target_flock_addr,
6986 const struct flock64 *fl)
6987{
6988 struct target_flock *target_fl;
6989 short l_type;
6990
6991 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
6992 return -TARGET_EFAULT;
6993 }
6994
Laurent Vivierae68ad92018-05-10 01:11:21 +02006995 l_type = host_to_target_flock(fl->l_type);
Peter Maydell213d3e92016-06-13 11:22:05 +01006996 __put_user(l_type, &target_fl->l_type);
6997 __put_user(fl->l_whence, &target_fl->l_whence);
6998 __put_user(fl->l_start, &target_fl->l_start);
6999 __put_user(fl->l_len, &target_fl->l_len);
7000 __put_user(fl->l_pid, &target_fl->l_pid);
7001 unlock_user_struct(target_fl, target_flock_addr, 1);
7002 return 0;
7003}
7004
7005typedef abi_long from_flock64_fn(struct flock64 *fl, abi_ulong target_addr);
7006typedef abi_long to_flock64_fn(abi_ulong target_addr, const struct flock64 *fl);
7007
7008#if defined(TARGET_ARM) && TARGET_ABI_BITS == 32
Richard Hendersonffe81d42022-01-06 20:25:59 -08007009struct target_oabi_flock64 {
7010 abi_short l_type;
7011 abi_short l_whence;
7012 abi_llong l_start;
7013 abi_llong l_len;
7014 abi_int l_pid;
7015} QEMU_PACKED;
7016
Laurent Vivier7f254c52018-05-02 23:57:30 +02007017static inline abi_long copy_from_user_oabi_flock64(struct flock64 *fl,
Peter Maydell213d3e92016-06-13 11:22:05 +01007018 abi_ulong target_flock_addr)
7019{
Laurent Vivier7f254c52018-05-02 23:57:30 +02007020 struct target_oabi_flock64 *target_fl;
Laurent Vivierae68ad92018-05-10 01:11:21 +02007021 int l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01007022
7023 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
7024 return -TARGET_EFAULT;
7025 }
7026
7027 __get_user(l_type, &target_fl->l_type);
Laurent Vivierae68ad92018-05-10 01:11:21 +02007028 l_type = target_to_host_flock(l_type);
7029 if (l_type < 0) {
7030 return l_type;
7031 }
7032 fl->l_type = l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01007033 __get_user(fl->l_whence, &target_fl->l_whence);
7034 __get_user(fl->l_start, &target_fl->l_start);
7035 __get_user(fl->l_len, &target_fl->l_len);
7036 __get_user(fl->l_pid, &target_fl->l_pid);
7037 unlock_user_struct(target_fl, target_flock_addr, 0);
7038 return 0;
7039}
7040
Laurent Vivier7f254c52018-05-02 23:57:30 +02007041static inline abi_long copy_to_user_oabi_flock64(abi_ulong target_flock_addr,
Peter Maydell213d3e92016-06-13 11:22:05 +01007042 const struct flock64 *fl)
7043{
Laurent Vivier7f254c52018-05-02 23:57:30 +02007044 struct target_oabi_flock64 *target_fl;
Peter Maydell213d3e92016-06-13 11:22:05 +01007045 short l_type;
7046
7047 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
7048 return -TARGET_EFAULT;
7049 }
7050
Laurent Vivierae68ad92018-05-10 01:11:21 +02007051 l_type = host_to_target_flock(fl->l_type);
Peter Maydell213d3e92016-06-13 11:22:05 +01007052 __put_user(l_type, &target_fl->l_type);
7053 __put_user(fl->l_whence, &target_fl->l_whence);
7054 __put_user(fl->l_start, &target_fl->l_start);
7055 __put_user(fl->l_len, &target_fl->l_len);
7056 __put_user(fl->l_pid, &target_fl->l_pid);
7057 unlock_user_struct(target_fl, target_flock_addr, 1);
7058 return 0;
7059}
7060#endif
7061
7062static inline abi_long copy_from_user_flock64(struct flock64 *fl,
7063 abi_ulong target_flock_addr)
7064{
7065 struct target_flock64 *target_fl;
Laurent Vivierae68ad92018-05-10 01:11:21 +02007066 int l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01007067
7068 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
7069 return -TARGET_EFAULT;
7070 }
7071
7072 __get_user(l_type, &target_fl->l_type);
Laurent Vivierae68ad92018-05-10 01:11:21 +02007073 l_type = target_to_host_flock(l_type);
7074 if (l_type < 0) {
7075 return l_type;
7076 }
7077 fl->l_type = l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01007078 __get_user(fl->l_whence, &target_fl->l_whence);
7079 __get_user(fl->l_start, &target_fl->l_start);
7080 __get_user(fl->l_len, &target_fl->l_len);
7081 __get_user(fl->l_pid, &target_fl->l_pid);
7082 unlock_user_struct(target_fl, target_flock_addr, 0);
7083 return 0;
7084}
7085
7086static inline abi_long copy_to_user_flock64(abi_ulong target_flock_addr,
7087 const struct flock64 *fl)
7088{
7089 struct target_flock64 *target_fl;
7090 short l_type;
7091
7092 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
7093 return -TARGET_EFAULT;
7094 }
7095
Laurent Vivierae68ad92018-05-10 01:11:21 +02007096 l_type = host_to_target_flock(fl->l_type);
Peter Maydell213d3e92016-06-13 11:22:05 +01007097 __put_user(l_type, &target_fl->l_type);
7098 __put_user(fl->l_whence, &target_fl->l_whence);
7099 __put_user(fl->l_start, &target_fl->l_start);
7100 __put_user(fl->l_len, &target_fl->l_len);
7101 __put_user(fl->l_pid, &target_fl->l_pid);
7102 unlock_user_struct(target_fl, target_flock_addr, 1);
7103 return 0;
7104}
7105
blueswir1992f48a2007-10-14 16:27:31 +00007106static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
bellard7775e9e2003-05-14 22:46:48 +00007107{
ths43f238d2007-01-05 20:55:49 +00007108 struct flock64 fl64;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01007109#ifdef F_GETOWN_EX
7110 struct f_owner_ex fox;
7111 struct target_f_owner_ex *target_fox;
7112#endif
blueswir1992f48a2007-10-14 16:27:31 +00007113 abi_long ret;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007114 int host_cmd = target_to_host_fcntl_cmd(cmd);
7115
7116 if (host_cmd == -TARGET_EINVAL)
7117 return host_cmd;
pbrook53a59602006-03-25 19:31:22 +00007118
bellard7775e9e2003-05-14 22:46:48 +00007119 switch(cmd) {
7120 case TARGET_F_GETLK:
Peter Maydell213d3e92016-06-13 11:22:05 +01007121 ret = copy_from_user_flock(&fl64, arg);
7122 if (ret) {
7123 return ret;
7124 }
Peter Maydell435da5e2016-06-13 11:22:05 +01007125 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00007126 if (ret == 0) {
Peter Maydell213d3e92016-06-13 11:22:05 +01007127 ret = copy_to_user_flock(arg, &fl64);
bellard7775e9e2003-05-14 22:46:48 +00007128 }
7129 break;
ths3b46e622007-09-17 08:09:54 +00007130
bellard7775e9e2003-05-14 22:46:48 +00007131 case TARGET_F_SETLK:
7132 case TARGET_F_SETLKW:
Peter Maydell213d3e92016-06-13 11:22:05 +01007133 ret = copy_from_user_flock(&fl64, arg);
7134 if (ret) {
7135 return ret;
7136 }
Peter Maydell435da5e2016-06-13 11:22:05 +01007137 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00007138 break;
ths3b46e622007-09-17 08:09:54 +00007139
bellard7775e9e2003-05-14 22:46:48 +00007140 case TARGET_F_GETLK64:
Andreas Schwab2d92c682020-05-25 09:59:28 +02007141 case TARGET_F_OFD_GETLK:
Peter Maydell213d3e92016-06-13 11:22:05 +01007142 ret = copy_from_user_flock64(&fl64, arg);
7143 if (ret) {
7144 return ret;
7145 }
Peter Maydell435da5e2016-06-13 11:22:05 +01007146 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
ths43f238d2007-01-05 20:55:49 +00007147 if (ret == 0) {
Peter Maydell213d3e92016-06-13 11:22:05 +01007148 ret = copy_to_user_flock64(arg, &fl64);
ths43f238d2007-01-05 20:55:49 +00007149 }
bellard9ee1fa22007-11-11 15:11:19 +00007150 break;
bellard7775e9e2003-05-14 22:46:48 +00007151 case TARGET_F_SETLK64:
7152 case TARGET_F_SETLKW64:
Andreas Schwab2d92c682020-05-25 09:59:28 +02007153 case TARGET_F_OFD_SETLK:
7154 case TARGET_F_OFD_SETLKW:
Peter Maydell213d3e92016-06-13 11:22:05 +01007155 ret = copy_from_user_flock64(&fl64, arg);
7156 if (ret) {
7157 return ret;
7158 }
Peter Maydell435da5e2016-06-13 11:22:05 +01007159 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00007160 break;
7161
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007162 case TARGET_F_GETFL:
Peter Maydell435da5e2016-06-13 11:22:05 +01007163 ret = get_errno(safe_fcntl(fd, host_cmd, arg));
bellard9ee1fa22007-11-11 15:11:19 +00007164 if (ret >= 0) {
7165 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
Helge Dellere0ddf8e2023-07-08 07:00:25 +02007166 /* tell 32-bit guests it uses largefile on 64-bit hosts: */
7167 if (O_LARGEFILE == 0 && HOST_LONG_BITS == 64) {
7168 ret |= TARGET_O_LARGEFILE;
7169 }
bellard9ee1fa22007-11-11 15:11:19 +00007170 }
bellardffa65c32004-01-04 23:57:22 +00007171 break;
7172
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007173 case TARGET_F_SETFL:
Peter Maydell435da5e2016-06-13 11:22:05 +01007174 ret = get_errno(safe_fcntl(fd, host_cmd,
7175 target_to_host_bitmask(arg,
7176 fcntl_flags_tbl)));
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007177 break;
7178
Andreas Schwab8d5d3002014-03-07 15:24:08 +01007179#ifdef F_GETOWN_EX
7180 case TARGET_F_GETOWN_EX:
Peter Maydell435da5e2016-06-13 11:22:05 +01007181 ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
Andreas Schwab8d5d3002014-03-07 15:24:08 +01007182 if (ret >= 0) {
7183 if (!lock_user_struct(VERIFY_WRITE, target_fox, arg, 0))
7184 return -TARGET_EFAULT;
7185 target_fox->type = tswap32(fox.type);
7186 target_fox->pid = tswap32(fox.pid);
7187 unlock_user_struct(target_fox, arg, 1);
7188 }
7189 break;
7190#endif
7191
7192#ifdef F_SETOWN_EX
7193 case TARGET_F_SETOWN_EX:
7194 if (!lock_user_struct(VERIFY_READ, target_fox, arg, 1))
7195 return -TARGET_EFAULT;
7196 fox.type = tswap32(target_fox->type);
7197 fox.pid = tswap32(target_fox->pid);
7198 unlock_user_struct(target_fox, arg, 0);
Peter Maydell435da5e2016-06-13 11:22:05 +01007199 ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
Andreas Schwab8d5d3002014-03-07 15:24:08 +01007200 break;
7201#endif
7202
Timothy Baldwina7b4c9b2020-07-29 21:06:44 +01007203 case TARGET_F_SETSIG:
7204 ret = get_errno(safe_fcntl(fd, host_cmd, target_to_host_signal(arg)));
7205 break;
7206
7207 case TARGET_F_GETSIG:
7208 ret = host_to_target_signal(get_errno(safe_fcntl(fd, host_cmd, arg)));
7209 break;
7210
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007211 case TARGET_F_SETOWN:
7212 case TARGET_F_GETOWN:
Ulrich Hecht7e22e542009-07-24 19:10:27 +02007213 case TARGET_F_SETLEASE:
7214 case TARGET_F_GETLEASE:
Peter Maydell7e3b92e2016-06-20 15:50:37 +01007215 case TARGET_F_SETPIPE_SZ:
7216 case TARGET_F_GETPIPE_SZ:
Shu-Chun Weng2bb963f2020-12-18 11:32:10 -08007217 case TARGET_F_ADD_SEALS:
7218 case TARGET_F_GET_SEALS:
Peter Maydell435da5e2016-06-13 11:22:05 +01007219 ret = get_errno(safe_fcntl(fd, host_cmd, arg));
bellardffa65c32004-01-04 23:57:22 +00007220 break;
7221
bellard7775e9e2003-05-14 22:46:48 +00007222 default:
Peter Maydell435da5e2016-06-13 11:22:05 +01007223 ret = get_errno(safe_fcntl(fd, cmd, arg));
bellard7775e9e2003-05-14 22:46:48 +00007224 break;
7225 }
7226 return ret;
7227}
7228
bellard67867302003-11-23 17:05:30 +00007229#ifdef USE_UID16
bellard7775e9e2003-05-14 22:46:48 +00007230
bellard67867302003-11-23 17:05:30 +00007231static inline int high2lowuid(int uid)
7232{
7233 if (uid > 65535)
7234 return 65534;
7235 else
7236 return uid;
7237}
7238
7239static inline int high2lowgid(int gid)
7240{
7241 if (gid > 65535)
7242 return 65534;
7243 else
7244 return gid;
7245}
7246
7247static inline int low2highuid(int uid)
7248{
7249 if ((int16_t)uid == -1)
7250 return -1;
7251 else
7252 return uid;
7253}
7254
7255static inline int low2highgid(int gid)
7256{
7257 if ((int16_t)gid == -1)
7258 return -1;
7259 else
7260 return gid;
7261}
Riku Voipio0c866a72011-04-18 15:23:06 +03007262static inline int tswapid(int id)
7263{
7264 return tswap16(id);
7265}
Peter Maydell76ca3102014-03-02 19:36:41 +00007266
7267#define put_user_id(x, gaddr) put_user_u16(x, gaddr)
7268
Riku Voipio0c866a72011-04-18 15:23:06 +03007269#else /* !USE_UID16 */
7270static inline int high2lowuid(int uid)
7271{
7272 return uid;
7273}
7274static inline int high2lowgid(int gid)
7275{
7276 return gid;
7277}
7278static inline int low2highuid(int uid)
7279{
7280 return uid;
7281}
7282static inline int low2highgid(int gid)
7283{
7284 return gid;
7285}
7286static inline int tswapid(int id)
7287{
7288 return tswap32(id);
7289}
Peter Maydell76ca3102014-03-02 19:36:41 +00007290
7291#define put_user_id(x, gaddr) put_user_u32(x, gaddr)
7292
bellard67867302003-11-23 17:05:30 +00007293#endif /* USE_UID16 */
bellard1b6b0292003-03-22 17:31:38 +00007294
Peter Maydellfd6f7792016-03-01 16:33:02 +00007295/* We must do direct syscalls for setting UID/GID, because we want to
7296 * implement the Linux system call semantics of "change only for this thread",
7297 * not the libc/POSIX semantics of "change for all threads in process".
7298 * (See http://ewontfix.com/17/ for more details.)
7299 * We use the 32-bit version of the syscalls if present; if it is not
7300 * then either the host architecture supports 32-bit UIDs natively with
7301 * the standard syscall, or the 16-bit UID is the best we can do.
7302 */
7303#ifdef __NR_setuid32
7304#define __NR_sys_setuid __NR_setuid32
7305#else
7306#define __NR_sys_setuid __NR_setuid
7307#endif
7308#ifdef __NR_setgid32
7309#define __NR_sys_setgid __NR_setgid32
7310#else
7311#define __NR_sys_setgid __NR_setgid
7312#endif
7313#ifdef __NR_setresuid32
7314#define __NR_sys_setresuid __NR_setresuid32
7315#else
7316#define __NR_sys_setresuid __NR_setresuid
7317#endif
7318#ifdef __NR_setresgid32
7319#define __NR_sys_setresgid __NR_setresgid32
7320#else
7321#define __NR_sys_setresgid __NR_setresgid
7322#endif
7323
7324_syscall1(int, sys_setuid, uid_t, uid)
7325_syscall1(int, sys_setgid, gid_t, gid)
7326_syscall3(int, sys_setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
7327_syscall3(int, sys_setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
7328
bellard31e31b82003-02-18 22:55:36 +00007329void syscall_init(void)
7330{
bellard2ab83ea2003-06-15 19:56:46 +00007331 IOCTLEntry *ie;
7332 const argtype *arg_type;
7333 int size;
7334
Alexander Graf8be656b2015-05-06 23:47:32 +02007335 thunk_init(STRUCT_MAX);
7336
Blue Swirl001faf32009-05-13 17:53:17 +00007337#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
ths5fafdf22007-09-16 21:08:06 +00007338#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
bellard31e31b82003-02-18 22:55:36 +00007339#include "syscall_types.h"
7340#undef STRUCT
7341#undef STRUCT_SPECIAL
bellard2ab83ea2003-06-15 19:56:46 +00007342
7343 /* we patch the ioctl size if necessary. We rely on the fact that
7344 no ioctl has all the bits at '1' in the size field */
7345 ie = ioctl_entries;
7346 while (ie->target_cmd != 0) {
7347 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
7348 TARGET_IOC_SIZEMASK) {
7349 arg_type = ie->arg_type;
7350 if (arg_type[0] != TYPE_PTR) {
ths5fafdf22007-09-16 21:08:06 +00007351 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00007352 ie->target_cmd);
7353 exit(1);
7354 }
7355 arg_type++;
7356 size = thunk_type_size(arg_type, 0);
ths5fafdf22007-09-16 21:08:06 +00007357 ie->target_cmd = (ie->target_cmd &
bellard2ab83ea2003-06-15 19:56:46 +00007358 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
7359 (size << TARGET_IOC_SIZESHIFT);
7360 }
thsb92c47c2007-11-01 00:07:38 +00007361
bellard2ab83ea2003-06-15 19:56:46 +00007362 /* automatic consistency check if same arch */
balrog872ea0c2008-09-21 02:31:19 +00007363#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
7364 (defined(__x86_64__) && defined(TARGET_X86_64))
7365 if (unlikely(ie->target_cmd != ie->host_cmd)) {
7366 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
7367 ie->name, ie->target_cmd, ie->host_cmd);
bellard2ab83ea2003-06-15 19:56:46 +00007368 }
7369#endif
7370 ie++;
7371 }
bellard31e31b82003-02-18 22:55:36 +00007372}
bellardc573ff62004-01-04 15:51:36 +00007373
pbrookce4defa2006-02-09 16:49:55 +00007374#ifdef TARGET_NR_truncate64
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02007375static inline abi_long target_truncate64(CPUArchState *cpu_env, const char *arg1,
blueswir1992f48a2007-10-14 16:27:31 +00007376 abi_long arg2,
7377 abi_long arg3,
7378 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00007379{
James Clarke8bf8e9d2017-09-15 20:33:13 +01007380 if (regpairs_aligned(cpu_env, TARGET_NR_truncate64)) {
pbrookce4defa2006-02-09 16:49:55 +00007381 arg2 = arg3;
7382 arg3 = arg4;
Riku Voipio48e515d2011-07-12 15:40:51 +03007383 }
pbrookce4defa2006-02-09 16:49:55 +00007384 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
7385}
7386#endif
7387
7388#ifdef TARGET_NR_ftruncate64
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02007389static inline abi_long target_ftruncate64(CPUArchState *cpu_env, abi_long arg1,
blueswir1992f48a2007-10-14 16:27:31 +00007390 abi_long arg2,
7391 abi_long arg3,
7392 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00007393{
James Clarke8bf8e9d2017-09-15 20:33:13 +01007394 if (regpairs_aligned(cpu_env, TARGET_NR_ftruncate64)) {
pbrookce4defa2006-02-09 16:49:55 +00007395 arg2 = arg3;
7396 arg3 = arg4;
Riku Voipio48e515d2011-07-12 15:40:51 +03007397 }
pbrookce4defa2006-02-09 16:49:55 +00007398 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
7399}
7400#endif
7401
Alistair Francis859e8a82020-03-12 15:13:49 -07007402#if defined(TARGET_NR_timer_settime) || \
7403 (defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD))
Filip Bozuta2c86c902020-07-22 17:34:20 +02007404static inline abi_long target_to_host_itimerspec(struct itimerspec *host_its,
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007405 abi_ulong target_addr)
7406{
Filip Bozuta2c86c902020-07-22 17:34:20 +02007407 if (target_to_host_timespec(&host_its->it_interval, target_addr +
7408 offsetof(struct target_itimerspec,
7409 it_interval)) ||
7410 target_to_host_timespec(&host_its->it_value, target_addr +
7411 offsetof(struct target_itimerspec,
7412 it_value))) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007413 return -TARGET_EFAULT;
7414 }
7415
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007416 return 0;
7417}
Alistair Francis859e8a82020-03-12 15:13:49 -07007418#endif
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007419
Filip Bozuta828cb3a2020-07-22 17:34:21 +02007420#if defined(TARGET_NR_timer_settime64) || \
7421 (defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD))
7422static inline abi_long target_to_host_itimerspec64(struct itimerspec *host_its,
7423 abi_ulong target_addr)
7424{
7425 if (target_to_host_timespec64(&host_its->it_interval, target_addr +
7426 offsetof(struct target__kernel_itimerspec,
7427 it_interval)) ||
7428 target_to_host_timespec64(&host_its->it_value, target_addr +
7429 offsetof(struct target__kernel_itimerspec,
7430 it_value))) {
7431 return -TARGET_EFAULT;
7432 }
7433
7434 return 0;
7435}
7436#endif
7437
Alistair Francis859e8a82020-03-12 15:13:49 -07007438#if ((defined(TARGET_NR_timerfd_gettime) || \
7439 defined(TARGET_NR_timerfd_settime)) && defined(CONFIG_TIMERFD)) || \
Filip Bozuta2c86c902020-07-22 17:34:20 +02007440 defined(TARGET_NR_timer_gettime) || defined(TARGET_NR_timer_settime)
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007441static inline abi_long host_to_target_itimerspec(abi_ulong target_addr,
Filip Bozuta2c86c902020-07-22 17:34:20 +02007442 struct itimerspec *host_its)
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007443{
Filip Bozuta2c86c902020-07-22 17:34:20 +02007444 if (host_to_target_timespec(target_addr + offsetof(struct target_itimerspec,
7445 it_interval),
7446 &host_its->it_interval) ||
7447 host_to_target_timespec(target_addr + offsetof(struct target_itimerspec,
7448 it_value),
7449 &host_its->it_value)) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007450 return -TARGET_EFAULT;
7451 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007452 return 0;
7453}
Alistair Francis859e8a82020-03-12 15:13:49 -07007454#endif
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007455
Filip Bozuta828cb3a2020-07-22 17:34:21 +02007456#if ((defined(TARGET_NR_timerfd_gettime64) || \
7457 defined(TARGET_NR_timerfd_settime64)) && defined(CONFIG_TIMERFD)) || \
7458 defined(TARGET_NR_timer_gettime64) || defined(TARGET_NR_timer_settime64)
7459static inline abi_long host_to_target_itimerspec64(abi_ulong target_addr,
7460 struct itimerspec *host_its)
7461{
7462 if (host_to_target_timespec64(target_addr +
7463 offsetof(struct target__kernel_itimerspec,
7464 it_interval),
7465 &host_its->it_interval) ||
7466 host_to_target_timespec64(target_addr +
7467 offsetof(struct target__kernel_itimerspec,
7468 it_value),
7469 &host_its->it_value)) {
7470 return -TARGET_EFAULT;
7471 }
7472 return 0;
7473}
7474#endif
7475
Alistair Francis859e8a82020-03-12 15:13:49 -07007476#if defined(TARGET_NR_adjtimex) || \
7477 (defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME))
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +02007478static inline abi_long target_to_host_timex(struct timex *host_tx,
7479 abi_long target_addr)
7480{
7481 struct target_timex *target_tx;
7482
7483 if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) {
7484 return -TARGET_EFAULT;
7485 }
7486
7487 __get_user(host_tx->modes, &target_tx->modes);
7488 __get_user(host_tx->offset, &target_tx->offset);
7489 __get_user(host_tx->freq, &target_tx->freq);
7490 __get_user(host_tx->maxerror, &target_tx->maxerror);
7491 __get_user(host_tx->esterror, &target_tx->esterror);
7492 __get_user(host_tx->status, &target_tx->status);
7493 __get_user(host_tx->constant, &target_tx->constant);
7494 __get_user(host_tx->precision, &target_tx->precision);
7495 __get_user(host_tx->tolerance, &target_tx->tolerance);
7496 __get_user(host_tx->time.tv_sec, &target_tx->time.tv_sec);
7497 __get_user(host_tx->time.tv_usec, &target_tx->time.tv_usec);
7498 __get_user(host_tx->tick, &target_tx->tick);
7499 __get_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7500 __get_user(host_tx->jitter, &target_tx->jitter);
7501 __get_user(host_tx->shift, &target_tx->shift);
7502 __get_user(host_tx->stabil, &target_tx->stabil);
7503 __get_user(host_tx->jitcnt, &target_tx->jitcnt);
7504 __get_user(host_tx->calcnt, &target_tx->calcnt);
7505 __get_user(host_tx->errcnt, &target_tx->errcnt);
7506 __get_user(host_tx->stbcnt, &target_tx->stbcnt);
7507 __get_user(host_tx->tai, &target_tx->tai);
7508
7509 unlock_user_struct(target_tx, target_addr, 0);
7510 return 0;
7511}
7512
7513static inline abi_long host_to_target_timex(abi_long target_addr,
7514 struct timex *host_tx)
7515{
7516 struct target_timex *target_tx;
7517
7518 if (!lock_user_struct(VERIFY_WRITE, target_tx, target_addr, 0)) {
7519 return -TARGET_EFAULT;
7520 }
7521
7522 __put_user(host_tx->modes, &target_tx->modes);
7523 __put_user(host_tx->offset, &target_tx->offset);
7524 __put_user(host_tx->freq, &target_tx->freq);
7525 __put_user(host_tx->maxerror, &target_tx->maxerror);
7526 __put_user(host_tx->esterror, &target_tx->esterror);
7527 __put_user(host_tx->status, &target_tx->status);
7528 __put_user(host_tx->constant, &target_tx->constant);
7529 __put_user(host_tx->precision, &target_tx->precision);
7530 __put_user(host_tx->tolerance, &target_tx->tolerance);
7531 __put_user(host_tx->time.tv_sec, &target_tx->time.tv_sec);
7532 __put_user(host_tx->time.tv_usec, &target_tx->time.tv_usec);
7533 __put_user(host_tx->tick, &target_tx->tick);
7534 __put_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7535 __put_user(host_tx->jitter, &target_tx->jitter);
7536 __put_user(host_tx->shift, &target_tx->shift);
7537 __put_user(host_tx->stabil, &target_tx->stabil);
7538 __put_user(host_tx->jitcnt, &target_tx->jitcnt);
7539 __put_user(host_tx->calcnt, &target_tx->calcnt);
7540 __put_user(host_tx->errcnt, &target_tx->errcnt);
7541 __put_user(host_tx->stbcnt, &target_tx->stbcnt);
7542 __put_user(host_tx->tai, &target_tx->tai);
7543
7544 unlock_user_struct(target_tx, target_addr, 1);
7545 return 0;
7546}
Alistair Francis859e8a82020-03-12 15:13:49 -07007547#endif
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +02007548
Filip Bozuta6ac03b22020-08-24 21:21:15 +02007549
7550#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
7551static inline abi_long target_to_host_timex64(struct timex *host_tx,
7552 abi_long target_addr)
7553{
7554 struct target__kernel_timex *target_tx;
7555
7556 if (copy_from_user_timeval64(&host_tx->time, target_addr +
7557 offsetof(struct target__kernel_timex,
7558 time))) {
7559 return -TARGET_EFAULT;
7560 }
7561
7562 if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) {
7563 return -TARGET_EFAULT;
7564 }
7565
7566 __get_user(host_tx->modes, &target_tx->modes);
7567 __get_user(host_tx->offset, &target_tx->offset);
7568 __get_user(host_tx->freq, &target_tx->freq);
7569 __get_user(host_tx->maxerror, &target_tx->maxerror);
7570 __get_user(host_tx->esterror, &target_tx->esterror);
7571 __get_user(host_tx->status, &target_tx->status);
7572 __get_user(host_tx->constant, &target_tx->constant);
7573 __get_user(host_tx->precision, &target_tx->precision);
7574 __get_user(host_tx->tolerance, &target_tx->tolerance);
7575 __get_user(host_tx->tick, &target_tx->tick);
7576 __get_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7577 __get_user(host_tx->jitter, &target_tx->jitter);
7578 __get_user(host_tx->shift, &target_tx->shift);
7579 __get_user(host_tx->stabil, &target_tx->stabil);
7580 __get_user(host_tx->jitcnt, &target_tx->jitcnt);
7581 __get_user(host_tx->calcnt, &target_tx->calcnt);
7582 __get_user(host_tx->errcnt, &target_tx->errcnt);
7583 __get_user(host_tx->stbcnt, &target_tx->stbcnt);
7584 __get_user(host_tx->tai, &target_tx->tai);
7585
7586 unlock_user_struct(target_tx, target_addr, 0);
7587 return 0;
7588}
7589
7590static inline abi_long host_to_target_timex64(abi_long target_addr,
7591 struct timex *host_tx)
7592{
7593 struct target__kernel_timex *target_tx;
7594
7595 if (copy_to_user_timeval64(target_addr +
7596 offsetof(struct target__kernel_timex, time),
7597 &host_tx->time)) {
7598 return -TARGET_EFAULT;
7599 }
7600
7601 if (!lock_user_struct(VERIFY_WRITE, target_tx, target_addr, 0)) {
7602 return -TARGET_EFAULT;
7603 }
7604
7605 __put_user(host_tx->modes, &target_tx->modes);
7606 __put_user(host_tx->offset, &target_tx->offset);
7607 __put_user(host_tx->freq, &target_tx->freq);
7608 __put_user(host_tx->maxerror, &target_tx->maxerror);
7609 __put_user(host_tx->esterror, &target_tx->esterror);
7610 __put_user(host_tx->status, &target_tx->status);
7611 __put_user(host_tx->constant, &target_tx->constant);
7612 __put_user(host_tx->precision, &target_tx->precision);
7613 __put_user(host_tx->tolerance, &target_tx->tolerance);
7614 __put_user(host_tx->tick, &target_tx->tick);
7615 __put_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7616 __put_user(host_tx->jitter, &target_tx->jitter);
7617 __put_user(host_tx->shift, &target_tx->shift);
7618 __put_user(host_tx->stabil, &target_tx->stabil);
7619 __put_user(host_tx->jitcnt, &target_tx->jitcnt);
7620 __put_user(host_tx->calcnt, &target_tx->calcnt);
7621 __put_user(host_tx->errcnt, &target_tx->errcnt);
7622 __put_user(host_tx->stbcnt, &target_tx->stbcnt);
7623 __put_user(host_tx->tai, &target_tx->tai);
7624
7625 unlock_user_struct(target_tx, target_addr, 1);
7626 return 0;
7627}
7628#endif
7629
Michael Forney96ff7582021-05-25 20:55:56 -07007630#ifndef HAVE_SIGEV_NOTIFY_THREAD_ID
7631#define sigev_notify_thread_id _sigev_un._tid
7632#endif
7633
Peter Maydellc0659762014-08-09 15:42:32 +01007634static inline abi_long target_to_host_sigevent(struct sigevent *host_sevp,
7635 abi_ulong target_addr)
7636{
7637 struct target_sigevent *target_sevp;
7638
7639 if (!lock_user_struct(VERIFY_READ, target_sevp, target_addr, 1)) {
7640 return -TARGET_EFAULT;
7641 }
7642
7643 /* This union is awkward on 64 bit systems because it has a 32 bit
7644 * integer and a pointer in it; we follow the conversion approach
7645 * used for handling sigval types in signal.c so the guest should get
7646 * the correct value back even if we did a 64 bit byteswap and it's
7647 * using the 32 bit integer.
7648 */
7649 host_sevp->sigev_value.sival_ptr =
7650 (void *)(uintptr_t)tswapal(target_sevp->sigev_value.sival_ptr);
7651 host_sevp->sigev_signo =
7652 target_to_host_signal(tswap32(target_sevp->sigev_signo));
7653 host_sevp->sigev_notify = tswap32(target_sevp->sigev_notify);
Michael Forney96ff7582021-05-25 20:55:56 -07007654 host_sevp->sigev_notify_thread_id = tswap32(target_sevp->_sigev_un._tid);
Peter Maydellc0659762014-08-09 15:42:32 +01007655
7656 unlock_user_struct(target_sevp, target_addr, 1);
7657 return 0;
7658}
7659
Tom Musta6f6a4032014-08-12 13:53:42 -05007660#if defined(TARGET_NR_mlockall)
7661static inline int target_to_host_mlockall_arg(int arg)
7662{
7663 int result = 0;
7664
Filip Bozuta02e5d7d2020-08-11 18:45:51 +02007665 if (arg & TARGET_MCL_CURRENT) {
Tom Musta6f6a4032014-08-12 13:53:42 -05007666 result |= MCL_CURRENT;
7667 }
Filip Bozuta02e5d7d2020-08-11 18:45:51 +02007668 if (arg & TARGET_MCL_FUTURE) {
Tom Musta6f6a4032014-08-12 13:53:42 -05007669 result |= MCL_FUTURE;
7670 }
Filip Bozuta02e5d7d2020-08-11 18:45:51 +02007671#ifdef MCL_ONFAULT
7672 if (arg & TARGET_MCL_ONFAULT) {
7673 result |= MCL_ONFAULT;
7674 }
7675#endif
7676
Tom Musta6f6a4032014-08-12 13:53:42 -05007677 return result;
7678}
7679#endif
7680
Helge Dellerfe080592022-12-15 08:27:46 +01007681static inline int target_to_host_msync_arg(abi_long arg)
7682{
7683 return ((arg & TARGET_MS_ASYNC) ? MS_ASYNC : 0) |
7684 ((arg & TARGET_MS_INVALIDATE) ? MS_INVALIDATE : 0) |
7685 ((arg & TARGET_MS_SYNC) ? MS_SYNC : 0) |
7686 (arg & ~(TARGET_MS_ASYNC | TARGET_MS_INVALIDATE | TARGET_MS_SYNC));
7687}
7688
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02007689#if (defined(TARGET_NR_stat64) || defined(TARGET_NR_lstat64) || \
7690 defined(TARGET_NR_fstat64) || defined(TARGET_NR_fstatat64) || \
7691 defined(TARGET_NR_newfstatat))
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02007692static inline abi_long host_to_target_stat64(CPUArchState *cpu_env,
balrog6a24a772008-09-20 02:23:36 +00007693 abi_ulong target_addr,
7694 struct stat *host_st)
7695{
Alexander Graf09701192013-09-03 20:12:15 +01007696#if defined(TARGET_ARM) && defined(TARGET_ABI32)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02007697 if (cpu_env->eabi) {
balrog6a24a772008-09-20 02:23:36 +00007698 struct target_eabi_stat64 *target_st;
7699
7700 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
7701 return -TARGET_EFAULT;
7702 memset(target_st, 0, sizeof(struct target_eabi_stat64));
7703 __put_user(host_st->st_dev, &target_st->st_dev);
7704 __put_user(host_st->st_ino, &target_st->st_ino);
7705#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
7706 __put_user(host_st->st_ino, &target_st->__st_ino);
7707#endif
7708 __put_user(host_st->st_mode, &target_st->st_mode);
7709 __put_user(host_st->st_nlink, &target_st->st_nlink);
7710 __put_user(host_st->st_uid, &target_st->st_uid);
7711 __put_user(host_st->st_gid, &target_st->st_gid);
7712 __put_user(host_st->st_rdev, &target_st->st_rdev);
7713 __put_user(host_st->st_size, &target_st->st_size);
7714 __put_user(host_st->st_blksize, &target_st->st_blksize);
7715 __put_user(host_st->st_blocks, &target_st->st_blocks);
7716 __put_user(host_st->st_atime, &target_st->target_st_atime);
7717 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
7718 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
Michael Forneyfebf6fa2021-05-25 20:55:31 -07007719#ifdef HAVE_STRUCT_STAT_ST_ATIM
Chen-Yu Tsai5f992db2019-05-23 00:21:47 +08007720 __put_user(host_st->st_atim.tv_nsec, &target_st->target_st_atime_nsec);
7721 __put_user(host_st->st_mtim.tv_nsec, &target_st->target_st_mtime_nsec);
7722 __put_user(host_st->st_ctim.tv_nsec, &target_st->target_st_ctime_nsec);
7723#endif
balrog6a24a772008-09-20 02:23:36 +00007724 unlock_user_struct(target_st, target_addr, 1);
7725 } else
7726#endif
7727 {
Stefan Weil20d155b2013-10-30 22:52:24 +01007728#if defined(TARGET_HAS_STRUCT_STAT64)
balrog6a24a772008-09-20 02:23:36 +00007729 struct target_stat64 *target_st;
Stefan Weil20d155b2013-10-30 22:52:24 +01007730#else
7731 struct target_stat *target_st;
aurel329d33b762009-04-08 23:07:05 +00007732#endif
balrog6a24a772008-09-20 02:23:36 +00007733
7734 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
7735 return -TARGET_EFAULT;
aurel329d33b762009-04-08 23:07:05 +00007736 memset(target_st, 0, sizeof(*target_st));
balrog6a24a772008-09-20 02:23:36 +00007737 __put_user(host_st->st_dev, &target_st->st_dev);
7738 __put_user(host_st->st_ino, &target_st->st_ino);
7739#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
7740 __put_user(host_st->st_ino, &target_st->__st_ino);
7741#endif
7742 __put_user(host_st->st_mode, &target_st->st_mode);
7743 __put_user(host_st->st_nlink, &target_st->st_nlink);
7744 __put_user(host_st->st_uid, &target_st->st_uid);
7745 __put_user(host_st->st_gid, &target_st->st_gid);
7746 __put_user(host_st->st_rdev, &target_st->st_rdev);
7747 /* XXX: better use of kernel struct */
7748 __put_user(host_st->st_size, &target_st->st_size);
7749 __put_user(host_st->st_blksize, &target_st->st_blksize);
7750 __put_user(host_st->st_blocks, &target_st->st_blocks);
7751 __put_user(host_st->st_atime, &target_st->target_st_atime);
7752 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
7753 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
Michael Forneyfebf6fa2021-05-25 20:55:31 -07007754#ifdef HAVE_STRUCT_STAT_ST_ATIM
Chen-Yu Tsai5f992db2019-05-23 00:21:47 +08007755 __put_user(host_st->st_atim.tv_nsec, &target_st->target_st_atime_nsec);
7756 __put_user(host_st->st_mtim.tv_nsec, &target_st->target_st_mtime_nsec);
7757 __put_user(host_st->st_ctim.tv_nsec, &target_st->target_st_ctime_nsec);
7758#endif
balrog6a24a772008-09-20 02:23:36 +00007759 unlock_user_struct(target_st, target_addr, 1);
7760 }
7761
7762 return 0;
7763}
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02007764#endif
balrog6a24a772008-09-20 02:23:36 +00007765
Aleksandar Rikaloefa92182019-06-28 12:43:34 +02007766#if defined(TARGET_NR_statx) && defined(__NR_statx)
7767static inline abi_long host_to_target_statx(struct target_statx *host_stx,
7768 abi_ulong target_addr)
7769{
7770 struct target_statx *target_stx;
7771
7772 if (!lock_user_struct(VERIFY_WRITE, target_stx, target_addr, 0)) {
7773 return -TARGET_EFAULT;
7774 }
7775 memset(target_stx, 0, sizeof(*target_stx));
7776
7777 __put_user(host_stx->stx_mask, &target_stx->stx_mask);
7778 __put_user(host_stx->stx_blksize, &target_stx->stx_blksize);
7779 __put_user(host_stx->stx_attributes, &target_stx->stx_attributes);
7780 __put_user(host_stx->stx_nlink, &target_stx->stx_nlink);
7781 __put_user(host_stx->stx_uid, &target_stx->stx_uid);
7782 __put_user(host_stx->stx_gid, &target_stx->stx_gid);
7783 __put_user(host_stx->stx_mode, &target_stx->stx_mode);
7784 __put_user(host_stx->stx_ino, &target_stx->stx_ino);
7785 __put_user(host_stx->stx_size, &target_stx->stx_size);
7786 __put_user(host_stx->stx_blocks, &target_stx->stx_blocks);
7787 __put_user(host_stx->stx_attributes_mask, &target_stx->stx_attributes_mask);
7788 __put_user(host_stx->stx_atime.tv_sec, &target_stx->stx_atime.tv_sec);
7789 __put_user(host_stx->stx_atime.tv_nsec, &target_stx->stx_atime.tv_nsec);
Ariadne Conilld1e26702019-11-22 11:40:40 -06007790 __put_user(host_stx->stx_btime.tv_sec, &target_stx->stx_btime.tv_sec);
7791 __put_user(host_stx->stx_btime.tv_nsec, &target_stx->stx_btime.tv_nsec);
7792 __put_user(host_stx->stx_ctime.tv_sec, &target_stx->stx_ctime.tv_sec);
7793 __put_user(host_stx->stx_ctime.tv_nsec, &target_stx->stx_ctime.tv_nsec);
7794 __put_user(host_stx->stx_mtime.tv_sec, &target_stx->stx_mtime.tv_sec);
7795 __put_user(host_stx->stx_mtime.tv_nsec, &target_stx->stx_mtime.tv_nsec);
Aleksandar Rikaloefa92182019-06-28 12:43:34 +02007796 __put_user(host_stx->stx_rdev_major, &target_stx->stx_rdev_major);
7797 __put_user(host_stx->stx_rdev_minor, &target_stx->stx_rdev_minor);
7798 __put_user(host_stx->stx_dev_major, &target_stx->stx_dev_major);
7799 __put_user(host_stx->stx_dev_minor, &target_stx->stx_dev_minor);
7800
7801 unlock_user_struct(target_stx, target_addr, 1);
7802
7803 return 0;
7804}
7805#endif
7806
Alistair Francis14690292020-03-18 15:47:01 -07007807static int do_sys_futex(int *uaddr, int op, int val,
7808 const struct timespec *timeout, int *uaddr2,
7809 int val3)
7810{
7811#if HOST_LONG_BITS == 64
7812#if defined(__NR_futex)
7813 /* always a 64-bit time_t, it doesn't define _time64 version */
7814 return sys_futex(uaddr, op, val, timeout, uaddr2, val3);
7815
7816#endif
7817#else /* HOST_LONG_BITS == 64 */
7818#if defined(__NR_futex_time64)
7819 if (sizeof(timeout->tv_sec) == 8) {
7820 /* _time64 function on 32bit arch */
7821 return sys_futex_time64(uaddr, op, val, timeout, uaddr2, val3);
7822 }
7823#endif
7824#if defined(__NR_futex)
7825 /* old function on 32bit arch */
7826 return sys_futex(uaddr, op, val, timeout, uaddr2, val3);
7827#endif
7828#endif /* HOST_LONG_BITS == 64 */
7829 g_assert_not_reached();
7830}
7831
7832static int do_safe_futex(int *uaddr, int op, int val,
7833 const struct timespec *timeout, int *uaddr2,
7834 int val3)
7835{
7836#if HOST_LONG_BITS == 64
7837#if defined(__NR_futex)
7838 /* always a 64-bit time_t, it doesn't define _time64 version */
7839 return get_errno(safe_futex(uaddr, op, val, timeout, uaddr2, val3));
7840#endif
7841#else /* HOST_LONG_BITS == 64 */
7842#if defined(__NR_futex_time64)
7843 if (sizeof(timeout->tv_sec) == 8) {
7844 /* _time64 function on 32bit arch */
7845 return get_errno(safe_futex_time64(uaddr, op, val, timeout, uaddr2,
7846 val3));
7847 }
7848#endif
7849#if defined(__NR_futex)
7850 /* old function on 32bit arch */
7851 return get_errno(safe_futex(uaddr, op, val, timeout, uaddr2, val3));
7852#endif
7853#endif /* HOST_LONG_BITS == 64 */
7854 return -TARGET_ENOSYS;
7855}
Aleksandar Rikaloefa92182019-06-28 12:43:34 +02007856
pbrookbd0c5662008-05-29 14:34:11 +00007857/* ??? Using host futex calls even when target atomic operations
7858 are not really atomic probably breaks things. However implementing
7859 futexes locally would make futexes shared between multiple processes
7860 tricky. However they're probably useless because guest atomic
7861 operations won't work either. */
Richard Henderson0fbc0f82022-08-28 19:09:59 -07007862#if defined(TARGET_NR_futex) || defined(TARGET_NR_futex_time64)
7863static int do_futex(CPUState *cpu, bool time64, target_ulong uaddr,
7864 int op, int val, target_ulong timeout,
7865 target_ulong uaddr2, int val3)
pbrookbd0c5662008-05-29 14:34:11 +00007866{
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007867 struct timespec ts, *pts = NULL;
7868 void *haddr2 = NULL;
Nathan Froyda16aae02009-08-03 08:43:29 -07007869 int base_op;
pbrookbd0c5662008-05-29 14:34:11 +00007870
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007871 /* We assume FUTEX_* constants are the same on both host and target. */
Martin Mohringa29ccd62009-05-04 21:34:56 +03007872#ifdef FUTEX_CMD_MASK
Nathan Froyda16aae02009-08-03 08:43:29 -07007873 base_op = op & FUTEX_CMD_MASK;
Martin Mohringa29ccd62009-05-04 21:34:56 +03007874#else
Nathan Froyda16aae02009-08-03 08:43:29 -07007875 base_op = op;
Martin Mohringa29ccd62009-05-04 21:34:56 +03007876#endif
Nathan Froyda16aae02009-08-03 08:43:29 -07007877 switch (base_op) {
pbrookbd0c5662008-05-29 14:34:11 +00007878 case FUTEX_WAIT:
John Rigbycce246e2013-02-23 16:14:07 -07007879 case FUTEX_WAIT_BITSET:
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007880 val = tswap32(val);
7881 break;
Richard Hendersonc72a90d2022-08-28 19:10:03 -07007882 case FUTEX_WAIT_REQUEUE_PI:
7883 val = tswap32(val);
7884 haddr2 = g2h(cpu, uaddr2);
7885 break;
7886 case FUTEX_LOCK_PI:
7887 case FUTEX_LOCK_PI2:
7888 break;
pbrookbd0c5662008-05-29 14:34:11 +00007889 case FUTEX_WAKE:
Richard Hendersona6180f82022-08-28 19:10:01 -07007890 case FUTEX_WAKE_BITSET:
Richard Hendersonc72a90d2022-08-28 19:10:03 -07007891 case FUTEX_TRYLOCK_PI:
7892 case FUTEX_UNLOCK_PI:
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007893 timeout = 0;
7894 break;
pbrookbd0c5662008-05-29 14:34:11 +00007895 case FUTEX_FD:
Richard Henderson0f946732022-08-28 19:10:02 -07007896 val = target_to_host_signal(val);
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007897 timeout = 0;
7898 break;
pbrookbd0c5662008-05-29 14:34:11 +00007899 case FUTEX_CMP_REQUEUE:
Richard Hendersonc72a90d2022-08-28 19:10:03 -07007900 case FUTEX_CMP_REQUEUE_PI:
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007901 val3 = tswap32(val3);
7902 /* fall through */
7903 case FUTEX_REQUEUE:
Nathan Froyda16aae02009-08-03 08:43:29 -07007904 case FUTEX_WAKE_OP:
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007905 /*
7906 * For these, the 4th argument is not TIMEOUT, but VAL2.
7907 * But the prototype of do_safe_futex takes a pointer, so
7908 * insert casts to satisfy the compiler. We do not need
7909 * to tswap VAL2 since it's not compared to guest memory.
7910 */
7911 pts = (struct timespec *)(uintptr_t)timeout;
7912 timeout = 0;
7913 haddr2 = g2h(cpu, uaddr2);
7914 break;
pbrookbd0c5662008-05-29 14:34:11 +00007915 default:
7916 return -TARGET_ENOSYS;
7917 }
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007918 if (timeout) {
7919 pts = &ts;
7920 if (time64
7921 ? target_to_host_timespec64(pts, timeout)
7922 : target_to_host_timespec(pts, timeout)) {
7923 return -TARGET_EFAULT;
7924 }
7925 }
7926 return do_safe_futex(g2h(cpu, uaddr), op, val, pts, haddr2, val3);
pbrookbd0c5662008-05-29 14:34:11 +00007927}
Alistair Francis859e8a82020-03-12 15:13:49 -07007928#endif
Alistair Francis14690292020-03-18 15:47:01 -07007929
Laurent Vivier0f0426f2015-09-01 22:27:33 +02007930#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
7931static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname,
7932 abi_long handle, abi_long mount_id,
7933 abi_long flags)
7934{
7935 struct file_handle *target_fh;
7936 struct file_handle *fh;
7937 int mid = 0;
7938 abi_long ret;
7939 char *name;
7940 unsigned int size, total_size;
7941
7942 if (get_user_s32(size, handle)) {
7943 return -TARGET_EFAULT;
7944 }
7945
7946 name = lock_user_string(pathname);
7947 if (!name) {
7948 return -TARGET_EFAULT;
7949 }
7950
7951 total_size = sizeof(struct file_handle) + size;
7952 target_fh = lock_user(VERIFY_WRITE, handle, total_size, 0);
7953 if (!target_fh) {
7954 unlock_user(name, pathname, 0);
7955 return -TARGET_EFAULT;
7956 }
7957
7958 fh = g_malloc0(total_size);
7959 fh->handle_bytes = size;
7960
7961 ret = get_errno(name_to_handle_at(dirfd, path(name), fh, &mid, flags));
7962 unlock_user(name, pathname, 0);
7963
7964 /* man name_to_handle_at(2):
7965 * Other than the use of the handle_bytes field, the caller should treat
7966 * the file_handle structure as an opaque data type
7967 */
7968
7969 memcpy(target_fh, fh, total_size);
7970 target_fh->handle_bytes = tswap32(fh->handle_bytes);
7971 target_fh->handle_type = tswap32(fh->handle_type);
7972 g_free(fh);
7973 unlock_user(target_fh, handle, total_size);
7974
7975 if (put_user_s32(mid, mount_id)) {
7976 return -TARGET_EFAULT;
7977 }
7978
7979 return ret;
7980
7981}
7982#endif
7983
7984#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
7985static abi_long do_open_by_handle_at(abi_long mount_fd, abi_long handle,
7986 abi_long flags)
7987{
7988 struct file_handle *target_fh;
7989 struct file_handle *fh;
7990 unsigned int size, total_size;
7991 abi_long ret;
7992
7993 if (get_user_s32(size, handle)) {
7994 return -TARGET_EFAULT;
7995 }
7996
7997 total_size = sizeof(struct file_handle) + size;
7998 target_fh = lock_user(VERIFY_READ, handle, total_size, 1);
7999 if (!target_fh) {
8000 return -TARGET_EFAULT;
8001 }
8002
Thomas Huthe9d49d52015-10-09 17:56:38 +02008003 fh = g_memdup(target_fh, total_size);
Laurent Vivier0f0426f2015-09-01 22:27:33 +02008004 fh->handle_bytes = size;
8005 fh->handle_type = tswap32(target_fh->handle_type);
8006
8007 ret = get_errno(open_by_handle_at(mount_fd, fh,
8008 target_to_host_bitmask(flags, fcntl_flags_tbl)));
8009
8010 g_free(fh);
8011
8012 unlock_user(target_fh, handle, total_size);
8013
8014 return ret;
8015}
8016#endif
pbrookbd0c5662008-05-29 14:34:11 +00008017
Laurent Viviere36800c2015-10-02 14:48:09 +02008018#if defined(TARGET_NR_signalfd) || defined(TARGET_NR_signalfd4)
8019
Laurent Viviere36800c2015-10-02 14:48:09 +02008020static abi_long do_signalfd4(int fd, abi_long mask, int flags)
8021{
8022 int host_flags;
8023 target_sigset_t *target_mask;
8024 sigset_t host_mask;
8025 abi_long ret;
8026
Helge Deller78721302021-02-10 07:12:14 +01008027 if (flags & ~(TARGET_O_NONBLOCK_MASK | TARGET_O_CLOEXEC)) {
Laurent Viviere36800c2015-10-02 14:48:09 +02008028 return -TARGET_EINVAL;
8029 }
8030 if (!lock_user_struct(VERIFY_READ, target_mask, mask, 1)) {
8031 return -TARGET_EFAULT;
8032 }
8033
8034 target_to_host_sigset(&host_mask, target_mask);
8035
8036 host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
8037
8038 ret = get_errno(signalfd(fd, &host_mask, host_flags));
8039 if (ret >= 0) {
8040 fd_trans_register(ret, &target_signalfd_trans);
8041 }
8042
8043 unlock_user_struct(target_mask, mask, 0);
8044
8045 return ret;
8046}
8047#endif
8048
pbrook1d9d8b52009-04-16 15:17:02 +00008049/* Map host to target signal numbers for the wait family of syscalls.
8050 Assume all other status bits are the same. */
Richard Hendersona05c6402012-09-15 11:34:20 -07008051int host_to_target_waitstatus(int status)
pbrook1d9d8b52009-04-16 15:17:02 +00008052{
8053 if (WIFSIGNALED(status)) {
8054 return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
8055 }
8056 if (WIFSTOPPED(status)) {
8057 return (host_to_target_signal(WSTOPSIG(status)) << 8)
8058 | (status & 0xff);
8059 }
8060 return status;
8061}
8062
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008063static int open_self_cmdline(CPUArchState *cpu_env, int fd)
Wim Vander Schelden76b94242014-06-18 11:02:39 +02008064{
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02008065 CPUState *cpu = env_cpu(cpu_env);
Andreas Schwab58de8b92017-03-20 12:31:55 +01008066 struct linux_binprm *bprm = ((TaskState *)cpu->opaque)->bprm;
8067 int i;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02008068
Andreas Schwab58de8b92017-03-20 12:31:55 +01008069 for (i = 0; i < bprm->argc; i++) {
8070 size_t len = strlen(bprm->argv[i]) + 1;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02008071
Andreas Schwab58de8b92017-03-20 12:31:55 +01008072 if (write(fd, bprm->argv[i], len) != len) {
Wim Vander Schelden76b94242014-06-18 11:02:39 +02008073 return -1;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02008074 }
8075 }
8076
Andreas Schwab58de8b92017-03-20 12:31:55 +01008077 return 0;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02008078}
8079
Ilya Leoshkevich77ae5762023-06-30 19:04:18 +01008080static void show_smaps(int fd, unsigned long size)
8081{
8082 unsigned long page_size_kb = TARGET_PAGE_SIZE >> 10;
8083 unsigned long size_kb = size >> 10;
8084
8085 dprintf(fd, "Size: %lu kB\n"
8086 "KernelPageSize: %lu kB\n"
8087 "MMUPageSize: %lu kB\n"
8088 "Rss: 0 kB\n"
8089 "Pss: 0 kB\n"
8090 "Pss_Dirty: 0 kB\n"
8091 "Shared_Clean: 0 kB\n"
8092 "Shared_Dirty: 0 kB\n"
8093 "Private_Clean: 0 kB\n"
8094 "Private_Dirty: 0 kB\n"
8095 "Referenced: 0 kB\n"
8096 "Anonymous: 0 kB\n"
8097 "LazyFree: 0 kB\n"
8098 "AnonHugePages: 0 kB\n"
8099 "ShmemPmdMapped: 0 kB\n"
8100 "FilePmdMapped: 0 kB\n"
8101 "Shared_Hugetlb: 0 kB\n"
8102 "Private_Hugetlb: 0 kB\n"
8103 "Swap: 0 kB\n"
8104 "SwapPss: 0 kB\n"
8105 "Locked: 0 kB\n"
8106 "THPeligible: 0\n", size_kb, page_size_kb, page_size_kb);
8107}
8108
8109static int open_self_maps_1(CPUArchState *cpu_env, int fd, bool smaps)
Alexander Graf36c08d42011-11-02 20:23:24 +01008110{
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02008111 CPUState *cpu = env_cpu(cpu_env);
Andreas Färber0429a972013-08-26 18:14:44 +02008112 TaskState *ts = cpu->opaque;
Alex Bennée01ef6b92020-04-03 20:11:46 +01008113 GSList *map_info = read_self_maps();
8114 GSList *s;
Alex Bennéebb551732020-04-03 20:11:47 +01008115 int count;
Alexander Graf36c08d42011-11-02 20:23:24 +01008116
Alex Bennée01ef6b92020-04-03 20:11:46 +01008117 for (s = map_info; s; s = g_slist_next(s)) {
8118 MapInfo *e = (MapInfo *) s->data;
Alexander Graf1a49ef22012-05-01 16:30:28 +01008119
Alex Bennée01ef6b92020-04-03 20:11:46 +01008120 if (h2g_valid(e->start)) {
8121 unsigned long min = e->start;
8122 unsigned long max = e->end;
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04008123 int flags = page_get_flags(h2g(min));
Alex Bennée01ef6b92020-04-03 20:11:46 +01008124 const char *path;
8125
8126 max = h2g_valid(max - 1) ?
Richard Henderson3e8f1622021-02-12 10:48:43 -08008127 max : (uintptr_t) g2h_untagged(GUEST_ADDR_MAX) + 1;
Alex Bennée01ef6b92020-04-03 20:11:46 +01008128
Richard Hendersonbef6f002023-07-07 21:40:52 +01008129 if (!page_check_range(h2g(min), max - min, flags)) {
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04008130 continue;
8131 }
Alex Bennée01ef6b92020-04-03 20:11:46 +01008132
Helge Deller0a3346b2022-09-24 13:44:59 +02008133#ifdef TARGET_HPPA
8134 if (h2g(max) == ts->info->stack_limit) {
8135#else
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04008136 if (h2g(min) == ts->info->stack_limit) {
Helge Deller0a3346b2022-09-24 13:44:59 +02008137#endif
Alex Bennéebb551732020-04-03 20:11:47 +01008138 path = "[stack]";
Alex Bennée01ef6b92020-04-03 20:11:46 +01008139 } else {
8140 path = e->path;
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04008141 }
Alex Bennée01ef6b92020-04-03 20:11:46 +01008142
Alex Bennéebb551732020-04-03 20:11:47 +01008143 count = dprintf(fd, TARGET_ABI_FMT_ptr "-" TARGET_ABI_FMT_ptr
8144 " %c%c%c%c %08" PRIx64 " %s %"PRId64,
8145 h2g(min), h2g(max - 1) + 1,
Nicolas Surbayrole08f3a962021-03-08 10:19:59 +01008146 (flags & PAGE_READ) ? 'r' : '-',
8147 (flags & PAGE_WRITE_ORG) ? 'w' : '-',
8148 (flags & PAGE_EXEC) ? 'x' : '-',
Andrey Kazmine13685a2021-12-27 15:50:48 +03008149 e->is_priv ? 'p' : 's',
Alex Bennéebb551732020-04-03 20:11:47 +01008150 (uint64_t) e->offset, e->dev, e->inode);
8151 if (path) {
8152 dprintf(fd, "%*s%s\n", 73 - count, "", path);
8153 } else {
8154 dprintf(fd, "\n");
8155 }
Ilya Leoshkevich77ae5762023-06-30 19:04:18 +01008156 if (smaps) {
8157 show_smaps(fd, max - min);
8158 dprintf(fd, "VmFlags:%s%s%s%s%s%s%s%s\n",
8159 (flags & PAGE_READ) ? " rd" : "",
8160 (flags & PAGE_WRITE_ORG) ? " wr" : "",
8161 (flags & PAGE_EXEC) ? " ex" : "",
8162 e->is_priv ? "" : " sh",
8163 (flags & PAGE_READ) ? " mr" : "",
8164 (flags & PAGE_WRITE_ORG) ? " mw" : "",
8165 (flags & PAGE_EXEC) ? " me" : "",
8166 e->is_priv ? "" : " ms");
8167 }
Alexander Graf1a49ef22012-05-01 16:30:28 +01008168 }
8169 }
8170
Alex Bennée01ef6b92020-04-03 20:11:46 +01008171 free_self_maps(map_info);
8172
Richard Hendersonbf02adc2020-02-12 19:22:22 -08008173#ifdef TARGET_VSYSCALL_PAGE
8174 /*
8175 * We only support execution from the vsyscall page.
8176 * This is as if CONFIG_LEGACY_VSYSCALL_XONLY=y from v5.3.
8177 */
Alex Bennéebb551732020-04-03 20:11:47 +01008178 count = dprintf(fd, TARGET_FMT_lx "-" TARGET_FMT_lx
8179 " --xp 00000000 00:00 0",
8180 TARGET_VSYSCALL_PAGE, TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE);
8181 dprintf(fd, "%*s%s\n", 73 - count, "", "[vsyscall]");
Ilya Leoshkevich77ae5762023-06-30 19:04:18 +01008182 if (smaps) {
8183 show_smaps(fd, TARGET_PAGE_SIZE);
8184 dprintf(fd, "VmFlags: ex\n");
8185 }
Richard Hendersonbf02adc2020-02-12 19:22:22 -08008186#endif
8187
Alexander Graf36c08d42011-11-02 20:23:24 +01008188 return 0;
8189}
8190
Ilya Leoshkevich77ae5762023-06-30 19:04:18 +01008191static int open_self_maps(CPUArchState *cpu_env, int fd)
8192{
8193 return open_self_maps_1(cpu_env, fd, false);
8194}
8195
8196static int open_self_smaps(CPUArchState *cpu_env, int fd)
8197{
8198 return open_self_maps_1(cpu_env, fd, true);
8199}
8200
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008201static int open_self_stat(CPUArchState *cpu_env, int fd)
Alexander Graf480b8e72011-11-02 20:23:25 +01008202{
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02008203 CPUState *cpu = env_cpu(cpu_env);
Andreas Färber0429a972013-08-26 18:14:44 +02008204 TaskState *ts = cpu->opaque;
Alex Bennée7ad4d5a2020-04-14 21:06:23 +01008205 g_autoptr(GString) buf = g_string_new(NULL);
Alexander Graf480b8e72011-11-02 20:23:25 +01008206 int i;
8207
8208 for (i = 0; i < 44; i++) {
Alex Bennée7ad4d5a2020-04-14 21:06:23 +01008209 if (i == 0) {
8210 /* pid */
8211 g_string_printf(buf, FMT_pid " ", getpid());
8212 } else if (i == 1) {
8213 /* app name */
8214 gchar *bin = g_strrstr(ts->bprm->argv[0], "/");
8215 bin = bin ? bin + 1 : ts->bprm->argv[0];
8216 g_string_printf(buf, "(%.15s) ", bin);
Andreas Schwab25bb27c2023-03-06 10:59:29 +01008217 } else if (i == 2) {
8218 /* task state */
8219 g_string_assign(buf, "R "); /* we are running right now */
Andreas Schwab7aa9fe32021-06-21 11:32:59 +02008220 } else if (i == 3) {
8221 /* ppid */
8222 g_string_printf(buf, FMT_pid " ", getppid());
Cameron Esfahanieb33cda2022-01-27 16:12:51 -08008223 } else if (i == 21) {
8224 /* starttime */
8225 g_string_printf(buf, "%" PRIu64 " ", ts->start_boottime);
Alex Bennée7ad4d5a2020-04-14 21:06:23 +01008226 } else if (i == 27) {
8227 /* stack bottom */
8228 g_string_printf(buf, TARGET_ABI_FMT_ld " ", ts->info->start_stack);
8229 } else {
8230 /* for the rest, there is MasterCard */
8231 g_string_printf(buf, "0%c", i == 43 ? '\n' : ' ');
8232 }
Alexander Graf480b8e72011-11-02 20:23:25 +01008233
Alex Bennée7ad4d5a2020-04-14 21:06:23 +01008234 if (write(fd, buf->str, buf->len) != buf->len) {
8235 return -1;
8236 }
Alexander Graf480b8e72011-11-02 20:23:25 +01008237 }
8238
8239 return 0;
8240}
8241
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008242static int open_self_auxv(CPUArchState *cpu_env, int fd)
Alexander Graf257450e2011-11-02 20:23:26 +01008243{
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02008244 CPUState *cpu = env_cpu(cpu_env);
Andreas Färber0429a972013-08-26 18:14:44 +02008245 TaskState *ts = cpu->opaque;
Alexander Graf257450e2011-11-02 20:23:26 +01008246 abi_ulong auxv = ts->info->saved_auxv;
8247 abi_ulong len = ts->info->auxv_len;
8248 char *ptr;
8249
8250 /*
8251 * Auxiliary vector is stored in target process stack.
8252 * read in whole auxv vector and copy it to file
8253 */
8254 ptr = lock_user(VERIFY_READ, auxv, len, 0);
8255 if (ptr != NULL) {
8256 while (len > 0) {
8257 ssize_t r;
8258 r = write(fd, ptr, len);
8259 if (r <= 0) {
8260 break;
8261 }
8262 len -= r;
8263 ptr += r;
8264 }
8265 lseek(fd, 0, SEEK_SET);
8266 unlock_user(ptr, auxv, len);
8267 }
8268
8269 return 0;
8270}
8271
Andreas Schwab463d8e72013-07-02 14:04:12 +01008272static int is_proc_myself(const char *filename, const char *entry)
8273{
8274 if (!strncmp(filename, "/proc/", strlen("/proc/"))) {
8275 filename += strlen("/proc/");
8276 if (!strncmp(filename, "self/", strlen("self/"))) {
8277 filename += strlen("self/");
8278 } else if (*filename >= '1' && *filename <= '9') {
8279 char myself[80];
8280 snprintf(myself, sizeof(myself), "%d/", getpid());
8281 if (!strncmp(filename, myself, strlen(myself))) {
8282 filename += strlen(myself);
8283 } else {
8284 return 0;
8285 }
8286 } else {
8287 return 0;
8288 }
8289 if (!strcmp(filename, entry)) {
8290 return 1;
8291 }
8292 }
8293 return 0;
8294}
8295
Helge Dellerbd5ccd62022-10-24 22:18:09 +02008296static void excp_dump_file(FILE *logfile, CPUArchState *env,
8297 const char *fmt, int code)
8298{
8299 if (logfile) {
8300 CPUState *cs = env_cpu(env);
8301
8302 fprintf(logfile, fmt, code);
8303 fprintf(logfile, "Failing executable: %s\n", exec_path);
8304 cpu_dump_state(cs, logfile, 0);
8305 open_self_maps(env, fileno(logfile));
8306 }
8307}
8308
8309void target_exception_dump(CPUArchState *env, const char *fmt, int code)
8310{
8311 /* dump to console */
8312 excp_dump_file(stderr, env, fmt, code);
8313
8314 /* dump to log file */
8315 if (qemu_log_separate()) {
8316 FILE *logfile = qemu_log_trylock();
8317
8318 excp_dump_file(logfile, env, fmt, code);
8319 qemu_log_unlock(logfile);
8320 }
8321}
8322
Marc-André Lureauee3eb3a2022-03-23 19:57:18 +04008323#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN || \
Afonso Bordado8ddc1712023-03-05 14:34:37 +00008324 defined(TARGET_SPARC) || defined(TARGET_M68K) || defined(TARGET_HPPA) || \
Ilya Leoshkevich1fb9bda2023-06-05 13:39:50 +02008325 defined(TARGET_RISCV) || defined(TARGET_S390X)
Laurent Vivierde6b9932013-08-30 01:46:40 +02008326static int is_proc(const char *filename, const char *entry)
8327{
8328 return strcmp(filename, entry) == 0;
8329}
Laurent Vivierfff69382019-05-17 15:31:48 +02008330#endif
Laurent Vivierde6b9932013-08-30 01:46:40 +02008331
Marc-André Lureauee3eb3a2022-03-23 19:57:18 +04008332#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008333static int open_net_route(CPUArchState *cpu_env, int fd)
Laurent Vivierde6b9932013-08-30 01:46:40 +02008334{
8335 FILE *fp;
8336 char *line = NULL;
8337 size_t len = 0;
8338 ssize_t read;
8339
8340 fp = fopen("/proc/net/route", "r");
8341 if (fp == NULL) {
Peter Maydella3ca7bb2016-05-12 18:47:26 +01008342 return -1;
Laurent Vivierde6b9932013-08-30 01:46:40 +02008343 }
8344
8345 /* read header */
8346
8347 read = getline(&line, &len, fp);
8348 dprintf(fd, "%s", line);
8349
8350 /* read routes */
8351
8352 while ((read = getline(&line, &len, fp)) != -1) {
8353 char iface[16];
8354 uint32_t dest, gw, mask;
8355 unsigned int flags, refcnt, use, metric, mtu, window, irtt;
Peter Maydell9d0bd0c2019-02-05 17:42:07 +00008356 int fields;
8357
8358 fields = sscanf(line,
8359 "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
8360 iface, &dest, &gw, &flags, &refcnt, &use, &metric,
8361 &mask, &mtu, &window, &irtt);
8362 if (fields != 11) {
8363 continue;
8364 }
Laurent Vivierde6b9932013-08-30 01:46:40 +02008365 dprintf(fd, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
8366 iface, tswap32(dest), tswap32(gw), flags, refcnt, use,
8367 metric, tswap32(mask), mtu, window, irtt);
8368 }
8369
8370 free(line);
8371 fclose(fp);
8372
8373 return 0;
8374}
8375#endif
8376
Laurent Vivierfff69382019-05-17 15:31:48 +02008377#if defined(TARGET_SPARC)
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008378static int open_cpuinfo(CPUArchState *cpu_env, int fd)
Laurent Vivierfff69382019-05-17 15:31:48 +02008379{
8380 dprintf(fd, "type\t\t: sun4u\n");
8381 return 0;
8382}
8383#endif
8384
Helge Deller93a56612020-04-24 23:06:48 +02008385#if defined(TARGET_HPPA)
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008386static int open_cpuinfo(CPUArchState *cpu_env, int fd)
Helge Deller93a56612020-04-24 23:06:48 +02008387{
Helge Dellere0174af2023-01-27 21:10:49 +01008388 int i, num_cpus;
8389
8390 num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
8391 for (i = 0; i < num_cpus; i++) {
8392 dprintf(fd, "processor\t: %d\n", i);
8393 dprintf(fd, "cpu family\t: PA-RISC 1.1e\n");
8394 dprintf(fd, "cpu\t\t: PA7300LC (PCX-L2)\n");
8395 dprintf(fd, "capabilities\t: os32\n");
8396 dprintf(fd, "model\t\t: 9000/778/B160L - "
8397 "Merlin L2 160 QEMU (9000/778/B160L)\n\n");
8398 }
Helge Deller93a56612020-04-24 23:06:48 +02008399 return 0;
8400}
8401#endif
8402
Afonso Bordado8ddc1712023-03-05 14:34:37 +00008403#if defined(TARGET_RISCV)
8404static int open_cpuinfo(CPUArchState *cpu_env, int fd)
8405{
8406 int i;
8407 int num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
8408 RISCVCPU *cpu = env_archcpu(cpu_env);
8409 const RISCVCPUConfig *cfg = riscv_cpu_cfg((CPURISCVState *) cpu_env);
8410 char *isa_string = riscv_isa_string(cpu);
8411 const char *mmu;
8412
8413 if (cfg->mmu) {
8414 mmu = (cpu_env->xl == MXL_RV32) ? "sv32" : "sv48";
8415 } else {
8416 mmu = "none";
8417 }
8418
8419 for (i = 0; i < num_cpus; i++) {
8420 dprintf(fd, "processor\t: %d\n", i);
8421 dprintf(fd, "hart\t\t: %d\n", i);
8422 dprintf(fd, "isa\t\t: %s\n", isa_string);
8423 dprintf(fd, "mmu\t\t: %s\n", mmu);
8424 dprintf(fd, "uarch\t\t: qemu\n\n");
8425 }
8426
8427 g_free(isa_string);
8428 return 0;
8429}
8430#endif
8431
Ilya Leoshkevich1fb9bda2023-06-05 13:39:50 +02008432#if defined(TARGET_S390X)
8433/*
8434 * Emulate what a Linux kernel running in qemu-system-s390x -M accel=tcg would
8435 * show in /proc/cpuinfo.
8436 *
8437 * Skip the following in order to match the missing support in op_ecag():
8438 * - show_cacheinfo().
8439 * - show_cpu_topology().
8440 * - show_cpu_mhz().
8441 *
8442 * Use fixed values for certain fields:
8443 * - bogomips per cpu - from a qemu-system-s390x run.
8444 * - max thread id = 0, since SMT / SIGP_SET_MULTI_THREADING is not supported.
8445 *
8446 * Keep the code structure close to arch/s390/kernel/processor.c.
8447 */
8448
8449static void show_facilities(int fd)
8450{
8451 size_t sizeof_stfl_bytes = 2048;
8452 g_autofree uint8_t *stfl_bytes = g_new0(uint8_t, sizeof_stfl_bytes);
8453 unsigned int bit;
8454
8455 dprintf(fd, "facilities :");
8456 s390_get_feat_block(S390_FEAT_TYPE_STFL, stfl_bytes);
8457 for (bit = 0; bit < sizeof_stfl_bytes * 8; bit++) {
8458 if (test_be_bit(bit, stfl_bytes)) {
8459 dprintf(fd, " %d", bit);
8460 }
8461 }
8462 dprintf(fd, "\n");
8463}
8464
8465static int cpu_ident(unsigned long n)
8466{
8467 return deposit32(0, CPU_ID_BITS - CPU_PHYS_ADDR_BITS, CPU_PHYS_ADDR_BITS,
8468 n);
8469}
8470
8471static void show_cpu_summary(CPUArchState *cpu_env, int fd)
8472{
8473 S390CPUModel *model = env_archcpu(cpu_env)->model;
8474 int num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
8475 uint32_t elf_hwcap = get_elf_hwcap();
8476 const char *hwcap_str;
8477 int i;
8478
8479 dprintf(fd, "vendor_id : IBM/S390\n"
8480 "# processors : %i\n"
8481 "bogomips per cpu: 13370.00\n",
8482 num_cpus);
8483 dprintf(fd, "max thread id : 0\n");
8484 dprintf(fd, "features\t: ");
8485 for (i = 0; i < sizeof(elf_hwcap) * 8; i++) {
8486 if (!(elf_hwcap & (1 << i))) {
8487 continue;
8488 }
8489 hwcap_str = elf_hwcap_str(i);
8490 if (hwcap_str) {
8491 dprintf(fd, "%s ", hwcap_str);
8492 }
8493 }
8494 dprintf(fd, "\n");
8495 show_facilities(fd);
8496 for (i = 0; i < num_cpus; i++) {
8497 dprintf(fd, "processor %d: "
8498 "version = %02X, "
8499 "identification = %06X, "
8500 "machine = %04X\n",
8501 i, model->cpu_ver, cpu_ident(i), model->def->type);
8502 }
8503}
8504
8505static void show_cpu_ids(CPUArchState *cpu_env, int fd, unsigned long n)
8506{
8507 S390CPUModel *model = env_archcpu(cpu_env)->model;
8508
8509 dprintf(fd, "version : %02X\n", model->cpu_ver);
8510 dprintf(fd, "identification : %06X\n", cpu_ident(n));
8511 dprintf(fd, "machine : %04X\n", model->def->type);
8512}
8513
8514static void show_cpuinfo(CPUArchState *cpu_env, int fd, unsigned long n)
8515{
8516 dprintf(fd, "\ncpu number : %ld\n", n);
8517 show_cpu_ids(cpu_env, fd, n);
8518}
8519
8520static int open_cpuinfo(CPUArchState *cpu_env, int fd)
8521{
8522 int num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
8523 int i;
8524
8525 show_cpu_summary(cpu_env, fd);
8526 for (i = 0; i < num_cpus; i++) {
8527 show_cpuinfo(cpu_env, fd, i);
8528 }
8529 return 0;
8530}
8531#endif
8532
Laurent Vivier4ab67132019-05-17 15:31:49 +02008533#if defined(TARGET_M68K)
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008534static int open_hardware(CPUArchState *cpu_env, int fd)
Laurent Vivier4ab67132019-05-17 15:31:49 +02008535{
8536 dprintf(fd, "Model:\t\tqemu-m68k\n");
8537 return 0;
8538}
8539#endif
8540
Ilya Leoshkevicha4dab0a2023-06-30 19:04:16 +01008541int do_guest_openat(CPUArchState *cpu_env, int dirfd, const char *pathname,
Ilya Leoshkevich35be8982023-06-30 19:04:17 +01008542 int flags, mode_t mode, bool safe)
Alexander Graf3be14d02011-11-02 20:23:23 +01008543{
8544 struct fake_open {
8545 const char *filename;
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008546 int (*fill)(CPUArchState *cpu_env, int fd);
Laurent Vivierde6b9932013-08-30 01:46:40 +02008547 int (*cmp)(const char *s1, const char *s2);
Alexander Graf3be14d02011-11-02 20:23:23 +01008548 };
8549 const struct fake_open *fake_open;
8550 static const struct fake_open fakes[] = {
Laurent Vivierde6b9932013-08-30 01:46:40 +02008551 { "maps", open_self_maps, is_proc_myself },
Ilya Leoshkevich77ae5762023-06-30 19:04:18 +01008552 { "smaps", open_self_smaps, is_proc_myself },
Laurent Vivierde6b9932013-08-30 01:46:40 +02008553 { "stat", open_self_stat, is_proc_myself },
8554 { "auxv", open_self_auxv, is_proc_myself },
Wim Vander Schelden76b94242014-06-18 11:02:39 +02008555 { "cmdline", open_self_cmdline, is_proc_myself },
Marc-André Lureauee3eb3a2022-03-23 19:57:18 +04008556#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN
Laurent Vivierde6b9932013-08-30 01:46:40 +02008557 { "/proc/net/route", open_net_route, is_proc },
8558#endif
Ilya Leoshkevich1fb9bda2023-06-05 13:39:50 +02008559#if defined(TARGET_SPARC) || defined(TARGET_HPPA) || \
8560 defined(TARGET_RISCV) || defined(TARGET_S390X)
Laurent Vivierfff69382019-05-17 15:31:48 +02008561 { "/proc/cpuinfo", open_cpuinfo, is_proc },
8562#endif
Laurent Vivier4ab67132019-05-17 15:31:49 +02008563#if defined(TARGET_M68K)
8564 { "/proc/hardware", open_hardware, is_proc },
8565#endif
Laurent Vivierde6b9932013-08-30 01:46:40 +02008566 { NULL, NULL, NULL }
Alexander Graf3be14d02011-11-02 20:23:23 +01008567 };
8568
Maxim Ostapenkoaa07f5e2014-05-02 11:17:07 +03008569 if (is_proc_myself(pathname, "exe")) {
Ilya Leoshkevich35be8982023-06-30 19:04:17 +01008570 if (safe) {
8571 return safe_openat(dirfd, exec_path, flags, mode);
8572 } else {
8573 return openat(dirfd, exec_path, flags, mode);
8574 }
Maxim Ostapenkoaa07f5e2014-05-02 11:17:07 +03008575 }
8576
Alexander Graf3be14d02011-11-02 20:23:23 +01008577 for (fake_open = fakes; fake_open->filename; fake_open++) {
Laurent Vivierde6b9932013-08-30 01:46:40 +02008578 if (fake_open->cmp(pathname, fake_open->filename)) {
Alexander Graf3be14d02011-11-02 20:23:23 +01008579 break;
8580 }
8581 }
8582
8583 if (fake_open->filename) {
8584 const char *tmpdir;
8585 char filename[PATH_MAX];
8586 int fd, r;
8587
Rainer Müller5b63de62022-07-29 17:49:51 +02008588 fd = memfd_create("qemu-open", 0);
Alexander Graf3be14d02011-11-02 20:23:23 +01008589 if (fd < 0) {
Rainer Müller5b63de62022-07-29 17:49:51 +02008590 if (errno != ENOSYS) {
8591 return fd;
8592 }
8593 /* create temporary file to map stat to */
8594 tmpdir = getenv("TMPDIR");
8595 if (!tmpdir)
8596 tmpdir = "/tmp";
8597 snprintf(filename, sizeof(filename), "%s/qemu-open.XXXXXX", tmpdir);
8598 fd = mkstemp(filename);
8599 if (fd < 0) {
8600 return fd;
8601 }
8602 unlink(filename);
Alexander Graf3be14d02011-11-02 20:23:23 +01008603 }
Alexander Graf3be14d02011-11-02 20:23:23 +01008604
8605 if ((r = fake_open->fill(cpu_env, fd))) {
Peter Maydella3ca7bb2016-05-12 18:47:26 +01008606 int e = errno;
Alexander Graf3be14d02011-11-02 20:23:23 +01008607 close(fd);
Peter Maydella3ca7bb2016-05-12 18:47:26 +01008608 errno = e;
Alexander Graf3be14d02011-11-02 20:23:23 +01008609 return r;
8610 }
8611 lseek(fd, 0, SEEK_SET);
8612
8613 return fd;
8614 }
8615
Ilya Leoshkevich35be8982023-06-30 19:04:17 +01008616 if (safe) {
8617 return safe_openat(dirfd, path(pathname), flags, mode);
8618 } else {
8619 return openat(dirfd, path(pathname), flags, mode);
8620 }
Alexander Graf3be14d02011-11-02 20:23:23 +01008621}
8622
Ilya Leoshkevicha4dab0a2023-06-30 19:04:16 +01008623ssize_t do_guest_readlink(const char *pathname, char *buf, size_t bufsiz)
8624{
8625 ssize_t ret;
8626
8627 if (!pathname || !buf) {
8628 errno = EFAULT;
8629 return -1;
8630 }
8631
8632 if (!bufsiz) {
8633 /* Short circuit this for the magic exe check. */
8634 errno = EINVAL;
8635 return -1;
8636 }
8637
8638 if (is_proc_myself((const char *)pathname, "exe")) {
8639 /*
8640 * Don't worry about sign mismatch as earlier mapping
8641 * logic would have thrown a bad address error.
8642 */
8643 ret = MIN(strlen(exec_path), bufsiz);
8644 /* We cannot NUL terminate the string. */
8645 memcpy(buf, exec_path, ret);
8646 } else {
8647 ret = readlink(path(pathname), buf, bufsiz);
8648 }
8649
8650 return ret;
8651}
8652
Pierrick Bouvier7a8d9f32023-07-05 14:10:23 +02008653static int do_execv(CPUArchState *cpu_env, int dirfd,
8654 abi_long pathname, abi_long guest_argp,
8655 abi_long guest_envp, int flags, bool is_execveat)
Drew DeVault156e1f62022-11-04 18:36:31 +01008656{
8657 int ret;
8658 char **argp, **envp;
8659 int argc, envc;
8660 abi_ulong gp;
8661 abi_ulong addr;
8662 char **q;
8663 void *p;
8664
8665 argc = 0;
8666
8667 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
8668 if (get_user_ual(addr, gp)) {
8669 return -TARGET_EFAULT;
8670 }
8671 if (!addr) {
8672 break;
8673 }
8674 argc++;
8675 }
8676 envc = 0;
8677 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
8678 if (get_user_ual(addr, gp)) {
8679 return -TARGET_EFAULT;
8680 }
8681 if (!addr) {
8682 break;
8683 }
8684 envc++;
8685 }
8686
8687 argp = g_new0(char *, argc + 1);
8688 envp = g_new0(char *, envc + 1);
8689
8690 for (gp = guest_argp, q = argp; gp; gp += sizeof(abi_ulong), q++) {
8691 if (get_user_ual(addr, gp)) {
8692 goto execve_efault;
8693 }
8694 if (!addr) {
8695 break;
8696 }
8697 *q = lock_user_string(addr);
8698 if (!*q) {
8699 goto execve_efault;
8700 }
8701 }
8702 *q = NULL;
8703
8704 for (gp = guest_envp, q = envp; gp; gp += sizeof(abi_ulong), q++) {
8705 if (get_user_ual(addr, gp)) {
8706 goto execve_efault;
8707 }
8708 if (!addr) {
8709 break;
8710 }
8711 *q = lock_user_string(addr);
8712 if (!*q) {
8713 goto execve_efault;
8714 }
8715 }
8716 *q = NULL;
8717
8718 /*
8719 * Although execve() is not an interruptible syscall it is
8720 * a special case where we must use the safe_syscall wrapper:
8721 * if we allow a signal to happen before we make the host
8722 * syscall then we will 'lose' it, because at the point of
8723 * execve the process leaves QEMU's control. So we use the
8724 * safe syscall wrapper to ensure that we either take the
8725 * signal as a guest signal, or else it does not happen
8726 * before the execve completes and makes it the other
8727 * program's problem.
8728 */
8729 p = lock_user_string(pathname);
8730 if (!p) {
8731 goto execve_efault;
8732 }
8733
Pierrick Bouvier7a8d9f32023-07-05 14:10:23 +02008734 const char *exe = p;
Drew DeVault156e1f62022-11-04 18:36:31 +01008735 if (is_proc_myself(p, "exe")) {
Pierrick Bouvier7a8d9f32023-07-05 14:10:23 +02008736 exe = exec_path;
Drew DeVault156e1f62022-11-04 18:36:31 +01008737 }
Pierrick Bouvier7a8d9f32023-07-05 14:10:23 +02008738 ret = is_execveat
8739 ? safe_execveat(dirfd, exe, argp, envp, flags)
8740 : safe_execve(exe, argp, envp);
8741 ret = get_errno(ret);
Drew DeVault156e1f62022-11-04 18:36:31 +01008742
8743 unlock_user(p, pathname, 0);
8744
8745 goto execve_end;
8746
8747execve_efault:
8748 ret = -TARGET_EFAULT;
8749
8750execve_end:
8751 for (gp = guest_argp, q = argp; *q; gp += sizeof(abi_ulong), q++) {
8752 if (get_user_ual(addr, gp) || !addr) {
8753 break;
8754 }
8755 unlock_user(*q, addr, 0);
8756 }
8757 for (gp = guest_envp, q = envp; *q; gp += sizeof(abi_ulong), q++) {
8758 if (get_user_ual(addr, gp) || !addr) {
8759 break;
8760 }
8761 unlock_user(*q, addr, 0);
8762 }
8763
8764 g_free(argp);
8765 g_free(envp);
8766 return ret;
8767}
8768
Alexander Grafaecc8862014-11-10 21:33:03 +01008769#define TIMER_MAGIC 0x0caf0000
8770#define TIMER_MAGIC_MASK 0xffff0000
8771
8772/* Convert QEMU provided timer ID back to internal 16bit index format */
8773static target_timer_t get_timer_id(abi_long arg)
8774{
8775 target_timer_t timerid = arg;
8776
8777 if ((timerid & TIMER_MAGIC_MASK) != TIMER_MAGIC) {
8778 return -TARGET_EINVAL;
8779 }
8780
8781 timerid &= 0xffff;
8782
8783 if (timerid >= ARRAY_SIZE(g_posix_timers)) {
8784 return -TARGET_EINVAL;
8785 }
8786
8787 return timerid;
8788}
8789
Samuel Thibault2e0a8712018-01-09 21:16:43 +01008790static int target_to_host_cpu_mask(unsigned long *host_mask,
8791 size_t host_size,
8792 abi_ulong target_addr,
8793 size_t target_size)
8794{
8795 unsigned target_bits = sizeof(abi_ulong) * 8;
8796 unsigned host_bits = sizeof(*host_mask) * 8;
8797 abi_ulong *target_mask;
8798 unsigned i, j;
8799
8800 assert(host_size >= target_size);
8801
8802 target_mask = lock_user(VERIFY_READ, target_addr, target_size, 1);
8803 if (!target_mask) {
8804 return -TARGET_EFAULT;
8805 }
8806 memset(host_mask, 0, host_size);
8807
8808 for (i = 0 ; i < target_size / sizeof(abi_ulong); i++) {
8809 unsigned bit = i * target_bits;
8810 abi_ulong val;
8811
8812 __get_user(val, &target_mask[i]);
8813 for (j = 0; j < target_bits; j++, bit++) {
8814 if (val & (1UL << j)) {
8815 host_mask[bit / host_bits] |= 1UL << (bit % host_bits);
8816 }
8817 }
8818 }
8819
8820 unlock_user(target_mask, target_addr, 0);
8821 return 0;
8822}
8823
8824static int host_to_target_cpu_mask(const unsigned long *host_mask,
8825 size_t host_size,
8826 abi_ulong target_addr,
8827 size_t target_size)
8828{
8829 unsigned target_bits = sizeof(abi_ulong) * 8;
8830 unsigned host_bits = sizeof(*host_mask) * 8;
8831 abi_ulong *target_mask;
8832 unsigned i, j;
8833
8834 assert(host_size >= target_size);
8835
8836 target_mask = lock_user(VERIFY_WRITE, target_addr, target_size, 0);
8837 if (!target_mask) {
8838 return -TARGET_EFAULT;
8839 }
8840
8841 for (i = 0 ; i < target_size / sizeof(abi_ulong); i++) {
8842 unsigned bit = i * target_bits;
8843 abi_ulong val = 0;
8844
8845 for (j = 0; j < target_bits; j++, bit++) {
8846 if (host_mask[bit / host_bits] & (1UL << (bit % host_bits))) {
8847 val |= 1UL << j;
8848 }
8849 }
8850 __put_user(val, &target_mask[i]);
8851 }
8852
8853 unlock_user(target_mask, target_addr, target_size);
8854 return 0;
8855}
8856
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008857#ifdef TARGET_NR_getdents
Richard Hendersonaee14c72021-11-14 11:35:39 +01008858static int do_getdents(abi_long dirfd, abi_long arg2, abi_long count)
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008859{
Richard Hendersonaee14c72021-11-14 11:35:39 +01008860 g_autofree void *hdirp = NULL;
8861 void *tdirp;
8862 int hlen, hoff, toff;
8863 int hreclen, treclen;
8864 off64_t prev_diroff = 0;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008865
Richard Hendersonaee14c72021-11-14 11:35:39 +01008866 hdirp = g_try_malloc(count);
8867 if (!hdirp) {
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008868 return -TARGET_ENOMEM;
8869 }
8870
Richard Hendersonaee14c72021-11-14 11:35:39 +01008871#ifdef EMULATE_GETDENTS_WITH_GETDENTS
8872 hlen = sys_getdents(dirfd, hdirp, count);
8873#else
8874 hlen = sys_getdents64(dirfd, hdirp, count);
8875#endif
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008876
Richard Hendersonaee14c72021-11-14 11:35:39 +01008877 hlen = get_errno(hlen);
8878 if (is_error(hlen)) {
8879 return hlen;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008880 }
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008881
Richard Hendersonaee14c72021-11-14 11:35:39 +01008882 tdirp = lock_user(VERIFY_WRITE, arg2, count, 0);
8883 if (!tdirp) {
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008884 return -TARGET_EFAULT;
8885 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008886
8887 for (hoff = toff = 0; hoff < hlen; hoff += hreclen, toff += treclen) {
8888#ifdef EMULATE_GETDENTS_WITH_GETDENTS
8889 struct linux_dirent *hde = hdirp + hoff;
8890#else
8891 struct linux_dirent64 *hde = hdirp + hoff;
8892#endif
8893 struct target_dirent *tde = tdirp + toff;
8894 int namelen;
8895 uint8_t type;
8896
8897 namelen = strlen(hde->d_name);
8898 hreclen = hde->d_reclen;
8899 treclen = offsetof(struct target_dirent, d_name) + namelen + 2;
8900 treclen = QEMU_ALIGN_UP(treclen, __alignof(struct target_dirent));
8901
8902 if (toff + treclen > count) {
8903 /*
8904 * If the host struct is smaller than the target struct, or
8905 * requires less alignment and thus packs into less space,
8906 * then the host can return more entries than we can pass
8907 * on to the guest.
8908 */
8909 if (toff == 0) {
8910 toff = -TARGET_EINVAL; /* result buffer is too small */
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008911 break;
8912 }
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008913 /*
Richard Hendersonaee14c72021-11-14 11:35:39 +01008914 * Return what we have, resetting the file pointer to the
8915 * location of the first record not returned.
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008916 */
Richard Hendersonaee14c72021-11-14 11:35:39 +01008917 lseek64(dirfd, prev_diroff, SEEK_SET);
8918 break;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008919 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008920
8921 prev_diroff = hde->d_off;
8922 tde->d_ino = tswapal(hde->d_ino);
8923 tde->d_off = tswapal(hde->d_off);
8924 tde->d_reclen = tswap16(treclen);
8925 memcpy(tde->d_name, hde->d_name, namelen + 1);
8926
8927 /*
8928 * The getdents type is in what was formerly a padding byte at the
8929 * end of the structure.
8930 */
8931#ifdef EMULATE_GETDENTS_WITH_GETDENTS
8932 type = *((uint8_t *)hde + hreclen - 1);
8933#else
8934 type = hde->d_type;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008935#endif
Richard Hendersonaee14c72021-11-14 11:35:39 +01008936 *((uint8_t *)tde + treclen - 1) = type;
8937 }
8938
8939 unlock_user(tdirp, arg2, toff);
8940 return toff;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008941}
8942#endif /* TARGET_NR_getdents */
8943
8944#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
Richard Hendersonaee14c72021-11-14 11:35:39 +01008945static int do_getdents64(abi_long dirfd, abi_long arg2, abi_long count)
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008946{
Richard Hendersonaee14c72021-11-14 11:35:39 +01008947 g_autofree void *hdirp = NULL;
8948 void *tdirp;
8949 int hlen, hoff, toff;
8950 int hreclen, treclen;
8951 off64_t prev_diroff = 0;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008952
Richard Hendersonaee14c72021-11-14 11:35:39 +01008953 hdirp = g_try_malloc(count);
8954 if (!hdirp) {
8955 return -TARGET_ENOMEM;
8956 }
8957
8958 hlen = get_errno(sys_getdents64(dirfd, hdirp, count));
8959 if (is_error(hlen)) {
8960 return hlen;
8961 }
8962
8963 tdirp = lock_user(VERIFY_WRITE, arg2, count, 0);
8964 if (!tdirp) {
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008965 return -TARGET_EFAULT;
8966 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008967
8968 for (hoff = toff = 0; hoff < hlen; hoff += hreclen, toff += treclen) {
8969 struct linux_dirent64 *hde = hdirp + hoff;
8970 struct target_dirent64 *tde = tdirp + toff;
8971 int namelen;
8972
8973 namelen = strlen(hde->d_name) + 1;
8974 hreclen = hde->d_reclen;
8975 treclen = offsetof(struct target_dirent64, d_name) + namelen;
8976 treclen = QEMU_ALIGN_UP(treclen, __alignof(struct target_dirent64));
8977
8978 if (toff + treclen > count) {
8979 /*
8980 * If the host struct is smaller than the target struct, or
8981 * requires less alignment and thus packs into less space,
8982 * then the host can return more entries than we can pass
8983 * on to the guest.
8984 */
8985 if (toff == 0) {
8986 toff = -TARGET_EINVAL; /* result buffer is too small */
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008987 break;
8988 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008989 /*
8990 * Return what we have, resetting the file pointer to the
8991 * location of the first record not returned.
8992 */
8993 lseek64(dirfd, prev_diroff, SEEK_SET);
8994 break;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008995 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008996
8997 prev_diroff = hde->d_off;
8998 tde->d_ino = tswap64(hde->d_ino);
8999 tde->d_off = tswap64(hde->d_off);
9000 tde->d_reclen = tswap16(treclen);
9001 tde->d_type = hde->d_type;
9002 memcpy(tde->d_name, hde->d_name, namelen);
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01009003 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01009004
9005 unlock_user(tdirp, arg2, toff);
9006 return toff;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01009007}
9008#endif /* TARGET_NR_getdents64 */
9009
Robbin Ehn9e1c7d92023-06-19 10:24:03 +02009010#if defined(TARGET_NR_riscv_hwprobe)
9011
9012#define RISCV_HWPROBE_KEY_MVENDORID 0
9013#define RISCV_HWPROBE_KEY_MARCHID 1
9014#define RISCV_HWPROBE_KEY_MIMPID 2
9015
9016#define RISCV_HWPROBE_KEY_BASE_BEHAVIOR 3
9017#define RISCV_HWPROBE_BASE_BEHAVIOR_IMA (1 << 0)
9018
9019#define RISCV_HWPROBE_KEY_IMA_EXT_0 4
9020#define RISCV_HWPROBE_IMA_FD (1 << 0)
9021#define RISCV_HWPROBE_IMA_C (1 << 1)
9022
9023#define RISCV_HWPROBE_KEY_CPUPERF_0 5
9024#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)
9025#define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0)
9026#define RISCV_HWPROBE_MISALIGNED_SLOW (2 << 0)
9027#define RISCV_HWPROBE_MISALIGNED_FAST (3 << 0)
9028#define RISCV_HWPROBE_MISALIGNED_UNSUPPORTED (4 << 0)
9029#define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0)
9030
9031struct riscv_hwprobe {
9032 abi_llong key;
9033 abi_ullong value;
9034};
9035
9036static void risc_hwprobe_fill_pairs(CPURISCVState *env,
9037 struct riscv_hwprobe *pair,
9038 size_t pair_count)
9039{
9040 const RISCVCPUConfig *cfg = riscv_cpu_cfg(env);
9041
9042 for (; pair_count > 0; pair_count--, pair++) {
9043 abi_llong key;
9044 abi_ullong value;
9045 __put_user(0, &pair->value);
9046 __get_user(key, &pair->key);
9047 switch (key) {
9048 case RISCV_HWPROBE_KEY_MVENDORID:
9049 __put_user(cfg->mvendorid, &pair->value);
9050 break;
9051 case RISCV_HWPROBE_KEY_MARCHID:
9052 __put_user(cfg->marchid, &pair->value);
9053 break;
9054 case RISCV_HWPROBE_KEY_MIMPID:
9055 __put_user(cfg->mimpid, &pair->value);
9056 break;
9057 case RISCV_HWPROBE_KEY_BASE_BEHAVIOR:
9058 value = riscv_has_ext(env, RVI) &&
9059 riscv_has_ext(env, RVM) &&
9060 riscv_has_ext(env, RVA) ?
9061 RISCV_HWPROBE_BASE_BEHAVIOR_IMA : 0;
9062 __put_user(value, &pair->value);
9063 break;
9064 case RISCV_HWPROBE_KEY_IMA_EXT_0:
9065 value = riscv_has_ext(env, RVF) &&
9066 riscv_has_ext(env, RVD) ?
9067 RISCV_HWPROBE_IMA_FD : 0;
9068 value |= riscv_has_ext(env, RVC) ?
9069 RISCV_HWPROBE_IMA_C : pair->value;
9070 __put_user(value, &pair->value);
9071 break;
9072 case RISCV_HWPROBE_KEY_CPUPERF_0:
9073 __put_user(RISCV_HWPROBE_MISALIGNED_FAST, &pair->value);
9074 break;
9075 default:
9076 __put_user(-1, &pair->key);
9077 break;
9078 }
9079 }
9080}
9081
9082static int cpu_set_valid(abi_long arg3, abi_long arg4)
9083{
9084 int ret, i, tmp;
9085 size_t host_mask_size, target_mask_size;
9086 unsigned long *host_mask;
9087
9088 /*
9089 * cpu_set_t represent CPU masks as bit masks of type unsigned long *.
9090 * arg3 contains the cpu count.
9091 */
9092 tmp = (8 * sizeof(abi_ulong));
9093 target_mask_size = ((arg3 + tmp - 1) / tmp) * sizeof(abi_ulong);
9094 host_mask_size = (target_mask_size + (sizeof(*host_mask) - 1)) &
9095 ~(sizeof(*host_mask) - 1);
9096
9097 host_mask = alloca(host_mask_size);
9098
9099 ret = target_to_host_cpu_mask(host_mask, host_mask_size,
9100 arg4, target_mask_size);
9101 if (ret != 0) {
9102 return ret;
9103 }
9104
9105 for (i = 0 ; i < host_mask_size / sizeof(*host_mask); i++) {
9106 if (host_mask[i] != 0) {
9107 return 0;
9108 }
9109 }
9110 return -TARGET_EINVAL;
9111}
9112
9113static abi_long do_riscv_hwprobe(CPUArchState *cpu_env, abi_long arg1,
9114 abi_long arg2, abi_long arg3,
9115 abi_long arg4, abi_long arg5)
9116{
9117 int ret;
9118 struct riscv_hwprobe *host_pairs;
9119
9120 /* flags must be 0 */
9121 if (arg5 != 0) {
9122 return -TARGET_EINVAL;
9123 }
9124
9125 /* check cpu_set */
9126 if (arg3 != 0) {
9127 ret = cpu_set_valid(arg3, arg4);
9128 if (ret != 0) {
9129 return ret;
9130 }
9131 } else if (arg4 != 0) {
9132 return -TARGET_EINVAL;
9133 }
9134
9135 /* no pairs */
9136 if (arg2 == 0) {
9137 return 0;
9138 }
9139
9140 host_pairs = lock_user(VERIFY_WRITE, arg1,
9141 sizeof(*host_pairs) * (size_t)arg2, 0);
9142 if (host_pairs == NULL) {
9143 return -TARGET_EFAULT;
9144 }
9145 risc_hwprobe_fill_pairs(cpu_env, host_pairs, arg2);
9146 unlock_user(host_pairs, arg1, sizeof(*host_pairs) * (size_t)arg2);
9147 return 0;
9148}
9149#endif /* TARGET_NR_riscv_hwprobe */
9150
YAMAMOTO Takashie10fbe82021-05-31 14:50:12 +09009151#if defined(TARGET_NR_pivot_root) && defined(__NR_pivot_root)
9152_syscall2(int, pivot_root, const char *, new_root, const char *, put_old)
9153#endif
9154
Thomas Weißschuh7f696cdd2023-04-24 17:34:29 +02009155#if defined(TARGET_NR_open_tree) && defined(__NR_open_tree)
9156#define __NR_sys_open_tree __NR_open_tree
9157_syscall3(int, sys_open_tree, int, __dfd, const char *, __filename,
9158 unsigned int, __flags)
9159#endif
9160
Thomas Weißschuh4b2d2752023-04-24 17:34:28 +02009161#if defined(TARGET_NR_move_mount) && defined(__NR_move_mount)
9162#define __NR_sys_move_mount __NR_move_mount
9163_syscall5(int, sys_move_mount, int, __from_dfd, const char *, __from_pathname,
9164 int, __to_dfd, const char *, __to_pathname, unsigned int, flag)
9165#endif
9166
Richard Hendersondc1ce182018-08-18 12:01:04 -07009167/* This is an internal helper for do_syscall so that it is easier
9168 * to have a single return point, so that actions, such as logging
9169 * of syscall results, can be performed.
9170 * All errnos that do_syscall() returns must be -TARGET_<errcode>.
9171 */
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02009172static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
Richard Hendersondc1ce182018-08-18 12:01:04 -07009173 abi_long arg2, abi_long arg3, abi_long arg4,
9174 abi_long arg5, abi_long arg6, abi_long arg7,
9175 abi_long arg8)
bellard31e31b82003-02-18 22:55:36 +00009176{
Richard Henderson29a0af62019-03-22 16:07:18 -07009177 CPUState *cpu = env_cpu(cpu_env);
blueswir1992f48a2007-10-14 16:27:31 +00009178 abi_long ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009179#if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) \
9180 || defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64) \
Aleksandar Rikaloefa92182019-06-28 12:43:34 +02009181 || defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64) \
9182 || defined(TARGET_NR_statx)
bellard31e31b82003-02-18 22:55:36 +00009183 struct stat st;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009184#endif
9185#if defined(TARGET_NR_statfs) || defined(TARGET_NR_statfs64) \
9186 || defined(TARGET_NR_fstatfs)
bellard56c8f682005-11-28 22:28:41 +00009187 struct statfs stfs;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009188#endif
pbrook53a59602006-03-25 19:31:22 +00009189 void *p;
ths3b46e622007-09-17 08:09:54 +00009190
bellard31e31b82003-02-18 22:55:36 +00009191 switch(num) {
9192 case TARGET_NR_exit:
Andreas Färber9b056fc2013-06-24 23:53:10 +02009193 /* In old applications this may be used to implement _exit(2).
zhaolichang6f9ff552020-09-17 15:50:25 +08009194 However in threaded applications it is used for thread termination,
Andreas Färber9b056fc2013-06-24 23:53:10 +02009195 and _exit_group is used for application termination.
9196 Do thread termination if we have more then one thread. */
Timothy E Baldwina0995882016-05-27 15:51:56 +01009197
9198 if (block_signals()) {
Richard Hendersonaf254a22021-11-22 19:47:33 +01009199 return -QEMU_ERESTARTSYS;
Timothy E Baldwina0995882016-05-27 15:51:56 +01009200 }
9201
Alex Bennée1f81ce92020-05-20 15:05:39 +01009202 pthread_mutex_lock(&clone_lock);
Alex Bennéedd1f6342016-09-30 22:31:01 +01009203
Andreas Färberbdc44642013-06-24 23:50:24 +02009204 if (CPU_NEXT(first_cpu)) {
Alex Bennée1f81ce92020-05-20 15:05:39 +01009205 TaskState *ts = cpu->opaque;
pbrookc2764712009-03-07 15:24:59 +00009206
Richard Henderson6490d9a2023-01-24 10:10:19 -10009207 if (ts->child_tidptr) {
9208 put_user_u32(0, ts->child_tidptr);
9209 do_sys_futex(g2h(cpu, ts->child_tidptr),
9210 FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
9211 }
9212
9213 object_unparent(OBJECT(cpu));
Alex Bennée1f81ce92020-05-20 15:05:39 +01009214 object_unref(OBJECT(cpu));
9215 /*
9216 * At this point the CPU should be unrealized and removed
9217 * from cpu lists. We can clean-up the rest of the thread
9218 * data without the lock held.
9219 */
Alex Bennéedd1f6342016-09-30 22:31:01 +01009220
Alex Bennée1f81ce92020-05-20 15:05:39 +01009221 pthread_mutex_unlock(&clone_lock);
Alex Bennéedd1f6342016-09-30 22:31:01 +01009222
Andreas Färbera2247f82013-06-09 19:47:04 +02009223 thread_cpu = NULL;
Andreas Färber9b056fc2013-06-24 23:53:10 +02009224 g_free(ts);
Emilio G. Cota70903762015-08-23 20:23:41 -04009225 rcu_unregister_thread();
Andreas Färber9b056fc2013-06-24 23:53:10 +02009226 pthread_exit(NULL);
9227 }
Alex Bennéedd1f6342016-09-30 22:31:01 +01009228
Alex Bennée1f81ce92020-05-20 15:05:39 +01009229 pthread_mutex_unlock(&clone_lock);
Alex Bennée708b6a62018-06-22 17:09:10 +01009230 preexit_cleanup(cpu_env, arg1);
pbrookc2764712009-03-07 15:24:59 +00009231 _exit(arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009232 return 0; /* avoid warning */
bellard31e31b82003-02-18 22:55:36 +00009233 case TARGET_NR_read:
Andreas Schwabba584f12019-03-05 17:45:05 +01009234 if (arg2 == 0 && arg3 == 0) {
9235 return get_errno(safe_read(arg1, 0, 0));
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009236 } else {
aurel3238d840e2009-01-30 19:48:17 +00009237 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009238 return -TARGET_EFAULT;
Timothy E Baldwin50afd022016-05-12 18:47:47 +01009239 ret = get_errno(safe_read(arg1, p, arg3));
Laurent Viviere36800c2015-10-02 14:48:09 +02009240 if (ret >= 0 &&
Laurent Vivier5d4d3662015-10-28 21:40:43 +01009241 fd_trans_host_to_target_data(arg1)) {
9242 ret = fd_trans_host_to_target_data(arg1)(p, ret);
Laurent Viviere36800c2015-10-02 14:48:09 +02009243 }
aurel3238d840e2009-01-30 19:48:17 +00009244 unlock_user(p, arg2, ret);
9245 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009246 return ret;
bellard31e31b82003-02-18 22:55:36 +00009247 case TARGET_NR_write:
Tony Garnock-Jones58cfa6c2018-09-08 19:22:05 +01009248 if (arg2 == 0 && arg3 == 0) {
9249 return get_errno(safe_write(arg1, 0, 0));
9250 }
bellard579a97f2007-11-11 14:26:47 +00009251 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009252 return -TARGET_EFAULT;
Laurent Vivier04b9bcf2017-03-01 10:37:47 +01009253 if (fd_trans_target_to_host_data(arg1)) {
9254 void *copy = g_malloc(arg3);
9255 memcpy(copy, p, arg3);
9256 ret = fd_trans_target_to_host_data(arg1)(copy, arg3);
9257 if (ret >= 0) {
9258 ret = get_errno(safe_write(arg1, copy, ret));
9259 }
9260 g_free(copy);
9261 } else {
9262 ret = get_errno(safe_write(arg1, p, arg3));
9263 }
pbrook53a59602006-03-25 19:31:22 +00009264 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009265 return ret;
9266
Chen Gang704eff62015-08-21 05:37:33 +08009267#ifdef TARGET_NR_open
bellard31e31b82003-02-18 22:55:36 +00009268 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00009269 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009270 return -TARGET_EFAULT;
Ilya Leoshkevicha4dab0a2023-06-30 19:04:16 +01009271 ret = get_errno(do_guest_openat(cpu_env, AT_FDCWD, p,
Riku Voipio0b2effd2014-08-06 10:36:37 +03009272 target_to_host_bitmask(arg2, fcntl_flags_tbl),
Ilya Leoshkevich35be8982023-06-30 19:04:17 +01009273 arg3, true));
Laurent Viviere36800c2015-10-02 14:48:09 +02009274 fd_trans_unregister(ret);
pbrook53a59602006-03-25 19:31:22 +00009275 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009276 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009277#endif
ths82424832007-09-24 09:21:55 +00009278 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00009279 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009280 return -TARGET_EFAULT;
Ilya Leoshkevicha4dab0a2023-06-30 19:04:16 +01009281 ret = get_errno(do_guest_openat(cpu_env, arg1, p,
Riku Voipio0b2effd2014-08-06 10:36:37 +03009282 target_to_host_bitmask(arg3, fcntl_flags_tbl),
Ilya Leoshkevich35be8982023-06-30 19:04:17 +01009283 arg4, true));
Laurent Viviere36800c2015-10-02 14:48:09 +02009284 fd_trans_unregister(ret);
bellard579a97f2007-11-11 14:26:47 +00009285 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009286 return ret;
Laurent Vivier0f0426f2015-09-01 22:27:33 +02009287#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
9288 case TARGET_NR_name_to_handle_at:
9289 ret = do_name_to_handle_at(arg1, arg2, arg3, arg4, arg5);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009290 return ret;
Laurent Vivier0f0426f2015-09-01 22:27:33 +02009291#endif
9292#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
9293 case TARGET_NR_open_by_handle_at:
9294 ret = do_open_by_handle_at(arg1, arg2, arg3);
Laurent Viviere36800c2015-10-02 14:48:09 +02009295 fd_trans_unregister(ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009296 return ret;
Laurent Vivier0f0426f2015-09-01 22:27:33 +02009297#endif
Helge Dellercc054c62022-09-18 21:45:46 +02009298#if defined(__NR_pidfd_open) && defined(TARGET_NR_pidfd_open)
9299 case TARGET_NR_pidfd_open:
9300 return get_errno(pidfd_open(arg1, arg2));
9301#endif
9302#if defined(__NR_pidfd_send_signal) && defined(TARGET_NR_pidfd_send_signal)
9303 case TARGET_NR_pidfd_send_signal:
9304 {
Laurent Vivier46187d72022-10-05 18:38:26 +02009305 siginfo_t uinfo, *puinfo;
Helge Dellercc054c62022-09-18 21:45:46 +02009306
Laurent Vivier46187d72022-10-05 18:38:26 +02009307 if (arg3) {
9308 p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
9309 if (!p) {
9310 return -TARGET_EFAULT;
9311 }
9312 target_to_host_siginfo(&uinfo, p);
9313 unlock_user(p, arg3, 0);
9314 puinfo = &uinfo;
9315 } else {
9316 puinfo = NULL;
Helge Dellercc054c62022-09-18 21:45:46 +02009317 }
Helge Dellercc054c62022-09-18 21:45:46 +02009318 ret = get_errno(pidfd_send_signal(arg1, target_to_host_signal(arg2),
Laurent Vivier46187d72022-10-05 18:38:26 +02009319 puinfo, arg4));
Helge Dellercc054c62022-09-18 21:45:46 +02009320 }
9321 return ret;
9322#endif
9323#if defined(__NR_pidfd_getfd) && defined(TARGET_NR_pidfd_getfd)
9324 case TARGET_NR_pidfd_getfd:
9325 return get_errno(pidfd_getfd(arg1, arg2, arg3));
9326#endif
bellard31e31b82003-02-18 22:55:36 +00009327 case TARGET_NR_close:
Laurent Viviere36800c2015-10-02 14:48:09 +02009328 fd_trans_unregister(arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009329 return get_errno(close(arg1));
Helge Delleraf804f32022-10-25 04:34:14 +02009330#if defined(__NR_close_range) && defined(TARGET_NR_close_range)
9331 case TARGET_NR_close_range:
9332 ret = get_errno(sys_close_range(arg1, arg2, arg3));
9333 if (ret == 0 && !(arg3 & CLOSE_RANGE_CLOEXEC)) {
9334 abi_long fd, maxfd;
9335 maxfd = MIN(arg2, target_fd_max);
9336 for (fd = arg1; fd < maxfd; fd++) {
9337 fd_trans_unregister(fd);
9338 }
9339 }
9340 return ret;
9341#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009342
bellard31e31b82003-02-18 22:55:36 +00009343 case TARGET_NR_brk:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009344 return do_brk(arg1);
Chen Gang704eff62015-08-21 05:37:33 +08009345#ifdef TARGET_NR_fork
bellard31e31b82003-02-18 22:55:36 +00009346 case TARGET_NR_fork:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009347 return get_errno(do_fork(cpu_env, TARGET_SIGCHLD, 0, 0, 0, 0));
Chen Gang704eff62015-08-21 05:37:33 +08009348#endif
thse5febef2007-04-01 18:31:35 +00009349#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00009350 case TARGET_NR_waitpid:
9351 {
pbrook53a59602006-03-25 19:31:22 +00009352 int status;
Timothy E Baldwin4af80a32016-05-12 18:47:49 +01009353 ret = get_errno(safe_wait4(arg1, &status, arg3, 0));
Alexander Graf53795572011-11-24 00:44:43 +01009354 if (!is_error(ret) && arg2 && ret
pbrook1d9d8b52009-04-16 15:17:02 +00009355 && put_user_s32(host_to_target_waitstatus(status), arg2))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009356 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00009357 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009358 return ret;
thse5febef2007-04-01 18:31:35 +00009359#endif
pbrookf0cbb612008-05-30 18:20:05 +00009360#ifdef TARGET_NR_waitid
9361 case TARGET_NR_waitid:
9362 {
9363 siginfo_t info;
9364 info.si_pid = 0;
Timothy E Baldwin4af80a32016-05-12 18:47:49 +01009365 ret = get_errno(safe_waitid(arg1, arg2, &info, arg4, NULL));
pbrookf0cbb612008-05-30 18:20:05 +00009366 if (!is_error(ret) && arg3 && info.si_pid != 0) {
Anthony Liguoric227f092009-10-01 16:12:16 -05009367 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009368 return -TARGET_EFAULT;
pbrookf0cbb612008-05-30 18:20:05 +00009369 host_to_target_siginfo(p, &info);
Anthony Liguoric227f092009-10-01 16:12:16 -05009370 unlock_user(p, arg3, sizeof(target_siginfo_t));
pbrookf0cbb612008-05-30 18:20:05 +00009371 }
9372 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009373 return ret;
pbrookf0cbb612008-05-30 18:20:05 +00009374#endif
j_mayer7a3148a2007-04-05 07:13:51 +00009375#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009376 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00009377 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009378 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009379 ret = get_errno(creat(p, arg2));
Laurent Viviere36800c2015-10-02 14:48:09 +02009380 fd_trans_unregister(ret);
pbrook53a59602006-03-25 19:31:22 +00009381 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009382 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00009383#endif
Chen Gang704eff62015-08-21 05:37:33 +08009384#ifdef TARGET_NR_link
bellard31e31b82003-02-18 22:55:36 +00009385 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00009386 {
9387 void * p2;
9388 p = lock_user_string(arg1);
9389 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00009390 if (!p || !p2)
9391 ret = -TARGET_EFAULT;
9392 else
9393 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00009394 unlock_user(p2, arg2, 0);
9395 unlock_user(p, arg1, 0);
9396 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009397 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009398#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01009399#if defined(TARGET_NR_linkat)
ths64f0ce42007-09-24 09:25:06 +00009400 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00009401 {
9402 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00009403 if (!arg2 || !arg4)
Richard Henderson2852aaf2018-08-18 12:01:06 -07009404 return -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00009405 p = lock_user_string(arg2);
9406 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00009407 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00009408 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00009409 else
Peter Maydellc0d472b2013-06-12 16:20:21 +01009410 ret = get_errno(linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00009411 unlock_user(p, arg2, 0);
9412 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00009413 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009414 return ret;
ths64f0ce42007-09-24 09:25:06 +00009415#endif
Chen Gang704eff62015-08-21 05:37:33 +08009416#ifdef TARGET_NR_unlink
bellard31e31b82003-02-18 22:55:36 +00009417 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00009418 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009419 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009420 ret = get_errno(unlink(p));
9421 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009422 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009423#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01009424#if defined(TARGET_NR_unlinkat)
ths8170f562007-09-24 09:24:11 +00009425 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00009426 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009427 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01009428 ret = get_errno(unlinkat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00009429 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009430 return ret;
balrogb7d35e62007-12-12 00:40:24 +00009431#endif
Drew DeVault55bbe4d2022-11-04 18:36:32 +01009432 case TARGET_NR_execveat:
Pierrick Bouvier7a8d9f32023-07-05 14:10:23 +02009433 return do_execv(cpu_env, arg1, arg2, arg3, arg4, arg5, true);
bellard31e31b82003-02-18 22:55:36 +00009434 case TARGET_NR_execve:
Pierrick Bouvier7a8d9f32023-07-05 14:10:23 +02009435 return do_execv(cpu_env, AT_FDCWD, arg1, arg2, arg3, 0, false);
bellard31e31b82003-02-18 22:55:36 +00009436 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00009437 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009438 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009439 ret = get_errno(chdir(p));
9440 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009441 return ret;
bellarda315a142005-01-30 22:59:18 +00009442#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00009443 case TARGET_NR_time:
9444 {
pbrook53a59602006-03-25 19:31:22 +00009445 time_t host_time;
9446 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00009447 if (!is_error(ret)
9448 && arg1
9449 && put_user_sal(host_time, arg1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009450 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00009451 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009452 return ret;
bellarda315a142005-01-30 22:59:18 +00009453#endif
Chen Gang704eff62015-08-21 05:37:33 +08009454#ifdef TARGET_NR_mknod
bellard31e31b82003-02-18 22:55:36 +00009455 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00009456 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009457 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009458 ret = get_errno(mknod(p, arg2, arg3));
9459 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009460 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009461#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01009462#if defined(TARGET_NR_mknodat)
ths75ac37a2007-09-24 09:23:05 +00009463 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00009464 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009465 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01009466 ret = get_errno(mknodat(arg1, p, arg3, arg4));
bellard579a97f2007-11-11 14:26:47 +00009467 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009468 return ret;
ths75ac37a2007-09-24 09:23:05 +00009469#endif
Chen Gang704eff62015-08-21 05:37:33 +08009470#ifdef TARGET_NR_chmod
bellard31e31b82003-02-18 22:55:36 +00009471 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00009472 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009473 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009474 ret = get_errno(chmod(p, arg2));
9475 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009476 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009477#endif
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009478#ifdef TARGET_NR_lseek
bellard31e31b82003-02-18 22:55:36 +00009479 case TARGET_NR_lseek:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009480 return get_errno(lseek(arg1, arg2, arg3));
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009481#endif
Richard Henderson92317332010-05-03 10:07:53 -07009482#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA)
9483 /* Alpha specific */
j_mayer7a3148a2007-04-05 07:13:51 +00009484 case TARGET_NR_getxpid:
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02009485 cpu_env->ir[IR_A4] = getppid();
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009486 return get_errno(getpid());
Richard Henderson92317332010-05-03 10:07:53 -07009487#endif
9488#ifdef TARGET_NR_getpid
9489 case TARGET_NR_getpid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009490 return get_errno(getpid());
Richard Henderson92317332010-05-03 10:07:53 -07009491#endif
bellard31e31b82003-02-18 22:55:36 +00009492 case TARGET_NR_mount:
Paul Burton356d7712014-06-22 11:25:37 +01009493 {
9494 /* need to look at the data field */
9495 void *p2, *p3;
9496
9497 if (arg1) {
9498 p = lock_user_string(arg1);
9499 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009500 return -TARGET_EFAULT;
Paul Burton356d7712014-06-22 11:25:37 +01009501 }
9502 } else {
9503 p = NULL;
9504 }
9505
9506 p2 = lock_user_string(arg2);
9507 if (!p2) {
9508 if (arg1) {
9509 unlock_user(p, arg1, 0);
9510 }
Richard Henderson2852aaf2018-08-18 12:01:06 -07009511 return -TARGET_EFAULT;
Paul Burton356d7712014-06-22 11:25:37 +01009512 }
9513
9514 if (arg3) {
9515 p3 = lock_user_string(arg3);
9516 if (!p3) {
9517 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00009518 unlock_user(p, arg1, 0);
Paul Burton356d7712014-06-22 11:25:37 +01009519 }
9520 unlock_user(p2, arg2, 0);
Richard Henderson2852aaf2018-08-18 12:01:06 -07009521 return -TARGET_EFAULT;
Paul Burton356d7712014-06-22 11:25:37 +01009522 }
9523 } else {
9524 p3 = NULL;
9525 }
9526
9527 /* FIXME - arg5 should be locked, but it isn't clear how to
9528 * do that since it's not guaranteed to be a NULL-terminated
9529 * string.
9530 */
9531 if (!arg5) {
9532 ret = mount(p, p2, p3, (unsigned long)arg4, NULL);
9533 } else {
Richard Henderson3e8f1622021-02-12 10:48:43 -08009534 ret = mount(p, p2, p3, (unsigned long)arg4, g2h(cpu, arg5));
Paul Burton356d7712014-06-22 11:25:37 +01009535 }
9536 ret = get_errno(ret);
9537
9538 if (arg1) {
9539 unlock_user(p, arg1, 0);
9540 }
9541 unlock_user(p2, arg2, 0);
9542 if (arg3) {
9543 unlock_user(p3, arg3, 0);
9544 }
9545 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009546 return ret;
Laurent Vivier6eb9dbf2020-05-02 21:46:42 +02009547#if defined(TARGET_NR_umount) || defined(TARGET_NR_oldumount)
9548#if defined(TARGET_NR_umount)
bellard31e31b82003-02-18 22:55:36 +00009549 case TARGET_NR_umount:
Laurent Vivier6eb9dbf2020-05-02 21:46:42 +02009550#endif
9551#if defined(TARGET_NR_oldumount)
9552 case TARGET_NR_oldumount:
9553#endif
bellard579a97f2007-11-11 14:26:47 +00009554 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009555 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009556 ret = get_errno(umount(p));
9557 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009558 return ret;
thse5febef2007-04-01 18:31:35 +00009559#endif
Thomas Weißschuh4b2d2752023-04-24 17:34:28 +02009560#if defined(TARGET_NR_move_mount) && defined(__NR_move_mount)
9561 case TARGET_NR_move_mount:
9562 {
9563 void *p2, *p4;
9564
9565 if (!arg2 || !arg4) {
9566 return -TARGET_EFAULT;
9567 }
9568
9569 p2 = lock_user_string(arg2);
9570 if (!p2) {
9571 return -TARGET_EFAULT;
9572 }
9573
9574 p4 = lock_user_string(arg4);
9575 if (!p4) {
9576 unlock_user(p2, arg2, 0);
9577 return -TARGET_EFAULT;
9578 }
9579 ret = get_errno(sys_move_mount(arg1, p2, arg3, p4, arg5));
9580
9581 unlock_user(p2, arg2, 0);
9582 unlock_user(p4, arg4, 0);
9583
9584 return ret;
9585 }
9586#endif
Thomas Weißschuh7f696cdd2023-04-24 17:34:29 +02009587#if defined(TARGET_NR_open_tree) && defined(__NR_open_tree)
9588 case TARGET_NR_open_tree:
9589 {
9590 void *p2;
9591 int host_flags;
9592
9593 if (!arg2) {
9594 return -TARGET_EFAULT;
9595 }
9596
9597 p2 = lock_user_string(arg2);
9598 if (!p2) {
9599 return -TARGET_EFAULT;
9600 }
9601
9602 host_flags = arg3 & ~TARGET_O_CLOEXEC;
9603 if (arg3 & TARGET_O_CLOEXEC) {
9604 host_flags |= O_CLOEXEC;
9605 }
9606
9607 ret = get_errno(sys_open_tree(arg1, p2, host_flags));
9608
9609 unlock_user(p2, arg2, 0);
9610
9611 return ret;
9612 }
9613#endif
j_mayer7a3148a2007-04-05 07:13:51 +00009614#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009615 case TARGET_NR_stime:
9616 {
Laurent Vivier0f1f2d42019-11-12 15:25:56 +01009617 struct timespec ts;
9618 ts.tv_nsec = 0;
9619 if (get_user_sal(ts.tv_sec, arg1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009620 return -TARGET_EFAULT;
Laurent Vivier0f1f2d42019-11-12 15:25:56 +01009621 }
9622 return get_errno(clock_settime(CLOCK_REALTIME, &ts));
bellard31e31b82003-02-18 22:55:36 +00009623 }
j_mayer7a3148a2007-04-05 07:13:51 +00009624#endif
j_mayer7a3148a2007-04-05 07:13:51 +00009625#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009626 case TARGET_NR_alarm:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009627 return alarm(arg1);
j_mayer7a3148a2007-04-05 07:13:51 +00009628#endif
j_mayer7a3148a2007-04-05 07:13:51 +00009629#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009630 case TARGET_NR_pause:
Timothy E Baldwinf59ec602016-05-27 15:51:55 +01009631 if (!block_signals()) {
9632 sigsuspend(&((TaskState *)cpu->opaque)->signal_mask);
9633 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009634 return -TARGET_EINTR;
j_mayer7a3148a2007-04-05 07:13:51 +00009635#endif
thse5febef2007-04-01 18:31:35 +00009636#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00009637 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00009638 {
pbrook53a59602006-03-25 19:31:22 +00009639 struct utimbuf tbuf, *host_tbuf;
9640 struct target_utimbuf *target_tbuf;
9641 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00009642 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009643 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02009644 tbuf.actime = tswapal(target_tbuf->actime);
9645 tbuf.modtime = tswapal(target_tbuf->modtime);
pbrook53a59602006-03-25 19:31:22 +00009646 unlock_user_struct(target_tbuf, arg2, 0);
9647 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00009648 } else {
pbrook53a59602006-03-25 19:31:22 +00009649 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00009650 }
bellard579a97f2007-11-11 14:26:47 +00009651 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009652 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009653 ret = get_errno(utime(p, host_tbuf));
9654 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00009655 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009656 return ret;
thse5febef2007-04-01 18:31:35 +00009657#endif
Chen Gang704eff62015-08-21 05:37:33 +08009658#ifdef TARGET_NR_utimes
bellard978a66f2004-12-06 22:58:05 +00009659 case TARGET_NR_utimes:
9660 {
bellard978a66f2004-12-06 22:58:05 +00009661 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00009662 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00009663 if (copy_from_user_timeval(&tv[0], arg2)
9664 || copy_from_user_timeval(&tv[1],
9665 arg2 + sizeof(struct target_timeval)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009666 return -TARGET_EFAULT;
bellard978a66f2004-12-06 22:58:05 +00009667 tvp = tv;
9668 } else {
9669 tvp = NULL;
9670 }
bellard579a97f2007-11-11 14:26:47 +00009671 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009672 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009673 ret = get_errno(utimes(p, tvp));
9674 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00009675 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009676 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009677#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01009678#if defined(TARGET_NR_futimesat)
balrogac8a6552008-09-20 02:25:39 +00009679 case TARGET_NR_futimesat:
9680 {
9681 struct timeval *tvp, tv[2];
9682 if (arg3) {
9683 if (copy_from_user_timeval(&tv[0], arg3)
9684 || copy_from_user_timeval(&tv[1],
9685 arg3 + sizeof(struct target_timeval)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009686 return -TARGET_EFAULT;
balrogac8a6552008-09-20 02:25:39 +00009687 tvp = tv;
9688 } else {
9689 tvp = NULL;
9690 }
Richard Henderson2852aaf2018-08-18 12:01:06 -07009691 if (!(p = lock_user_string(arg2))) {
9692 return -TARGET_EFAULT;
9693 }
Peter Maydellc0d472b2013-06-12 16:20:21 +01009694 ret = get_errno(futimesat(arg1, path(p), tvp));
balrogac8a6552008-09-20 02:25:39 +00009695 unlock_user(p, arg2, 0);
9696 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009697 return ret;
balrogac8a6552008-09-20 02:25:39 +00009698#endif
Chen Gang704eff62015-08-21 05:37:33 +08009699#ifdef TARGET_NR_access
bellard31e31b82003-02-18 22:55:36 +00009700 case TARGET_NR_access:
Richard Henderson2852aaf2018-08-18 12:01:06 -07009701 if (!(p = lock_user_string(arg1))) {
9702 return -TARGET_EFAULT;
9703 }
Ulrich Hecht719f9082009-07-03 17:09:29 +02009704 ret = get_errno(access(path(p), arg2));
pbrook53a59602006-03-25 19:31:22 +00009705 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009706 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009707#endif
ths92a34c12007-09-24 09:27:49 +00009708#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
9709 case TARGET_NR_faccessat:
Richard Henderson2852aaf2018-08-18 12:01:06 -07009710 if (!(p = lock_user_string(arg2))) {
9711 return -TARGET_EFAULT;
9712 }
Peter Maydellc0d472b2013-06-12 16:20:21 +01009713 ret = get_errno(faccessat(arg1, p, arg3, 0));
bellard579a97f2007-11-11 14:26:47 +00009714 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009715 return ret;
ths92a34c12007-09-24 09:27:49 +00009716#endif
WANG Xuerui35a2c852022-10-09 14:08:13 +08009717#if defined(TARGET_NR_faccessat2)
9718 case TARGET_NR_faccessat2:
9719 if (!(p = lock_user_string(arg2))) {
9720 return -TARGET_EFAULT;
9721 }
9722 ret = get_errno(faccessat(arg1, p, arg3, arg4));
9723 unlock_user(p, arg2, 0);
9724 return ret;
9725#endif
j_mayer7a3148a2007-04-05 07:13:51 +00009726#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009727 case TARGET_NR_nice:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009728 return get_errno(nice(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +00009729#endif
bellard31e31b82003-02-18 22:55:36 +00009730 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00009731 sync();
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009732 return 0;
Aleksandar Markovic5a03cd02016-10-10 13:23:30 +02009733#if defined(TARGET_NR_syncfs) && defined(CONFIG_SYNCFS)
9734 case TARGET_NR_syncfs:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009735 return get_errno(syncfs(arg1));
Aleksandar Markovic5a03cd02016-10-10 13:23:30 +02009736#endif
bellard31e31b82003-02-18 22:55:36 +00009737 case TARGET_NR_kill:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009738 return get_errno(safe_kill(arg1, target_to_host_signal(arg2)));
Chen Gang704eff62015-08-21 05:37:33 +08009739#ifdef TARGET_NR_rename
bellard31e31b82003-02-18 22:55:36 +00009740 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00009741 {
9742 void *p2;
9743 p = lock_user_string(arg1);
9744 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00009745 if (!p || !p2)
9746 ret = -TARGET_EFAULT;
9747 else
9748 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00009749 unlock_user(p2, arg2, 0);
9750 unlock_user(p, arg1, 0);
9751 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009752 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009753#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01009754#if defined(TARGET_NR_renameat)
ths722183f2007-09-24 09:24:37 +00009755 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00009756 {
bellard579a97f2007-11-11 14:26:47 +00009757 void *p2;
ths722183f2007-09-24 09:24:37 +00009758 p = lock_user_string(arg2);
9759 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00009760 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00009761 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00009762 else
Peter Maydellc0d472b2013-06-12 16:20:21 +01009763 ret = get_errno(renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00009764 unlock_user(p2, arg4, 0);
9765 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00009766 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009767 return ret;
ths722183f2007-09-24 09:24:37 +00009768#endif
Andreas Schwab95d03072018-01-23 11:53:31 +01009769#if defined(TARGET_NR_renameat2)
9770 case TARGET_NR_renameat2:
9771 {
9772 void *p2;
9773 p = lock_user_string(arg2);
9774 p2 = lock_user_string(arg4);
9775 if (!p || !p2) {
9776 ret = -TARGET_EFAULT;
9777 } else {
9778 ret = get_errno(sys_renameat2(arg1, p, arg3, p2, arg5));
9779 }
9780 unlock_user(p2, arg4, 0);
9781 unlock_user(p, arg2, 0);
9782 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009783 return ret;
Andreas Schwab95d03072018-01-23 11:53:31 +01009784#endif
Chen Gang704eff62015-08-21 05:37:33 +08009785#ifdef TARGET_NR_mkdir
bellard31e31b82003-02-18 22:55:36 +00009786 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00009787 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009788 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009789 ret = get_errno(mkdir(p, arg2));
9790 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009791 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009792#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01009793#if defined(TARGET_NR_mkdirat)
ths4472ad02007-09-24 09:22:32 +00009794 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00009795 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009796 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01009797 ret = get_errno(mkdirat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00009798 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009799 return ret;
ths4472ad02007-09-24 09:22:32 +00009800#endif
Chen Gang704eff62015-08-21 05:37:33 +08009801#ifdef TARGET_NR_rmdir
bellard31e31b82003-02-18 22:55:36 +00009802 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00009803 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009804 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009805 ret = get_errno(rmdir(p));
9806 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009807 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009808#endif
bellard31e31b82003-02-18 22:55:36 +00009809 case TARGET_NR_dup:
9810 ret = get_errno(dup(arg1));
Laurent Viviere36800c2015-10-02 14:48:09 +02009811 if (ret >= 0) {
9812 fd_trans_dup(arg1, ret);
9813 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009814 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009815#ifdef TARGET_NR_pipe
bellard31e31b82003-02-18 22:55:36 +00009816 case TARGET_NR_pipe:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009817 return do_pipe(cpu_env, arg1, 0, 0);
Chen Gang704eff62015-08-21 05:37:33 +08009818#endif
Riku Voipio099d6b02009-05-05 12:10:04 +03009819#ifdef TARGET_NR_pipe2
9820 case TARGET_NR_pipe2:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009821 return do_pipe(cpu_env, arg1,
9822 target_to_host_bitmask(arg2, fcntl_flags_tbl), 1);
Riku Voipio099d6b02009-05-05 12:10:04 +03009823#endif
bellard31e31b82003-02-18 22:55:36 +00009824 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00009825 {
pbrook53a59602006-03-25 19:31:22 +00009826 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00009827 struct tms tms;
9828 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00009829 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00009830 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
9831 if (!tmsp)
Richard Henderson2852aaf2018-08-18 12:01:06 -07009832 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02009833 tmsp->tms_utime = tswapal(host_to_target_clock_t(tms.tms_utime));
9834 tmsp->tms_stime = tswapal(host_to_target_clock_t(tms.tms_stime));
9835 tmsp->tms_cutime = tswapal(host_to_target_clock_t(tms.tms_cutime));
9836 tmsp->tms_cstime = tswapal(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00009837 }
bellardc596ed12003-07-13 17:32:31 +00009838 if (!is_error(ret))
9839 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00009840 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009841 return ret;
bellard31e31b82003-02-18 22:55:36 +00009842 case TARGET_NR_acct:
aurel3238d840e2009-01-30 19:48:17 +00009843 if (arg1 == 0) {
9844 ret = get_errno(acct(NULL));
9845 } else {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009846 if (!(p = lock_user_string(arg1))) {
9847 return -TARGET_EFAULT;
9848 }
aurel3238d840e2009-01-30 19:48:17 +00009849 ret = get_errno(acct(path(p)));
9850 unlock_user(p, arg1, 0);
9851 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009852 return ret;
Richard Henderson8070e7b2013-07-24 09:50:00 -10009853#ifdef TARGET_NR_umount2
bellard31e31b82003-02-18 22:55:36 +00009854 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00009855 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009856 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009857 ret = get_errno(umount2(p, arg2));
9858 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009859 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00009860#endif
bellard31e31b82003-02-18 22:55:36 +00009861 case TARGET_NR_ioctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009862 return do_ioctl(arg1, arg2, arg3);
Michael Clark47ae93c2018-03-03 01:31:11 +13009863#ifdef TARGET_NR_fcntl
bellard31e31b82003-02-18 22:55:36 +00009864 case TARGET_NR_fcntl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009865 return do_fcntl(arg1, arg2, arg3);
Michael Clark47ae93c2018-03-03 01:31:11 +13009866#endif
bellard31e31b82003-02-18 22:55:36 +00009867 case TARGET_NR_setpgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009868 return get_errno(setpgid(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00009869 case TARGET_NR_umask:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009870 return get_errno(umask(arg1));
bellard31e31b82003-02-18 22:55:36 +00009871 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00009872 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009873 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009874 ret = get_errno(chroot(p));
9875 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009876 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009877#ifdef TARGET_NR_dup2
bellard31e31b82003-02-18 22:55:36 +00009878 case TARGET_NR_dup2:
9879 ret = get_errno(dup2(arg1, arg2));
Laurent Viviere36800c2015-10-02 14:48:09 +02009880 if (ret >= 0) {
9881 fd_trans_dup(arg1, arg2);
9882 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009883 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009884#endif
Ulrich Hechtd0927932009-09-17 20:22:14 +03009885#if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3)
9886 case TARGET_NR_dup3:
Peter Maydell10fa9932017-12-15 15:18:00 +00009887 {
9888 int host_flags;
9889
9890 if ((arg3 & ~TARGET_O_CLOEXEC) != 0) {
9891 return -EINVAL;
9892 }
9893 host_flags = target_to_host_bitmask(arg3, fcntl_flags_tbl);
9894 ret = get_errno(dup3(arg1, arg2, host_flags));
Laurent Viviere36800c2015-10-02 14:48:09 +02009895 if (ret >= 0) {
9896 fd_trans_dup(arg1, arg2);
9897 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009898 return ret;
Peter Maydell10fa9932017-12-15 15:18:00 +00009899 }
Ulrich Hechtd0927932009-09-17 20:22:14 +03009900#endif
j_mayer7a3148a2007-04-05 07:13:51 +00009901#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009902 case TARGET_NR_getppid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009903 return get_errno(getppid());
j_mayer7a3148a2007-04-05 07:13:51 +00009904#endif
Chen Gang704eff62015-08-21 05:37:33 +08009905#ifdef TARGET_NR_getpgrp
bellard31e31b82003-02-18 22:55:36 +00009906 case TARGET_NR_getpgrp:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009907 return get_errno(getpgrp());
Chen Gang704eff62015-08-21 05:37:33 +08009908#endif
bellard31e31b82003-02-18 22:55:36 +00009909 case TARGET_NR_setsid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009910 return get_errno(setsid());
thse5febef2007-04-01 18:31:35 +00009911#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00009912 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00009913 {
Richard Henderson02d0de12021-04-22 16:02:26 -07009914#if defined(TARGET_MIPS)
bellard106ec872006-06-27 21:08:10 +00009915 struct target_sigaction act, oact, *pact, *old_act;
9916
9917 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00009918 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009919 return -TARGET_EFAULT;
bellard106ec872006-06-27 21:08:10 +00009920 act._sa_handler = old_act->_sa_handler;
9921 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
9922 act.sa_flags = old_act->sa_flags;
9923 unlock_user_struct(old_act, arg2, 0);
9924 pact = &act;
9925 } else {
9926 pact = NULL;
9927 }
9928
Richard Henderson02fb28e2021-04-22 16:02:23 -07009929 ret = get_errno(do_sigaction(arg1, pact, &oact, 0));
bellard106ec872006-06-27 21:08:10 +00009930
9931 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00009932 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009933 return -TARGET_EFAULT;
bellard106ec872006-06-27 21:08:10 +00009934 old_act->_sa_handler = oact._sa_handler;
9935 old_act->sa_flags = oact.sa_flags;
9936 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
9937 old_act->sa_mask.sig[1] = 0;
9938 old_act->sa_mask.sig[2] = 0;
9939 old_act->sa_mask.sig[3] = 0;
9940 unlock_user_struct(old_act, arg3, 1);
9941 }
Richard Henderson6049f4f2009-12-27 18:30:03 -08009942#else
9943 struct target_old_sigaction *old_act;
9944 struct target_sigaction act, oact, *pact;
9945 if (arg2) {
9946 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009947 return -TARGET_EFAULT;
Richard Henderson6049f4f2009-12-27 18:30:03 -08009948 act._sa_handler = old_act->_sa_handler;
9949 target_siginitset(&act.sa_mask, old_act->sa_mask);
9950 act.sa_flags = old_act->sa_flags;
Richard Hendersonca192272021-04-22 16:02:24 -07009951#ifdef TARGET_ARCH_HAS_SA_RESTORER
Richard Henderson6049f4f2009-12-27 18:30:03 -08009952 act.sa_restorer = old_act->sa_restorer;
Richard Hendersonca192272021-04-22 16:02:24 -07009953#endif
Richard Henderson6049f4f2009-12-27 18:30:03 -08009954 unlock_user_struct(old_act, arg2, 0);
9955 pact = &act;
9956 } else {
9957 pact = NULL;
9958 }
Richard Henderson02fb28e2021-04-22 16:02:23 -07009959 ret = get_errno(do_sigaction(arg1, pact, &oact, 0));
Richard Henderson6049f4f2009-12-27 18:30:03 -08009960 if (!is_error(ret) && arg3) {
9961 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009962 return -TARGET_EFAULT;
Richard Henderson6049f4f2009-12-27 18:30:03 -08009963 old_act->_sa_handler = oact._sa_handler;
9964 old_act->sa_mask = oact.sa_mask.sig[0];
9965 old_act->sa_flags = oact.sa_flags;
Richard Hendersonca192272021-04-22 16:02:24 -07009966#ifdef TARGET_ARCH_HAS_SA_RESTORER
Richard Henderson6049f4f2009-12-27 18:30:03 -08009967 old_act->sa_restorer = oact.sa_restorer;
Richard Hendersonca192272021-04-22 16:02:24 -07009968#endif
Richard Henderson6049f4f2009-12-27 18:30:03 -08009969 unlock_user_struct(old_act, arg3, 1);
9970 }
ths388bb212007-05-13 13:58:00 +00009971#endif
bellard31e31b82003-02-18 22:55:36 +00009972 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009973 return ret;
thse5febef2007-04-01 18:31:35 +00009974#endif
bellard66fb9762003-03-23 01:06:05 +00009975 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00009976 {
Richard Henderson0f6f9902021-04-22 16:02:25 -07009977 /*
9978 * For Alpha and SPARC this is a 5 argument syscall, with
Peter Maydell78bfef72017-11-06 18:33:26 +00009979 * a 'restorer' parameter which must be copied into the
9980 * sa_restorer field of the sigaction struct.
9981 * For Alpha that 'restorer' is arg5; for SPARC it is arg4,
9982 * and arg5 is the sigsetsize.
Peter Maydell78bfef72017-11-06 18:33:26 +00009983 */
Richard Henderson0f6f9902021-04-22 16:02:25 -07009984#if defined(TARGET_ALPHA)
9985 target_ulong sigsetsize = arg4;
9986 target_ulong restorer = arg5;
9987#elif defined(TARGET_SPARC)
Peter Maydell78bfef72017-11-06 18:33:26 +00009988 target_ulong restorer = arg4;
9989 target_ulong sigsetsize = arg5;
9990#else
9991 target_ulong sigsetsize = arg4;
Richard Henderson02fb28e2021-04-22 16:02:23 -07009992 target_ulong restorer = 0;
Peter Maydell78bfef72017-11-06 18:33:26 +00009993#endif
Richard Hendersonfb804392021-04-22 16:02:27 -07009994 struct target_sigaction *act = NULL;
9995 struct target_sigaction *oact = NULL;
pbrook53a59602006-03-25 19:31:22 +00009996
Peter Maydell78bfef72017-11-06 18:33:26 +00009997 if (sigsetsize != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009998 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01009999 }
Richard Hendersonfb804392021-04-22 16:02:27 -070010000 if (arg2 && !lock_user_struct(VERIFY_READ, act, arg2, 1)) {
10001 return -TARGET_EFAULT;
Peter Maydell78bfef72017-11-06 18:33:26 +000010002 }
Richard Hendersonfb804392021-04-22 16:02:27 -070010003 if (arg3 && !lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
10004 ret = -TARGET_EFAULT;
10005 } else {
10006 ret = get_errno(do_sigaction(arg1, act, oact, restorer));
10007 if (oact) {
10008 unlock_user_struct(oact, arg3, 1);
bellard579a97f2007-11-11 14:26:47 +000010009 }
Richard Hendersonfb804392021-04-22 16:02:27 -070010010 }
10011 if (act) {
pbrook53a59602006-03-25 19:31:22 +000010012 unlock_user_struct(act, arg2, 0);
Richard Hendersonfb804392021-04-22 16:02:27 -070010013 }
pbrook53a59602006-03-25 19:31:22 +000010014 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010015 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +000010016#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +000010017 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +000010018 {
10019 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +000010020 abi_ulong target_set;
Peter Maydell3d3efba2016-05-27 15:51:49 +010010021 ret = do_sigprocmask(0, NULL, &cur_set);
10022 if (!ret) {
10023 host_to_target_old_sigset(&target_set, &cur_set);
10024 ret = target_set;
10025 }
bellard66fb9762003-03-23 01:06:05 +000010026 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010027 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +000010028#endif
10029#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +000010030 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +000010031 {
Miloš Stojanovića8617d82017-05-15 16:59:43 +020010032 sigset_t set, oset;
blueswir1992f48a2007-10-14 16:27:31 +000010033 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +000010034 target_to_host_old_sigset(&set, &target_set);
Peter Maydell3d3efba2016-05-27 15:51:49 +010010035 ret = do_sigprocmask(SIG_SETMASK, &set, &oset);
10036 if (!ret) {
10037 host_to_target_old_sigset(&target_set, &oset);
10038 ret = target_set;
10039 }
bellard66fb9762003-03-23 01:06:05 +000010040 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010041 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +000010042#endif
thse5febef2007-04-01 18:31:35 +000010043#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +000010044 case TARGET_NR_sigprocmask:
10045 {
Richard Hendersona5b3b132010-05-03 10:07:55 -070010046#if defined(TARGET_ALPHA)
10047 sigset_t set, oldset;
10048 abi_ulong mask;
10049 int how;
10050
10051 switch (arg1) {
10052 case TARGET_SIG_BLOCK:
10053 how = SIG_BLOCK;
10054 break;
10055 case TARGET_SIG_UNBLOCK:
10056 how = SIG_UNBLOCK;
10057 break;
10058 case TARGET_SIG_SETMASK:
10059 how = SIG_SETMASK;
10060 break;
10061 default:
Richard Henderson259841c2018-08-18 12:01:09 -070010062 return -TARGET_EINVAL;
Richard Hendersona5b3b132010-05-03 10:07:55 -070010063 }
10064 mask = arg2;
10065 target_to_host_old_sigset(&set, &mask);
10066
Peter Maydell3d3efba2016-05-27 15:51:49 +010010067 ret = do_sigprocmask(how, &set, &oldset);
Richard Hendersona5b3b132010-05-03 10:07:55 -070010068 if (!is_error(ret)) {
10069 host_to_target_old_sigset(&mask, &oldset);
10070 ret = mask;
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020010071 cpu_env->ir[IR_V0] = 0; /* force no error */
Richard Hendersona5b3b132010-05-03 10:07:55 -070010072 }
10073#else
bellard66fb9762003-03-23 01:06:05 +000010074 sigset_t set, oldset, *set_ptr;
Richard Hendersona5b3b132010-05-03 10:07:55 -070010075 int how;
ths3b46e622007-09-17 08:09:54 +000010076
pbrook53a59602006-03-25 19:31:22 +000010077 if (arg2) {
Patrick Ventureebce1712022-01-26 13:25:59 -080010078 p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1);
10079 if (!p) {
10080 return -TARGET_EFAULT;
10081 }
10082 target_to_host_old_sigset(&set, p);
10083 unlock_user(p, arg2, 0);
10084 set_ptr = &set;
Richard Hendersona5b3b132010-05-03 10:07:55 -070010085 switch (arg1) {
bellard66fb9762003-03-23 01:06:05 +000010086 case TARGET_SIG_BLOCK:
10087 how = SIG_BLOCK;
10088 break;
10089 case TARGET_SIG_UNBLOCK:
10090 how = SIG_UNBLOCK;
10091 break;
10092 case TARGET_SIG_SETMASK:
10093 how = SIG_SETMASK;
10094 break;
10095 default:
Richard Henderson259841c2018-08-18 12:01:09 -070010096 return -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +000010097 }
bellard66fb9762003-03-23 01:06:05 +000010098 } else {
10099 how = 0;
10100 set_ptr = NULL;
10101 }
Peter Maydell3d3efba2016-05-27 15:51:49 +010010102 ret = do_sigprocmask(how, set_ptr, &oldset);
pbrook53a59602006-03-25 19:31:22 +000010103 if (!is_error(ret) && arg3) {
Anthony Liguoric227f092009-10-01 16:12:16 -050010104 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010105 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010106 host_to_target_old_sigset(p, &oldset);
Anthony Liguoric227f092009-10-01 16:12:16 -050010107 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +000010108 }
Richard Hendersona5b3b132010-05-03 10:07:55 -070010109#endif
bellard66fb9762003-03-23 01:06:05 +000010110 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010111 return ret;
thse5febef2007-04-01 18:31:35 +000010112#endif
bellard66fb9762003-03-23 01:06:05 +000010113 case TARGET_NR_rt_sigprocmask:
10114 {
10115 int how = arg1;
10116 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +000010117
Peter Maydellc8157012016-06-30 14:23:24 +010010118 if (arg4 != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010119 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +010010120 }
10121
pbrook53a59602006-03-25 19:31:22 +000010122 if (arg2) {
Shu-Chun Wengd3ced2a2022-01-26 13:25:58 -080010123 p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1);
10124 if (!p) {
10125 return -TARGET_EFAULT;
10126 }
10127 target_to_host_sigset(&set, p);
10128 unlock_user(p, arg2, 0);
10129 set_ptr = &set;
bellard66fb9762003-03-23 01:06:05 +000010130 switch(how) {
10131 case TARGET_SIG_BLOCK:
10132 how = SIG_BLOCK;
10133 break;
10134 case TARGET_SIG_UNBLOCK:
10135 how = SIG_UNBLOCK;
10136 break;
10137 case TARGET_SIG_SETMASK:
10138 how = SIG_SETMASK;
10139 break;
10140 default:
Richard Henderson259841c2018-08-18 12:01:09 -070010141 return -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +000010142 }
bellard66fb9762003-03-23 01:06:05 +000010143 } else {
10144 how = 0;
10145 set_ptr = NULL;
10146 }
Peter Maydell3d3efba2016-05-27 15:51:49 +010010147 ret = do_sigprocmask(how, set_ptr, &oldset);
pbrook53a59602006-03-25 19:31:22 +000010148 if (!is_error(ret) && arg3) {
Anthony Liguoric227f092009-10-01 16:12:16 -050010149 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010150 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010151 host_to_target_sigset(p, &oldset);
Anthony Liguoric227f092009-10-01 16:12:16 -050010152 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +000010153 }
10154 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010155 return ret;
thse5febef2007-04-01 18:31:35 +000010156#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +000010157 case TARGET_NR_sigpending:
10158 {
10159 sigset_t set;
10160 ret = get_errno(sigpending(&set));
10161 if (!is_error(ret)) {
Anthony Liguoric227f092009-10-01 16:12:16 -050010162 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010163 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010164 host_to_target_old_sigset(p, &set);
Anthony Liguoric227f092009-10-01 16:12:16 -050010165 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +000010166 }
10167 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010168 return ret;
thse5febef2007-04-01 18:31:35 +000010169#endif
bellard66fb9762003-03-23 01:06:05 +000010170 case TARGET_NR_rt_sigpending:
10171 {
10172 sigset_t set;
Peter Maydellc8157012016-06-30 14:23:24 +010010173
10174 /* Yes, this check is >, not != like most. We follow the kernel's
10175 * logic and it does it like this because it implements
10176 * NR_sigpending through the same code path, and in that case
10177 * the old_sigset_t is smaller in size.
10178 */
10179 if (arg2 > sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010180 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +010010181 }
10182
bellard66fb9762003-03-23 01:06:05 +000010183 ret = get_errno(sigpending(&set));
10184 if (!is_error(ret)) {
Anthony Liguoric227f092009-10-01 16:12:16 -050010185 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010186 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010187 host_to_target_sigset(p, &set);
Anthony Liguoric227f092009-10-01 16:12:16 -050010188 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +000010189 }
10190 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010191 return ret;
thse5febef2007-04-01 18:31:35 +000010192#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +000010193 case TARGET_NR_sigsuspend:
10194 {
Richard Henderson0a99f092022-03-15 01:43:05 -070010195 sigset_t *set;
10196
Richard Hendersonf43ce122010-05-03 10:07:54 -070010197#if defined(TARGET_ALPHA)
Richard Henderson0a99f092022-03-15 01:43:05 -070010198 TaskState *ts = cpu->opaque;
Richard Henderson7fb5ef32022-03-15 01:43:04 -070010199 /* target_to_host_old_sigset will bswap back */
10200 abi_ulong mask = tswapal(arg1);
Richard Henderson0a99f092022-03-15 01:43:05 -070010201 set = &ts->sigsuspend_mask;
10202 target_to_host_old_sigset(set, &mask);
Richard Hendersonf43ce122010-05-03 10:07:54 -070010203#else
Richard Henderson0a99f092022-03-15 01:43:05 -070010204 ret = process_sigsuspend_mask(&set, arg1, sizeof(target_sigset_t));
10205 if (ret != 0) {
10206 return ret;
Peter Maydell3d3efba2016-05-27 15:51:49 +010010207 }
Richard Henderson0a99f092022-03-15 01:43:05 -070010208#endif
10209 ret = get_errno(safe_rt_sigsuspend(set, SIGSET_T_SIZE));
10210 finish_sigsuspend_mask(ret);
bellard66fb9762003-03-23 01:06:05 +000010211 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010212 return ret;
thse5febef2007-04-01 18:31:35 +000010213#endif
bellard66fb9762003-03-23 01:06:05 +000010214 case TARGET_NR_rt_sigsuspend:
10215 {
Richard Henderson0a99f092022-03-15 01:43:05 -070010216 sigset_t *set;
Peter Maydellc8157012016-06-30 14:23:24 +010010217
Richard Henderson0a99f092022-03-15 01:43:05 -070010218 ret = process_sigsuspend_mask(&set, arg1, arg2);
10219 if (ret != 0) {
10220 return ret;
Peter Maydellc8157012016-06-30 14:23:24 +010010221 }
Richard Henderson0a99f092022-03-15 01:43:05 -070010222 ret = get_errno(safe_rt_sigsuspend(set, SIGSET_T_SIZE));
10223 finish_sigsuspend_mask(ret);
bellard66fb9762003-03-23 01:06:05 +000010224 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010225 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070010226#ifdef TARGET_NR_rt_sigtimedwait
bellard66fb9762003-03-23 01:06:05 +000010227 case TARGET_NR_rt_sigtimedwait:
10228 {
bellard66fb9762003-03-23 01:06:05 +000010229 sigset_t set;
10230 struct timespec uts, *puts;
10231 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +000010232
Peter Maydellc8157012016-06-30 14:23:24 +010010233 if (arg4 != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010234 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +010010235 }
10236
Anthony Liguoric227f092009-10-01 16:12:16 -050010237 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010238 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010239 target_to_host_sigset(&set, p);
10240 unlock_user(p, arg1, 0);
10241 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +000010242 puts = &uts;
Filip Bozuta4d213002020-07-24 20:16:51 +020010243 if (target_to_host_timespec(puts, arg3)) {
10244 return -TARGET_EFAULT;
10245 }
bellard66fb9762003-03-23 01:06:05 +000010246 } else {
10247 puts = NULL;
10248 }
Peter Maydellb3f82332016-06-06 19:58:08 +010010249 ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts,
10250 SIGSET_T_SIZE));
Petar Jovanovic974a1962014-03-03 15:07:41 +010010251 if (!is_error(ret)) {
10252 if (arg2) {
10253 p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t),
10254 0);
10255 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010256 return -TARGET_EFAULT;
Petar Jovanovic974a1962014-03-03 15:07:41 +010010257 }
10258 host_to_target_siginfo(p, &uinfo);
10259 unlock_user(p, arg2, sizeof(target_siginfo_t));
10260 }
10261 ret = host_to_target_signal(ret);
bellard66fb9762003-03-23 01:06:05 +000010262 }
10263 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010264 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070010265#endif
Filip Bozutaddcbde12020-08-24 21:21:16 +020010266#ifdef TARGET_NR_rt_sigtimedwait_time64
10267 case TARGET_NR_rt_sigtimedwait_time64:
10268 {
10269 sigset_t set;
10270 struct timespec uts, *puts;
10271 siginfo_t uinfo;
10272
10273 if (arg4 != sizeof(target_sigset_t)) {
10274 return -TARGET_EINVAL;
10275 }
10276
10277 p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
10278 if (!p) {
10279 return -TARGET_EFAULT;
10280 }
10281 target_to_host_sigset(&set, p);
10282 unlock_user(p, arg1, 0);
10283 if (arg3) {
10284 puts = &uts;
10285 if (target_to_host_timespec64(puts, arg3)) {
10286 return -TARGET_EFAULT;
10287 }
10288 } else {
10289 puts = NULL;
10290 }
10291 ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts,
10292 SIGSET_T_SIZE));
10293 if (!is_error(ret)) {
10294 if (arg2) {
10295 p = lock_user(VERIFY_WRITE, arg2,
10296 sizeof(target_siginfo_t), 0);
10297 if (!p) {
10298 return -TARGET_EFAULT;
10299 }
10300 host_to_target_siginfo(p, &uinfo);
10301 unlock_user(p, arg2, sizeof(target_siginfo_t));
10302 }
10303 ret = host_to_target_signal(ret);
10304 }
10305 }
10306 return ret;
10307#endif
bellard66fb9762003-03-23 01:06:05 +000010308 case TARGET_NR_rt_sigqueueinfo:
10309 {
10310 siginfo_t uinfo;
Peter Maydell4debae62016-06-20 15:50:36 +010010311
10312 p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
10313 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010314 return -TARGET_EFAULT;
Peter Maydell4debae62016-06-20 15:50:36 +010010315 }
pbrook53a59602006-03-25 19:31:22 +000010316 target_to_host_siginfo(&uinfo, p);
Miloš Stojanovićd8b6d892017-05-15 16:59:44 +020010317 unlock_user(p, arg3, 0);
fanwenjie9b9145f2022-08-31 11:55:25 +080010318 ret = get_errno(sys_rt_sigqueueinfo(arg1, target_to_host_signal(arg2), &uinfo));
bellard66fb9762003-03-23 01:06:05 +000010319 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010320 return ret;
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +020010321 case TARGET_NR_rt_tgsigqueueinfo:
10322 {
10323 siginfo_t uinfo;
10324
10325 p = lock_user(VERIFY_READ, arg4, sizeof(target_siginfo_t), 1);
10326 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010327 return -TARGET_EFAULT;
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +020010328 }
10329 target_to_host_siginfo(&uinfo, p);
10330 unlock_user(p, arg4, 0);
fanwenjie9b9145f2022-08-31 11:55:25 +080010331 ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, target_to_host_signal(arg3), &uinfo));
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +020010332 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010333 return ret;
thse5febef2007-04-01 18:31:35 +000010334#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +000010335 case TARGET_NR_sigreturn:
Peter Maydell3d3efba2016-05-27 15:51:49 +010010336 if (block_signals()) {
Richard Hendersonaf254a22021-11-22 19:47:33 +010010337 return -QEMU_ERESTARTSYS;
Peter Maydell3d3efba2016-05-27 15:51:49 +010010338 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010339 return do_sigreturn(cpu_env);
thse5febef2007-04-01 18:31:35 +000010340#endif
bellard66fb9762003-03-23 01:06:05 +000010341 case TARGET_NR_rt_sigreturn:
Peter Maydell3d3efba2016-05-27 15:51:49 +010010342 if (block_signals()) {
Richard Hendersonaf254a22021-11-22 19:47:33 +010010343 return -QEMU_ERESTARTSYS;
Peter Maydell3d3efba2016-05-27 15:51:49 +010010344 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010345 return do_rt_sigreturn(cpu_env);
bellard31e31b82003-02-18 22:55:36 +000010346 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +000010347 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010348 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010349 ret = get_errno(sethostname(p, arg2));
10350 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010351 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010352#ifdef TARGET_NR_setrlimit
bellard31e31b82003-02-18 22:55:36 +000010353 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +000010354 {
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +030010355 int resource = target_to_host_resource(arg1);
pbrook53a59602006-03-25 19:31:22 +000010356 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +000010357 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +000010358 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010359 return -TARGET_EFAULT;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +090010360 rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
10361 rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +000010362 unlock_user_struct(target_rlim, arg2, 0);
Max Filippov5dfa88f2018-09-17 11:13:14 -070010363 /*
10364 * If we just passed through resource limit settings for memory then
10365 * they would also apply to QEMU's own allocations, and QEMU will
10366 * crash or hang or die if its allocations fail. Ideally we would
10367 * track the guest allocations in QEMU and apply the limits ourselves.
10368 * For now, just tell the guest the call succeeded but don't actually
10369 * limit anything.
10370 */
10371 if (resource != RLIMIT_AS &&
10372 resource != RLIMIT_DATA &&
10373 resource != RLIMIT_STACK) {
10374 return get_errno(setrlimit(resource, &rlim));
10375 } else {
10376 return 0;
10377 }
bellard9de5e442003-03-23 16:49:39 +000010378 }
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010379#endif
10380#ifdef TARGET_NR_getrlimit
bellard31e31b82003-02-18 22:55:36 +000010381 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +000010382 {
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +030010383 int resource = target_to_host_resource(arg1);
pbrook53a59602006-03-25 19:31:22 +000010384 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +000010385 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +000010386
bellard9de5e442003-03-23 16:49:39 +000010387 ret = get_errno(getrlimit(resource, &rlim));
10388 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +000010389 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010390 return -TARGET_EFAULT;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +090010391 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
10392 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +000010393 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +000010394 }
10395 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010396 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010397#endif
bellard31e31b82003-02-18 22:55:36 +000010398 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +000010399 {
10400 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +000010401 ret = get_errno(getrusage(arg1, &rusage));
10402 if (!is_error(ret)) {
Petar Jovanovica39fb272014-04-08 19:24:30 +020010403 ret = host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +000010404 }
10405 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010406 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070010407#if defined(TARGET_NR_gettimeofday)
bellard31e31b82003-02-18 22:55:36 +000010408 case TARGET_NR_gettimeofday:
10409 {
bellard31e31b82003-02-18 22:55:36 +000010410 struct timeval tv;
Richard Hendersona52f5f82020-02-12 19:22:23 -080010411 struct timezone tz;
10412
10413 ret = get_errno(gettimeofday(&tv, &tz));
bellard31e31b82003-02-18 22:55:36 +000010414 if (!is_error(ret)) {
Richard Hendersona52f5f82020-02-12 19:22:23 -080010415 if (arg1 && copy_to_user_timeval(arg1, &tv)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010416 return -TARGET_EFAULT;
Richard Hendersona52f5f82020-02-12 19:22:23 -080010417 }
10418 if (arg2 && copy_to_user_timezone(arg2, &tz)) {
10419 return -TARGET_EFAULT;
10420 }
bellard31e31b82003-02-18 22:55:36 +000010421 }
10422 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010423 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070010424#endif
10425#if defined(TARGET_NR_settimeofday)
bellard31e31b82003-02-18 22:55:36 +000010426 case TARGET_NR_settimeofday:
10427 {
Paul Burtonb67d8032014-06-22 11:25:41 +010010428 struct timeval tv, *ptv = NULL;
Paul Burtonef4467e2014-06-22 11:25:40 +010010429 struct timezone tz, *ptz = NULL;
10430
Paul Burtonb67d8032014-06-22 11:25:41 +010010431 if (arg1) {
10432 if (copy_from_user_timeval(&tv, arg1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010433 return -TARGET_EFAULT;
Paul Burtonb67d8032014-06-22 11:25:41 +010010434 }
10435 ptv = &tv;
10436 }
Paul Burtonef4467e2014-06-22 11:25:40 +010010437
10438 if (arg2) {
10439 if (copy_from_user_timezone(&tz, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010440 return -TARGET_EFAULT;
Paul Burtonef4467e2014-06-22 11:25:40 +010010441 }
10442 ptz = &tz;
10443 }
10444
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010445 return get_errno(settimeofday(ptv, ptz));
bellard31e31b82003-02-18 22:55:36 +000010446 }
Alistair Francis859e8a82020-03-12 15:13:49 -070010447#endif
Laurent Vivier9468a5d2013-01-10 22:30:50 +010010448#if defined(TARGET_NR_select)
bellard31e31b82003-02-18 22:55:36 +000010449 case TARGET_NR_select:
Laurent Vivier5457dc92016-07-08 01:17:27 +020010450#if defined(TARGET_WANT_NI_OLD_SELECT)
10451 /* some architectures used to have old_select here
10452 * but now ENOSYS it.
10453 */
10454 ret = -TARGET_ENOSYS;
10455#elif defined(TARGET_WANT_OLD_SYS_SELECT)
10456 ret = do_old_select(arg1);
Laurent Vivier9468a5d2013-01-10 22:30:50 +010010457#else
Laurent Vivier5457dc92016-07-08 01:17:27 +020010458 ret = do_select(arg1, arg2, arg3, arg4, arg5);
Laurent Vivier9468a5d2013-01-10 22:30:50 +010010459#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010460 return ret;
bellard048f6b42005-11-26 18:47:20 +000010461#endif
Riku Voipio9e423822010-05-07 12:28:05 +000010462#ifdef TARGET_NR_pselect6
10463 case TARGET_NR_pselect6:
Filip Bozutae5ce9682020-08-25 00:30:49 +020010464 return do_pselect6(arg1, arg2, arg3, arg4, arg5, arg6, false);
10465#endif
10466#ifdef TARGET_NR_pselect6_time64
10467 case TARGET_NR_pselect6_time64:
10468 return do_pselect6(arg1, arg2, arg3, arg4, arg5, arg6, true);
Riku Voipio9e423822010-05-07 12:28:05 +000010469#endif
Chen Gang704eff62015-08-21 05:37:33 +080010470#ifdef TARGET_NR_symlink
bellard31e31b82003-02-18 22:55:36 +000010471 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +000010472 {
10473 void *p2;
10474 p = lock_user_string(arg1);
10475 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +000010476 if (!p || !p2)
10477 ret = -TARGET_EFAULT;
10478 else
10479 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +000010480 unlock_user(p2, arg2, 0);
10481 unlock_user(p, arg1, 0);
10482 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010483 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080010484#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +010010485#if defined(TARGET_NR_symlinkat)
thsf0b62432007-09-24 09:25:40 +000010486 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +000010487 {
bellard579a97f2007-11-11 14:26:47 +000010488 void *p2;
thsf0b62432007-09-24 09:25:40 +000010489 p = lock_user_string(arg1);
10490 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +000010491 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +000010492 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +000010493 else
Peter Maydellc0d472b2013-06-12 16:20:21 +010010494 ret = get_errno(symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +000010495 unlock_user(p2, arg3, 0);
10496 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +000010497 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010498 return ret;
thsf0b62432007-09-24 09:25:40 +000010499#endif
Chen Gang704eff62015-08-21 05:37:33 +080010500#ifdef TARGET_NR_readlink
bellard31e31b82003-02-18 22:55:36 +000010501 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +000010502 {
Andreas Schwab463d8e72013-07-02 14:04:12 +010010503 void *p2;
pbrook53a59602006-03-25 19:31:22 +000010504 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +000010505 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
Ilya Leoshkevicha4dab0a2023-06-30 19:04:16 +010010506 ret = get_errno(do_guest_readlink(p, p2, arg3));
pbrook53a59602006-03-25 19:31:22 +000010507 unlock_user(p2, arg2, ret);
10508 unlock_user(p, arg1, 0);
10509 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010510 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080010511#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +010010512#if defined(TARGET_NR_readlinkat)
ths5e0ccb12007-09-24 09:26:10 +000010513 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +000010514 {
bellard579a97f2007-11-11 14:26:47 +000010515 void *p2;
ths5e0ccb12007-09-24 09:26:10 +000010516 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +000010517 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
Andreas Schwab463d8e72013-07-02 14:04:12 +010010518 if (!p || !p2) {
10519 ret = -TARGET_EFAULT;
Jameson Nash65d48302022-08-08 15:07:27 -040010520 } else if (!arg4) {
10521 /* Short circuit this for the magic exe check. */
10522 ret = -TARGET_EINVAL;
Andreas Schwab463d8e72013-07-02 14:04:12 +010010523 } else if (is_proc_myself((const char *)p, "exe")) {
Helge Deller258bec32022-12-05 12:38:25 +010010524 /*
10525 * Don't worry about sign mismatch as earlier mapping
10526 * logic would have thrown a bad address error.
10527 */
10528 ret = MIN(strlen(exec_path), arg4);
10529 /* We cannot NUL terminate the string. */
10530 memcpy(p2, exec_path, ret);
Andreas Schwab463d8e72013-07-02 14:04:12 +010010531 } else {
Peter Maydellc0d472b2013-06-12 16:20:21 +010010532 ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
Andreas Schwab463d8e72013-07-02 14:04:12 +010010533 }
bellard579a97f2007-11-11 14:26:47 +000010534 unlock_user(p2, arg3, ret);
10535 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +000010536 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010537 return ret;
ths5e0ccb12007-09-24 09:26:10 +000010538#endif
thse5febef2007-04-01 18:31:35 +000010539#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +000010540 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +000010541 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010542 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010543 ret = get_errno(swapon(p, arg2));
10544 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010545 return ret;
thse5febef2007-04-01 18:31:35 +000010546#endif
bellard31e31b82003-02-18 22:55:36 +000010547 case TARGET_NR_reboot:
Laurent Vivierc07ecc62013-01-07 11:40:06 +000010548 if (arg3 == LINUX_REBOOT_CMD_RESTART2) {
10549 /* arg4 must be ignored in all other cases */
10550 p = lock_user_string(arg4);
10551 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010552 return -TARGET_EFAULT;
Laurent Vivierc07ecc62013-01-07 11:40:06 +000010553 }
10554 ret = get_errno(reboot(arg1, arg2, arg3, p));
10555 unlock_user(p, arg4, 0);
10556 } else {
10557 ret = get_errno(reboot(arg1, arg2, arg3, NULL));
10558 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010559 return ret;
thse5febef2007-04-01 18:31:35 +000010560#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +000010561 case TARGET_NR_mmap:
Alexander Graf09701192013-09-03 20:12:15 +010010562#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
10563 (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
Ulrich Hechta4c075f2009-07-24 16:57:31 +020010564 defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \
10565 || defined(TARGET_S390X)
bellard31e31b82003-02-18 22:55:36 +000010566 {
blueswir1992f48a2007-10-14 16:27:31 +000010567 abi_ulong *v;
10568 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +000010569 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010570 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +020010571 v1 = tswapal(v[0]);
10572 v2 = tswapal(v[1]);
10573 v3 = tswapal(v[2]);
10574 v4 = tswapal(v[3]);
10575 v5 = tswapal(v[4]);
10576 v6 = tswapal(v[5]);
pbrook53a59602006-03-25 19:31:22 +000010577 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +000010578 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +000010579 target_to_host_bitmask(v4, mmap_flags_tbl),
10580 v5, v6));
bellard31e31b82003-02-18 22:55:36 +000010581 }
bellard31e31b82003-02-18 22:55:36 +000010582#else
Richard Hendersonee1bf832021-02-12 10:48:44 -080010583 /* mmap pointers are always untagged */
ths5fafdf22007-09-16 21:08:06 +000010584 ret = get_errno(target_mmap(arg1, arg2, arg3,
10585 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +000010586 arg5,
10587 arg6));
bellard31e31b82003-02-18 22:55:36 +000010588#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010589 return ret;
thse5febef2007-04-01 18:31:35 +000010590#endif
bellarda315a142005-01-30 22:59:18 +000010591#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +000010592 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +000010593#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +000010594#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +000010595#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010596 ret = target_mmap(arg1, arg2, arg3,
10597 target_to_host_bitmask(arg4, mmap_flags_tbl),
Richard Henderson55baec02023-07-07 21:40:41 +010010598 arg5, (off_t)(abi_ulong)arg6 << MMAP_SHIFT);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010599 return get_errno(ret);
bellarda315a142005-01-30 22:59:18 +000010600#endif
bellard31e31b82003-02-18 22:55:36 +000010601 case TARGET_NR_munmap:
Richard Hendersonee1bf832021-02-12 10:48:44 -080010602 arg1 = cpu_untagged_addr(cpu, arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010603 return get_errno(target_munmap(arg1, arg2));
bellard9de5e442003-03-23 16:49:39 +000010604 case TARGET_NR_mprotect:
Richard Hendersonee1bf832021-02-12 10:48:44 -080010605 arg1 = cpu_untagged_addr(cpu, arg1);
Paul Brook97374d32010-06-16 13:03:51 +010010606 {
Andreas Färber0429a972013-08-26 18:14:44 +020010607 TaskState *ts = cpu->opaque;
Paul Brook97374d32010-06-16 13:03:51 +010010608 /* Special hack to detect libc making the stack executable. */
10609 if ((arg3 & PROT_GROWSDOWN)
10610 && arg1 >= ts->info->stack_limit
10611 && arg1 <= ts->info->start_stack) {
10612 arg3 &= ~PROT_GROWSDOWN;
10613 arg2 = arg2 + arg1 - ts->info->stack_limit;
10614 arg1 = ts->info->stack_limit;
10615 }
10616 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010617 return get_errno(target_mprotect(arg1, arg2, arg3));
thse5febef2007-04-01 18:31:35 +000010618#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +000010619 case TARGET_NR_mremap:
Richard Hendersonee1bf832021-02-12 10:48:44 -080010620 arg1 = cpu_untagged_addr(cpu, arg1);
10621 /* mremap new_addr (arg5) is always untagged */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010622 return get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
thse5febef2007-04-01 18:31:35 +000010623#endif
pbrook53a59602006-03-25 19:31:22 +000010624 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +000010625#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +000010626 case TARGET_NR_msync:
Helge Dellerfe080592022-12-15 08:27:46 +010010627 return get_errno(msync(g2h(cpu, arg1), arg2,
10628 target_to_host_msync_arg(arg3)));
thse5febef2007-04-01 18:31:35 +000010629#endif
10630#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +000010631 case TARGET_NR_mlock:
Richard Henderson3e8f1622021-02-12 10:48:43 -080010632 return get_errno(mlock(g2h(cpu, arg1), arg2));
thse5febef2007-04-01 18:31:35 +000010633#endif
10634#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +000010635 case TARGET_NR_munlock:
Richard Henderson3e8f1622021-02-12 10:48:43 -080010636 return get_errno(munlock(g2h(cpu, arg1), arg2));
thse5febef2007-04-01 18:31:35 +000010637#endif
10638#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +000010639 case TARGET_NR_mlockall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010640 return get_errno(mlockall(target_to_host_mlockall_arg(arg1)));
thse5febef2007-04-01 18:31:35 +000010641#endif
10642#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +000010643 case TARGET_NR_munlockall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010644 return get_errno(munlockall());
thse5febef2007-04-01 18:31:35 +000010645#endif
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010646#ifdef TARGET_NR_truncate
bellard31e31b82003-02-18 22:55:36 +000010647 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +000010648 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010649 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010650 ret = get_errno(truncate(p, arg2));
10651 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010652 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010653#endif
10654#ifdef TARGET_NR_ftruncate
bellard31e31b82003-02-18 22:55:36 +000010655 case TARGET_NR_ftruncate:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010656 return get_errno(ftruncate(arg1, arg2));
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010657#endif
bellard31e31b82003-02-18 22:55:36 +000010658 case TARGET_NR_fchmod:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010659 return get_errno(fchmod(arg1, arg2));
Peter Maydellc0d472b2013-06-12 16:20:21 +010010660#if defined(TARGET_NR_fchmodat)
ths814d7972007-09-24 09:26:51 +000010661 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +000010662 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010663 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +010010664 ret = get_errno(fchmodat(arg1, p, arg3, 0));
bellard579a97f2007-11-11 14:26:47 +000010665 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010666 return ret;
ths814d7972007-09-24 09:26:51 +000010667#endif
bellard31e31b82003-02-18 22:55:36 +000010668 case TARGET_NR_getpriority:
Richard Henderson95c09822012-06-07 15:14:50 -070010669 /* Note that negative values are valid for getpriority, so we must
10670 differentiate based on errno settings. */
10671 errno = 0;
10672 ret = getpriority(arg1, arg2);
10673 if (ret == -1 && errno != 0) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010674 return -host_to_target_errno(errno);
Richard Henderson95c09822012-06-07 15:14:50 -070010675 }
10676#ifdef TARGET_ALPHA
10677 /* Return value is the unbiased priority. Signal no error. */
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020010678 cpu_env->ir[IR_V0] = 0;
Richard Henderson95c09822012-06-07 15:14:50 -070010679#else
10680 /* Return value is a biased priority to avoid negative numbers. */
10681 ret = 20 - ret;
10682#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010683 return ret;
bellard31e31b82003-02-18 22:55:36 +000010684 case TARGET_NR_setpriority:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010685 return get_errno(setpriority(arg1, arg2, arg3));
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010686#ifdef TARGET_NR_statfs
bellard31e31b82003-02-18 22:55:36 +000010687 case TARGET_NR_statfs:
Richard Henderson2852aaf2018-08-18 12:01:06 -070010688 if (!(p = lock_user_string(arg1))) {
10689 return -TARGET_EFAULT;
10690 }
pbrook53a59602006-03-25 19:31:22 +000010691 ret = get_errno(statfs(path(p), &stfs));
10692 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +000010693 convert_statfs:
10694 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +000010695 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +000010696
bellard579a97f2007-11-11 14:26:47 +000010697 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010698 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000010699 __put_user(stfs.f_type, &target_stfs->f_type);
10700 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
10701 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
10702 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
10703 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
10704 __put_user(stfs.f_files, &target_stfs->f_files);
10705 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
10706 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
10707 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
10708 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
Alexander Graf229d3372012-09-19 04:39:53 +020010709 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
Shea Levyd4247ec2018-03-01 06:15:00 -050010710#ifdef _STATFS_F_FLAGS
10711 __put_user(stfs.f_flags, &target_stfs->f_flags);
10712#else
10713 __put_user(0, &target_stfs->f_flags);
10714#endif
Alexander Graf229d3372012-09-19 04:39:53 +020010715 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
pbrook53a59602006-03-25 19:31:22 +000010716 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +000010717 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010718 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010719#endif
10720#ifdef TARGET_NR_fstatfs
bellard31e31b82003-02-18 22:55:36 +000010721 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +000010722 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +000010723 goto convert_statfs;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010724#endif
bellard56c8f682005-11-28 22:28:41 +000010725#ifdef TARGET_NR_statfs64
10726 case TARGET_NR_statfs64:
Richard Henderson2852aaf2018-08-18 12:01:06 -070010727 if (!(p = lock_user_string(arg1))) {
10728 return -TARGET_EFAULT;
10729 }
pbrook53a59602006-03-25 19:31:22 +000010730 ret = get_errno(statfs(path(p), &stfs));
10731 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +000010732 convert_statfs64:
10733 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +000010734 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +000010735
bellard579a97f2007-11-11 14:26:47 +000010736 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010737 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000010738 __put_user(stfs.f_type, &target_stfs->f_type);
10739 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
10740 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
10741 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
10742 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
10743 __put_user(stfs.f_files, &target_stfs->f_files);
10744 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
10745 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
10746 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
10747 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
Alexander Graf229d3372012-09-19 04:39:53 +020010748 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
Frajob94e2b42020-01-30 15:00:30 +020010749#ifdef _STATFS_F_FLAGS
10750 __put_user(stfs.f_flags, &target_stfs->f_flags);
10751#else
10752 __put_user(0, &target_stfs->f_flags);
10753#endif
Alexander Graf229d3372012-09-19 04:39:53 +020010754 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
bellard579a97f2007-11-11 14:26:47 +000010755 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +000010756 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010757 return ret;
bellard56c8f682005-11-28 22:28:41 +000010758 case TARGET_NR_fstatfs64:
10759 ret = get_errno(fstatfs(arg1, &stfs));
10760 goto convert_statfs64;
10761#endif
thse5febef2007-04-01 18:31:35 +000010762#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +000010763 case TARGET_NR_socketcall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010764 return do_socketcall(arg1, arg2);
thse5febef2007-04-01 18:31:35 +000010765#endif
bellard3532fa72006-06-24 15:06:03 +000010766#ifdef TARGET_NR_accept
10767 case TARGET_NR_accept:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010768 return do_accept4(arg1, arg2, arg3, 0);
Peter Maydella94b4982013-02-08 04:35:04 +000010769#endif
10770#ifdef TARGET_NR_accept4
10771 case TARGET_NR_accept4:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010772 return do_accept4(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +000010773#endif
10774#ifdef TARGET_NR_bind
10775 case TARGET_NR_bind:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010776 return do_bind(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +000010777#endif
10778#ifdef TARGET_NR_connect
10779 case TARGET_NR_connect:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010780 return do_connect(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +000010781#endif
10782#ifdef TARGET_NR_getpeername
10783 case TARGET_NR_getpeername:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010784 return do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +000010785#endif
10786#ifdef TARGET_NR_getsockname
10787 case TARGET_NR_getsockname:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010788 return do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +000010789#endif
10790#ifdef TARGET_NR_getsockopt
10791 case TARGET_NR_getsockopt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010792 return do_getsockopt(arg1, arg2, arg3, arg4, arg5);
bellard3532fa72006-06-24 15:06:03 +000010793#endif
10794#ifdef TARGET_NR_listen
10795 case TARGET_NR_listen:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010796 return get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +000010797#endif
10798#ifdef TARGET_NR_recv
10799 case TARGET_NR_recv:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010800 return do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +000010801#endif
10802#ifdef TARGET_NR_recvfrom
10803 case TARGET_NR_recvfrom:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010804 return do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +000010805#endif
10806#ifdef TARGET_NR_recvmsg
10807 case TARGET_NR_recvmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010808 return do_sendrecvmsg(arg1, arg2, arg3, 0);
bellard3532fa72006-06-24 15:06:03 +000010809#endif
10810#ifdef TARGET_NR_send
10811 case TARGET_NR_send:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010812 return do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +000010813#endif
10814#ifdef TARGET_NR_sendmsg
10815 case TARGET_NR_sendmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010816 return do_sendrecvmsg(arg1, arg2, arg3, 1);
bellard3532fa72006-06-24 15:06:03 +000010817#endif
Alexander Graff19e00d2014-03-02 19:36:42 +000010818#ifdef TARGET_NR_sendmmsg
10819 case TARGET_NR_sendmmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010820 return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1);
Alistair Francis859e8a82020-03-12 15:13:49 -070010821#endif
10822#ifdef TARGET_NR_recvmmsg
Alexander Graff19e00d2014-03-02 19:36:42 +000010823 case TARGET_NR_recvmmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010824 return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0);
Alexander Graff19e00d2014-03-02 19:36:42 +000010825#endif
bellard3532fa72006-06-24 15:06:03 +000010826#ifdef TARGET_NR_sendto
10827 case TARGET_NR_sendto:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010828 return do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +000010829#endif
10830#ifdef TARGET_NR_shutdown
10831 case TARGET_NR_shutdown:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010832 return get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +000010833#endif
Laurent Vivierf894efd2016-02-21 10:56:23 +010010834#if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
10835 case TARGET_NR_getrandom:
10836 p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
10837 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010838 return -TARGET_EFAULT;
Laurent Vivierf894efd2016-02-21 10:56:23 +010010839 }
10840 ret = get_errno(getrandom(p, arg2, arg3));
10841 unlock_user(p, arg1, ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010842 return ret;
Laurent Vivierf894efd2016-02-21 10:56:23 +010010843#endif
bellard3532fa72006-06-24 15:06:03 +000010844#ifdef TARGET_NR_socket
10845 case TARGET_NR_socket:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010846 return do_socket(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +000010847#endif
10848#ifdef TARGET_NR_socketpair
10849 case TARGET_NR_socketpair:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010850 return do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +000010851#endif
10852#ifdef TARGET_NR_setsockopt
10853 case TARGET_NR_setsockopt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010854 return do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
bellard3532fa72006-06-24 15:06:03 +000010855#endif
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010856#if defined(TARGET_NR_syslog)
bellard31e31b82003-02-18 22:55:36 +000010857 case TARGET_NR_syslog:
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010858 {
10859 int len = arg2;
ths7494b0f2007-02-11 18:26:53 +000010860
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010861 switch (arg1) {
10862 case TARGET_SYSLOG_ACTION_CLOSE: /* Close log */
10863 case TARGET_SYSLOG_ACTION_OPEN: /* Open log */
10864 case TARGET_SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
10865 case TARGET_SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging */
10866 case TARGET_SYSLOG_ACTION_CONSOLE_ON: /* Enable logging */
10867 case TARGET_SYSLOG_ACTION_CONSOLE_LEVEL: /* Set messages level */
10868 case TARGET_SYSLOG_ACTION_SIZE_UNREAD: /* Number of chars */
10869 case TARGET_SYSLOG_ACTION_SIZE_BUFFER: /* Size of the buffer */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010870 return get_errno(sys_syslog((int)arg1, NULL, (int)arg3));
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010871 case TARGET_SYSLOG_ACTION_READ: /* Read from log */
10872 case TARGET_SYSLOG_ACTION_READ_CLEAR: /* Read/clear msgs */
10873 case TARGET_SYSLOG_ACTION_READ_ALL: /* Read last messages */
10874 {
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010875 if (len < 0) {
Richard Henderson259841c2018-08-18 12:01:09 -070010876 return -TARGET_EINVAL;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010877 }
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010878 if (len == 0) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010879 return 0;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010880 }
10881 p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
10882 if (!p) {
Richard Henderson259841c2018-08-18 12:01:09 -070010883 return -TARGET_EFAULT;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010884 }
10885 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
10886 unlock_user(p, arg2, arg3);
10887 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010888 return ret;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010889 default:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010890 return -TARGET_EINVAL;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010891 }
10892 }
10893 break;
10894#endif
bellard31e31b82003-02-18 22:55:36 +000010895 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +000010896 {
bellard66fb9762003-03-23 01:06:05 +000010897 struct itimerval value, ovalue, *pvalue;
10898
pbrook53a59602006-03-25 19:31:22 +000010899 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +000010900 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +000010901 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
10902 || copy_from_user_timeval(&pvalue->it_value,
10903 arg2 + sizeof(struct target_timeval)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010904 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +000010905 } else {
10906 pvalue = NULL;
10907 }
10908 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +000010909 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +000010910 if (copy_to_user_timeval(arg3,
10911 &ovalue.it_interval)
10912 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
10913 &ovalue.it_value))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010914 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +000010915 }
10916 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010917 return ret;
bellard31e31b82003-02-18 22:55:36 +000010918 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +000010919 {
bellard66fb9762003-03-23 01:06:05 +000010920 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +000010921
bellard66fb9762003-03-23 01:06:05 +000010922 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +000010923 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +000010924 if (copy_to_user_timeval(arg2,
10925 &value.it_interval)
10926 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
10927 &value.it_value))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010928 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +000010929 }
10930 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010931 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080010932#ifdef TARGET_NR_stat
bellard31e31b82003-02-18 22:55:36 +000010933 case TARGET_NR_stat:
Richard Henderson2852aaf2018-08-18 12:01:06 -070010934 if (!(p = lock_user_string(arg1))) {
10935 return -TARGET_EFAULT;
10936 }
pbrook53a59602006-03-25 19:31:22 +000010937 ret = get_errno(stat(path(p), &st));
10938 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +000010939 goto do_stat;
Chen Gang704eff62015-08-21 05:37:33 +080010940#endif
10941#ifdef TARGET_NR_lstat
bellard31e31b82003-02-18 22:55:36 +000010942 case TARGET_NR_lstat:
Richard Henderson2852aaf2018-08-18 12:01:06 -070010943 if (!(p = lock_user_string(arg1))) {
10944 return -TARGET_EFAULT;
10945 }
pbrook53a59602006-03-25 19:31:22 +000010946 ret = get_errno(lstat(path(p), &st));
10947 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +000010948 goto do_stat;
Chen Gang704eff62015-08-21 05:37:33 +080010949#endif
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010950#ifdef TARGET_NR_fstat
bellard31e31b82003-02-18 22:55:36 +000010951 case TARGET_NR_fstat:
10952 {
10953 ret = get_errno(fstat(arg1, &st));
Chen Gang704eff62015-08-21 05:37:33 +080010954#if defined(TARGET_NR_stat) || defined(TARGET_NR_lstat)
bellard31e31b82003-02-18 22:55:36 +000010955 do_stat:
Chen Gang704eff62015-08-21 05:37:33 +080010956#endif
bellard31e31b82003-02-18 22:55:36 +000010957 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +000010958 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +000010959
bellard579a97f2007-11-11 14:26:47 +000010960 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010961 return -TARGET_EFAULT;
Ulrich Hecht12727912009-07-24 19:10:32 +020010962 memset(target_st, 0, sizeof(*target_st));
bellardd2fd1af2007-11-14 18:08:56 +000010963 __put_user(st.st_dev, &target_st->st_dev);
10964 __put_user(st.st_ino, &target_st->st_ino);
10965 __put_user(st.st_mode, &target_st->st_mode);
10966 __put_user(st.st_uid, &target_st->st_uid);
10967 __put_user(st.st_gid, &target_st->st_gid);
10968 __put_user(st.st_nlink, &target_st->st_nlink);
10969 __put_user(st.st_rdev, &target_st->st_rdev);
10970 __put_user(st.st_size, &target_st->st_size);
10971 __put_user(st.st_blksize, &target_st->st_blksize);
10972 __put_user(st.st_blocks, &target_st->st_blocks);
10973 __put_user(st.st_atime, &target_st->target_st_atime);
10974 __put_user(st.st_mtime, &target_st->target_st_mtime);
10975 __put_user(st.st_ctime, &target_st->target_st_ctime);
Michael Forneyfebf6fa2021-05-25 20:55:31 -070010976#if defined(HAVE_STRUCT_STAT_ST_ATIM) && defined(TARGET_STAT_HAVE_NSEC)
Chen-Yu Tsai5f992db2019-05-23 00:21:47 +080010977 __put_user(st.st_atim.tv_nsec,
10978 &target_st->target_st_atime_nsec);
10979 __put_user(st.st_mtim.tv_nsec,
10980 &target_st->target_st_mtime_nsec);
10981 __put_user(st.st_ctim.tv_nsec,
10982 &target_st->target_st_ctime_nsec);
10983#endif
pbrook53a59602006-03-25 19:31:22 +000010984 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +000010985 }
10986 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010987 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010988#endif
bellard31e31b82003-02-18 22:55:36 +000010989 case TARGET_NR_vhangup:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010990 return get_errno(vhangup());
bellard42ad6ae2005-01-03 22:48:11 +000010991#ifdef TARGET_NR_syscall
10992 case TARGET_NR_syscall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010993 return do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5,
10994 arg6, arg7, arg8, 0);
bellard42ad6ae2005-01-03 22:48:11 +000010995#endif
Alistair Francis859e8a82020-03-12 15:13:49 -070010996#if defined(TARGET_NR_wait4)
bellard31e31b82003-02-18 22:55:36 +000010997 case TARGET_NR_wait4:
10998 {
10999 int status;
blueswir1992f48a2007-10-14 16:27:31 +000011000 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +000011001 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +000011002 abi_ulong target_rusage = arg4;
Petar Jovanovica39fb272014-04-08 19:24:30 +020011003 abi_long rusage_err;
bellard31e31b82003-02-18 22:55:36 +000011004 if (target_rusage)
11005 rusage_ptr = &rusage;
11006 else
11007 rusage_ptr = NULL;
Timothy E Baldwin4af80a32016-05-12 18:47:49 +010011008 ret = get_errno(safe_wait4(arg1, &status, arg3, rusage_ptr));
bellard31e31b82003-02-18 22:55:36 +000011009 if (!is_error(ret)) {
Alexander Graf53795572011-11-24 00:44:43 +010011010 if (status_ptr && ret) {
pbrook1d9d8b52009-04-16 15:17:02 +000011011 status = host_to_target_waitstatus(status);
bellard2f619692007-11-16 10:46:05 +000011012 if (put_user_s32(status, status_ptr))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011013 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +000011014 }
Petar Jovanovica39fb272014-04-08 19:24:30 +020011015 if (target_rusage) {
11016 rusage_err = host_to_target_rusage(target_rusage, &rusage);
11017 if (rusage_err) {
11018 ret = rusage_err;
11019 }
11020 }
bellard31e31b82003-02-18 22:55:36 +000011021 }
11022 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011023 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070011024#endif
thse5febef2007-04-01 18:31:35 +000011025#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +000011026 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +000011027 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011028 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011029 ret = get_errno(swapoff(p));
11030 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011031 return ret;
thse5febef2007-04-01 18:31:35 +000011032#endif
bellard31e31b82003-02-18 22:55:36 +000011033 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +000011034 {
pbrook53a59602006-03-25 19:31:22 +000011035 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +000011036 struct sysinfo value;
11037 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +000011038 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +000011039 {
bellard579a97f2007-11-11 14:26:47 +000011040 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011041 return -TARGET_EFAULT;
bellarda5448a72004-06-19 16:59:03 +000011042 __put_user(value.uptime, &target_value->uptime);
11043 __put_user(value.loads[0], &target_value->loads[0]);
11044 __put_user(value.loads[1], &target_value->loads[1]);
11045 __put_user(value.loads[2], &target_value->loads[2]);
11046 __put_user(value.totalram, &target_value->totalram);
11047 __put_user(value.freeram, &target_value->freeram);
11048 __put_user(value.sharedram, &target_value->sharedram);
11049 __put_user(value.bufferram, &target_value->bufferram);
11050 __put_user(value.totalswap, &target_value->totalswap);
11051 __put_user(value.freeswap, &target_value->freeswap);
11052 __put_user(value.procs, &target_value->procs);
11053 __put_user(value.totalhigh, &target_value->totalhigh);
11054 __put_user(value.freehigh, &target_value->freehigh);
11055 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +000011056 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +000011057 }
11058 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011059 return ret;
thse5febef2007-04-01 18:31:35 +000011060#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +000011061 case TARGET_NR_ipc:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011062 return do_ipc(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
thse5febef2007-04-01 18:31:35 +000011063#endif
aurel32e5289082009-04-18 16:16:12 +000011064#ifdef TARGET_NR_semget
11065 case TARGET_NR_semget:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011066 return get_errno(semget(arg1, arg2, arg3));
aurel32e5289082009-04-18 16:16:12 +000011067#endif
11068#ifdef TARGET_NR_semop
11069 case TARGET_NR_semop:
Filip Bozutacac46eb2020-08-25 00:30:50 +020011070 return do_semtimedop(arg1, arg2, arg3, 0, false);
Matus Kyseld8c08b12020-06-26 14:46:11 +020011071#endif
11072#ifdef TARGET_NR_semtimedop
11073 case TARGET_NR_semtimedop:
Filip Bozutacac46eb2020-08-25 00:30:50 +020011074 return do_semtimedop(arg1, arg2, arg3, arg4, false);
11075#endif
11076#ifdef TARGET_NR_semtimedop_time64
11077 case TARGET_NR_semtimedop_time64:
11078 return do_semtimedop(arg1, arg2, arg3, arg4, true);
aurel32e5289082009-04-18 16:16:12 +000011079#endif
11080#ifdef TARGET_NR_semctl
11081 case TARGET_NR_semctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011082 return do_semctl(arg1, arg2, arg3, arg4);
aurel32e5289082009-04-18 16:16:12 +000011083#endif
aurel32eeb438c2008-10-13 21:08:55 +000011084#ifdef TARGET_NR_msgctl
11085 case TARGET_NR_msgctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011086 return do_msgctl(arg1, arg2, arg3);
aurel32eeb438c2008-10-13 21:08:55 +000011087#endif
11088#ifdef TARGET_NR_msgget
11089 case TARGET_NR_msgget:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011090 return get_errno(msgget(arg1, arg2));
aurel32eeb438c2008-10-13 21:08:55 +000011091#endif
11092#ifdef TARGET_NR_msgrcv
11093 case TARGET_NR_msgrcv:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011094 return do_msgrcv(arg1, arg2, arg3, arg4, arg5);
aurel32eeb438c2008-10-13 21:08:55 +000011095#endif
11096#ifdef TARGET_NR_msgsnd
11097 case TARGET_NR_msgsnd:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011098 return do_msgsnd(arg1, arg2, arg3, arg4);
aurel32eeb438c2008-10-13 21:08:55 +000011099#endif
Riku Voipio88a8c982009-04-03 10:42:00 +030011100#ifdef TARGET_NR_shmget
11101 case TARGET_NR_shmget:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011102 return get_errno(shmget(arg1, arg2, arg3));
Riku Voipio88a8c982009-04-03 10:42:00 +030011103#endif
11104#ifdef TARGET_NR_shmctl
11105 case TARGET_NR_shmctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011106 return do_shmctl(arg1, arg2, arg3);
Riku Voipio88a8c982009-04-03 10:42:00 +030011107#endif
11108#ifdef TARGET_NR_shmat
11109 case TARGET_NR_shmat:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011110 return do_shmat(cpu_env, arg1, arg2, arg3);
Riku Voipio88a8c982009-04-03 10:42:00 +030011111#endif
11112#ifdef TARGET_NR_shmdt
11113 case TARGET_NR_shmdt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011114 return do_shmdt(arg1);
Riku Voipio88a8c982009-04-03 10:42:00 +030011115#endif
bellard31e31b82003-02-18 22:55:36 +000011116 case TARGET_NR_fsync:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011117 return get_errno(fsync(arg1));
bellard31e31b82003-02-18 22:55:36 +000011118 case TARGET_NR_clone:
Peter Maydell4ce62432013-07-16 18:44:57 +010011119 /* Linux manages to have three different orderings for its
11120 * arguments to clone(); the BACKWARDS and BACKWARDS2 defines
11121 * match the kernel's CONFIG_CLONE_* settings.
11122 * Microblaze is further special in that it uses a sixth
11123 * implicit argument to clone for the TLS pointer.
11124 */
11125#if defined(TARGET_MICROBLAZE)
Edgar E. Iglesiasa5b3bdc2012-04-26 14:17:41 +020011126 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5));
Peter Maydell4ce62432013-07-16 18:44:57 +010011127#elif defined(TARGET_CLONE_BACKWARDS)
11128 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
11129#elif defined(TARGET_CLONE_BACKWARDS2)
Ulrich Hechta4c075f2009-07-24 16:57:31 +020011130 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
aurel320b6d3ae2008-09-15 07:43:43 +000011131#else
Peter Maydell4ce62432013-07-16 18:44:57 +010011132 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
aurel320b6d3ae2008-09-15 07:43:43 +000011133#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011134 return ret;
bellardec86b0f2003-04-11 00:15:04 +000011135#ifdef __NR_exit_group
11136 /* new thread calls */
11137 case TARGET_NR_exit_group:
Alex Bennée708b6a62018-06-22 17:09:10 +010011138 preexit_cleanup(cpu_env, arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011139 return get_errno(exit_group(arg1));
bellardec86b0f2003-04-11 00:15:04 +000011140#endif
bellard31e31b82003-02-18 22:55:36 +000011141 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +000011142 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011143 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011144 ret = get_errno(setdomainname(p, arg2));
11145 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011146 return ret;
bellard31e31b82003-02-18 22:55:36 +000011147 case TARGET_NR_uname:
11148 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +000011149 {
11150 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +000011151
bellard579a97f2007-11-11 14:26:47 +000011152 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011153 return -TARGET_EFAULT;
bellard29e619b2004-09-13 21:41:04 +000011154 ret = get_errno(sys_uname(buf));
11155 if (!is_error(ret)) {
Peter Maydell332c9782016-07-12 13:02:16 +010011156 /* Overwrite the native machine name with whatever is being
bellard29e619b2004-09-13 21:41:04 +000011157 emulated. */
Philippe Mathieu-Daudé871f95c2017-07-24 15:27:47 -030011158 g_strlcpy(buf->machine, cpu_to_uname_machine(cpu_env),
11159 sizeof(buf->machine));
pbrookc5937222006-05-14 11:30:38 +000011160 /* Allow the user to override the reported release. */
Peter Maydell332c9782016-07-12 13:02:16 +010011161 if (qemu_uname_release && *qemu_uname_release) {
11162 g_strlcpy(buf->release, qemu_uname_release,
11163 sizeof(buf->release));
11164 }
bellard29e619b2004-09-13 21:41:04 +000011165 }
pbrook53a59602006-03-25 19:31:22 +000011166 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +000011167 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011168 return ret;
bellard6dbad632003-03-16 18:05:05 +000011169#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +000011170 case TARGET_NR_modify_ldt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011171 return do_modify_ldt(cpu_env, arg1, arg2, arg3);
j_mayer84409dd2007-04-06 08:56:50 +000011172#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +000011173 case TARGET_NR_vm86:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011174 return do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +000011175#endif
j_mayer84409dd2007-04-06 08:56:50 +000011176#endif
Alistair Francis859e8a82020-03-12 15:13:49 -070011177#if defined(TARGET_NR_adjtimex)
bellard31e31b82003-02-18 22:55:36 +000011178 case TARGET_NR_adjtimex:
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +020011179 {
11180 struct timex host_buf;
11181
11182 if (target_to_host_timex(&host_buf, arg1) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011183 return -TARGET_EFAULT;
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +020011184 }
11185 ret = get_errno(adjtimex(&host_buf));
11186 if (!is_error(ret)) {
11187 if (host_to_target_timex(arg1, &host_buf) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011188 return -TARGET_EFAULT;
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +020011189 }
11190 }
11191 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011192 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070011193#endif
Aleksandar Markovic38860a02016-10-10 13:23:29 +020011194#if defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME)
11195 case TARGET_NR_clock_adjtime:
11196 {
Peter Maydellaab74612023-07-17 11:05:07 +010011197 struct timex htx;
Aleksandar Markovic38860a02016-10-10 13:23:29 +020011198
Peter Maydellaab74612023-07-17 11:05:07 +010011199 if (target_to_host_timex(&htx, arg2) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011200 return -TARGET_EFAULT;
Aleksandar Markovic38860a02016-10-10 13:23:29 +020011201 }
Peter Maydellaab74612023-07-17 11:05:07 +010011202 ret = get_errno(clock_adjtime(arg1, &htx));
11203 if (!is_error(ret) && host_to_target_timex(arg2, &htx)) {
11204 return -TARGET_EFAULT;
Aleksandar Markovic38860a02016-10-10 13:23:29 +020011205 }
11206 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011207 return ret;
Aleksandar Markovic38860a02016-10-10 13:23:29 +020011208#endif
Filip Bozuta6ac03b22020-08-24 21:21:15 +020011209#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
11210 case TARGET_NR_clock_adjtime64:
11211 {
11212 struct timex htx;
11213
11214 if (target_to_host_timex64(&htx, arg2) != 0) {
11215 return -TARGET_EFAULT;
11216 }
11217 ret = get_errno(clock_adjtime(arg1, &htx));
11218 if (!is_error(ret) && host_to_target_timex64(arg2, &htx)) {
11219 return -TARGET_EFAULT;
11220 }
11221 }
11222 return ret;
11223#endif
bellard31e31b82003-02-18 22:55:36 +000011224 case TARGET_NR_getpgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011225 return get_errno(getpgid(arg1));
bellard31e31b82003-02-18 22:55:36 +000011226 case TARGET_NR_fchdir:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011227 return get_errno(fchdir(arg1));
bellard31e31b82003-02-18 22:55:36 +000011228 case TARGET_NR_personality:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011229 return get_errno(personality(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +000011230#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +000011231 case TARGET_NR__llseek:
11232 {
11233 int64_t res;
Peter Maydell0c1592d2011-02-22 13:02:26 +000011234#if !defined(__NR_llseek)
Peter Maydell9fea2732016-08-11 18:59:39 +010011235 res = lseek(arg1, ((uint64_t)arg2 << 32) | (abi_ulong)arg3, arg5);
Peter Maydell0c1592d2011-02-22 13:02:26 +000011236 if (res == -1) {
11237 ret = get_errno(res);
11238 } else {
11239 ret = 0;
11240 }
11241#else
bellard31e31b82003-02-18 22:55:36 +000011242 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard4f2ac232004-04-26 19:44:02 +000011243#endif
Peter Maydell0c1592d2011-02-22 13:02:26 +000011244 if ((ret == 0) && put_user_s64(res, arg4)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011245 return -TARGET_EFAULT;
Peter Maydell0c1592d2011-02-22 13:02:26 +000011246 }
bellard31e31b82003-02-18 22:55:36 +000011247 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011248 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +000011249#endif
Chen Gang704eff62015-08-21 05:37:33 +080011250#ifdef TARGET_NR_getdents
bellard31e31b82003-02-18 22:55:36 +000011251 case TARGET_NR_getdents:
Richard Hendersonfd08ddb2021-11-14 11:35:36 +010011252 return do_getdents(arg1, arg2, arg3);
Chen Gang704eff62015-08-21 05:37:33 +080011253#endif /* TARGET_NR_getdents */
ths3ae43202007-09-16 21:39:48 +000011254#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +000011255 case TARGET_NR_getdents64:
Richard Hendersonfd08ddb2021-11-14 11:35:36 +010011256 return do_getdents64(arg1, arg2, arg3);
bellarda541f292004-04-12 20:39:29 +000011257#endif /* TARGET_NR_getdents64 */
Laurent Vivier9468a5d2013-01-10 22:30:50 +010011258#if defined(TARGET_NR__newselect)
bellard31e31b82003-02-18 22:55:36 +000011259 case TARGET_NR__newselect:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011260 return do_select(arg1, arg2, arg3, arg4, arg5);
thse5febef2007-04-01 18:31:35 +000011261#endif
Filip Bozutae5ce9682020-08-25 00:30:49 +020011262#ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +000011263 case TARGET_NR_poll:
Filip Bozutae5ce9682020-08-25 00:30:49 +020011264 return do_ppoll(arg1, arg2, arg3, arg4, arg5, false, false);
11265#endif
11266#ifdef TARGET_NR_ppoll
Mike Frysingerd8035d42011-02-07 01:05:51 -050011267 case TARGET_NR_ppoll:
Filip Bozutae5ce9682020-08-25 00:30:49 +020011268 return do_ppoll(arg1, arg2, arg3, arg4, arg5, true, false);
11269#endif
11270#ifdef TARGET_NR_ppoll_time64
11271 case TARGET_NR_ppoll_time64:
11272 return do_ppoll(arg1, arg2, arg3, arg4, arg5, true, true);
thse5febef2007-04-01 18:31:35 +000011273#endif
bellard31e31b82003-02-18 22:55:36 +000011274 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +000011275 /* NOTE: the flock constant seems to be the same for every
11276 Linux platform */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011277 return get_errno(safe_flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +000011278 case TARGET_NR_readv:
11279 {
Richard Hendersonf287b2c2012-09-15 13:20:25 -070011280 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
11281 if (vec != NULL) {
Peter Maydell918c03e2016-06-06 19:58:02 +010011282 ret = get_errno(safe_readv(arg1, vec, arg3));
Richard Hendersonf287b2c2012-09-15 13:20:25 -070011283 unlock_iovec(vec, arg2, arg3, 1);
11284 } else {
11285 ret = -host_to_target_errno(errno);
11286 }
bellard31e31b82003-02-18 22:55:36 +000011287 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011288 return ret;
bellard31e31b82003-02-18 22:55:36 +000011289 case TARGET_NR_writev:
11290 {
Richard Hendersonf287b2c2012-09-15 13:20:25 -070011291 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
11292 if (vec != NULL) {
Peter Maydell918c03e2016-06-06 19:58:02 +010011293 ret = get_errno(safe_writev(arg1, vec, arg3));
Richard Hendersonf287b2c2012-09-15 13:20:25 -070011294 unlock_iovec(vec, arg2, arg3, 0);
11295 } else {
11296 ret = -host_to_target_errno(errno);
11297 }
bellard31e31b82003-02-18 22:55:36 +000011298 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011299 return ret;
Dejan Jovicevic0f263862016-10-11 11:52:46 +020011300#if defined(TARGET_NR_preadv)
11301 case TARGET_NR_preadv:
11302 {
11303 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
11304 if (vec != NULL) {
Max Filippov9ac22512018-04-04 17:30:41 -070011305 unsigned long low, high;
11306
11307 target_to_host_low_high(arg4, arg5, &low, &high);
11308 ret = get_errno(safe_preadv(arg1, vec, arg3, low, high));
Dejan Jovicevic0f263862016-10-11 11:52:46 +020011309 unlock_iovec(vec, arg2, arg3, 1);
11310 } else {
11311 ret = -host_to_target_errno(errno);
11312 }
11313 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011314 return ret;
Dejan Jovicevic0f263862016-10-11 11:52:46 +020011315#endif
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +020011316#if defined(TARGET_NR_pwritev)
11317 case TARGET_NR_pwritev:
11318 {
11319 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
11320 if (vec != NULL) {
Max Filippov9ac22512018-04-04 17:30:41 -070011321 unsigned long low, high;
11322
11323 target_to_host_low_high(arg4, arg5, &low, &high);
11324 ret = get_errno(safe_pwritev(arg1, vec, arg3, low, high));
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +020011325 unlock_iovec(vec, arg2, arg3, 0);
11326 } else {
11327 ret = -host_to_target_errno(errno);
11328 }
11329 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011330 return ret;
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +020011331#endif
bellard31e31b82003-02-18 22:55:36 +000011332 case TARGET_NR_getsid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011333 return get_errno(getsid(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +000011334#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +000011335 case TARGET_NR_fdatasync:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011336 return get_errno(fdatasync(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +000011337#endif
Mike Frysinger737de1d2011-02-07 01:05:55 -050011338 case TARGET_NR_sched_getaffinity:
11339 {
11340 unsigned int mask_size;
11341 unsigned long *mask;
11342
11343 /*
11344 * sched_getaffinity needs multiples of ulong, so need to take
11345 * care of mismatches between target ulong and host ulong sizes.
11346 */
11347 if (arg2 & (sizeof(abi_ulong) - 1)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011348 return -TARGET_EINVAL;
Mike Frysinger737de1d2011-02-07 01:05:55 -050011349 }
11350 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
11351
11352 mask = alloca(mask_size);
Samuel Thibault2e0a8712018-01-09 21:16:43 +010011353 memset(mask, 0, mask_size);
Mike Frysinger737de1d2011-02-07 01:05:55 -050011354 ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
11355
11356 if (!is_error(ret)) {
Peter Maydellbe3bd282014-05-15 14:40:23 +010011357 if (ret > arg2) {
11358 /* More data returned than the caller's buffer will fit.
11359 * This only happens if sizeof(abi_long) < sizeof(long)
11360 * and the caller passed us a buffer holding an odd number
11361 * of abi_longs. If the host kernel is actually using the
11362 * extra 4 bytes then fail EINVAL; otherwise we can just
11363 * ignore them and only copy the interesting part.
11364 */
11365 int numcpus = sysconf(_SC_NPROCESSORS_CONF);
11366 if (numcpus > arg2 * 8) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011367 return -TARGET_EINVAL;
Peter Maydellbe3bd282014-05-15 14:40:23 +010011368 }
11369 ret = arg2;
11370 }
11371
Samuel Thibault5fdefcf2018-02-11 18:47:04 +010011372 if (host_to_target_cpu_mask(mask, mask_size, arg3, ret)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011373 return -TARGET_EFAULT;
Samuel Thibault5fdefcf2018-02-11 18:47:04 +010011374 }
Mike Frysinger737de1d2011-02-07 01:05:55 -050011375 }
11376 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011377 return ret;
Mike Frysinger737de1d2011-02-07 01:05:55 -050011378 case TARGET_NR_sched_setaffinity:
11379 {
11380 unsigned int mask_size;
11381 unsigned long *mask;
11382
11383 /*
11384 * sched_setaffinity needs multiples of ulong, so need to take
11385 * care of mismatches between target ulong and host ulong sizes.
11386 */
11387 if (arg2 & (sizeof(abi_ulong) - 1)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011388 return -TARGET_EINVAL;
Mike Frysinger737de1d2011-02-07 01:05:55 -050011389 }
11390 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
Mike Frysinger737de1d2011-02-07 01:05:55 -050011391 mask = alloca(mask_size);
Samuel Thibault2e0a8712018-01-09 21:16:43 +010011392
11393 ret = target_to_host_cpu_mask(mask, mask_size, arg3, arg2);
11394 if (ret) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011395 return ret;
Mike Frysinger737de1d2011-02-07 01:05:55 -050011396 }
Mike Frysinger737de1d2011-02-07 01:05:55 -050011397
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011398 return get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
Mike Frysinger737de1d2011-02-07 01:05:55 -050011399 }
Samuel Thibaultb827c3e2018-01-12 09:14:35 +010011400 case TARGET_NR_getcpu:
11401 {
11402 unsigned cpu, node;
11403 ret = get_errno(sys_getcpu(arg1 ? &cpu : NULL,
11404 arg2 ? &node : NULL,
11405 NULL));
11406 if (is_error(ret)) {
Richard Henderson259841c2018-08-18 12:01:09 -070011407 return ret;
Samuel Thibaultb827c3e2018-01-12 09:14:35 +010011408 }
11409 if (arg1 && put_user_u32(cpu, arg1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011410 return -TARGET_EFAULT;
Samuel Thibaultb827c3e2018-01-12 09:14:35 +010011411 }
11412 if (arg2 && put_user_u32(node, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011413 return -TARGET_EFAULT;
Samuel Thibaultb827c3e2018-01-12 09:14:35 +010011414 }
11415 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011416 return ret;
bellard31e31b82003-02-18 22:55:36 +000011417 case TARGET_NR_sched_setparam:
bellard5cd43932003-03-29 16:54:36 +000011418 {
Tonis Tiigi407a1192022-01-04 20:18:19 -080011419 struct target_sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +000011420 struct sched_param schp;
pbrook53a59602006-03-25 19:31:22 +000011421
Tom Mustaa1d5c5b2014-08-12 13:53:38 -050011422 if (arg2 == 0) {
11423 return -TARGET_EINVAL;
11424 }
Tonis Tiigi407a1192022-01-04 20:18:19 -080011425 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011426 return -TARGET_EFAULT;
Tonis Tiigi407a1192022-01-04 20:18:19 -080011427 }
bellard5cd43932003-03-29 16:54:36 +000011428 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +000011429 unlock_user_struct(target_schp, arg2, 0);
Tonis Tiigi407a1192022-01-04 20:18:19 -080011430 return get_errno(sys_sched_setparam(arg1, &schp));
bellard5cd43932003-03-29 16:54:36 +000011431 }
bellard31e31b82003-02-18 22:55:36 +000011432 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +000011433 {
Tonis Tiigi407a1192022-01-04 20:18:19 -080011434 struct target_sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +000011435 struct sched_param schp;
Tom Mustaa1d5c5b2014-08-12 13:53:38 -050011436
11437 if (arg2 == 0) {
11438 return -TARGET_EINVAL;
11439 }
Tonis Tiigi407a1192022-01-04 20:18:19 -080011440 ret = get_errno(sys_sched_getparam(arg1, &schp));
bellard5cd43932003-03-29 16:54:36 +000011441 if (!is_error(ret)) {
Tonis Tiigi407a1192022-01-04 20:18:19 -080011442 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011443 return -TARGET_EFAULT;
Tonis Tiigi407a1192022-01-04 20:18:19 -080011444 }
bellard5cd43932003-03-29 16:54:36 +000011445 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +000011446 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +000011447 }
11448 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011449 return ret;
bellard31e31b82003-02-18 22:55:36 +000011450 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +000011451 {
Tonis Tiigi407a1192022-01-04 20:18:19 -080011452 struct target_sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +000011453 struct sched_param schp;
Tom Mustaa1d5c5b2014-08-12 13:53:38 -050011454 if (arg3 == 0) {
11455 return -TARGET_EINVAL;
11456 }
Tonis Tiigi407a1192022-01-04 20:18:19 -080011457 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011458 return -TARGET_EFAULT;
Tonis Tiigi407a1192022-01-04 20:18:19 -080011459 }
bellard5cd43932003-03-29 16:54:36 +000011460 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +000011461 unlock_user_struct(target_schp, arg3, 0);
Tonis Tiigi407a1192022-01-04 20:18:19 -080011462 return get_errno(sys_sched_setscheduler(arg1, arg2, &schp));
bellard5cd43932003-03-29 16:54:36 +000011463 }
bellard31e31b82003-02-18 22:55:36 +000011464 case TARGET_NR_sched_getscheduler:
Tonis Tiigi407a1192022-01-04 20:18:19 -080011465 return get_errno(sys_sched_getscheduler(arg1));
Tonis Tiigi45ad7612022-01-04 20:18:18 -080011466 case TARGET_NR_sched_getattr:
11467 {
11468 struct target_sched_attr *target_scha;
11469 struct sched_attr scha;
11470 if (arg2 == 0) {
11471 return -TARGET_EINVAL;
11472 }
11473 if (arg3 > sizeof(scha)) {
11474 arg3 = sizeof(scha);
11475 }
11476 ret = get_errno(sys_sched_getattr(arg1, &scha, arg3, arg4));
11477 if (!is_error(ret)) {
11478 target_scha = lock_user(VERIFY_WRITE, arg2, arg3, 0);
11479 if (!target_scha) {
11480 return -TARGET_EFAULT;
11481 }
11482 target_scha->size = tswap32(scha.size);
11483 target_scha->sched_policy = tswap32(scha.sched_policy);
11484 target_scha->sched_flags = tswap64(scha.sched_flags);
11485 target_scha->sched_nice = tswap32(scha.sched_nice);
11486 target_scha->sched_priority = tswap32(scha.sched_priority);
11487 target_scha->sched_runtime = tswap64(scha.sched_runtime);
11488 target_scha->sched_deadline = tswap64(scha.sched_deadline);
11489 target_scha->sched_period = tswap64(scha.sched_period);
11490 if (scha.size > offsetof(struct sched_attr, sched_util_min)) {
11491 target_scha->sched_util_min = tswap32(scha.sched_util_min);
11492 target_scha->sched_util_max = tswap32(scha.sched_util_max);
11493 }
11494 unlock_user(target_scha, arg2, arg3);
11495 }
11496 return ret;
11497 }
11498 case TARGET_NR_sched_setattr:
11499 {
11500 struct target_sched_attr *target_scha;
11501 struct sched_attr scha;
11502 uint32_t size;
11503 int zeroed;
11504 if (arg2 == 0) {
11505 return -TARGET_EINVAL;
11506 }
11507 if (get_user_u32(size, arg2)) {
11508 return -TARGET_EFAULT;
11509 }
11510 if (!size) {
11511 size = offsetof(struct target_sched_attr, sched_util_min);
11512 }
11513 if (size < offsetof(struct target_sched_attr, sched_util_min)) {
11514 if (put_user_u32(sizeof(struct target_sched_attr), arg2)) {
11515 return -TARGET_EFAULT;
11516 }
11517 return -TARGET_E2BIG;
11518 }
11519
11520 zeroed = check_zeroed_user(arg2, sizeof(struct target_sched_attr), size);
11521 if (zeroed < 0) {
11522 return zeroed;
11523 } else if (zeroed == 0) {
11524 if (put_user_u32(sizeof(struct target_sched_attr), arg2)) {
11525 return -TARGET_EFAULT;
11526 }
11527 return -TARGET_E2BIG;
11528 }
11529 if (size > sizeof(struct target_sched_attr)) {
11530 size = sizeof(struct target_sched_attr);
11531 }
11532
11533 target_scha = lock_user(VERIFY_READ, arg2, size, 1);
11534 if (!target_scha) {
11535 return -TARGET_EFAULT;
11536 }
11537 scha.size = size;
11538 scha.sched_policy = tswap32(target_scha->sched_policy);
11539 scha.sched_flags = tswap64(target_scha->sched_flags);
11540 scha.sched_nice = tswap32(target_scha->sched_nice);
11541 scha.sched_priority = tswap32(target_scha->sched_priority);
11542 scha.sched_runtime = tswap64(target_scha->sched_runtime);
11543 scha.sched_deadline = tswap64(target_scha->sched_deadline);
11544 scha.sched_period = tswap64(target_scha->sched_period);
11545 if (size > offsetof(struct target_sched_attr, sched_util_min)) {
11546 scha.sched_util_min = tswap32(target_scha->sched_util_min);
11547 scha.sched_util_max = tswap32(target_scha->sched_util_max);
11548 }
11549 unlock_user(target_scha, arg2, 0);
11550 return get_errno(sys_sched_setattr(arg1, &scha, arg3));
11551 }
bellard31e31b82003-02-18 22:55:36 +000011552 case TARGET_NR_sched_yield:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011553 return get_errno(sched_yield());
bellard31e31b82003-02-18 22:55:36 +000011554 case TARGET_NR_sched_get_priority_max:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011555 return get_errno(sched_get_priority_max(arg1));
bellard31e31b82003-02-18 22:55:36 +000011556 case TARGET_NR_sched_get_priority_min:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011557 return get_errno(sched_get_priority_min(arg1));
Alistair Francis859e8a82020-03-12 15:13:49 -070011558#ifdef TARGET_NR_sched_rr_get_interval
bellard31e31b82003-02-18 22:55:36 +000011559 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +000011560 {
bellard5cd43932003-03-29 16:54:36 +000011561 struct timespec ts;
11562 ret = get_errno(sched_rr_get_interval(arg1, &ts));
11563 if (!is_error(ret)) {
Tom Mustad4290c42014-08-12 13:53:39 -050011564 ret = host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +000011565 }
11566 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011567 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070011568#endif
Filip Bozutaddcbde12020-08-24 21:21:16 +020011569#ifdef TARGET_NR_sched_rr_get_interval_time64
11570 case TARGET_NR_sched_rr_get_interval_time64:
11571 {
11572 struct timespec ts;
11573 ret = get_errno(sched_rr_get_interval(arg1, &ts));
11574 if (!is_error(ret)) {
11575 ret = host_to_target_timespec64(arg2, &ts);
11576 }
11577 }
11578 return ret;
11579#endif
Alistair Francis859e8a82020-03-12 15:13:49 -070011580#if defined(TARGET_NR_nanosleep)
bellard31e31b82003-02-18 22:55:36 +000011581 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +000011582 {
bellard1b6b0292003-03-22 17:31:38 +000011583 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +000011584 target_to_host_timespec(&req, arg1);
Peter Maydell9e518222016-06-06 19:58:09 +010011585 ret = get_errno(safe_nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +000011586 if (is_error(ret) && arg2) {
11587 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +000011588 }
11589 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011590 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070011591#endif
bellard31e31b82003-02-18 22:55:36 +000011592 case TARGET_NR_prctl:
Richard Henderson87e9bf22021-12-27 07:01:22 -080011593 return do_prctl(cpu_env, arg1, arg2, arg3, arg4, arg5);
ths39b9aae2007-02-11 18:36:44 +000011594 break;
bellardd2fd1af2007-11-14 18:08:56 +000011595#ifdef TARGET_NR_arch_prctl
11596 case TARGET_NR_arch_prctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011597 return do_arch_prctl(cpu_env, arg1, arg2);
bellardd2fd1af2007-11-14 18:08:56 +000011598#endif
aurel32f2c7ba12008-03-28 22:32:06 +000011599#ifdef TARGET_NR_pread64
11600 case TARGET_NR_pread64:
James Clarke8bf8e9d2017-09-15 20:33:13 +010011601 if (regpairs_aligned(cpu_env, num)) {
Alexander Grafae017a52012-09-29 15:32:39 +000011602 arg4 = arg5;
11603 arg5 = arg6;
11604 }
Peter Maydell2bd3f892019-01-08 18:49:00 +000011605 if (arg2 == 0 && arg3 == 0) {
11606 /* Special-case NULL buffer and zero length, which should succeed */
11607 p = 0;
11608 } else {
11609 p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
11610 if (!p) {
11611 return -TARGET_EFAULT;
11612 }
11613 }
aurel32f2c7ba12008-03-28 22:32:06 +000011614 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
11615 unlock_user(p, arg2, ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011616 return ret;
aurel32f2c7ba12008-03-28 22:32:06 +000011617 case TARGET_NR_pwrite64:
James Clarke8bf8e9d2017-09-15 20:33:13 +010011618 if (regpairs_aligned(cpu_env, num)) {
Alexander Grafae017a52012-09-29 15:32:39 +000011619 arg4 = arg5;
11620 arg5 = arg6;
11621 }
Peter Maydell2bd3f892019-01-08 18:49:00 +000011622 if (arg2 == 0 && arg3 == 0) {
11623 /* Special-case NULL buffer and zero length, which should succeed */
11624 p = 0;
11625 } else {
11626 p = lock_user(VERIFY_READ, arg2, arg3, 1);
11627 if (!p) {
11628 return -TARGET_EFAULT;
11629 }
11630 }
aurel32f2c7ba12008-03-28 22:32:06 +000011631 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
11632 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011633 return ret;
aurel32f2c7ba12008-03-28 22:32:06 +000011634#endif
bellard31e31b82003-02-18 22:55:36 +000011635 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +000011636 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011637 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011638 ret = get_errno(sys_getcwd1(p, arg2));
11639 unlock_user(p, arg1, ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011640 return ret;
bellard31e31b82003-02-18 22:55:36 +000011641 case TARGET_NR_capget:
11642 case TARGET_NR_capset:
Peter Maydelle0eb2102014-03-17 12:15:35 +000011643 {
11644 struct target_user_cap_header *target_header;
11645 struct target_user_cap_data *target_data = NULL;
11646 struct __user_cap_header_struct header;
11647 struct __user_cap_data_struct data[2];
11648 struct __user_cap_data_struct *dataptr = NULL;
11649 int i, target_datalen;
11650 int data_items = 1;
11651
11652 if (!lock_user_struct(VERIFY_WRITE, target_header, arg1, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011653 return -TARGET_EFAULT;
Peter Maydelle0eb2102014-03-17 12:15:35 +000011654 }
11655 header.version = tswap32(target_header->version);
11656 header.pid = tswap32(target_header->pid);
11657
Peter Maydellec864872014-03-19 16:07:30 +000011658 if (header.version != _LINUX_CAPABILITY_VERSION) {
Peter Maydelle0eb2102014-03-17 12:15:35 +000011659 /* Version 2 and up takes pointer to two user_data structs */
11660 data_items = 2;
11661 }
11662
11663 target_datalen = sizeof(*target_data) * data_items;
11664
11665 if (arg2) {
11666 if (num == TARGET_NR_capget) {
11667 target_data = lock_user(VERIFY_WRITE, arg2, target_datalen, 0);
11668 } else {
11669 target_data = lock_user(VERIFY_READ, arg2, target_datalen, 1);
11670 }
11671 if (!target_data) {
11672 unlock_user_struct(target_header, arg1, 0);
Richard Henderson2852aaf2018-08-18 12:01:06 -070011673 return -TARGET_EFAULT;
Peter Maydelle0eb2102014-03-17 12:15:35 +000011674 }
11675
11676 if (num == TARGET_NR_capset) {
11677 for (i = 0; i < data_items; i++) {
11678 data[i].effective = tswap32(target_data[i].effective);
11679 data[i].permitted = tswap32(target_data[i].permitted);
11680 data[i].inheritable = tswap32(target_data[i].inheritable);
11681 }
11682 }
11683
11684 dataptr = data;
11685 }
11686
11687 if (num == TARGET_NR_capget) {
11688 ret = get_errno(capget(&header, dataptr));
11689 } else {
11690 ret = get_errno(capset(&header, dataptr));
11691 }
11692
11693 /* The kernel always updates version for both capget and capset */
11694 target_header->version = tswap32(header.version);
11695 unlock_user_struct(target_header, arg1, 1);
11696
11697 if (arg2) {
11698 if (num == TARGET_NR_capget) {
11699 for (i = 0; i < data_items; i++) {
11700 target_data[i].effective = tswap32(data[i].effective);
11701 target_data[i].permitted = tswap32(data[i].permitted);
11702 target_data[i].inheritable = tswap32(data[i].inheritable);
11703 }
11704 unlock_user(target_data, arg2, target_datalen);
11705 } else {
11706 unlock_user(target_data, arg2, 0);
11707 }
11708 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011709 return ret;
Peter Maydelle0eb2102014-03-17 12:15:35 +000011710 }
bellard31e31b82003-02-18 22:55:36 +000011711 case TARGET_NR_sigaltstack:
Richard Henderson6b208752021-04-25 19:53:12 -070011712 return do_sigaltstack(arg1, arg2, cpu_env);
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011713
11714#ifdef CONFIG_SENDFILE
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020011715#ifdef TARGET_NR_sendfile
bellard31e31b82003-02-18 22:55:36 +000011716 case TARGET_NR_sendfile:
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011717 {
11718 off_t *offp = NULL;
11719 off_t off;
11720 if (arg3) {
11721 ret = get_user_sal(off, arg3);
11722 if (is_error(ret)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011723 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011724 }
11725 offp = &off;
11726 }
11727 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
11728 if (!is_error(ret) && arg3) {
11729 abi_long ret2 = put_user_sal(off, arg3);
11730 if (is_error(ret2)) {
11731 ret = ret2;
11732 }
11733 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011734 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011735 }
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020011736#endif
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011737#ifdef TARGET_NR_sendfile64
11738 case TARGET_NR_sendfile64:
11739 {
11740 off_t *offp = NULL;
11741 off_t off;
11742 if (arg3) {
11743 ret = get_user_s64(off, arg3);
11744 if (is_error(ret)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011745 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011746 }
11747 offp = &off;
11748 }
11749 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
11750 if (!is_error(ret) && arg3) {
11751 abi_long ret2 = put_user_s64(off, arg3);
11752 if (is_error(ret2)) {
11753 ret = ret2;
11754 }
11755 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011756 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011757 }
11758#endif
bellardebc05482003-09-30 21:08:41 +000011759#endif
bellard048f6b42005-11-26 18:47:20 +000011760#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +000011761 case TARGET_NR_vfork:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011762 return get_errno(do_fork(cpu_env,
11763 CLONE_VFORK | CLONE_VM | TARGET_SIGCHLD,
11764 0, 0, 0, 0));
bellard048f6b42005-11-26 18:47:20 +000011765#endif
bellardebc05482003-09-30 21:08:41 +000011766#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +000011767 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +000011768 {
11769 struct rlimit rlim;
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +030011770 int resource = target_to_host_resource(arg1);
11771 ret = get_errno(getrlimit(resource, &rlim));
bellard728584b2003-04-29 20:43:36 +000011772 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +000011773 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +000011774 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011775 return -TARGET_EFAULT;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +090011776 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
11777 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +000011778 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +000011779 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011780 return ret;
bellard728584b2003-04-29 20:43:36 +000011781 }
bellardebc05482003-09-30 21:08:41 +000011782#endif
bellarda315a142005-01-30 22:59:18 +000011783#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +000011784 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +000011785 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011786 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011787 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
11788 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011789 return ret;
bellarda315a142005-01-30 22:59:18 +000011790#endif
11791#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +000011792 case TARGET_NR_ftruncate64:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011793 return target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellarda315a142005-01-30 22:59:18 +000011794#endif
11795#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +000011796 case TARGET_NR_stat64:
Richard Henderson2852aaf2018-08-18 12:01:06 -070011797 if (!(p = lock_user_string(arg1))) {
11798 return -TARGET_EFAULT;
11799 }
pbrook53a59602006-03-25 19:31:22 +000011800 ret = get_errno(stat(path(p), &st));
11801 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +000011802 if (!is_error(ret))
11803 ret = host_to_target_stat64(cpu_env, arg2, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011804 return ret;
bellarda315a142005-01-30 22:59:18 +000011805#endif
11806#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +000011807 case TARGET_NR_lstat64:
Richard Henderson2852aaf2018-08-18 12:01:06 -070011808 if (!(p = lock_user_string(arg1))) {
11809 return -TARGET_EFAULT;
11810 }
pbrook53a59602006-03-25 19:31:22 +000011811 ret = get_errno(lstat(path(p), &st));
11812 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +000011813 if (!is_error(ret))
11814 ret = host_to_target_stat64(cpu_env, arg2, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011815 return ret;
bellarda315a142005-01-30 22:59:18 +000011816#endif
11817#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +000011818 case TARGET_NR_fstat64:
balrog6a24a772008-09-20 02:23:36 +000011819 ret = get_errno(fstat(arg1, &st));
11820 if (!is_error(ret))
11821 ret = host_to_target_stat64(cpu_env, arg2, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011822 return ret;
bellardec86b0f2003-04-11 00:15:04 +000011823#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +010011824#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat))
aurel329d33b762009-04-08 23:07:05 +000011825#ifdef TARGET_NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +000011826 case TARGET_NR_fstatat64:
aurel329d33b762009-04-08 23:07:05 +000011827#endif
11828#ifdef TARGET_NR_newfstatat
11829 case TARGET_NR_newfstatat:
11830#endif
Richard Henderson2852aaf2018-08-18 12:01:06 -070011831 if (!(p = lock_user_string(arg2))) {
11832 return -TARGET_EFAULT;
11833 }
Peter Maydellc0d472b2013-06-12 16:20:21 +010011834 ret = get_errno(fstatat(arg1, path(p), &st, arg4));
Richard Henderson2852aaf2018-08-18 12:01:06 -070011835 unlock_user(p, arg2, 0);
balrog6a24a772008-09-20 02:23:36 +000011836 if (!is_error(ret))
11837 ret = host_to_target_stat64(cpu_env, arg3, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011838 return ret;
bellarda315a142005-01-30 22:59:18 +000011839#endif
Aleksandar Rikaloefa92182019-06-28 12:43:34 +020011840#if defined(TARGET_NR_statx)
11841 case TARGET_NR_statx:
11842 {
11843 struct target_statx *target_stx;
11844 int dirfd = arg1;
11845 int flags = arg3;
11846
11847 p = lock_user_string(arg2);
11848 if (p == NULL) {
11849 return -TARGET_EFAULT;
11850 }
11851#if defined(__NR_statx)
11852 {
11853 /*
11854 * It is assumed that struct statx is architecture independent.
11855 */
11856 struct target_statx host_stx;
11857 int mask = arg4;
11858
11859 ret = get_errno(sys_statx(dirfd, p, flags, mask, &host_stx));
11860 if (!is_error(ret)) {
11861 if (host_to_target_statx(&host_stx, arg5) != 0) {
11862 unlock_user(p, arg2, 0);
11863 return -TARGET_EFAULT;
11864 }
11865 }
11866
11867 if (ret != -TARGET_ENOSYS) {
11868 unlock_user(p, arg2, 0);
11869 return ret;
11870 }
11871 }
11872#endif
11873 ret = get_errno(fstatat(dirfd, path(p), &st, flags));
11874 unlock_user(p, arg2, 0);
11875
11876 if (!is_error(ret)) {
11877 if (!lock_user_struct(VERIFY_WRITE, target_stx, arg5, 0)) {
11878 return -TARGET_EFAULT;
11879 }
11880 memset(target_stx, 0, sizeof(*target_stx));
11881 __put_user(major(st.st_dev), &target_stx->stx_dev_major);
11882 __put_user(minor(st.st_dev), &target_stx->stx_dev_minor);
11883 __put_user(st.st_ino, &target_stx->stx_ino);
11884 __put_user(st.st_mode, &target_stx->stx_mode);
11885 __put_user(st.st_uid, &target_stx->stx_uid);
11886 __put_user(st.st_gid, &target_stx->stx_gid);
11887 __put_user(st.st_nlink, &target_stx->stx_nlink);
11888 __put_user(major(st.st_rdev), &target_stx->stx_rdev_major);
11889 __put_user(minor(st.st_rdev), &target_stx->stx_rdev_minor);
11890 __put_user(st.st_size, &target_stx->stx_size);
11891 __put_user(st.st_blksize, &target_stx->stx_blksize);
11892 __put_user(st.st_blocks, &target_stx->stx_blocks);
11893 __put_user(st.st_atime, &target_stx->stx_atime.tv_sec);
11894 __put_user(st.st_mtime, &target_stx->stx_mtime.tv_sec);
11895 __put_user(st.st_ctime, &target_stx->stx_ctime.tv_sec);
11896 unlock_user_struct(target_stx, arg5, 1);
11897 }
11898 }
11899 return ret;
11900#endif
Chen Gang704eff62015-08-21 05:37:33 +080011901#ifdef TARGET_NR_lchown
bellard67867302003-11-23 17:05:30 +000011902 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +000011903 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011904 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011905 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
11906 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011907 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080011908#endif
Riku Voipio0c866a72011-04-18 15:23:06 +030011909#ifdef TARGET_NR_getuid
bellard67867302003-11-23 17:05:30 +000011910 case TARGET_NR_getuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011911 return get_errno(high2lowuid(getuid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030011912#endif
11913#ifdef TARGET_NR_getgid
bellard67867302003-11-23 17:05:30 +000011914 case TARGET_NR_getgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011915 return get_errno(high2lowgid(getgid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030011916#endif
11917#ifdef TARGET_NR_geteuid
bellard67867302003-11-23 17:05:30 +000011918 case TARGET_NR_geteuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011919 return get_errno(high2lowuid(geteuid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030011920#endif
11921#ifdef TARGET_NR_getegid
bellard67867302003-11-23 17:05:30 +000011922 case TARGET_NR_getegid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011923 return get_errno(high2lowgid(getegid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030011924#endif
bellard67867302003-11-23 17:05:30 +000011925 case TARGET_NR_setreuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011926 return get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
bellard67867302003-11-23 17:05:30 +000011927 case TARGET_NR_setregid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011928 return get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
bellard67867302003-11-23 17:05:30 +000011929 case TARGET_NR_getgroups:
Michael Tokarev725160f2023-06-03 20:23:38 +030011930 { /* the same code as for TARGET_NR_getgroups32 */
bellard67867302003-11-23 17:05:30 +000011931 int gidsetsize = arg1;
Riku Voipio0c866a72011-04-18 15:23:06 +030011932 target_id *target_grouplist;
Michael Tokarev1e35d322023-04-09 13:53:27 +030011933 g_autofree gid_t *grouplist = NULL;
bellard67867302003-11-23 17:05:30 +000011934 int i;
11935
Peter Maydell8fbf89a2023-06-09 17:29:15 +010011936 if (gidsetsize > NGROUPS_MAX || gidsetsize < 0) {
Michael Tokarev1e35d322023-04-09 13:53:27 +030011937 return -TARGET_EINVAL;
bellard67867302003-11-23 17:05:30 +000011938 }
Michael Tokarev1e35d322023-04-09 13:53:27 +030011939 if (gidsetsize > 0) {
11940 grouplist = g_try_new(gid_t, gidsetsize);
11941 if (!grouplist) {
11942 return -TARGET_ENOMEM;
11943 }
11944 }
11945 ret = get_errno(getgroups(gidsetsize, grouplist));
11946 if (!is_error(ret) && gidsetsize > 0) {
11947 target_grouplist = lock_user(VERIFY_WRITE, arg2,
11948 gidsetsize * sizeof(target_id), 0);
11949 if (!target_grouplist) {
11950 return -TARGET_EFAULT;
11951 }
11952 for (i = 0; i < ret; i++) {
11953 target_grouplist[i] = tswapid(high2lowgid(grouplist[i]));
11954 }
11955 unlock_user(target_grouplist, arg2,
11956 gidsetsize * sizeof(target_id));
11957 }
11958 return ret;
bellard67867302003-11-23 17:05:30 +000011959 }
bellard67867302003-11-23 17:05:30 +000011960 case TARGET_NR_setgroups:
Michael Tokarev725160f2023-06-03 20:23:38 +030011961 { /* the same code as for TARGET_NR_setgroups32 */
bellard67867302003-11-23 17:05:30 +000011962 int gidsetsize = arg1;
Riku Voipio0c866a72011-04-18 15:23:06 +030011963 target_id *target_grouplist;
Michael Tokarev1e35d322023-04-09 13:53:27 +030011964 g_autofree gid_t *grouplist = NULL;
bellard67867302003-11-23 17:05:30 +000011965 int i;
Michael Tokarev1e35d322023-04-09 13:53:27 +030011966
11967 if (gidsetsize > NGROUPS_MAX || gidsetsize < 0) {
11968 return -TARGET_EINVAL;
11969 }
11970 if (gidsetsize > 0) {
11971 grouplist = g_try_new(gid_t, gidsetsize);
11972 if (!grouplist) {
11973 return -TARGET_ENOMEM;
11974 }
11975 target_grouplist = lock_user(VERIFY_READ, arg2,
11976 gidsetsize * sizeof(target_id), 1);
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050011977 if (!target_grouplist) {
Richard Henderson259841c2018-08-18 12:01:09 -070011978 return -TARGET_EFAULT;
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050011979 }
11980 for (i = 0; i < gidsetsize; i++) {
11981 grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
11982 }
Michael Tokarev1e35d322023-04-09 13:53:27 +030011983 unlock_user(target_grouplist, arg2,
11984 gidsetsize * sizeof(target_id));
bellard579a97f2007-11-11 14:26:47 +000011985 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011986 return get_errno(setgroups(gidsetsize, grouplist));
bellard67867302003-11-23 17:05:30 +000011987 }
bellard67867302003-11-23 17:05:30 +000011988 case TARGET_NR_fchown:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011989 return get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
Peter Maydellc0d472b2013-06-12 16:20:21 +010011990#if defined(TARGET_NR_fchownat)
thsccfa72b2007-09-24 09:23:34 +000011991 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +000011992 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011993 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +010011994 ret = get_errno(fchownat(arg1, p, low2highuid(arg3),
11995 low2highgid(arg4), arg5));
bellard579a97f2007-11-11 14:26:47 +000011996 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011997 return ret;
thsccfa72b2007-09-24 09:23:34 +000011998#endif
bellard67867302003-11-23 17:05:30 +000011999#ifdef TARGET_NR_setresuid
12000 case TARGET_NR_setresuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012001 return get_errno(sys_setresuid(low2highuid(arg1),
12002 low2highuid(arg2),
12003 low2highuid(arg3)));
bellard67867302003-11-23 17:05:30 +000012004#endif
12005#ifdef TARGET_NR_getresuid
12006 case TARGET_NR_getresuid:
12007 {
pbrook53a59602006-03-25 19:31:22 +000012008 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +000012009 ret = get_errno(getresuid(&ruid, &euid, &suid));
12010 if (!is_error(ret)) {
Peter Maydell76ca3102014-03-02 19:36:41 +000012011 if (put_user_id(high2lowuid(ruid), arg1)
12012 || put_user_id(high2lowuid(euid), arg2)
12013 || put_user_id(high2lowuid(suid), arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070012014 return -TARGET_EFAULT;
bellard67867302003-11-23 17:05:30 +000012015 }
12016 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012017 return ret;
bellard67867302003-11-23 17:05:30 +000012018#endif
12019#ifdef TARGET_NR_getresgid
12020 case TARGET_NR_setresgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012021 return get_errno(sys_setresgid(low2highgid(arg1),
12022 low2highgid(arg2),
12023 low2highgid(arg3)));
bellard67867302003-11-23 17:05:30 +000012024#endif
12025#ifdef TARGET_NR_getresgid
12026 case TARGET_NR_getresgid:
12027 {
pbrook53a59602006-03-25 19:31:22 +000012028 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +000012029 ret = get_errno(getresgid(&rgid, &egid, &sgid));
12030 if (!is_error(ret)) {
Peter Maydell76ca3102014-03-02 19:36:41 +000012031 if (put_user_id(high2lowgid(rgid), arg1)
12032 || put_user_id(high2lowgid(egid), arg2)
12033 || put_user_id(high2lowgid(sgid), arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070012034 return -TARGET_EFAULT;
bellard67867302003-11-23 17:05:30 +000012035 }
12036 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012037 return ret;
bellard67867302003-11-23 17:05:30 +000012038#endif
Chen Gang704eff62015-08-21 05:37:33 +080012039#ifdef TARGET_NR_chown
bellard67867302003-11-23 17:05:30 +000012040 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +000012041 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070012042 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000012043 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
12044 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012045 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080012046#endif
bellard67867302003-11-23 17:05:30 +000012047 case TARGET_NR_setuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012048 return get_errno(sys_setuid(low2highuid(arg1)));
bellard67867302003-11-23 17:05:30 +000012049 case TARGET_NR_setgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012050 return get_errno(sys_setgid(low2highgid(arg1)));
bellard67867302003-11-23 17:05:30 +000012051 case TARGET_NR_setfsuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012052 return get_errno(setfsuid(arg1));
bellard67867302003-11-23 17:05:30 +000012053 case TARGET_NR_setfsgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012054 return get_errno(setfsgid(arg1));
bellard67867302003-11-23 17:05:30 +000012055
bellarda315a142005-01-30 22:59:18 +000012056#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +000012057 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +000012058 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070012059 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000012060 ret = get_errno(lchown(p, arg2, arg3));
12061 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012062 return ret;
bellarda315a142005-01-30 22:59:18 +000012063#endif
12064#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +000012065 case TARGET_NR_getuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012066 return get_errno(getuid());
bellarda315a142005-01-30 22:59:18 +000012067#endif
aurel3264b4d282008-11-14 17:20:15 +000012068
12069#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
12070 /* Alpha specific */
12071 case TARGET_NR_getxuid:
Richard Hendersonba0e2762009-12-09 15:56:29 -080012072 {
12073 uid_t euid;
12074 euid=geteuid();
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020012075 cpu_env->ir[IR_A4]=euid;
Richard Hendersonba0e2762009-12-09 15:56:29 -080012076 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012077 return get_errno(getuid());
aurel3264b4d282008-11-14 17:20:15 +000012078#endif
12079#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
12080 /* Alpha specific */
12081 case TARGET_NR_getxgid:
Richard Hendersonba0e2762009-12-09 15:56:29 -080012082 {
12083 uid_t egid;
12084 egid=getegid();
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020012085 cpu_env->ir[IR_A4]=egid;
Richard Hendersonba0e2762009-12-09 15:56:29 -080012086 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012087 return get_errno(getgid());
aurel3264b4d282008-11-14 17:20:15 +000012088#endif
Richard Hendersonba0e2762009-12-09 15:56:29 -080012089#if defined(TARGET_NR_osf_getsysinfo) && defined(TARGET_ALPHA)
12090 /* Alpha specific */
12091 case TARGET_NR_osf_getsysinfo:
12092 ret = -TARGET_EOPNOTSUPP;
12093 switch (arg1) {
12094 case TARGET_GSI_IEEE_FP_CONTROL:
12095 {
Richard Henderson21ba8562019-04-26 15:20:51 -070012096 uint64_t fpcr = cpu_alpha_load_fpcr(cpu_env);
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020012097 uint64_t swcr = cpu_env->swcr;
Richard Hendersonba0e2762009-12-09 15:56:29 -080012098
Richard Henderson21ba8562019-04-26 15:20:51 -070012099 swcr &= ~SWCR_STATUS_MASK;
12100 swcr |= (fpcr >> 35) & SWCR_STATUS_MASK;
Richard Hendersonba0e2762009-12-09 15:56:29 -080012101
12102 if (put_user_u64 (swcr, arg2))
Richard Henderson2852aaf2018-08-18 12:01:06 -070012103 return -TARGET_EFAULT;
Richard Hendersonba0e2762009-12-09 15:56:29 -080012104 ret = 0;
12105 }
12106 break;
12107
12108 /* case GSI_IEEE_STATE_AT_SIGNAL:
12109 -- Not implemented in linux kernel.
12110 case GSI_UACPROC:
12111 -- Retrieves current unaligned access state; not much used.
12112 case GSI_PROC_TYPE:
12113 -- Retrieves implver information; surely not used.
12114 case GSI_GET_HWRPB:
12115 -- Grabs a copy of the HWRPB; surely not used.
12116 */
12117 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012118 return ret;
Richard Hendersonba0e2762009-12-09 15:56:29 -080012119#endif
12120#if defined(TARGET_NR_osf_setsysinfo) && defined(TARGET_ALPHA)
12121 /* Alpha specific */
12122 case TARGET_NR_osf_setsysinfo:
12123 ret = -TARGET_EOPNOTSUPP;
12124 switch (arg1) {
12125 case TARGET_SSI_IEEE_FP_CONTROL:
Richard Hendersonba0e2762009-12-09 15:56:29 -080012126 {
Richard Henderson21ba8562019-04-26 15:20:51 -070012127 uint64_t swcr, fpcr;
Richard Hendersonba0e2762009-12-09 15:56:29 -080012128
Richard Henderson6e06d512012-06-01 09:08:21 -070012129 if (get_user_u64 (swcr, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012130 return -TARGET_EFAULT;
Richard Henderson6e06d512012-06-01 09:08:21 -070012131 }
Richard Hendersonba0e2762009-12-09 15:56:29 -080012132
Richard Henderson21ba8562019-04-26 15:20:51 -070012133 /*
12134 * The kernel calls swcr_update_status to update the
12135 * status bits from the fpcr at every point that it
12136 * could be queried. Therefore, we store the status
12137 * bits only in FPCR.
12138 */
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020012139 cpu_env->swcr = swcr & (SWCR_TRAP_ENABLE_MASK | SWCR_MAP_MASK);
Richard Hendersonba0e2762009-12-09 15:56:29 -080012140
Richard Henderson21ba8562019-04-26 15:20:51 -070012141 fpcr = cpu_alpha_load_fpcr(cpu_env);
12142 fpcr &= ((uint64_t)FPCR_DYN_MASK << 32);
12143 fpcr |= alpha_ieee_swcr_to_fpcr(swcr);
Richard Henderson6e06d512012-06-01 09:08:21 -070012144 cpu_alpha_store_fpcr(cpu_env, fpcr);
12145 ret = 0;
12146 }
12147 break;
12148
12149 case TARGET_SSI_IEEE_RAISE_EXCEPTION:
12150 {
Richard Henderson21ba8562019-04-26 15:20:51 -070012151 uint64_t exc, fpcr, fex;
Richard Henderson6e06d512012-06-01 09:08:21 -070012152
12153 if (get_user_u64(exc, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012154 return -TARGET_EFAULT;
Richard Henderson6e06d512012-06-01 09:08:21 -070012155 }
Richard Henderson21ba8562019-04-26 15:20:51 -070012156 exc &= SWCR_STATUS_MASK;
12157 fpcr = cpu_alpha_load_fpcr(cpu_env);
Richard Hendersonba0e2762009-12-09 15:56:29 -080012158
Richard Henderson6e06d512012-06-01 09:08:21 -070012159 /* Old exceptions are not signaled. */
Richard Henderson21ba8562019-04-26 15:20:51 -070012160 fex = alpha_ieee_fpcr_to_swcr(fpcr);
12161 fex = exc & ~fex;
12162 fex >>= SWCR_STATUS_TO_EXCSUM_SHIFT;
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020012163 fex &= (cpu_env)->swcr;
Richard Hendersonba0e2762009-12-09 15:56:29 -080012164
Richard Henderson21ba8562019-04-26 15:20:51 -070012165 /* Update the hardware fpcr. */
12166 fpcr |= alpha_ieee_swcr_to_fpcr(exc);
12167 cpu_alpha_store_fpcr(cpu_env, fpcr);
12168
12169 if (fex) {
12170 int si_code = TARGET_FPE_FLTUNK;
Richard Henderson6e06d512012-06-01 09:08:21 -070012171 target_siginfo_t info;
Richard Henderson21ba8562019-04-26 15:20:51 -070012172
12173 if (fex & SWCR_TRAP_ENABLE_DNO) {
12174 si_code = TARGET_FPE_FLTUND;
12175 }
12176 if (fex & SWCR_TRAP_ENABLE_INE) {
12177 si_code = TARGET_FPE_FLTRES;
12178 }
12179 if (fex & SWCR_TRAP_ENABLE_UNF) {
12180 si_code = TARGET_FPE_FLTUND;
12181 }
12182 if (fex & SWCR_TRAP_ENABLE_OVF) {
12183 si_code = TARGET_FPE_FLTOVF;
12184 }
12185 if (fex & SWCR_TRAP_ENABLE_DZE) {
12186 si_code = TARGET_FPE_FLTDIV;
12187 }
12188 if (fex & SWCR_TRAP_ENABLE_INV) {
12189 si_code = TARGET_FPE_FLTINV;
12190 }
12191
Richard Henderson6e06d512012-06-01 09:08:21 -070012192 info.si_signo = SIGFPE;
12193 info.si_errno = 0;
12194 info.si_code = si_code;
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020012195 info._sifields._sigfault._addr = (cpu_env)->pc;
12196 queue_signal(cpu_env, info.si_signo,
Peter Maydell9d2803f2016-07-28 16:44:46 +010012197 QEMU_SI_FAULT, &info);
Richard Hendersonba0e2762009-12-09 15:56:29 -080012198 }
Richard Henderson21ba8562019-04-26 15:20:51 -070012199 ret = 0;
Richard Hendersonba0e2762009-12-09 15:56:29 -080012200 }
12201 break;
12202
12203 /* case SSI_NVPAIRS:
12204 -- Used with SSIN_UACPROC to enable unaligned accesses.
12205 case SSI_IEEE_STATE_AT_SIGNAL:
12206 case SSI_IEEE_IGNORE_STATE_AT_SIGNAL:
12207 -- Not implemented in linux kernel
12208 */
12209 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012210 return ret;
Richard Hendersonba0e2762009-12-09 15:56:29 -080012211#endif
12212#ifdef TARGET_NR_osf_sigprocmask
12213 /* Alpha specific. */
12214 case TARGET_NR_osf_sigprocmask:
12215 {
12216 abi_ulong mask;
Juan Quintelabc088ba2011-06-16 17:37:10 +010012217 int how;
Richard Hendersonba0e2762009-12-09 15:56:29 -080012218 sigset_t set, oldset;
12219
12220 switch(arg1) {
12221 case TARGET_SIG_BLOCK:
12222 how = SIG_BLOCK;
12223 break;
12224 case TARGET_SIG_UNBLOCK:
12225 how = SIG_UNBLOCK;
12226 break;
12227 case TARGET_SIG_SETMASK:
12228 how = SIG_SETMASK;
12229 break;
12230 default:
Richard Henderson259841c2018-08-18 12:01:09 -070012231 return -TARGET_EINVAL;
Richard Hendersonba0e2762009-12-09 15:56:29 -080012232 }
12233 mask = arg2;
12234 target_to_host_old_sigset(&set, &mask);
Peter Maydell3d3efba2016-05-27 15:51:49 +010012235 ret = do_sigprocmask(how, &set, &oldset);
12236 if (!ret) {
12237 host_to_target_old_sigset(&mask, &oldset);
12238 ret = mask;
12239 }
Richard Hendersonba0e2762009-12-09 15:56:29 -080012240 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012241 return ret;
Richard Hendersonba0e2762009-12-09 15:56:29 -080012242#endif
aurel3264b4d282008-11-14 17:20:15 +000012243
bellarda315a142005-01-30 22:59:18 +000012244#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +000012245 case TARGET_NR_getgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012246 return get_errno(getgid());
bellarda315a142005-01-30 22:59:18 +000012247#endif
12248#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +000012249 case TARGET_NR_geteuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012250 return get_errno(geteuid());
bellarda315a142005-01-30 22:59:18 +000012251#endif
12252#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +000012253 case TARGET_NR_getegid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012254 return get_errno(getegid());
bellarda315a142005-01-30 22:59:18 +000012255#endif
12256#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +000012257 case TARGET_NR_setreuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012258 return get_errno(setreuid(arg1, arg2));
bellarda315a142005-01-30 22:59:18 +000012259#endif
12260#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +000012261 case TARGET_NR_setregid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012262 return get_errno(setregid(arg1, arg2));
bellarda315a142005-01-30 22:59:18 +000012263#endif
12264#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +000012265 case TARGET_NR_getgroups32:
Michael Tokarev725160f2023-06-03 20:23:38 +030012266 { /* the same code as for TARGET_NR_getgroups */
bellard99c475a2005-01-31 20:45:13 +000012267 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +000012268 uint32_t *target_grouplist;
Michael Tokarev1e35d322023-04-09 13:53:27 +030012269 g_autofree gid_t *grouplist = NULL;
bellard99c475a2005-01-31 20:45:13 +000012270 int i;
12271
Peter Maydell8fbf89a2023-06-09 17:29:15 +010012272 if (gidsetsize > NGROUPS_MAX || gidsetsize < 0) {
Michael Tokarev1e35d322023-04-09 13:53:27 +030012273 return -TARGET_EINVAL;
12274 }
12275 if (gidsetsize > 0) {
12276 grouplist = g_try_new(gid_t, gidsetsize);
12277 if (!grouplist) {
12278 return -TARGET_ENOMEM;
12279 }
12280 }
bellard99c475a2005-01-31 20:45:13 +000012281 ret = get_errno(getgroups(gidsetsize, grouplist));
Michael Tokarev1e35d322023-04-09 13:53:27 +030012282 if (!is_error(ret) && gidsetsize > 0) {
12283 target_grouplist = lock_user(VERIFY_WRITE, arg2,
12284 gidsetsize * 4, 0);
bellard579a97f2007-11-11 14:26:47 +000012285 if (!target_grouplist) {
Richard Henderson259841c2018-08-18 12:01:09 -070012286 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000012287 }
Michael Tokarev1e35d322023-04-09 13:53:27 +030012288 for (i = 0; i < ret; i++) {
pbrook53a59602006-03-25 19:31:22 +000012289 target_grouplist[i] = tswap32(grouplist[i]);
Michael Tokarev1e35d322023-04-09 13:53:27 +030012290 }
pbrook53a59602006-03-25 19:31:22 +000012291 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +000012292 }
Michael Tokarev1e35d322023-04-09 13:53:27 +030012293 return ret;
bellard99c475a2005-01-31 20:45:13 +000012294 }
bellarda315a142005-01-30 22:59:18 +000012295#endif
12296#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +000012297 case TARGET_NR_setgroups32:
Michael Tokarev725160f2023-06-03 20:23:38 +030012298 { /* the same code as for TARGET_NR_setgroups */
bellard99c475a2005-01-31 20:45:13 +000012299 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +000012300 uint32_t *target_grouplist;
Michael Tokarev1e35d322023-04-09 13:53:27 +030012301 g_autofree gid_t *grouplist = NULL;
bellard99c475a2005-01-31 20:45:13 +000012302 int i;
ths3b46e622007-09-17 08:09:54 +000012303
Michael Tokarev1e35d322023-04-09 13:53:27 +030012304 if (gidsetsize > NGROUPS_MAX || gidsetsize < 0) {
12305 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +000012306 }
Michael Tokarev1e35d322023-04-09 13:53:27 +030012307 if (gidsetsize > 0) {
12308 grouplist = g_try_new(gid_t, gidsetsize);
12309 if (!grouplist) {
12310 return -TARGET_ENOMEM;
12311 }
12312 target_grouplist = lock_user(VERIFY_READ, arg2,
12313 gidsetsize * 4, 1);
12314 if (!target_grouplist) {
12315 return -TARGET_EFAULT;
12316 }
12317 for (i = 0; i < gidsetsize; i++) {
12318 grouplist[i] = tswap32(target_grouplist[i]);
12319 }
12320 unlock_user(target_grouplist, arg2, 0);
12321 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012322 return get_errno(setgroups(gidsetsize, grouplist));
bellard99c475a2005-01-31 20:45:13 +000012323 }
bellarda315a142005-01-30 22:59:18 +000012324#endif
12325#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +000012326 case TARGET_NR_fchown32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012327 return get_errno(fchown(arg1, arg2, arg3));
bellarda315a142005-01-30 22:59:18 +000012328#endif
12329#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +000012330 case TARGET_NR_setresuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012331 return get_errno(sys_setresuid(arg1, arg2, arg3));
bellarda315a142005-01-30 22:59:18 +000012332#endif
12333#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +000012334 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +000012335 {
pbrook53a59602006-03-25 19:31:22 +000012336 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +000012337 ret = get_errno(getresuid(&ruid, &euid, &suid));
12338 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +000012339 if (put_user_u32(ruid, arg1)
12340 || put_user_u32(euid, arg2)
12341 || put_user_u32(suid, arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070012342 return -TARGET_EFAULT;
bellardb03c60f2003-03-23 17:19:56 +000012343 }
12344 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012345 return ret;
bellarda315a142005-01-30 22:59:18 +000012346#endif
12347#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +000012348 case TARGET_NR_setresgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012349 return get_errno(sys_setresgid(arg1, arg2, arg3));
bellarda315a142005-01-30 22:59:18 +000012350#endif
12351#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +000012352 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +000012353 {
pbrook53a59602006-03-25 19:31:22 +000012354 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +000012355 ret = get_errno(getresgid(&rgid, &egid, &sgid));
12356 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +000012357 if (put_user_u32(rgid, arg1)
12358 || put_user_u32(egid, arg2)
12359 || put_user_u32(sgid, arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070012360 return -TARGET_EFAULT;
bellardb03c60f2003-03-23 17:19:56 +000012361 }
12362 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012363 return ret;
bellarda315a142005-01-30 22:59:18 +000012364#endif
12365#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +000012366 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +000012367 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070012368 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000012369 ret = get_errno(chown(p, arg2, arg3));
12370 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012371 return ret;
bellarda315a142005-01-30 22:59:18 +000012372#endif
12373#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +000012374 case TARGET_NR_setuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012375 return get_errno(sys_setuid(arg1));
bellarda315a142005-01-30 22:59:18 +000012376#endif
12377#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +000012378 case TARGET_NR_setgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012379 return get_errno(sys_setgid(arg1));
bellarda315a142005-01-30 22:59:18 +000012380#endif
12381#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +000012382 case TARGET_NR_setfsuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012383 return get_errno(setfsuid(arg1));
bellarda315a142005-01-30 22:59:18 +000012384#endif
12385#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +000012386 case TARGET_NR_setfsgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012387 return get_errno(setfsgid(arg1));
bellarda315a142005-01-30 22:59:18 +000012388#endif
bellardffa65c32004-01-04 23:57:22 +000012389#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +000012390 case TARGET_NR_mincore:
aurel3204bb9ac2008-10-01 21:46:41 +000012391 {
Thomas Weißschuhf443a262023-04-22 12:03:14 +020012392 void *a = lock_user(VERIFY_NONE, arg1, arg2, 0);
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000012393 if (!a) {
Richard Henderson259841c2018-08-18 12:01:09 -070012394 return -TARGET_ENOMEM;
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000012395 }
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000012396 p = lock_user_string(arg3);
12397 if (!p) {
Richard Henderson259841c2018-08-18 12:01:09 -070012398 ret = -TARGET_EFAULT;
12399 } else {
12400 ret = get_errno(mincore(a, arg2, p));
12401 unlock_user(p, arg3, ret);
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000012402 }
aurel3204bb9ac2008-10-01 21:46:41 +000012403 unlock_user(a, arg1, 0);
12404 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012405 return ret;
bellardffa65c32004-01-04 23:57:22 +000012406#endif
aurel32408321b2008-10-01 21:46:32 +000012407#ifdef TARGET_NR_arm_fadvise64_64
12408 case TARGET_NR_arm_fadvise64_64:
Peter Maydelle0156a92016-05-31 15:45:09 +010012409 /* arm_fadvise64_64 looks like fadvise64_64 but
12410 * with different argument order: fd, advice, offset, len
12411 * rather than the usual fd, offset, len, advice.
12412 * Note that offset and len are both 64-bit so appear as
12413 * pairs of 32-bit registers.
12414 */
12415 ret = posix_fadvise(arg1, target_offset64(arg3, arg4),
12416 target_offset64(arg5, arg6), arg2);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012417 return -host_to_target_errno(ret);
aurel32408321b2008-10-01 21:46:32 +000012418#endif
Peter Maydellbadd3cd2016-05-31 15:45:10 +010012419
WANG Xueruieeed2292022-10-06 16:55:00 +080012420#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
Peter Maydellbadd3cd2016-05-31 15:45:10 +010012421
12422#ifdef TARGET_NR_fadvise64_64
12423 case TARGET_NR_fadvise64_64:
Max Filippov64a563d2018-04-01 15:02:34 -070012424#if defined(TARGET_PPC) || defined(TARGET_XTENSA)
Laurent Vivier43046b52017-03-02 01:11:45 +010012425 /* 6 args: fd, advice, offset (high, low), len (high, low) */
12426 ret = arg2;
12427 arg2 = arg3;
12428 arg3 = arg4;
12429 arg4 = arg5;
12430 arg5 = arg6;
12431 arg6 = ret;
12432#else
Peter Maydellbadd3cd2016-05-31 15:45:10 +010012433 /* 6 args: fd, offset (high, low), len (high, low), advice */
James Clarke8bf8e9d2017-09-15 20:33:13 +010012434 if (regpairs_aligned(cpu_env, num)) {
Peter Maydellbadd3cd2016-05-31 15:45:10 +010012435 /* offset is in (3,4), len in (5,6) and advice in 7 */
12436 arg2 = arg3;
12437 arg3 = arg4;
12438 arg4 = arg5;
12439 arg5 = arg6;
12440 arg6 = arg7;
12441 }
Laurent Vivier43046b52017-03-02 01:11:45 +010012442#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012443 ret = posix_fadvise(arg1, target_offset64(arg2, arg3),
12444 target_offset64(arg4, arg5), arg6);
12445 return -host_to_target_errno(ret);
Peter Maydellbadd3cd2016-05-31 15:45:10 +010012446#endif
12447
12448#ifdef TARGET_NR_fadvise64
12449 case TARGET_NR_fadvise64:
12450 /* 5 args: fd, offset (high, low), len, advice */
James Clarke8bf8e9d2017-09-15 20:33:13 +010012451 if (regpairs_aligned(cpu_env, num)) {
Peter Maydellbadd3cd2016-05-31 15:45:10 +010012452 /* offset is in (3,4), len in 5 and advice in 6 */
12453 arg2 = arg3;
12454 arg3 = arg4;
12455 arg4 = arg5;
12456 arg5 = arg6;
12457 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012458 ret = posix_fadvise(arg1, target_offset64(arg2, arg3), arg4, arg5);
12459 return -host_to_target_errno(ret);
Peter Maydellbadd3cd2016-05-31 15:45:10 +010012460#endif
12461
12462#else /* not a 32-bit ABI */
Peter Maydelle0156a92016-05-31 15:45:09 +010012463#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_fadvise64)
aurel32408321b2008-10-01 21:46:32 +000012464#ifdef TARGET_NR_fadvise64_64
12465 case TARGET_NR_fadvise64_64:
12466#endif
Ulrich Hechte72d2cc2009-07-24 19:10:31 +020012467#ifdef TARGET_NR_fadvise64
12468 case TARGET_NR_fadvise64:
12469#endif
12470#ifdef TARGET_S390X
12471 switch (arg4) {
12472 case 4: arg4 = POSIX_FADV_NOREUSE + 1; break; /* make sure it's an invalid value */
12473 case 5: arg4 = POSIX_FADV_NOREUSE + 2; break; /* ditto */
12474 case 6: arg4 = POSIX_FADV_DONTNEED; break;
12475 case 7: arg4 = POSIX_FADV_NOREUSE; break;
12476 default: break;
12477 }
12478#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012479 return -host_to_target_errno(posix_fadvise(arg1, arg2, arg3, arg4));
aurel32408321b2008-10-01 21:46:32 +000012480#endif
Peter Maydellbadd3cd2016-05-31 15:45:10 +010012481#endif /* end of 64-bit ABI fadvise handling */
12482
bellardffa65c32004-01-04 23:57:22 +000012483#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +000012484 case TARGET_NR_madvise:
Ilya Leoshkevich892a4f62022-06-21 16:42:05 +020012485 return target_madvise(arg1, arg2, arg3);
bellardffa65c32004-01-04 23:57:22 +000012486#endif
Alex Bennéebbf5f2a2020-04-03 20:11:40 +010012487#ifdef TARGET_NR_fcntl64
bellard31e31b82003-02-18 22:55:36 +000012488 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +000012489 {
Alex Bennéebbf5f2a2020-04-03 20:11:40 +010012490 int cmd;
12491 struct flock64 fl;
Peter Maydell213d3e92016-06-13 11:22:05 +010012492 from_flock64_fn *copyfrom = copy_from_user_flock64;
12493 to_flock64_fn *copyto = copy_to_user_flock64;
12494
pbrookce4defa2006-02-09 16:49:55 +000012495#ifdef TARGET_ARM
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020012496 if (!cpu_env->eabi) {
Laurent Vivier7f254c52018-05-02 23:57:30 +020012497 copyfrom = copy_from_user_oabi_flock64;
12498 copyto = copy_to_user_oabi_flock64;
Peter Maydell213d3e92016-06-13 11:22:05 +010012499 }
pbrookce4defa2006-02-09 16:49:55 +000012500#endif
bellard77e46722003-04-29 20:39:06 +000012501
Alex Bennéebbf5f2a2020-04-03 20:11:40 +010012502 cmd = target_to_host_fcntl_cmd(arg2);
Peter Maydell31b63192011-12-05 23:11:50 +000012503 if (cmd == -TARGET_EINVAL) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012504 return cmd;
Peter Maydell31b63192011-12-05 23:11:50 +000012505 }
thsb1e341e2007-03-20 21:50:52 +000012506
bellard60cd49d2003-03-16 22:53:56 +000012507 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +000012508 case TARGET_F_GETLK64:
Peter Maydell213d3e92016-06-13 11:22:05 +010012509 ret = copyfrom(&fl, arg3);
12510 if (ret) {
12511 break;
ths58134272007-03-31 18:59:32 +000012512 }
Laurent Vivieraf8ab2b2018-07-13 14:58:05 +020012513 ret = get_errno(safe_fcntl(arg1, cmd, &fl));
Peter Maydell213d3e92016-06-13 11:22:05 +010012514 if (ret == 0) {
12515 ret = copyto(arg3, &fl);
12516 }
bellard77e46722003-04-29 20:39:06 +000012517 break;
12518
thsb1e341e2007-03-20 21:50:52 +000012519 case TARGET_F_SETLK64:
12520 case TARGET_F_SETLKW64:
Peter Maydell213d3e92016-06-13 11:22:05 +010012521 ret = copyfrom(&fl, arg3);
12522 if (ret) {
12523 break;
pbrookce4defa2006-02-09 16:49:55 +000012524 }
Peter Maydell435da5e2016-06-13 11:22:05 +010012525 ret = get_errno(safe_fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +000012526 break;
bellard60cd49d2003-03-16 22:53:56 +000012527 default:
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +020012528 ret = do_fcntl(arg1, arg2, arg3);
bellard60cd49d2003-03-16 22:53:56 +000012529 break;
12530 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012531 return ret;
bellard77e46722003-04-29 20:39:06 +000012532 }
bellard60cd49d2003-03-16 22:53:56 +000012533#endif
ths7d600c82006-12-08 01:32:58 +000012534#ifdef TARGET_NR_cacheflush
12535 case TARGET_NR_cacheflush:
12536 /* self-modifying code is handled automatically, so nothing needed */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012537 return 0;
ths7d600c82006-12-08 01:32:58 +000012538#endif
bellardc573ff62004-01-04 15:51:36 +000012539#ifdef TARGET_NR_getpagesize
12540 case TARGET_NR_getpagesize:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012541 return TARGET_PAGE_SIZE;
bellardc573ff62004-01-04 15:51:36 +000012542#endif
bellard31e31b82003-02-18 22:55:36 +000012543 case TARGET_NR_gettid:
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +000012544 return get_errno(sys_gettid());
thse5febef2007-04-01 18:31:35 +000012545#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +000012546 case TARGET_NR_readahead:
WANG Xueruieeed2292022-10-06 16:55:00 +080012547#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
James Clarke8bf8e9d2017-09-15 20:33:13 +010012548 if (regpairs_aligned(cpu_env, num)) {
aurel322054ac92008-10-13 21:08:07 +000012549 arg2 = arg3;
12550 arg3 = arg4;
12551 arg4 = arg5;
12552 }
Lena Djokic77c68502016-11-24 17:08:56 +010012553 ret = get_errno(readahead(arg1, target_offset64(arg2, arg3) , arg4));
aurel322054ac92008-10-13 21:08:07 +000012554#else
12555 ret = get_errno(readahead(arg1, arg2, arg3));
12556#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012557 return ret;
thse5febef2007-04-01 18:31:35 +000012558#endif
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012559#ifdef CONFIG_ATTR
bellardebc05482003-09-30 21:08:41 +000012560#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +000012561 case TARGET_NR_listxattr:
12562 case TARGET_NR_llistxattr:
Peter Maydellfb5590f2011-12-14 15:37:19 +000012563 {
12564 void *p, *b = 0;
12565 if (arg2) {
12566 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
12567 if (!b) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012568 return -TARGET_EFAULT;
Peter Maydellfb5590f2011-12-14 15:37:19 +000012569 }
12570 }
12571 p = lock_user_string(arg1);
12572 if (p) {
12573 if (num == TARGET_NR_listxattr) {
12574 ret = get_errno(listxattr(p, b, arg3));
12575 } else {
12576 ret = get_errno(llistxattr(p, b, arg3));
12577 }
12578 } else {
12579 ret = -TARGET_EFAULT;
12580 }
12581 unlock_user(p, arg1, 0);
12582 unlock_user(b, arg2, arg3);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012583 return ret;
Peter Maydellfb5590f2011-12-14 15:37:19 +000012584 }
12585 case TARGET_NR_flistxattr:
12586 {
12587 void *b = 0;
12588 if (arg2) {
12589 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
12590 if (!b) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012591 return -TARGET_EFAULT;
Peter Maydellfb5590f2011-12-14 15:37:19 +000012592 }
12593 }
12594 ret = get_errno(flistxattr(arg1, b, arg3));
12595 unlock_user(b, arg2, arg3);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012596 return ret;
Peter Maydellfb5590f2011-12-14 15:37:19 +000012597 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012598 case TARGET_NR_setxattr:
Peter Maydell30297b52011-12-14 15:37:18 +000012599 case TARGET_NR_lsetxattr:
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012600 {
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012601 void *p, *n, *v = 0;
12602 if (arg3) {
12603 v = lock_user(VERIFY_READ, arg3, arg4, 1);
12604 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012605 return -TARGET_EFAULT;
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012606 }
12607 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012608 p = lock_user_string(arg1);
12609 n = lock_user_string(arg2);
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012610 if (p && n) {
Peter Maydell30297b52011-12-14 15:37:18 +000012611 if (num == TARGET_NR_setxattr) {
12612 ret = get_errno(setxattr(p, n, v, arg4, arg5));
12613 } else {
12614 ret = get_errno(lsetxattr(p, n, v, arg4, arg5));
12615 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012616 } else {
12617 ret = -TARGET_EFAULT;
12618 }
12619 unlock_user(p, arg1, 0);
12620 unlock_user(n, arg2, 0);
12621 unlock_user(v, arg3, 0);
12622 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012623 return ret;
Peter Maydell30297b52011-12-14 15:37:18 +000012624 case TARGET_NR_fsetxattr:
12625 {
12626 void *n, *v = 0;
12627 if (arg3) {
12628 v = lock_user(VERIFY_READ, arg3, arg4, 1);
12629 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012630 return -TARGET_EFAULT;
Peter Maydell30297b52011-12-14 15:37:18 +000012631 }
12632 }
12633 n = lock_user_string(arg2);
12634 if (n) {
12635 ret = get_errno(fsetxattr(arg1, n, v, arg4, arg5));
12636 } else {
12637 ret = -TARGET_EFAULT;
12638 }
12639 unlock_user(n, arg2, 0);
12640 unlock_user(v, arg3, 0);
12641 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012642 return ret;
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012643 case TARGET_NR_getxattr:
Peter Maydell30297b52011-12-14 15:37:18 +000012644 case TARGET_NR_lgetxattr:
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012645 {
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012646 void *p, *n, *v = 0;
12647 if (arg3) {
12648 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
12649 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012650 return -TARGET_EFAULT;
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012651 }
12652 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012653 p = lock_user_string(arg1);
12654 n = lock_user_string(arg2);
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012655 if (p && n) {
Peter Maydell30297b52011-12-14 15:37:18 +000012656 if (num == TARGET_NR_getxattr) {
12657 ret = get_errno(getxattr(p, n, v, arg4));
12658 } else {
12659 ret = get_errno(lgetxattr(p, n, v, arg4));
12660 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012661 } else {
12662 ret = -TARGET_EFAULT;
12663 }
12664 unlock_user(p, arg1, 0);
12665 unlock_user(n, arg2, 0);
12666 unlock_user(v, arg3, arg4);
12667 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012668 return ret;
Peter Maydell30297b52011-12-14 15:37:18 +000012669 case TARGET_NR_fgetxattr:
12670 {
12671 void *n, *v = 0;
12672 if (arg3) {
12673 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
12674 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012675 return -TARGET_EFAULT;
Peter Maydell30297b52011-12-14 15:37:18 +000012676 }
12677 }
12678 n = lock_user_string(arg2);
12679 if (n) {
12680 ret = get_errno(fgetxattr(arg1, n, v, arg4));
12681 } else {
12682 ret = -TARGET_EFAULT;
12683 }
12684 unlock_user(n, arg2, 0);
12685 unlock_user(v, arg3, arg4);
12686 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012687 return ret;
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012688 case TARGET_NR_removexattr:
Peter Maydell30297b52011-12-14 15:37:18 +000012689 case TARGET_NR_lremovexattr:
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012690 {
12691 void *p, *n;
12692 p = lock_user_string(arg1);
12693 n = lock_user_string(arg2);
12694 if (p && n) {
Peter Maydell30297b52011-12-14 15:37:18 +000012695 if (num == TARGET_NR_removexattr) {
12696 ret = get_errno(removexattr(p, n));
12697 } else {
12698 ret = get_errno(lremovexattr(p, n));
12699 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012700 } else {
12701 ret = -TARGET_EFAULT;
12702 }
12703 unlock_user(p, arg1, 0);
12704 unlock_user(n, arg2, 0);
12705 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012706 return ret;
Peter Maydell30297b52011-12-14 15:37:18 +000012707 case TARGET_NR_fremovexattr:
12708 {
12709 void *n;
12710 n = lock_user_string(arg2);
12711 if (n) {
12712 ret = get_errno(fremovexattr(arg1, n));
12713 } else {
12714 ret = -TARGET_EFAULT;
12715 }
12716 unlock_user(n, arg2, 0);
12717 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012718 return ret;
bellardebc05482003-09-30 21:08:41 +000012719#endif
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012720#endif /* CONFIG_ATTR */
bellardebc05482003-09-30 21:08:41 +000012721#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +000012722 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +000012723#if defined(TARGET_MIPS)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020012724 cpu_env->active_tc.CP0_UserLocal = arg1;
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012725 return 0;
edgar_iglef967792009-01-07 14:19:38 +000012726#elif defined(TARGET_CRIS)
12727 if (arg1 & 0xff)
12728 ret = -TARGET_EINVAL;
12729 else {
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020012730 cpu_env->pregs[PR_PID] = arg1;
edgar_iglef967792009-01-07 14:19:38 +000012731 ret = 0;
12732 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012733 return ret;
bellard8d18e892007-11-14 15:18:40 +000012734#elif defined(TARGET_I386) && defined(TARGET_ABI32)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012735 return do_set_thread_area(cpu_env, arg1);
Peter Maydell1ccd9372013-07-16 18:44:55 +010012736#elif defined(TARGET_M68K)
12737 {
Andreas Färber0429a972013-08-26 18:14:44 +020012738 TaskState *ts = cpu->opaque;
Peter Maydell1ccd9372013-07-16 18:44:55 +010012739 ts->tp_value = arg1;
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012740 return 0;
Peter Maydell1ccd9372013-07-16 18:44:55 +010012741 }
ths6f5b89a2007-03-02 20:48:00 +000012742#else
Richard Henderson10f45d92018-08-18 12:01:07 -070012743 return -TARGET_ENOSYS;
ths6f5b89a2007-03-02 20:48:00 +000012744#endif
12745#endif
12746#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +000012747 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +000012748#if defined(TARGET_I386) && defined(TARGET_ABI32)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012749 return do_get_thread_area(cpu_env, arg1);
Peter Maydell1ccd9372013-07-16 18:44:55 +010012750#elif defined(TARGET_M68K)
12751 {
Andreas Färber0429a972013-08-26 18:14:44 +020012752 TaskState *ts = cpu->opaque;
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012753 return ts->tp_value;
Peter Maydell1ccd9372013-07-16 18:44:55 +010012754 }
bellard8d18e892007-11-14 15:18:40 +000012755#else
Richard Henderson10f45d92018-08-18 12:01:07 -070012756 return -TARGET_ENOSYS;
bellardebc05482003-09-30 21:08:41 +000012757#endif
bellard8d18e892007-11-14 15:18:40 +000012758#endif
bellard48dc41e2006-06-21 18:15:50 +000012759#ifdef TARGET_NR_getdomainname
12760 case TARGET_NR_getdomainname:
Richard Henderson10f45d92018-08-18 12:01:07 -070012761 return -TARGET_ENOSYS;
bellard48dc41e2006-06-21 18:15:50 +000012762#endif
ths6f5b89a2007-03-02 20:48:00 +000012763
Max Filippov12e33402018-04-01 13:13:49 -070012764#ifdef TARGET_NR_clock_settime
12765 case TARGET_NR_clock_settime:
12766 {
12767 struct timespec ts;
12768
12769 ret = target_to_host_timespec(&ts, arg2);
12770 if (!is_error(ret)) {
12771 ret = get_errno(clock_settime(arg1, &ts));
12772 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012773 return ret;
Max Filippov12e33402018-04-01 13:13:49 -070012774 }
12775#endif
Alistair Francisc6c8d102020-03-12 15:13:53 -070012776#ifdef TARGET_NR_clock_settime64
12777 case TARGET_NR_clock_settime64:
12778 {
12779 struct timespec ts;
12780
12781 ret = target_to_host_timespec64(&ts, arg2);
12782 if (!is_error(ret)) {
12783 ret = get_errno(clock_settime(arg1, &ts));
12784 }
12785 return ret;
12786 }
12787#endif
thsb5906f92007-03-19 13:32:45 +000012788#ifdef TARGET_NR_clock_gettime
12789 case TARGET_NR_clock_gettime:
12790 {
12791 struct timespec ts;
12792 ret = get_errno(clock_gettime(arg1, &ts));
12793 if (!is_error(ret)) {
Max Filippovb9f99082018-04-01 13:14:04 -070012794 ret = host_to_target_timespec(arg2, &ts);
thsb5906f92007-03-19 13:32:45 +000012795 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012796 return ret;
thsb5906f92007-03-19 13:32:45 +000012797 }
12798#endif
Alistair Francisc6c8d102020-03-12 15:13:53 -070012799#ifdef TARGET_NR_clock_gettime64
12800 case TARGET_NR_clock_gettime64:
12801 {
12802 struct timespec ts;
12803 ret = get_errno(clock_gettime(arg1, &ts));
12804 if (!is_error(ret)) {
12805 ret = host_to_target_timespec64(arg2, &ts);
12806 }
12807 return ret;
12808 }
12809#endif
thsb5906f92007-03-19 13:32:45 +000012810#ifdef TARGET_NR_clock_getres
12811 case TARGET_NR_clock_getres:
12812 {
12813 struct timespec ts;
12814 ret = get_errno(clock_getres(arg1, &ts));
12815 if (!is_error(ret)) {
12816 host_to_target_timespec(arg2, &ts);
12817 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012818 return ret;
thsb5906f92007-03-19 13:32:45 +000012819 }
12820#endif
Filip Bozuta828cb3a2020-07-22 17:34:21 +020012821#ifdef TARGET_NR_clock_getres_time64
12822 case TARGET_NR_clock_getres_time64:
12823 {
12824 struct timespec ts;
12825 ret = get_errno(clock_getres(arg1, &ts));
12826 if (!is_error(ret)) {
12827 host_to_target_timespec64(arg2, &ts);
12828 }
12829 return ret;
12830 }
12831#endif
pbrook63d76512008-05-29 13:43:29 +000012832#ifdef TARGET_NR_clock_nanosleep
12833 case TARGET_NR_clock_nanosleep:
12834 {
12835 struct timespec ts;
Filip Bozutab09d6402020-07-27 22:13:26 +020012836 if (target_to_host_timespec(&ts, arg3)) {
12837 return -TARGET_EFAULT;
12838 }
Peter Maydell9e518222016-06-06 19:58:09 +010012839 ret = get_errno(safe_clock_nanosleep(arg1, arg2,
12840 &ts, arg4 ? &ts : NULL));
Laurent Vivier8ec68a02020-07-24 07:45:05 +010012841 /*
12842 * if the call is interrupted by a signal handler, it fails
12843 * with error -TARGET_EINTR and if arg4 is not NULL and arg2 is not
12844 * TIMER_ABSTIME, it returns the remaining unslept time in arg4.
12845 */
Filip Bozutab09d6402020-07-27 22:13:26 +020012846 if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME &&
12847 host_to_target_timespec(arg4, &ts)) {
12848 return -TARGET_EFAULT;
Laurent Vivier8ec68a02020-07-24 07:45:05 +010012849 }
Tom Musta8fbe8fd2014-08-12 13:53:41 -050012850
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012851 return ret;
pbrook63d76512008-05-29 13:43:29 +000012852 }
12853#endif
Filip Bozuta6ac03b22020-08-24 21:21:15 +020012854#ifdef TARGET_NR_clock_nanosleep_time64
12855 case TARGET_NR_clock_nanosleep_time64:
12856 {
12857 struct timespec ts;
12858
12859 if (target_to_host_timespec64(&ts, arg3)) {
12860 return -TARGET_EFAULT;
12861 }
12862
12863 ret = get_errno(safe_clock_nanosleep(arg1, arg2,
12864 &ts, arg4 ? &ts : NULL));
12865
12866 if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME &&
12867 host_to_target_timespec64(arg4, &ts)) {
12868 return -TARGET_EFAULT;
12869 }
12870 return ret;
12871 }
12872#endif
thsb5906f92007-03-19 13:32:45 +000012873
Helge Deller9a7f6822022-05-28 12:52:10 +020012874#if defined(TARGET_NR_set_tid_address)
ths6f5b89a2007-03-02 20:48:00 +000012875 case TARGET_NR_set_tid_address:
Helge Deller9a7f6822022-05-28 12:52:10 +020012876 {
12877 TaskState *ts = cpu->opaque;
12878 ts->child_tidptr = arg1;
12879 /* do not call host set_tid_address() syscall, instead return tid() */
12880 return get_errno(sys_gettid());
12881 }
ths6f5b89a2007-03-02 20:48:00 +000012882#endif
12883
ths4cae1d12007-07-12 11:06:53 +000012884 case TARGET_NR_tkill:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012885 return get_errno(safe_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +000012886
ths71455572007-06-21 21:45:30 +000012887 case TARGET_NR_tgkill:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012888 return get_errno(safe_tgkill((int)arg1, (int)arg2,
12889 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +000012890
ths4f2b1fe2007-06-21 21:57:12 +000012891#ifdef TARGET_NR_set_robust_list
12892 case TARGET_NR_set_robust_list:
Peter Maydelle9a970a2013-02-08 04:34:54 +000012893 case TARGET_NR_get_robust_list:
12894 /* The ABI for supporting robust futexes has userspace pass
12895 * the kernel a pointer to a linked list which is updated by
12896 * userspace after the syscall; the list is walked by the kernel
12897 * when the thread exits. Since the linked list in QEMU guest
12898 * memory isn't a valid linked list for the host and we have
12899 * no way to reliably intercept the thread-death event, we can't
12900 * support these. Silently return ENOSYS so that guest userspace
12901 * falls back to a non-robust futex implementation (which should
12902 * be OK except in the corner case of the guest crashing while
12903 * holding a mutex that is shared with another process via
12904 * shared memory).
12905 */
Richard Henderson10f45d92018-08-18 12:01:07 -070012906 return -TARGET_ENOSYS;
ths4f2b1fe2007-06-21 21:57:12 +000012907#endif
12908
Peter Maydell1acae9f2013-07-02 14:04:12 +010012909#if defined(TARGET_NR_utimensat)
ths9007f0e2007-09-25 17:50:37 +000012910 case TARGET_NR_utimensat:
12911 {
Riku Voipioebc996f2009-04-21 15:01:51 +030012912 struct timespec *tsp, ts[2];
12913 if (!arg3) {
12914 tsp = NULL;
12915 } else {
Filip Bozutab3a3af72020-08-11 13:31:01 +020012916 if (target_to_host_timespec(ts, arg3)) {
12917 return -TARGET_EFAULT;
12918 }
12919 if (target_to_host_timespec(ts + 1, arg3 +
12920 sizeof(struct target_timespec))) {
12921 return -TARGET_EFAULT;
12922 }
Riku Voipioebc996f2009-04-21 15:01:51 +030012923 tsp = ts;
12924 }
ths9007f0e2007-09-25 17:50:37 +000012925 if (!arg2)
Riku Voipioebc996f2009-04-21 15:01:51 +030012926 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
ths9007f0e2007-09-25 17:50:37 +000012927 else {
bellard579a97f2007-11-11 14:26:47 +000012928 if (!(p = lock_user_string(arg2))) {
Richard Henderson259841c2018-08-18 12:01:09 -070012929 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000012930 }
Riku Voipioebc996f2009-04-21 15:01:51 +030012931 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
bellard579a97f2007-11-11 14:26:47 +000012932 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +000012933 }
12934 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012935 return ret;
ths9007f0e2007-09-25 17:50:37 +000012936#endif
Filip Bozutacac46eb2020-08-25 00:30:50 +020012937#ifdef TARGET_NR_utimensat_time64
12938 case TARGET_NR_utimensat_time64:
12939 {
12940 struct timespec *tsp, ts[2];
12941 if (!arg3) {
12942 tsp = NULL;
12943 } else {
12944 if (target_to_host_timespec64(ts, arg3)) {
12945 return -TARGET_EFAULT;
12946 }
12947 if (target_to_host_timespec64(ts + 1, arg3 +
12948 sizeof(struct target__kernel_timespec))) {
12949 return -TARGET_EFAULT;
12950 }
12951 tsp = ts;
12952 }
12953 if (!arg2)
12954 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
12955 else {
12956 p = lock_user_string(arg2);
12957 if (!p) {
12958 return -TARGET_EFAULT;
12959 }
12960 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
12961 unlock_user(p, arg2, 0);
12962 }
12963 }
12964 return ret;
12965#endif
Alistair Francis859e8a82020-03-12 15:13:49 -070012966#ifdef TARGET_NR_futex
pbrookbd0c5662008-05-29 14:34:11 +000012967 case TARGET_NR_futex:
Richard Henderson0fbc0f82022-08-28 19:09:59 -070012968 return do_futex(cpu, false, arg1, arg2, arg3, arg4, arg5, arg6);
Alistair Francis859e8a82020-03-12 15:13:49 -070012969#endif
Alistair Francis14690292020-03-18 15:47:01 -070012970#ifdef TARGET_NR_futex_time64
12971 case TARGET_NR_futex_time64:
Richard Henderson0fbc0f82022-08-28 19:09:59 -070012972 return do_futex(cpu, true, arg1, arg2, arg3, arg4, arg5, arg6);
Alistair Francis14690292020-03-18 15:47:01 -070012973#endif
Paul Brook33f53ac2022-01-26 20:26:36 +000012974#ifdef CONFIG_INOTIFY
12975#if defined(TARGET_NR_inotify_init)
aurel3239b59762008-10-01 21:46:50 +000012976 case TARGET_NR_inotify_init:
Paul Brook33f53ac2022-01-26 20:26:36 +000012977 ret = get_errno(inotify_init());
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030012978 if (ret >= 0) {
12979 fd_trans_register(ret, &target_inotify_trans);
12980 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012981 return ret;
aurel3239b59762008-10-01 21:46:50 +000012982#endif
Paul Brook33f53ac2022-01-26 20:26:36 +000012983#if defined(TARGET_NR_inotify_init1) && defined(CONFIG_INOTIFY1)
Riku Voipioc05c7a72010-03-26 15:25:11 +000012984 case TARGET_NR_inotify_init1:
Paul Brook33f53ac2022-01-26 20:26:36 +000012985 ret = get_errno(inotify_init1(target_to_host_bitmask(arg1,
Lena Djokicfea243e2016-11-24 17:08:53 +010012986 fcntl_flags_tbl)));
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030012987 if (ret >= 0) {
12988 fd_trans_register(ret, &target_inotify_trans);
12989 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012990 return ret;
Riku Voipioc05c7a72010-03-26 15:25:11 +000012991#endif
Paul Brook33f53ac2022-01-26 20:26:36 +000012992#if defined(TARGET_NR_inotify_add_watch)
aurel3239b59762008-10-01 21:46:50 +000012993 case TARGET_NR_inotify_add_watch:
12994 p = lock_user_string(arg2);
Paul Brook33f53ac2022-01-26 20:26:36 +000012995 ret = get_errno(inotify_add_watch(arg1, path(p), arg3));
aurel3239b59762008-10-01 21:46:50 +000012996 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012997 return ret;
aurel3239b59762008-10-01 21:46:50 +000012998#endif
Paul Brook33f53ac2022-01-26 20:26:36 +000012999#if defined(TARGET_NR_inotify_rm_watch)
aurel3239b59762008-10-01 21:46:50 +000013000 case TARGET_NR_inotify_rm_watch:
Paul Brook33f53ac2022-01-26 20:26:36 +000013001 return get_errno(inotify_rm_watch(arg1, arg2));
13002#endif
aurel3239b59762008-10-01 21:46:50 +000013003#endif
ths9007f0e2007-09-25 17:50:37 +000013004
Nathan Froyd8ec9cf82009-07-22 09:14:36 -070013005#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
aurel3224e10032009-04-15 16:11:43 +000013006 case TARGET_NR_mq_open:
13007 {
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020013008 struct mq_attr posix_mq_attr;
Lena Djokic26400772016-11-24 17:08:58 +010013009 struct mq_attr *pposix_mq_attr;
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020013010 int host_flags;
aurel3224e10032009-04-15 16:11:43 +000013011
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020013012 host_flags = target_to_host_bitmask(arg2, fcntl_flags_tbl);
Lena Djokic26400772016-11-24 17:08:58 +010013013 pposix_mq_attr = NULL;
13014 if (arg4) {
13015 if (copy_from_user_mq_attr(&posix_mq_attr, arg4) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013016 return -TARGET_EFAULT;
Lena Djokic26400772016-11-24 17:08:58 +010013017 }
13018 pposix_mq_attr = &posix_mq_attr;
Tom Mustab6ce1f62014-08-12 13:53:36 -050013019 }
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020013020 p = lock_user_string(arg1 - 1);
13021 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013022 return -TARGET_EFAULT;
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020013023 }
Lena Djokic26400772016-11-24 17:08:58 +010013024 ret = get_errno(mq_open(p, host_flags, arg3, pposix_mq_attr));
aurel3224e10032009-04-15 16:11:43 +000013025 unlock_user (p, arg1, 0);
13026 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013027 return ret;
aurel3224e10032009-04-15 16:11:43 +000013028
13029 case TARGET_NR_mq_unlink:
13030 p = lock_user_string(arg1 - 1);
Peter Maydell32112152016-07-12 13:02:13 +010013031 if (!p) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013032 return -TARGET_EFAULT;
Peter Maydell32112152016-07-12 13:02:13 +010013033 }
aurel3224e10032009-04-15 16:11:43 +000013034 ret = get_errno(mq_unlink(p));
13035 unlock_user (p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013036 return ret;
aurel3224e10032009-04-15 16:11:43 +000013037
Alistair Francis859e8a82020-03-12 15:13:49 -070013038#ifdef TARGET_NR_mq_timedsend
aurel3224e10032009-04-15 16:11:43 +000013039 case TARGET_NR_mq_timedsend:
13040 {
13041 struct timespec ts;
13042
13043 p = lock_user (VERIFY_READ, arg2, arg3, 1);
13044 if (arg5 != 0) {
Filip Bozutadcbcf5c2020-08-24 21:37:51 +020013045 if (target_to_host_timespec(&ts, arg5)) {
13046 return -TARGET_EFAULT;
13047 }
Peter Maydelld40ecd62016-06-06 19:58:06 +010013048 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts));
Filip Bozutadcbcf5c2020-08-24 21:37:51 +020013049 if (!is_error(ret) && host_to_target_timespec(arg5, &ts)) {
13050 return -TARGET_EFAULT;
13051 }
Peter Maydelld40ecd62016-06-06 19:58:06 +010013052 } else {
13053 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL));
aurel3224e10032009-04-15 16:11:43 +000013054 }
aurel3224e10032009-04-15 16:11:43 +000013055 unlock_user (p, arg2, arg3);
13056 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013057 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070013058#endif
Filip Bozutad107e372020-08-24 21:37:52 +020013059#ifdef TARGET_NR_mq_timedsend_time64
13060 case TARGET_NR_mq_timedsend_time64:
13061 {
13062 struct timespec ts;
13063
13064 p = lock_user(VERIFY_READ, arg2, arg3, 1);
13065 if (arg5 != 0) {
13066 if (target_to_host_timespec64(&ts, arg5)) {
13067 return -TARGET_EFAULT;
13068 }
13069 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts));
13070 if (!is_error(ret) && host_to_target_timespec64(arg5, &ts)) {
13071 return -TARGET_EFAULT;
13072 }
13073 } else {
13074 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL));
13075 }
13076 unlock_user(p, arg2, arg3);
13077 }
13078 return ret;
13079#endif
aurel3224e10032009-04-15 16:11:43 +000013080
Alistair Francis859e8a82020-03-12 15:13:49 -070013081#ifdef TARGET_NR_mq_timedreceive
aurel3224e10032009-04-15 16:11:43 +000013082 case TARGET_NR_mq_timedreceive:
13083 {
13084 struct timespec ts;
13085 unsigned int prio;
13086
13087 p = lock_user (VERIFY_READ, arg2, arg3, 1);
13088 if (arg5 != 0) {
Filip Bozutadcbcf5c2020-08-24 21:37:51 +020013089 if (target_to_host_timespec(&ts, arg5)) {
13090 return -TARGET_EFAULT;
13091 }
Peter Maydelld40ecd62016-06-06 19:58:06 +010013092 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
13093 &prio, &ts));
Filip Bozutadcbcf5c2020-08-24 21:37:51 +020013094 if (!is_error(ret) && host_to_target_timespec(arg5, &ts)) {
13095 return -TARGET_EFAULT;
13096 }
Peter Maydelld40ecd62016-06-06 19:58:06 +010013097 } else {
13098 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
13099 &prio, NULL));
aurel3224e10032009-04-15 16:11:43 +000013100 }
aurel3224e10032009-04-15 16:11:43 +000013101 unlock_user (p, arg2, arg3);
13102 if (arg4 != 0)
13103 put_user_u32(prio, arg4);
13104 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013105 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070013106#endif
Filip Bozutad107e372020-08-24 21:37:52 +020013107#ifdef TARGET_NR_mq_timedreceive_time64
13108 case TARGET_NR_mq_timedreceive_time64:
13109 {
13110 struct timespec ts;
13111 unsigned int prio;
13112
13113 p = lock_user(VERIFY_READ, arg2, arg3, 1);
13114 if (arg5 != 0) {
13115 if (target_to_host_timespec64(&ts, arg5)) {
13116 return -TARGET_EFAULT;
13117 }
13118 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
13119 &prio, &ts));
13120 if (!is_error(ret) && host_to_target_timespec64(arg5, &ts)) {
13121 return -TARGET_EFAULT;
13122 }
13123 } else {
13124 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
13125 &prio, NULL));
13126 }
13127 unlock_user(p, arg2, arg3);
13128 if (arg4 != 0) {
13129 put_user_u32(prio, arg4);
13130 }
13131 }
13132 return ret;
13133#endif
aurel3224e10032009-04-15 16:11:43 +000013134
13135 /* Not implemented for now... */
13136/* case TARGET_NR_mq_notify: */
13137/* break; */
13138
13139 case TARGET_NR_mq_getsetattr:
13140 {
13141 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
13142 ret = 0;
aurel3224e10032009-04-15 16:11:43 +000013143 if (arg2 != 0) {
13144 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
Max Filippova23ea402018-03-31 08:20:15 -070013145 ret = get_errno(mq_setattr(arg1, &posix_mq_attr_in,
13146 &posix_mq_attr_out));
13147 } else if (arg3 != 0) {
13148 ret = get_errno(mq_getattr(arg1, &posix_mq_attr_out));
aurel3224e10032009-04-15 16:11:43 +000013149 }
Max Filippova23ea402018-03-31 08:20:15 -070013150 if (ret == 0 && arg3 != 0) {
13151 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
13152 }
aurel3224e10032009-04-15 16:11:43 +000013153 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013154 return ret;
aurel3224e10032009-04-15 16:11:43 +000013155#endif
13156
vibisreenivasan3ce34df2009-05-16 18:32:41 +053013157#ifdef CONFIG_SPLICE
13158#ifdef TARGET_NR_tee
13159 case TARGET_NR_tee:
13160 {
13161 ret = get_errno(tee(arg1,arg2,arg3,arg4));
13162 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013163 return ret;
vibisreenivasan3ce34df2009-05-16 18:32:41 +053013164#endif
13165#ifdef TARGET_NR_splice
13166 case TARGET_NR_splice:
13167 {
13168 loff_t loff_in, loff_out;
13169 loff_t *ploff_in = NULL, *ploff_out = NULL;
Andreas Schwab17644b32015-03-10 17:11:35 +010013170 if (arg2) {
13171 if (get_user_u64(loff_in, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013172 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010013173 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053013174 ploff_in = &loff_in;
13175 }
Andreas Schwab17644b32015-03-10 17:11:35 +010013176 if (arg4) {
13177 if (get_user_u64(loff_out, arg4)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013178 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010013179 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053013180 ploff_out = &loff_out;
13181 }
13182 ret = get_errno(splice(arg1, ploff_in, arg3, ploff_out, arg5, arg6));
Andreas Schwab17644b32015-03-10 17:11:35 +010013183 if (arg2) {
13184 if (put_user_u64(loff_in, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013185 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010013186 }
13187 }
13188 if (arg4) {
13189 if (put_user_u64(loff_out, arg4)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013190 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010013191 }
13192 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053013193 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013194 return ret;
vibisreenivasan3ce34df2009-05-16 18:32:41 +053013195#endif
13196#ifdef TARGET_NR_vmsplice
13197 case TARGET_NR_vmsplice:
13198 {
Richard Hendersonf287b2c2012-09-15 13:20:25 -070013199 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
13200 if (vec != NULL) {
13201 ret = get_errno(vmsplice(arg1, vec, arg3, arg4));
13202 unlock_iovec(vec, arg2, arg3, 0);
13203 } else {
13204 ret = -host_to_target_errno(errno);
13205 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053013206 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013207 return ret;
vibisreenivasan3ce34df2009-05-16 18:32:41 +053013208#endif
13209#endif /* CONFIG_SPLICE */
Riku Voipioc2882b92009-08-12 15:08:24 +030013210#ifdef CONFIG_EVENTFD
13211#if defined(TARGET_NR_eventfd)
13212 case TARGET_NR_eventfd:
13213 ret = get_errno(eventfd(arg1, 0));
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030013214 if (ret >= 0) {
13215 fd_trans_register(ret, &target_eventfd_trans);
13216 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013217 return ret;
Riku Voipioc2882b92009-08-12 15:08:24 +030013218#endif
13219#if defined(TARGET_NR_eventfd2)
13220 case TARGET_NR_eventfd2:
Petar Jovanovic5947c692013-04-08 20:26:10 +020013221 {
Helge Deller78721302021-02-10 07:12:14 +010013222 int host_flags = arg2 & (~(TARGET_O_NONBLOCK_MASK | TARGET_O_CLOEXEC));
Petar Jovanovic5947c692013-04-08 20:26:10 +020013223 if (arg2 & TARGET_O_NONBLOCK) {
13224 host_flags |= O_NONBLOCK;
13225 }
13226 if (arg2 & TARGET_O_CLOEXEC) {
13227 host_flags |= O_CLOEXEC;
13228 }
13229 ret = get_errno(eventfd(arg1, host_flags));
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030013230 if (ret >= 0) {
13231 fd_trans_register(ret, &target_eventfd_trans);
13232 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013233 return ret;
Petar Jovanovic5947c692013-04-08 20:26:10 +020013234 }
Riku Voipioc2882b92009-08-12 15:08:24 +030013235#endif
13236#endif /* CONFIG_EVENTFD */
Ulrich Hechtd0927932009-09-17 20:22:14 +030013237#if defined(CONFIG_FALLOCATE) && defined(TARGET_NR_fallocate)
13238 case TARGET_NR_fallocate:
WANG Xueruieeed2292022-10-06 16:55:00 +080013239#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
Alexander Graf20249ae2012-02-06 21:37:07 +010013240 ret = get_errno(fallocate(arg1, arg2, target_offset64(arg3, arg4),
13241 target_offset64(arg5, arg6)));
13242#else
Ulrich Hechtd0927932009-09-17 20:22:14 +030013243 ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
Alexander Graf20249ae2012-02-06 21:37:07 +010013244#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013245 return ret;
Ulrich Hechtd0927932009-09-17 20:22:14 +030013246#endif
Peter Maydellc727f472011-01-06 11:05:10 +000013247#if defined(CONFIG_SYNC_FILE_RANGE)
13248#if defined(TARGET_NR_sync_file_range)
13249 case TARGET_NR_sync_file_range:
WANG Xueruieeed2292022-10-06 16:55:00 +080013250#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
Riku Voipiobfcedc52011-06-20 16:24:39 +030013251#if defined(TARGET_MIPS)
13252 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
13253 target_offset64(arg5, arg6), arg7));
13254#else
Peter Maydellc727f472011-01-06 11:05:10 +000013255 ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3),
13256 target_offset64(arg4, arg5), arg6));
Riku Voipiobfcedc52011-06-20 16:24:39 +030013257#endif /* !TARGET_MIPS */
Peter Maydellc727f472011-01-06 11:05:10 +000013258#else
13259 ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4));
13260#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013261 return ret;
Peter Maydellc727f472011-01-06 11:05:10 +000013262#endif
Laurent Vivier5bcb4982020-03-10 11:33:50 +010013263#if defined(TARGET_NR_sync_file_range2) || \
13264 defined(TARGET_NR_arm_sync_file_range)
Peter Maydellc727f472011-01-06 11:05:10 +000013265#if defined(TARGET_NR_sync_file_range2)
13266 case TARGET_NR_sync_file_range2:
Laurent Vivier5bcb4982020-03-10 11:33:50 +010013267#endif
13268#if defined(TARGET_NR_arm_sync_file_range)
13269 case TARGET_NR_arm_sync_file_range:
13270#endif
Peter Maydellc727f472011-01-06 11:05:10 +000013271 /* This is like sync_file_range but the arguments are reordered */
WANG Xueruieeed2292022-10-06 16:55:00 +080013272#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
Peter Maydellc727f472011-01-06 11:05:10 +000013273 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
13274 target_offset64(arg5, arg6), arg2));
13275#else
13276 ret = get_errno(sync_file_range(arg1, arg3, arg4, arg2));
13277#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013278 return ret;
Peter Maydellc727f472011-01-06 11:05:10 +000013279#endif
13280#endif
Laurent Viviere36800c2015-10-02 14:48:09 +020013281#if defined(TARGET_NR_signalfd4)
13282 case TARGET_NR_signalfd4:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013283 return do_signalfd4(arg1, arg2, arg4);
Laurent Viviere36800c2015-10-02 14:48:09 +020013284#endif
13285#if defined(TARGET_NR_signalfd)
13286 case TARGET_NR_signalfd:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013287 return do_signalfd4(arg1, arg2, 0);
Laurent Viviere36800c2015-10-02 14:48:09 +020013288#endif
Peter Maydell3b6edd12011-02-15 18:35:05 +000013289#if defined(CONFIG_EPOLL)
13290#if defined(TARGET_NR_epoll_create)
13291 case TARGET_NR_epoll_create:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013292 return get_errno(epoll_create(arg1));
Peter Maydell3b6edd12011-02-15 18:35:05 +000013293#endif
13294#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1)
13295 case TARGET_NR_epoll_create1:
Sergei Trofimovich386d3862020-04-15 23:05:08 +010013296 return get_errno(epoll_create1(target_to_host_bitmask(arg1, fcntl_flags_tbl)));
Peter Maydell3b6edd12011-02-15 18:35:05 +000013297#endif
13298#if defined(TARGET_NR_epoll_ctl)
13299 case TARGET_NR_epoll_ctl:
13300 {
13301 struct epoll_event ep;
13302 struct epoll_event *epp = 0;
13303 if (arg4) {
LemonBoyc7811022020-04-17 17:34:54 +020013304 if (arg2 != EPOLL_CTL_DEL) {
13305 struct target_epoll_event *target_ep;
13306 if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) {
13307 return -TARGET_EFAULT;
13308 }
13309 ep.events = tswap32(target_ep->events);
13310 /*
13311 * The epoll_data_t union is just opaque data to the kernel,
13312 * so we transfer all 64 bits across and need not worry what
13313 * actual data type it is.
13314 */
13315 ep.data.u64 = tswap64(target_ep->data.u64);
13316 unlock_user_struct(target_ep, arg4, 0);
Peter Maydell3b6edd12011-02-15 18:35:05 +000013317 }
LemonBoyc7811022020-04-17 17:34:54 +020013318 /*
13319 * before kernel 2.6.9, EPOLL_CTL_DEL operation required a
13320 * non-null pointer, even though this argument is ignored.
13321 *
Peter Maydell3b6edd12011-02-15 18:35:05 +000013322 */
Peter Maydell3b6edd12011-02-15 18:35:05 +000013323 epp = &ep;
13324 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013325 return get_errno(epoll_ctl(arg1, arg2, arg3, epp));
Peter Maydell3b6edd12011-02-15 18:35:05 +000013326 }
13327#endif
13328
Peter Maydell227f0212016-06-06 19:58:11 +010013329#if defined(TARGET_NR_epoll_wait) || defined(TARGET_NR_epoll_pwait)
Peter Maydell3b6edd12011-02-15 18:35:05 +000013330#if defined(TARGET_NR_epoll_wait)
13331 case TARGET_NR_epoll_wait:
13332#endif
Peter Maydell227f0212016-06-06 19:58:11 +010013333#if defined(TARGET_NR_epoll_pwait)
Peter Maydell3b6edd12011-02-15 18:35:05 +000013334 case TARGET_NR_epoll_pwait:
13335#endif
13336 {
13337 struct target_epoll_event *target_ep;
13338 struct epoll_event *ep;
13339 int epfd = arg1;
13340 int maxevents = arg3;
13341 int timeout = arg4;
13342
Peter Maydell2ba7fae32016-07-18 15:35:59 +010013343 if (maxevents <= 0 || maxevents > TARGET_EP_MAX_EVENTS) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013344 return -TARGET_EINVAL;
Peter Maydell2ba7fae32016-07-18 15:35:59 +010013345 }
13346
Peter Maydell3b6edd12011-02-15 18:35:05 +000013347 target_ep = lock_user(VERIFY_WRITE, arg2,
13348 maxevents * sizeof(struct target_epoll_event), 1);
13349 if (!target_ep) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013350 return -TARGET_EFAULT;
Peter Maydell3b6edd12011-02-15 18:35:05 +000013351 }
13352
Peter Maydell04c95f42016-07-18 15:36:00 +010013353 ep = g_try_new(struct epoll_event, maxevents);
13354 if (!ep) {
13355 unlock_user(target_ep, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013356 return -TARGET_ENOMEM;
Peter Maydell04c95f42016-07-18 15:36:00 +010013357 }
Peter Maydell3b6edd12011-02-15 18:35:05 +000013358
13359 switch (num) {
Peter Maydell227f0212016-06-06 19:58:11 +010013360#if defined(TARGET_NR_epoll_pwait)
Peter Maydell3b6edd12011-02-15 18:35:05 +000013361 case TARGET_NR_epoll_pwait:
13362 {
Richard Hendersoncd0e31a2022-03-15 01:43:07 -070013363 sigset_t *set = NULL;
Peter Maydell3b6edd12011-02-15 18:35:05 +000013364
13365 if (arg5) {
Richard Hendersoncd0e31a2022-03-15 01:43:07 -070013366 ret = process_sigsuspend_mask(&set, arg5, arg6);
13367 if (ret != 0) {
Peter Maydellc8157012016-06-30 14:23:24 +010013368 break;
13369 }
Peter Maydell3b6edd12011-02-15 18:35:05 +000013370 }
13371
Peter Maydell227f0212016-06-06 19:58:11 +010013372 ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
13373 set, SIGSET_T_SIZE));
Richard Hendersoncd0e31a2022-03-15 01:43:07 -070013374
13375 if (set) {
13376 finish_sigsuspend_mask(ret);
13377 }
Peter Maydell3b6edd12011-02-15 18:35:05 +000013378 break;
13379 }
13380#endif
13381#if defined(TARGET_NR_epoll_wait)
13382 case TARGET_NR_epoll_wait:
Peter Maydell227f0212016-06-06 19:58:11 +010013383 ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
13384 NULL, 0));
Peter Maydell3b6edd12011-02-15 18:35:05 +000013385 break;
13386#endif
13387 default:
13388 ret = -TARGET_ENOSYS;
13389 }
13390 if (!is_error(ret)) {
13391 int i;
13392 for (i = 0; i < ret; i++) {
13393 target_ep[i].events = tswap32(ep[i].events);
13394 target_ep[i].data.u64 = tswap64(ep[i].data.u64);
13395 }
Peter Maydell04c95f42016-07-18 15:36:00 +010013396 unlock_user(target_ep, arg2,
13397 ret * sizeof(struct target_epoll_event));
13398 } else {
13399 unlock_user(target_ep, arg2, 0);
Peter Maydell3b6edd12011-02-15 18:35:05 +000013400 }
Peter Maydell04c95f42016-07-18 15:36:00 +010013401 g_free(ep);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013402 return ret;
Peter Maydell3b6edd12011-02-15 18:35:05 +000013403 }
13404#endif
13405#endif
Peter Maydell163a05a2011-06-27 17:44:52 +010013406#ifdef TARGET_NR_prlimit64
13407 case TARGET_NR_prlimit64:
13408 {
13409 /* args: pid, resource number, ptr to new rlimit, ptr to old rlimit */
13410 struct target_rlimit64 *target_rnew, *target_rold;
13411 struct host_rlimit64 rnew, rold, *rnewp = 0;
Felix Janda95018012014-12-02 22:11:17 +010013412 int resource = target_to_host_resource(arg2);
Tobias Koch055d92f2020-03-05 21:24:00 +010013413
13414 if (arg3 && (resource != RLIMIT_AS &&
13415 resource != RLIMIT_DATA &&
13416 resource != RLIMIT_STACK)) {
Peter Maydell163a05a2011-06-27 17:44:52 +010013417 if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013418 return -TARGET_EFAULT;
Peter Maydell163a05a2011-06-27 17:44:52 +010013419 }
Ilya Leoshkevich9c1da8b2023-02-24 01:39:06 +010013420 __get_user(rnew.rlim_cur, &target_rnew->rlim_cur);
13421 __get_user(rnew.rlim_max, &target_rnew->rlim_max);
Peter Maydell163a05a2011-06-27 17:44:52 +010013422 unlock_user_struct(target_rnew, arg3, 0);
13423 rnewp = &rnew;
13424 }
13425
Felix Janda95018012014-12-02 22:11:17 +010013426 ret = get_errno(sys_prlimit64(arg1, resource, rnewp, arg4 ? &rold : 0));
Peter Maydell163a05a2011-06-27 17:44:52 +010013427 if (!is_error(ret) && arg4) {
13428 if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013429 return -TARGET_EFAULT;
Peter Maydell163a05a2011-06-27 17:44:52 +010013430 }
Ilya Leoshkevich9c1da8b2023-02-24 01:39:06 +010013431 __put_user(rold.rlim_cur, &target_rold->rlim_cur);
13432 __put_user(rold.rlim_max, &target_rold->rlim_max);
Peter Maydell163a05a2011-06-27 17:44:52 +010013433 unlock_user_struct(target_rold, arg4, 1);
13434 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013435 return ret;
Peter Maydell163a05a2011-06-27 17:44:52 +010013436 }
13437#endif
Richard Henderson3d21d292012-09-15 13:20:46 -070013438#ifdef TARGET_NR_gethostname
13439 case TARGET_NR_gethostname:
13440 {
13441 char *name = lock_user(VERIFY_WRITE, arg1, arg2, 0);
13442 if (name) {
13443 ret = get_errno(gethostname(name, arg2));
13444 unlock_user(name, arg1, arg2);
13445 } else {
13446 ret = -TARGET_EFAULT;
13447 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013448 return ret;
Richard Henderson3d21d292012-09-15 13:20:46 -070013449 }
13450#endif
Riku Voipio89aaf1a2013-07-24 09:44:26 +030013451#ifdef TARGET_NR_atomic_cmpxchg_32
13452 case TARGET_NR_atomic_cmpxchg_32:
13453 {
13454 /* should use start_exclusive from main.c */
13455 abi_ulong mem_value;
13456 if (get_user_u32(mem_value, arg6)) {
13457 target_siginfo_t info;
13458 info.si_signo = SIGSEGV;
13459 info.si_errno = 0;
13460 info.si_code = TARGET_SEGV_MAPERR;
13461 info._sifields._sigfault._addr = arg6;
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020013462 queue_signal(cpu_env, info.si_signo, QEMU_SI_FAULT, &info);
Riku Voipio89aaf1a2013-07-24 09:44:26 +030013463 ret = 0xdeadbeef;
13464
13465 }
13466 if (mem_value == arg2)
13467 put_user_u32(arg1, arg6);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013468 return mem_value;
Riku Voipio89aaf1a2013-07-24 09:44:26 +030013469 }
13470#endif
13471#ifdef TARGET_NR_atomic_barrier
13472 case TARGET_NR_atomic_barrier:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013473 /* Like the kernel implementation and the
13474 qemu arm barrier, no-op this? */
13475 return 0;
Riku Voipio89aaf1a2013-07-24 09:44:26 +030013476#endif
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013477
13478#ifdef TARGET_NR_timer_create
13479 case TARGET_NR_timer_create:
13480 {
13481 /* args: clockid_t clockid, struct sigevent *sevp, timer_t *timerid */
13482
13483 struct sigevent host_sevp = { {0}, }, *phost_sevp = NULL;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013484
13485 int clkid = arg1;
13486 int timer_index = next_free_host_timer();
13487
13488 if (timer_index < 0) {
13489 ret = -TARGET_EAGAIN;
13490 } else {
13491 timer_t *phtimer = g_posix_timers + timer_index;
13492
13493 if (arg2) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013494 phost_sevp = &host_sevp;
Peter Maydellc0659762014-08-09 15:42:32 +010013495 ret = target_to_host_sigevent(phost_sevp, arg2);
13496 if (ret != 0) {
Peter Maydell9e598992022-07-25 12:00:35 +010013497 free_host_timer_slot(timer_index);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013498 return ret;
Peter Maydellc0659762014-08-09 15:42:32 +010013499 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013500 }
13501
13502 ret = get_errno(timer_create(clkid, phost_sevp, phtimer));
13503 if (ret) {
Peter Maydell9e598992022-07-25 12:00:35 +010013504 free_host_timer_slot(timer_index);
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013505 } else {
Alexander Grafaecc8862014-11-10 21:33:03 +010013506 if (put_user(TIMER_MAGIC | timer_index, arg3, target_timer_t)) {
Peter Maydell9e598992022-07-25 12:00:35 +010013507 timer_delete(*phtimer);
13508 free_host_timer_slot(timer_index);
Richard Henderson2852aaf2018-08-18 12:01:06 -070013509 return -TARGET_EFAULT;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013510 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013511 }
13512 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013513 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013514 }
13515#endif
13516
13517#ifdef TARGET_NR_timer_settime
13518 case TARGET_NR_timer_settime:
13519 {
13520 /* args: timer_t timerid, int flags, const struct itimerspec *new_value,
13521 * struct itimerspec * old_value */
Alexander Grafaecc8862014-11-10 21:33:03 +010013522 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020013523
Alexander Grafaecc8862014-11-10 21:33:03 +010013524 if (timerid < 0) {
13525 ret = timerid;
13526 } else if (arg3 == 0) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013527 ret = -TARGET_EINVAL;
13528 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020013529 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013530 struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
13531
Marc-André Lureau40c80b52017-01-19 10:15:32 -050013532 if (target_to_host_itimerspec(&hspec_new, arg3)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013533 return -TARGET_EFAULT;
Marc-André Lureau40c80b52017-01-19 10:15:32 -050013534 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013535 ret = get_errno(
13536 timer_settime(htimer, arg2, &hspec_new, &hspec_old));
Marc-André Lureau40c80b52017-01-19 10:15:32 -050013537 if (arg4 && host_to_target_itimerspec(arg4, &hspec_old)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013538 return -TARGET_EFAULT;
Marc-André Lureau40c80b52017-01-19 10:15:32 -050013539 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013540 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013541 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013542 }
13543#endif
13544
Filip Bozuta828cb3a2020-07-22 17:34:21 +020013545#ifdef TARGET_NR_timer_settime64
13546 case TARGET_NR_timer_settime64:
13547 {
13548 target_timer_t timerid = get_timer_id(arg1);
13549
13550 if (timerid < 0) {
13551 ret = timerid;
13552 } else if (arg3 == 0) {
13553 ret = -TARGET_EINVAL;
13554 } else {
13555 timer_t htimer = g_posix_timers[timerid];
13556 struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
13557
13558 if (target_to_host_itimerspec64(&hspec_new, arg3)) {
13559 return -TARGET_EFAULT;
13560 }
13561 ret = get_errno(
13562 timer_settime(htimer, arg2, &hspec_new, &hspec_old));
13563 if (arg4 && host_to_target_itimerspec64(arg4, &hspec_old)) {
13564 return -TARGET_EFAULT;
13565 }
13566 }
13567 return ret;
13568 }
13569#endif
13570
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013571#ifdef TARGET_NR_timer_gettime
13572 case TARGET_NR_timer_gettime:
13573 {
13574 /* args: timer_t timerid, struct itimerspec *curr_value */
Alexander Grafaecc8862014-11-10 21:33:03 +010013575 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020013576
Alexander Grafaecc8862014-11-10 21:33:03 +010013577 if (timerid < 0) {
13578 ret = timerid;
13579 } else if (!arg2) {
13580 ret = -TARGET_EFAULT;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013581 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020013582 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013583 struct itimerspec hspec;
13584 ret = get_errno(timer_gettime(htimer, &hspec));
13585
13586 if (host_to_target_itimerspec(arg2, &hspec)) {
13587 ret = -TARGET_EFAULT;
13588 }
13589 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013590 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013591 }
13592#endif
13593
Filip Bozuta828cb3a2020-07-22 17:34:21 +020013594#ifdef TARGET_NR_timer_gettime64
13595 case TARGET_NR_timer_gettime64:
13596 {
13597 /* args: timer_t timerid, struct itimerspec64 *curr_value */
13598 target_timer_t timerid = get_timer_id(arg1);
13599
13600 if (timerid < 0) {
13601 ret = timerid;
13602 } else if (!arg2) {
13603 ret = -TARGET_EFAULT;
13604 } else {
13605 timer_t htimer = g_posix_timers[timerid];
13606 struct itimerspec hspec;
13607 ret = get_errno(timer_gettime(htimer, &hspec));
13608
13609 if (host_to_target_itimerspec64(arg2, &hspec)) {
13610 ret = -TARGET_EFAULT;
13611 }
13612 }
13613 return ret;
13614 }
13615#endif
13616
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013617#ifdef TARGET_NR_timer_getoverrun
13618 case TARGET_NR_timer_getoverrun:
13619 {
13620 /* args: timer_t timerid */
Alexander Grafaecc8862014-11-10 21:33:03 +010013621 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020013622
Alexander Grafaecc8862014-11-10 21:33:03 +010013623 if (timerid < 0) {
13624 ret = timerid;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013625 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020013626 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013627 ret = get_errno(timer_getoverrun(htimer));
13628 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013629 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013630 }
13631#endif
13632
13633#ifdef TARGET_NR_timer_delete
13634 case TARGET_NR_timer_delete:
13635 {
13636 /* args: timer_t timerid */
Alexander Grafaecc8862014-11-10 21:33:03 +010013637 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020013638
Alexander Grafaecc8862014-11-10 21:33:03 +010013639 if (timerid < 0) {
13640 ret = timerid;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013641 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020013642 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013643 ret = get_errno(timer_delete(htimer));
Peter Maydell9e598992022-07-25 12:00:35 +010013644 free_host_timer_slot(timerid);
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013645 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013646 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013647 }
13648#endif
13649
Riku Voipio51834342014-06-22 11:25:42 +010013650#if defined(TARGET_NR_timerfd_create) && defined(CONFIG_TIMERFD)
13651 case TARGET_NR_timerfd_create:
Mathis Mariond759a622023-02-20 09:58:19 +010013652 ret = get_errno(timerfd_create(arg1,
13653 target_to_host_bitmask(arg2, fcntl_flags_tbl)));
13654 if (ret >= 0) {
13655 fd_trans_register(ret, &target_timerfd_trans);
13656 }
13657 return ret;
Riku Voipio51834342014-06-22 11:25:42 +010013658#endif
13659
13660#if defined(TARGET_NR_timerfd_gettime) && defined(CONFIG_TIMERFD)
13661 case TARGET_NR_timerfd_gettime:
13662 {
13663 struct itimerspec its_curr;
13664
13665 ret = get_errno(timerfd_gettime(arg1, &its_curr));
13666
13667 if (arg2 && host_to_target_itimerspec(arg2, &its_curr)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013668 return -TARGET_EFAULT;
Riku Voipio51834342014-06-22 11:25:42 +010013669 }
13670 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013671 return ret;
Riku Voipio51834342014-06-22 11:25:42 +010013672#endif
13673
Filip Bozuta828cb3a2020-07-22 17:34:21 +020013674#if defined(TARGET_NR_timerfd_gettime64) && defined(CONFIG_TIMERFD)
13675 case TARGET_NR_timerfd_gettime64:
13676 {
13677 struct itimerspec its_curr;
13678
13679 ret = get_errno(timerfd_gettime(arg1, &its_curr));
13680
13681 if (arg2 && host_to_target_itimerspec64(arg2, &its_curr)) {
13682 return -TARGET_EFAULT;
13683 }
13684 }
13685 return ret;
13686#endif
13687
Riku Voipio51834342014-06-22 11:25:42 +010013688#if defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD)
13689 case TARGET_NR_timerfd_settime:
13690 {
13691 struct itimerspec its_new, its_old, *p_new;
13692
13693 if (arg3) {
13694 if (target_to_host_itimerspec(&its_new, arg3)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013695 return -TARGET_EFAULT;
Riku Voipio51834342014-06-22 11:25:42 +010013696 }
13697 p_new = &its_new;
13698 } else {
13699 p_new = NULL;
13700 }
13701
13702 ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
13703
13704 if (arg4 && host_to_target_itimerspec(arg4, &its_old)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013705 return -TARGET_EFAULT;
Riku Voipio51834342014-06-22 11:25:42 +010013706 }
13707 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013708 return ret;
Riku Voipio51834342014-06-22 11:25:42 +010013709#endif
13710
Filip Bozuta828cb3a2020-07-22 17:34:21 +020013711#if defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)
13712 case TARGET_NR_timerfd_settime64:
13713 {
13714 struct itimerspec its_new, its_old, *p_new;
13715
13716 if (arg3) {
13717 if (target_to_host_itimerspec64(&its_new, arg3)) {
13718 return -TARGET_EFAULT;
13719 }
13720 p_new = &its_new;
13721 } else {
13722 p_new = NULL;
13723 }
13724
13725 ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
13726
13727 if (arg4 && host_to_target_itimerspec64(arg4, &its_old)) {
13728 return -TARGET_EFAULT;
13729 }
13730 }
13731 return ret;
13732#endif
13733
Paul Burtonab31cda2014-06-22 11:25:43 +010013734#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
13735 case TARGET_NR_ioprio_get:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013736 return get_errno(ioprio_get(arg1, arg2));
Paul Burtonab31cda2014-06-22 11:25:43 +010013737#endif
13738
13739#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
13740 case TARGET_NR_ioprio_set:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013741 return get_errno(ioprio_set(arg1, arg2, arg3));
Paul Burtonab31cda2014-06-22 11:25:43 +010013742#endif
13743
Riku Voipio9af5c902014-08-12 15:58:57 +030013744#if defined(TARGET_NR_setns) && defined(CONFIG_SETNS)
13745 case TARGET_NR_setns:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013746 return get_errno(setns(arg1, arg2));
Riku Voipio9af5c902014-08-12 15:58:57 +030013747#endif
13748#if defined(TARGET_NR_unshare) && defined(CONFIG_SETNS)
13749 case TARGET_NR_unshare:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013750 return get_errno(unshare(arg1));
Riku Voipio9af5c902014-08-12 15:58:57 +030013751#endif
Laurent Vivier2f147882016-09-25 22:20:20 +020013752#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
13753 case TARGET_NR_kcmp:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013754 return get_errno(kcmp(arg1, arg2, arg3, arg4, arg5));
Laurent Vivier2f147882016-09-25 22:20:20 +020013755#endif
Richard Hendersonfa97e382018-07-18 13:06:48 -070013756#ifdef TARGET_NR_swapcontext
13757 case TARGET_NR_swapcontext:
13758 /* PowerPC specific. */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013759 return do_swapcontext(cpu_env, arg1, arg2, arg3);
Richard Hendersonfa97e382018-07-18 13:06:48 -070013760#endif
Shu-Chun Weng9bdfa4d2019-08-19 11:09:47 -070013761#ifdef TARGET_NR_memfd_create
13762 case TARGET_NR_memfd_create:
13763 p = lock_user_string(arg1);
13764 if (!p) {
13765 return -TARGET_EFAULT;
13766 }
13767 ret = get_errno(memfd_create(p, arg2));
13768 fd_trans_unregister(ret);
13769 unlock_user(p, arg1, 0);
13770 return ret;
13771#endif
Andreas Schwab85004762019-05-13 11:02:53 +020013772#if defined TARGET_NR_membarrier && defined __NR_membarrier
13773 case TARGET_NR_membarrier:
13774 return get_errno(membarrier(arg1, arg2));
13775#endif
Riku Voipio9af5c902014-08-12 15:58:57 +030013776
Andreas Schwab84946452020-11-12 12:45:16 +010013777#if defined(TARGET_NR_copy_file_range) && defined(__NR_copy_file_range)
13778 case TARGET_NR_copy_file_range:
13779 {
13780 loff_t inoff, outoff;
13781 loff_t *pinoff = NULL, *poutoff = NULL;
13782
13783 if (arg2) {
13784 if (get_user_u64(inoff, arg2)) {
13785 return -TARGET_EFAULT;
13786 }
13787 pinoff = &inoff;
13788 }
13789 if (arg4) {
13790 if (get_user_u64(outoff, arg4)) {
13791 return -TARGET_EFAULT;
13792 }
13793 poutoff = &outoff;
13794 }
Giuseppe Musacchio0fa259d2021-05-03 19:41:59 +020013795 /* Do not sign-extend the count parameter. */
Andreas Schwab84946452020-11-12 12:45:16 +010013796 ret = get_errno(safe_copy_file_range(arg1, pinoff, arg3, poutoff,
Giuseppe Musacchio0fa259d2021-05-03 19:41:59 +020013797 (abi_ulong)arg5, arg6));
Andreas Schwab84946452020-11-12 12:45:16 +010013798 if (!is_error(ret) && ret > 0) {
13799 if (arg2) {
13800 if (put_user_u64(inoff, arg2)) {
13801 return -TARGET_EFAULT;
13802 }
13803 }
13804 if (arg4) {
13805 if (put_user_u64(outoff, arg4)) {
13806 return -TARGET_EFAULT;
13807 }
13808 }
13809 }
13810 }
13811 return ret;
13812#endif
13813
YAMAMOTO Takashie10fbe82021-05-31 14:50:12 +090013814#if defined(TARGET_NR_pivot_root)
13815 case TARGET_NR_pivot_root:
13816 {
13817 void *p2;
13818 p = lock_user_string(arg1); /* new_root */
13819 p2 = lock_user_string(arg2); /* put_old */
13820 if (!p || !p2) {
13821 ret = -TARGET_EFAULT;
13822 } else {
13823 ret = get_errno(pivot_root(p, p2));
13824 }
13825 unlock_user(p2, arg2, 0);
13826 unlock_user(p, arg1, 0);
13827 }
13828 return ret;
13829#endif
13830
Robbin Ehn9e1c7d92023-06-19 10:24:03 +020013831#if defined(TARGET_NR_riscv_hwprobe)
13832 case TARGET_NR_riscv_hwprobe:
13833 return do_riscv_hwprobe(cpu_env, arg1, arg2, arg3, arg4, arg5);
13834#endif
13835
bellard31e31b82003-02-18 22:55:36 +000013836 default:
Philippe Mathieu-Daudé122f9c82018-07-06 12:51:25 -030013837 qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013838 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +000013839 }
bellard31e31b82003-02-18 22:55:36 +000013840 return ret;
13841}
Richard Hendersondc1ce182018-08-18 12:01:04 -070013842
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +020013843abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1,
Richard Hendersondc1ce182018-08-18 12:01:04 -070013844 abi_long arg2, abi_long arg3, abi_long arg4,
13845 abi_long arg5, abi_long arg6, abi_long arg7,
13846 abi_long arg8)
13847{
Richard Henderson29a0af62019-03-22 16:07:18 -070013848 CPUState *cpu = env_cpu(cpu_env);
Richard Hendersondc1ce182018-08-18 12:01:04 -070013849 abi_long ret;
13850
13851#ifdef DEBUG_ERESTARTSYS
13852 /* Debug-only code for exercising the syscall-restart code paths
13853 * in the per-architecture cpu main loops: restart every syscall
13854 * the guest makes once before letting it through.
13855 */
13856 {
13857 static bool flag;
13858 flag = !flag;
13859 if (flag) {
Richard Hendersonaf254a22021-11-22 19:47:33 +010013860 return -QEMU_ERESTARTSYS;
Richard Hendersondc1ce182018-08-18 12:01:04 -070013861 }
13862 }
13863#endif
13864
Emilio G. Cotac36f7a62018-10-21 13:27:44 -040013865 record_syscall_start(cpu, num, arg1,
13866 arg2, arg3, arg4, arg5, arg6, arg7, arg8);
Richard Hendersondc1ce182018-08-18 12:01:04 -070013867
Josh Kunz4b25a502020-02-03 18:54:14 -080013868 if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
Filip Bozutae400e112020-08-11 18:45:49 +020013869 print_syscall(cpu_env, num, arg1, arg2, arg3, arg4, arg5, arg6);
Josh Kunz4b25a502020-02-03 18:54:14 -080013870 }
13871
13872 ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4,
13873 arg5, arg6, arg7, arg8);
13874
13875 if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
Filip Bozutae400e112020-08-11 18:45:49 +020013876 print_syscall_ret(cpu_env, num, ret, arg1, arg2,
13877 arg3, arg4, arg5, arg6);
Richard Hendersondc1ce182018-08-18 12:01:04 -070013878 }
13879
Emilio G. Cotac36f7a62018-10-21 13:27:44 -040013880 record_syscall_return(cpu, num, ret);
Richard Hendersondc1ce182018-08-18 12:01:04 -070013881 return ret;
13882}