blob: 1e868e9b0e279be7c827d04762bb16fc6ee5b4c1 [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"
bellard31e31b82003-02-18 22:55:36 +000025#include <elf.h>
26#include <endian.h>
John Spencerc56dc772012-12-10 07:59:46 +010027#include <grp.h>
thsd08d3bb2007-03-19 13:09:22 +000028#include <sys/ipc.h>
29#include <sys/msg.h>
bellard31e31b82003-02-18 22:55:36 +000030#include <sys/wait.h>
bellard31e31b82003-02-18 22:55:36 +000031#include <sys/mount.h>
John Spencer586b0be2012-12-26 00:49:49 +010032#include <sys/file.h>
33#include <sys/fsuid.h>
34#include <sys/personality.h>
ths39b9aae2007-02-11 18:36:44 +000035#include <sys/prctl.h>
bellard31e31b82003-02-18 22:55:36 +000036#include <sys/resource.h>
bellard31e31b82003-02-18 22:55:36 +000037#include <sys/swap.h>
Peter Maydelle0eb2102014-03-17 12:15:35 +000038#include <linux/capability.h>
bellard31e31b82003-02-18 22:55:36 +000039#include <sched.h>
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +020040#include <sys/timex.h>
bellard31e31b82003-02-18 22:55:36 +000041#include <sys/socket.h>
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +020042#include <linux/sockios.h>
aurel32607175e2009-04-15 16:11:59 +000043#include <sys/un.h>
bellard31e31b82003-02-18 22:55:36 +000044#include <sys/uio.h>
Felix Janda0839f112016-09-30 19:40:21 -040045#include <poll.h>
bellard32f36bc2003-03-30 21:29:48 +000046#include <sys/times.h>
bellard8853f862004-02-22 14:57:26 +000047#include <sys/shm.h>
thsfa294812007-02-02 22:05:00 +000048#include <sys/sem.h>
bellard56c8f682005-11-28 22:28:41 +000049#include <sys/statfs.h>
bellardebc05482003-09-30 21:08:41 +000050#include <utime.h>
bellarda5448a72004-06-19 16:59:03 +000051#include <sys/sysinfo.h>
Laurent Viviere36800c2015-10-02 14:48:09 +020052#include <sys/signalfd.h>
bellard72f03902003-02-18 23:33:18 +000053//#include <sys/user.h>
Shu-Chun Weng22db1212020-12-18 11:32:12 -080054#include <netinet/in.h>
bellard8853f862004-02-22 14:57:26 +000055#include <netinet/ip.h>
bellard7854b052003-03-29 17:22:23 +000056#include <netinet/tcp.h>
Shu-Chun Wengfe51b0a2020-12-18 11:32:11 -080057#include <netinet/udp.h>
Laurent Vivier86fcd942011-03-30 01:35:23 +020058#include <linux/wireless.h>
Jing Huang920394d2012-07-24 13:59:23 +000059#include <linux/icmp.h>
Helge Delleree1ac3a2017-02-18 23:31:30 +010060#include <linux/icmpv6.h>
Shu-Chun Weng6addf062020-09-28 18:48:01 -070061#include <linux/if_tun.h>
Shu-Chun Weng22db1212020-12-18 11:32:12 -080062#include <linux/in6.h>
Helge Delleree1ac3a2017-02-18 23:31:30 +010063#include <linux/errqueue.h>
Marco A L Barbosad6d6d6f2017-10-05 10:55:30 -030064#include <linux/random.h>
Riku Voipiod80a1902014-10-01 16:05:46 +030065#ifdef CONFIG_TIMERFD
66#include <sys/timerfd.h>
67#endif
Riku Voipioc2882b92009-08-12 15:08:24 +030068#ifdef CONFIG_EVENTFD
69#include <sys/eventfd.h>
70#endif
Peter Maydell3b6edd12011-02-15 18:35:05 +000071#ifdef CONFIG_EPOLL
72#include <sys/epoll.h>
73#endif
An-Cheng Huanga790ae32011-08-09 12:34:06 -070074#ifdef CONFIG_ATTR
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010075#include "qemu/xattr.h"
An-Cheng Huanga790ae32011-08-09 12:34:06 -070076#endif
Peter Maydella8fd1ab2013-02-08 07:31:55 +000077#ifdef CONFIG_SENDFILE
78#include <sys/sendfile.h>
79#endif
Thomas Huth4a9d5f82020-11-18 18:10:51 +010080#ifdef HAVE_SYS_KCOV_H
Aleksandar Markovicbd27e672020-01-16 23:49:50 +010081#include <sys/kcov.h>
82#endif
bellard31e31b82003-02-18 22:55:36 +000083
84#define termios host_termios
85#define winsize host_winsize
86#define termio host_termio
bellard04369ff2003-03-20 22:33:23 +000087#define sgttyb host_sgttyb /* same as target */
88#define tchars host_tchars /* same as target */
89#define ltchars host_ltchars /* same as target */
bellard31e31b82003-02-18 22:55:36 +000090
91#include <linux/termios.h>
92#include <linux/unistd.h>
bellard31e31b82003-02-18 22:55:36 +000093#include <linux/cdrom.h>
94#include <linux/hdreg.h>
95#include <linux/soundcard.h>
bellard19b84f32003-05-08 15:41:49 +000096#include <linux/kd.h>
balrog8fbd6b52008-09-20 03:03:09 +000097#include <linux/mtio.h>
Martin Mohring350d1772009-05-04 21:21:41 +030098#include <linux/fs.h>
Yunqiang Suab22b4d2019-09-04 14:59:24 +020099#include <linux/fd.h>
Peter Maydelldace20d2011-01-10 13:11:24 +0000100#if defined(CONFIG_FIEMAP)
Peter Maydell285da2b2011-01-06 15:04:18 +0000101#include <linux/fiemap.h>
Peter Maydelldace20d2011-01-10 13:11:24 +0000102#endif
Ulrich Hechtf7680a52009-10-16 17:00:44 +0200103#include <linux/fb.h>
Cortland Tölva6c753a62018-10-08 09:35:20 -0700104#if defined(CONFIG_USBFS)
105#include <linux/usbdevice_fs.h>
Cortland Tölvaa1333672018-10-08 09:35:21 -0700106#include <linux/usb/ch9.h>
Cortland Tölva6c753a62018-10-08 09:35:20 -0700107#endif
Ulrich Hechtf7680a52009-10-16 17:00:44 +0200108#include <linux/vt.h>
Alexander Graf56e904e2012-01-31 18:42:06 +0100109#include <linux/dm-ioctl.h>
Laurent Vivierc07ecc62013-01-07 11:40:06 +0000110#include <linux/reboot.h>
Laurent Vivier7ff7b662013-07-02 14:04:12 +0100111#include <linux/route.h>
Laurent Vivierf57d4192013-08-30 01:46:41 +0200112#include <linux/filter.h>
Andreas Färberfff8c532014-01-18 07:38:30 +0100113#include <linux/blkpg.h>
Laurent Viviera82ea932016-06-27 00:18:22 +0200114#include <netpacket/packet.h>
Laurent Vivier6c5b5642016-05-22 18:56:19 +0200115#include <linux/netlink.h>
Yunqiang Suf31dddd2019-06-19 16:17:11 +0200116#include <linux/if_alg.h>
Filip Bozuta68365f92020-01-15 20:36:35 +0100117#include <linux/rtc.h>
Filip Bozuta1c4c6fc2020-01-15 20:36:41 +0100118#include <sound/asound.h>
Thomas Huth48f670e2020-11-18 18:10:52 +0100119#ifdef HAVE_BTRFS_H
Filip Bozutad6092e02020-08-23 21:50:07 +0200120#include <linux/btrfs.h>
121#endif
Chen Gange865b972020-06-05 09:32:21 +0800122#ifdef HAVE_DRM_H
123#include <libdrm/drm.h>
Chen Gang913b03c2020-08-02 21:39:38 +0800124#include <libdrm/i915_drm.h>
Chen Gange865b972020-06-05 09:32:21 +0800125#endif
pbrookd7e40362008-05-23 16:06:43 +0000126#include "linux_loop.h"
Riku Voipio18cb0082014-02-19 12:59:58 +0200127#include "uname.h"
bellard31e31b82003-02-18 22:55:36 +0000128
bellard3ef693a2003-03-23 20:17:16 +0000129#include "qemu.h"
Peter Maydell3b249d22021-09-08 16:44:03 +0100130#include "user-internals.h"
Peter Maydella44d57a2021-09-08 16:43:58 +0100131#include "strace.h"
Peter Maydell2113aed2021-09-08 16:43:59 +0100132#include "signal-common.h"
Peter Maydell3ad0a762021-09-08 16:44:00 +0100133#include "loader.h"
Peter Maydell5423e6d2021-09-08 16:44:01 +0100134#include "user-mmap.h"
Richard Hendersonbbf15aa2021-11-17 16:14:00 +0100135#include "user/safe-syscall.h"
Richard Henderson5ebdd772019-03-14 13:10:53 -0700136#include "qemu/guest-random.h"
Alex Bennée01ef6b92020-04-03 20:11:46 +0100137#include "qemu/selfmap.h"
Emilio G. Cotac36f7a62018-10-21 13:27:44 -0400138#include "user/syscall-trace.h"
Richard Henderson5da40632021-11-17 15:46:05 +0100139#include "special-errno.h"
Richard Henderson51977e22019-03-12 19:22:20 -0700140#include "qapi/error.h"
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200141#include "fd-trans.h"
Philippe Mathieu-Daudédcb32f12020-01-01 12:23:00 +0100142#include "tcg/tcg.h"
Helge Dellerbd5ccd62022-10-24 22:18:09 +0200143#include "cpu_loop-common.h"
bellard31e31b82003-02-18 22:55:36 +0000144
Peter Maydell5ea2fc82016-08-02 18:41:27 +0100145#ifndef CLONE_IO
146#define CLONE_IO 0x80000000 /* Clone io context */
147#endif
148
149/* We can't directly call the host clone syscall, because this will
150 * badly confuse libc (breaking mutexes, for example). So we must
151 * divide clone flags into:
152 * * flag combinations that look like pthread_create()
153 * * flag combinations that look like fork()
154 * * flags we can implement within QEMU itself
155 * * flags we can't support and will return an error for
156 */
157/* For thread creation, all these flags must be present; for
158 * fork, none must be present.
159 */
160#define CLONE_THREAD_FLAGS \
161 (CLONE_VM | CLONE_FS | CLONE_FILES | \
162 CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM)
163
164/* These flags are ignored:
165 * CLONE_DETACHED is now ignored by the kernel;
166 * CLONE_IO is just an optimisation hint to the I/O scheduler
167 */
168#define CLONE_IGNORED_FLAGS \
169 (CLONE_DETACHED | CLONE_IO)
170
171/* Flags for fork which we can implement within QEMU itself */
172#define CLONE_OPTIONAL_FORK_FLAGS \
173 (CLONE_SETTLS | CLONE_PARENT_SETTID | \
174 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID)
175
176/* Flags for thread creation which we can implement within QEMU itself */
177#define CLONE_OPTIONAL_THREAD_FLAGS \
178 (CLONE_SETTLS | CLONE_PARENT_SETTID | \
179 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | CLONE_PARENT)
180
181#define CLONE_INVALID_FORK_FLAGS \
182 (~(CSIGNAL | CLONE_OPTIONAL_FORK_FLAGS | CLONE_IGNORED_FLAGS))
183
184#define CLONE_INVALID_THREAD_FLAGS \
185 (~(CSIGNAL | CLONE_THREAD_FLAGS | CLONE_OPTIONAL_THREAD_FLAGS | \
186 CLONE_IGNORED_FLAGS))
187
188/* CLONE_VFORK is special cased early in do_fork(). The other flag bits
189 * have almost all been allocated. We cannot support any of
190 * CLONE_NEWNS, CLONE_NEWCGROUP, CLONE_NEWUTS, CLONE_NEWIPC,
191 * CLONE_NEWUSER, CLONE_NEWPID, CLONE_NEWNET, CLONE_PTRACE, CLONE_UNTRACED.
192 * The checks against the invalid thread masks above will catch these.
193 * (The one remaining unallocated bit is 0x1000 which used to be CLONE_PID.)
194 */
pbrook30813ce2008-06-02 15:45:44 +0000195
Timothy E Baldwin71a8f7f2016-05-12 18:47:45 +0100196/* Define DEBUG_ERESTARTSYS to force every syscall to be restarted
197 * once. This exercises the codepaths for restart.
198 */
199//#define DEBUG_ERESTARTSYS
bellard31e31b82003-02-18 22:55:36 +0000200
bellard1a9353d2003-03-16 20:28:50 +0000201//#include <linux/msdos_fs.h>
Richard Henderson540a7362021-11-14 11:35:37 +0100202#define VFAT_IOCTL_READDIR_BOTH \
203 _IOC(_IOC_READ, 'r', 1, (sizeof(struct linux_dirent) + 256) * 2)
204#define VFAT_IOCTL_READDIR_SHORT \
205 _IOC(_IOC_READ, 'r', 2, (sizeof(struct linux_dirent) + 256) * 2)
bellard1a9353d2003-03-16 20:28:50 +0000206
bellard70a194b2003-08-11 22:20:16 +0000207#undef _syscall0
208#undef _syscall1
209#undef _syscall2
210#undef _syscall3
211#undef _syscall4
212#undef _syscall5
bellard83fcb512006-06-14 13:37:16 +0000213#undef _syscall6
bellard70a194b2003-08-11 22:20:16 +0000214
bellard83fcb512006-06-14 13:37:16 +0000215#define _syscall0(type,name) \
blueswir18fcd3692008-08-17 20:26:25 +0000216static type name (void) \
bellard83fcb512006-06-14 13:37:16 +0000217{ \
218 return syscall(__NR_##name); \
bellard70a194b2003-08-11 22:20:16 +0000219}
220
bellard83fcb512006-06-14 13:37:16 +0000221#define _syscall1(type,name,type1,arg1) \
blueswir18fcd3692008-08-17 20:26:25 +0000222static type name (type1 arg1) \
bellard83fcb512006-06-14 13:37:16 +0000223{ \
224 return syscall(__NR_##name, arg1); \
bellard70a194b2003-08-11 22:20:16 +0000225}
226
bellard83fcb512006-06-14 13:37:16 +0000227#define _syscall2(type,name,type1,arg1,type2,arg2) \
blueswir18fcd3692008-08-17 20:26:25 +0000228static type name (type1 arg1,type2 arg2) \
bellard83fcb512006-06-14 13:37:16 +0000229{ \
230 return syscall(__NR_##name, arg1, arg2); \
bellard70a194b2003-08-11 22:20:16 +0000231}
232
bellard83fcb512006-06-14 13:37:16 +0000233#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
blueswir18fcd3692008-08-17 20:26:25 +0000234static type name (type1 arg1,type2 arg2,type3 arg3) \
bellard83fcb512006-06-14 13:37:16 +0000235{ \
236 return syscall(__NR_##name, arg1, arg2, arg3); \
bellard70a194b2003-08-11 22:20:16 +0000237}
238
bellard83fcb512006-06-14 13:37:16 +0000239#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
blueswir18fcd3692008-08-17 20:26:25 +0000240static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
bellard83fcb512006-06-14 13:37:16 +0000241{ \
242 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
bellard70a194b2003-08-11 22:20:16 +0000243}
244
bellard83fcb512006-06-14 13:37:16 +0000245#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
246 type5,arg5) \
blueswir18fcd3692008-08-17 20:26:25 +0000247static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
bellard83fcb512006-06-14 13:37:16 +0000248{ \
249 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
bellard70a194b2003-08-11 22:20:16 +0000250}
bellard83fcb512006-06-14 13:37:16 +0000251
252
253#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
254 type5,arg5,type6,arg6) \
blueswir18fcd3692008-08-17 20:26:25 +0000255static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
256 type6 arg6) \
bellard83fcb512006-06-14 13:37:16 +0000257{ \
258 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
259}
260
bellard70a194b2003-08-11 22:20:16 +0000261
bellard31e31b82003-02-18 22:55:36 +0000262#define __NR_sys_uname __NR_uname
bellard72f03902003-02-18 23:33:18 +0000263#define __NR_sys_getcwd1 __NR_getcwd
bellard72f03902003-02-18 23:33:18 +0000264#define __NR_sys_getdents __NR_getdents
bellarddab2ed92003-03-22 15:23:14 +0000265#define __NR_sys_getdents64 __NR_getdents64
thsc6cda172007-10-09 03:42:34 +0000266#define __NR_sys_getpriority __NR_getpriority
bellard66fb9762003-03-23 01:06:05 +0000267#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +0200268#define __NR_sys_rt_tgsigqueueinfo __NR_rt_tgsigqueueinfo
ths7494b0f2007-02-11 18:26:53 +0000269#define __NR_sys_syslog __NR_syslog
Alistair Francis14690292020-03-18 15:47:01 -0700270#if defined(__NR_futex)
271# define __NR_sys_futex __NR_futex
272#endif
273#if defined(__NR_futex_time64)
274# define __NR_sys_futex_time64 __NR_futex_time64
275#endif
Aleksandar Rikaloefa92182019-06-28 12:43:34 +0200276#define __NR_sys_statx __NR_statx
bellard31e31b82003-02-18 22:55:36 +0000277
Peter Maydellb1cef6d2018-01-25 16:19:49 +0000278#if defined(__alpha__) || defined(__x86_64__) || defined(__s390x__)
bellard9af9eaa2003-04-07 21:34:41 +0000279#define __NR__llseek __NR_lseek
280#endif
281
James Hogana29e5ba2014-03-25 21:51:08 +0000282/* Newer kernel ports have llseek() instead of _llseek() */
283#if defined(TARGET_NR_llseek) && !defined(TARGET_NR__llseek)
284#define TARGET_NR__llseek TARGET_NR_llseek
285#endif
286
Helge Deller78721302021-02-10 07:12:14 +0100287/* some platforms need to mask more bits than just TARGET_O_NONBLOCK */
288#ifndef TARGET_O_NONBLOCK_MASK
289#define TARGET_O_NONBLOCK_MASK TARGET_O_NONBLOCK
290#endif
291
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +0000292#define __NR_sys_gettid __NR_gettid
293_syscall0(int, sys_gettid)
Peter Maydell2b3f64c2018-04-19 13:57:40 +0100294
295/* For the 64-bit guest on 32-bit host case we must emulate
296 * getdents using getdents64, because otherwise the host
297 * might hand us back more dirent records than we can fit
298 * into the guest buffer after structure format conversion.
299 * Otherwise we emulate getdents with getdents if the host has it.
300 */
301#if defined(__NR_getdents) && HOST_LONG_BITS >= TARGET_ABI_BITS
302#define EMULATE_GETDENTS_WITH_GETDENTS
303#endif
304
305#if defined(TARGET_NR_getdents) && defined(EMULATE_GETDENTS_WITH_GETDENTS)
aurel323b3f24a2009-04-15 16:12:13 +0000306_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
Peter Maydell3307e232013-06-12 16:20:21 +0100307#endif
Peter Maydell2b3f64c2018-04-19 13:57:40 +0100308#if (defined(TARGET_NR_getdents) && \
309 !defined(EMULATE_GETDENTS_WITH_GETDENTS)) || \
Peter Maydell3307e232013-06-12 16:20:21 +0100310 (defined(TARGET_NR_getdents64) && defined(__NR_getdents64))
aurel323b3f24a2009-04-15 16:12:13 +0000311_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
312#endif
Richard Hendersond35b2612010-06-04 12:14:10 -0700313#if defined(TARGET_NR__llseek) && defined(__NR_llseek)
aurel323b3f24a2009-04-15 16:12:13 +0000314_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
315 loff_t *, res, uint, wh);
316#endif
Miloš Stojanovićc1a402a2017-05-15 16:59:45 +0200317_syscall3(int, sys_rt_sigqueueinfo, pid_t, pid, int, sig, siginfo_t *, uinfo)
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +0200318_syscall4(int, sys_rt_tgsigqueueinfo, pid_t, pid, pid_t, tid, int, sig,
319 siginfo_t *, uinfo)
aurel323b3f24a2009-04-15 16:12:13 +0000320_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
aurel323b3f24a2009-04-15 16:12:13 +0000321#ifdef __NR_exit_group
322_syscall1(int,exit_group,int,error_code)
323#endif
Helge Delleraf804f32022-10-25 04:34:14 +0200324#if defined(__NR_close_range) && defined(TARGET_NR_close_range)
325#define __NR_sys_close_range __NR_close_range
326_syscall3(int,sys_close_range,int,first,int,last,int,flags)
327#ifndef CLOSE_RANGE_CLOEXEC
328#define CLOSE_RANGE_CLOEXEC (1U << 2)
329#endif
330#endif
Alistair Francis14690292020-03-18 15:47:01 -0700331#if defined(__NR_futex)
aurel323b3f24a2009-04-15 16:12:13 +0000332_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
333 const struct timespec *,timeout,int *,uaddr2,int,val3)
334#endif
Alistair Francis14690292020-03-18 15:47:01 -0700335#if defined(__NR_futex_time64)
336_syscall6(int,sys_futex_time64,int *,uaddr,int,op,int,val,
337 const struct timespec *,timeout,int *,uaddr2,int,val3)
338#endif
Helge Dellercc054c62022-09-18 21:45:46 +0200339#if defined(__NR_pidfd_open) && defined(TARGET_NR_pidfd_open)
340_syscall2(int, pidfd_open, pid_t, pid, unsigned int, flags);
341#endif
342#if defined(__NR_pidfd_send_signal) && defined(TARGET_NR_pidfd_send_signal)
343_syscall4(int, pidfd_send_signal, int, pidfd, int, sig, siginfo_t *, info,
344 unsigned int, flags);
345#endif
346#if defined(__NR_pidfd_getfd) && defined(TARGET_NR_pidfd_getfd)
347_syscall3(int, pidfd_getfd, int, pidfd, int, targetfd, unsigned int, flags);
348#endif
Mike Frysinger737de1d2011-02-07 01:05:55 -0500349#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
350_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
351 unsigned long *, user_mask_ptr);
352#define __NR_sys_sched_setaffinity __NR_sched_setaffinity
353_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
354 unsigned long *, user_mask_ptr);
Tonis Tiigi45ad7612022-01-04 20:18:18 -0800355/* sched_attr is not defined in glibc */
356struct sched_attr {
357 uint32_t size;
358 uint32_t sched_policy;
359 uint64_t sched_flags;
360 int32_t sched_nice;
361 uint32_t sched_priority;
362 uint64_t sched_runtime;
363 uint64_t sched_deadline;
364 uint64_t sched_period;
365 uint32_t sched_util_min;
366 uint32_t sched_util_max;
367};
368#define __NR_sys_sched_getattr __NR_sched_getattr
369_syscall4(int, sys_sched_getattr, pid_t, pid, struct sched_attr *, attr,
370 unsigned int, size, unsigned int, flags);
371#define __NR_sys_sched_setattr __NR_sched_setattr
372_syscall3(int, sys_sched_setattr, pid_t, pid, struct sched_attr *, attr,
373 unsigned int, flags);
Tonis Tiigi407a1192022-01-04 20:18:19 -0800374#define __NR_sys_sched_getscheduler __NR_sched_getscheduler
375_syscall1(int, sys_sched_getscheduler, pid_t, pid);
376#define __NR_sys_sched_setscheduler __NR_sched_setscheduler
377_syscall3(int, sys_sched_setscheduler, pid_t, pid, int, policy,
378 const struct sched_param *, param);
379#define __NR_sys_sched_getparam __NR_sched_getparam
380_syscall2(int, sys_sched_getparam, pid_t, pid,
381 struct sched_param *, param);
382#define __NR_sys_sched_setparam __NR_sched_setparam
383_syscall2(int, sys_sched_setparam, pid_t, pid,
384 const struct sched_param *, param);
Samuel Thibaultb827c3e2018-01-12 09:14:35 +0100385#define __NR_sys_getcpu __NR_getcpu
386_syscall3(int, sys_getcpu, unsigned *, cpu, unsigned *, node, void *, tcache);
Alexander Graf0f6b4d22011-09-27 14:39:42 +0200387_syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd,
388 void *, arg);
Peter Maydelle0eb2102014-03-17 12:15:35 +0000389_syscall2(int, capget, struct __user_cap_header_struct *, header,
390 struct __user_cap_data_struct *, data);
391_syscall2(int, capset, struct __user_cap_header_struct *, header,
392 struct __user_cap_data_struct *, data);
Paul Burtonab31cda2014-06-22 11:25:43 +0100393#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
394_syscall2(int, ioprio_get, int, which, int, who)
395#endif
396#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
397_syscall3(int, ioprio_set, int, which, int, who, int, ioprio)
398#endif
Laurent Vivierf894efd2016-02-21 10:56:23 +0100399#if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
400_syscall3(int, getrandom, void *, buf, size_t, buflen, unsigned int, flags)
401#endif
aurel323b3f24a2009-04-15 16:12:13 +0000402
Laurent Vivier2f147882016-09-25 22:20:20 +0200403#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
404_syscall5(int, kcmp, pid_t, pid1, pid_t, pid2, int, type,
405 unsigned long, idx1, unsigned long, idx2)
406#endif
407
Aleksandar Rikaloefa92182019-06-28 12:43:34 +0200408/*
409 * It is assumed that struct statx is architecture independent.
410 */
411#if defined(TARGET_NR_statx) && defined(__NR_statx)
412_syscall5(int, sys_statx, int, dirfd, const char *, pathname, int, flags,
413 unsigned int, mask, struct target_statx *, statxbuf)
414#endif
Andreas Schwab85004762019-05-13 11:02:53 +0200415#if defined(TARGET_NR_membarrier) && defined(__NR_membarrier)
416_syscall2(int, membarrier, int, cmd, int, flags)
417#endif
Aleksandar Rikaloefa92182019-06-28 12:43:34 +0200418
Philippe Mathieu-Daudé180d4ef2021-05-17 07:52:43 +0200419static const bitmask_transtbl fcntl_flags_tbl[] = {
aurel323b3f24a2009-04-15 16:12:13 +0000420 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
421 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
422 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
423 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
424 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
425 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
426 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
427 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
Richard Hendersonafc87632012-07-25 14:30:34 -0700428 { TARGET_O_SYNC, TARGET_O_DSYNC, O_SYNC, O_DSYNC, },
aurel323b3f24a2009-04-15 16:12:13 +0000429 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
430 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
431 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
432 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
aurel323b3f24a2009-04-15 16:12:13 +0000433#if defined(O_DIRECT)
434 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
435#endif
Richard Hendersonafc87632012-07-25 14:30:34 -0700436#if defined(O_NOATIME)
437 { TARGET_O_NOATIME, TARGET_O_NOATIME, O_NOATIME, O_NOATIME },
438#endif
439#if defined(O_CLOEXEC)
440 { TARGET_O_CLOEXEC, TARGET_O_CLOEXEC, O_CLOEXEC, O_CLOEXEC },
441#endif
442#if defined(O_PATH)
443 { TARGET_O_PATH, TARGET_O_PATH, O_PATH, O_PATH },
444#endif
Riku Voipio5f9cee42017-08-08 16:01:19 +0300445#if defined(O_TMPFILE)
446 { TARGET_O_TMPFILE, TARGET_O_TMPFILE, O_TMPFILE, O_TMPFILE },
447#endif
Richard Hendersonafc87632012-07-25 14:30:34 -0700448 /* Don't terminate the list prematurely on 64-bit host+guest. */
449#if TARGET_O_LARGEFILE != 0 || O_LARGEFILE != 0
450 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
451#endif
aurel323b3f24a2009-04-15 16:12:13 +0000452 { 0, 0, 0, 0 }
453};
454
Andreas Schwab0f6bb192020-07-23 12:27:13 +0200455_syscall2(int, sys_getcwd1, char *, buf, size_t, size)
aurel323b3f24a2009-04-15 16:12:13 +0000456
Filip Bozutacac46eb2020-08-25 00:30:50 +0200457#if defined(TARGET_NR_utimensat) || defined(TARGET_NR_utimensat_time64)
Peter Maydell700fa582016-07-18 11:47:55 +0100458#if defined(__NR_utimensat)
Peter Maydell1acae9f2013-07-02 14:04:12 +0100459#define __NR_sys_utimensat __NR_utimensat
ths9007f0e2007-09-25 17:50:37 +0000460_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
461 const struct timespec *,tsp,int,flags)
Peter Maydell1acae9f2013-07-02 14:04:12 +0100462#else
463static int sys_utimensat(int dirfd, const char *pathname,
464 const struct timespec times[2], int flags)
465{
466 errno = ENOSYS;
467 return -1;
468}
ths9007f0e2007-09-25 17:50:37 +0000469#endif
Peter Maydell1acae9f2013-07-02 14:04:12 +0100470#endif /* TARGET_NR_utimensat */
aurel323b3f24a2009-04-15 16:12:13 +0000471
Andreas Schwab95d03072018-01-23 11:53:31 +0100472#ifdef TARGET_NR_renameat2
473#if defined(__NR_renameat2)
474#define __NR_sys_renameat2 __NR_renameat2
475_syscall5(int, sys_renameat2, int, oldfd, const char *, old, int, newfd,
476 const char *, new, unsigned int, flags)
477#else
478static int sys_renameat2(int oldfd, const char *old,
479 int newfd, const char *new, int flags)
480{
481 if (flags == 0) {
482 return renameat(oldfd, old, newfd, new);
483 }
484 errno = ENOSYS;
485 return -1;
486}
487#endif
488#endif /* TARGET_NR_renameat2 */
489
aurel323b3f24a2009-04-15 16:12:13 +0000490#ifdef CONFIG_INOTIFY
aurel328690e422009-04-17 13:50:32 +0000491#include <sys/inotify.h>
aurel323b3f24a2009-04-15 16:12:13 +0000492#else
493/* Userspace can usually survive runtime without inotify */
494#undef TARGET_NR_inotify_init
Riku Voipioc05c7a72010-03-26 15:25:11 +0000495#undef TARGET_NR_inotify_init1
aurel323b3f24a2009-04-15 16:12:13 +0000496#undef TARGET_NR_inotify_add_watch
497#undef TARGET_NR_inotify_rm_watch
498#endif /* CONFIG_INOTIFY */
499
Peter Maydell163a05a2011-06-27 17:44:52 +0100500#if defined(TARGET_NR_prlimit64)
501#ifndef __NR_prlimit64
502# define __NR_prlimit64 -1
503#endif
504#define __NR_sys_prlimit64 __NR_prlimit64
505/* The glibc rlimit structure may not be that used by the underlying syscall */
506struct host_rlimit64 {
507 uint64_t rlim_cur;
508 uint64_t rlim_max;
509};
510_syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
511 const struct host_rlimit64 *, new_limit,
512 struct host_rlimit64 *, old_limit)
513#endif
514
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +1100515
516#if defined(TARGET_NR_timer_create)
zhaolichang6f9ff552020-09-17 15:50:25 +0800517/* Maximum of 32 active POSIX timers allowed at any one time. */
Peter Maydell9e598992022-07-25 12:00:35 +0100518#define GUEST_TIMER_MAX 32
519static timer_t g_posix_timers[GUEST_TIMER_MAX];
520static int g_posix_timer_allocated[GUEST_TIMER_MAX];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +1100521
522static inline int next_free_host_timer(void)
523{
Peter Maydell9e598992022-07-25 12:00:35 +0100524 int k;
525 for (k = 0; k < ARRAY_SIZE(g_posix_timer_allocated); k++) {
526 if (qatomic_xchg(g_posix_timer_allocated + k, 1) == 0) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +1100527 return k;
528 }
529 }
530 return -1;
531}
Peter Maydell9e598992022-07-25 12:00:35 +0100532
533static inline void free_host_timer_slot(int id)
534{
535 qatomic_store_release(g_posix_timer_allocated + id, 0);
536}
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +1100537#endif
538
Philippe Mathieu-Daudé3ffe3262021-07-08 19:05:49 +0200539static inline int host_to_target_errno(int host_errno)
ths637947f2007-06-01 12:09:19 +0000540{
Philippe Mathieu-Daudé3ffe3262021-07-08 19:05:49 +0200541 switch (host_errno) {
542#define E(X) case X: return TARGET_##X;
543#include "errnos.c.inc"
544#undef E
545 default:
546 return host_errno;
Timothy E Baldwin24661192016-05-12 18:47:25 +0100547 }
ths637947f2007-06-01 12:09:19 +0000548}
549
Philippe Mathieu-Daudé3ffe3262021-07-08 19:05:49 +0200550static inline int target_to_host_errno(int target_errno)
thsb92c47c2007-11-01 00:07:38 +0000551{
Philippe Mathieu-Daudé3ffe3262021-07-08 19:05:49 +0200552 switch (target_errno) {
553#define E(X) case TARGET_##X: return X;
554#include "errnos.c.inc"
555#undef E
556 default:
557 return target_errno;
Timothy E Baldwin24661192016-05-12 18:47:25 +0100558 }
thsb92c47c2007-11-01 00:07:38 +0000559}
560
Ilya Leoshkevich892a4f62022-06-21 16:42:05 +0200561abi_long get_errno(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000562{
563 if (ret == -1)
ths637947f2007-06-01 12:09:19 +0000564 return -host_to_target_errno(errno);
bellard31e31b82003-02-18 22:55:36 +0000565 else
566 return ret;
567}
568
Peter Maydell7dcdaea2016-06-06 19:58:18 +0100569const char *target_strerror(int err)
thsb92c47c2007-11-01 00:07:38 +0000570{
Richard Hendersonaf254a22021-11-22 19:47:33 +0100571 if (err == QEMU_ERESTARTSYS) {
Peter Maydellda2a34f2016-06-06 19:58:19 +0100572 return "To be restarted";
573 }
Richard Henderson57a0c932021-11-17 05:14:52 -0800574 if (err == QEMU_ESIGRETURN) {
Peter Maydellda2a34f2016-06-06 19:58:19 +0100575 return "Successful exit from sigreturn";
576 }
577
thsb92c47c2007-11-01 00:07:38 +0000578 return strerror(target_to_host_errno(err));
579}
580
Tonis Tiigi45ad7612022-01-04 20:18:18 -0800581static int check_zeroed_user(abi_long addr, size_t ksize, size_t usize)
582{
583 int i;
584 uint8_t b;
585 if (usize <= ksize) {
586 return 1;
587 }
588 for (i = ksize; i < usize; i++) {
589 if (get_user_u8(b, addr + i)) {
590 return -TARGET_EFAULT;
591 }
592 if (b != 0) {
593 return 0;
594 }
595 }
596 return 1;
597}
598
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100599#define safe_syscall0(type, name) \
600static type safe_##name(void) \
601{ \
602 return safe_syscall(__NR_##name); \
603}
604
605#define safe_syscall1(type, name, type1, arg1) \
606static type safe_##name(type1 arg1) \
607{ \
608 return safe_syscall(__NR_##name, arg1); \
609}
610
611#define safe_syscall2(type, name, type1, arg1, type2, arg2) \
612static type safe_##name(type1 arg1, type2 arg2) \
613{ \
614 return safe_syscall(__NR_##name, arg1, arg2); \
615}
616
617#define safe_syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
618static type safe_##name(type1 arg1, type2 arg2, type3 arg3) \
619{ \
620 return safe_syscall(__NR_##name, arg1, arg2, arg3); \
621}
622
623#define safe_syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
624 type4, arg4) \
625static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
626{ \
627 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4); \
628}
629
630#define safe_syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \
631 type4, arg4, type5, arg5) \
632static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
633 type5 arg5) \
634{ \
635 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
636}
637
638#define safe_syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \
639 type4, arg4, type5, arg5, type6, arg6) \
640static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
641 type5 arg5, type6 arg6) \
642{ \
643 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
644}
645
Timothy E Baldwin50afd022016-05-12 18:47:47 +0100646safe_syscall3(ssize_t, read, int, fd, void *, buff, size_t, count)
647safe_syscall3(ssize_t, write, int, fd, const void *, buff, size_t, count)
Timothy E Baldwinc10a0732016-05-12 18:47:48 +0100648safe_syscall4(int, openat, int, dirfd, const char *, pathname, \
649 int, flags, mode_t, mode)
Alistair Francis859e8a82020-03-12 15:13:49 -0700650#if defined(TARGET_NR_wait4) || defined(TARGET_NR_waitpid)
Timothy E Baldwin4af80a32016-05-12 18:47:49 +0100651safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \
652 struct rusage *, rusage)
Alistair Francis859e8a82020-03-12 15:13:49 -0700653#endif
Timothy E Baldwin4af80a32016-05-12 18:47:49 +0100654safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \
655 int, options, struct rusage *, rusage)
Drew DeVault55bbe4d2022-11-04 18:36:32 +0100656safe_syscall5(int, execveat, int, dirfd, const char *, filename,
657 char **, argv, char **, envp, int, flags)
Alistair Francis859e8a82020-03-12 15:13:49 -0700658#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \
Filip Bozutae5ce9682020-08-25 00:30:49 +0200659 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
Peter Maydell6df9d382016-05-12 18:47:51 +0100660safe_syscall6(int, pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, \
661 fd_set *, exceptfds, struct timespec *, timeout, void *, sig)
Alistair Francis859e8a82020-03-12 15:13:49 -0700662#endif
Filip Bozutae5ce9682020-08-25 00:30:49 +0200663#if defined(TARGET_NR_ppoll) || defined(TARGET_NR_ppoll_time64)
Peter Maydella6130232016-06-06 19:58:10 +0100664safe_syscall5(int, ppoll, struct pollfd *, ufds, unsigned int, nfds,
665 struct timespec *, tsp, const sigset_t *, sigmask,
666 size_t, sigsetsize)
Alistair Francis859e8a82020-03-12 15:13:49 -0700667#endif
Peter Maydell227f0212016-06-06 19:58:11 +0100668safe_syscall6(int, epoll_pwait, int, epfd, struct epoll_event *, events,
669 int, maxevents, int, timeout, const sigset_t *, sigmask,
670 size_t, sigsetsize)
Alistair Francis14690292020-03-18 15:47:01 -0700671#if defined(__NR_futex)
Peter Maydelld509eeb2016-05-12 18:47:52 +0100672safe_syscall6(int,futex,int *,uaddr,int,op,int,val, \
673 const struct timespec *,timeout,int *,uaddr2,int,val3)
Alistair Francis859e8a82020-03-12 15:13:49 -0700674#endif
Alistair Francis14690292020-03-18 15:47:01 -0700675#if defined(__NR_futex_time64)
676safe_syscall6(int,futex_time64,int *,uaddr,int,op,int,val, \
677 const struct timespec *,timeout,int *,uaddr2,int,val3)
678#endif
Peter Maydell2fe4fba2016-05-27 15:51:48 +0100679safe_syscall2(int, rt_sigsuspend, sigset_t *, newset, size_t, sigsetsize)
Peter Maydellbef653d2016-05-27 15:51:57 +0100680safe_syscall2(int, kill, pid_t, pid, int, sig)
681safe_syscall2(int, tkill, int, tid, int, sig)
682safe_syscall3(int, tgkill, int, tgid, int, pid, int, sig)
Peter Maydell918c03e2016-06-06 19:58:02 +0100683safe_syscall3(ssize_t, readv, int, fd, const struct iovec *, iov, int, iovcnt)
684safe_syscall3(ssize_t, writev, int, fd, const struct iovec *, iov, int, iovcnt)
Dejan Jovicevic0f263862016-10-11 11:52:46 +0200685safe_syscall5(ssize_t, preadv, int, fd, const struct iovec *, iov, int, iovcnt,
686 unsigned long, pos_l, unsigned long, pos_h)
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +0200687safe_syscall5(ssize_t, pwritev, int, fd, const struct iovec *, iov, int, iovcnt,
688 unsigned long, pos_l, unsigned long, pos_h)
Peter Maydell2a3c7612016-06-06 19:58:03 +0100689safe_syscall3(int, connect, int, fd, const struct sockaddr *, addr,
690 socklen_t, addrlen)
Peter Maydell66687532016-06-06 19:58:04 +0100691safe_syscall6(ssize_t, sendto, int, fd, const void *, buf, size_t, len,
692 int, flags, const struct sockaddr *, addr, socklen_t, addrlen)
693safe_syscall6(ssize_t, recvfrom, int, fd, void *, buf, size_t, len,
694 int, flags, struct sockaddr *, addr, socklen_t *, addrlen)
695safe_syscall3(ssize_t, sendmsg, int, fd, const struct msghdr *, msg, int, flags)
696safe_syscall3(ssize_t, recvmsg, int, fd, struct msghdr *, msg, int, flags)
Peter Maydell2a845982016-06-06 19:58:07 +0100697safe_syscall2(int, flock, int, fd, int, operation)
Filip Bozutaddcbde12020-08-24 21:21:16 +0200698#if defined(TARGET_NR_rt_sigtimedwait) || defined(TARGET_NR_rt_sigtimedwait_time64)
Peter Maydellb3f82332016-06-06 19:58:08 +0100699safe_syscall4(int, rt_sigtimedwait, const sigset_t *, these, siginfo_t *, uinfo,
700 const struct timespec *, uts, size_t, sigsetsize)
Alistair Francis859e8a82020-03-12 15:13:49 -0700701#endif
Peter Maydellff6dc132016-06-06 19:58:13 +0100702safe_syscall4(int, accept4, int, fd, struct sockaddr *, addr, socklen_t *, len,
703 int, flags)
Alistair Francis859e8a82020-03-12 15:13:49 -0700704#if defined(TARGET_NR_nanosleep)
Peter Maydell9e518222016-06-06 19:58:09 +0100705safe_syscall2(int, nanosleep, const struct timespec *, req,
706 struct timespec *, rem)
Alistair Francis859e8a82020-03-12 15:13:49 -0700707#endif
Filip Bozuta6ac03b22020-08-24 21:21:15 +0200708#if defined(TARGET_NR_clock_nanosleep) || \
709 defined(TARGET_NR_clock_nanosleep_time64)
Peter Maydell9e518222016-06-06 19:58:09 +0100710safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags,
711 const struct timespec *, req, struct timespec *, rem)
712#endif
Laurent Vivier524fa342019-05-29 10:48:04 +0200713#ifdef __NR_ipc
Matus Kyseld8c08b12020-06-26 14:46:11 +0200714#ifdef __s390x__
715safe_syscall5(int, ipc, int, call, long, first, long, second, long, third,
716 void *, ptr)
717#else
Peter Maydell89f9fe42016-06-06 19:58:05 +0100718safe_syscall6(int, ipc, int, call, long, first, long, second, long, third,
719 void *, ptr, long, fifth)
Laurent Vivier86e63692019-05-23 19:54:13 +0200720#endif
Matus Kyseld8c08b12020-06-26 14:46:11 +0200721#endif
Laurent Vivier86e63692019-05-23 19:54:13 +0200722#ifdef __NR_msgsnd
723safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz,
724 int, flags)
Laurent Vivier86e63692019-05-23 19:54:13 +0200725#endif
726#ifdef __NR_msgrcv
727safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz,
728 long, msgtype, int, flags)
Laurent Vivier86e63692019-05-23 19:54:13 +0200729#endif
730#ifdef __NR_semtimedop
731safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops,
732 unsigned, nsops, const struct timespec *, timeout)
Peter Maydell89f9fe42016-06-06 19:58:05 +0100733#endif
Filip Bozutad107e372020-08-24 21:37:52 +0200734#if defined(TARGET_NR_mq_timedsend) || \
735 defined(TARGET_NR_mq_timedsend_time64)
Peter Maydelld40ecd62016-06-06 19:58:06 +0100736safe_syscall5(int, mq_timedsend, int, mqdes, const char *, msg_ptr,
737 size_t, len, unsigned, prio, const struct timespec *, timeout)
Alistair Francis859e8a82020-03-12 15:13:49 -0700738#endif
Filip Bozutad107e372020-08-24 21:37:52 +0200739#if defined(TARGET_NR_mq_timedreceive) || \
740 defined(TARGET_NR_mq_timedreceive_time64)
Peter Maydelld40ecd62016-06-06 19:58:06 +0100741safe_syscall5(int, mq_timedreceive, int, mqdes, char *, msg_ptr,
742 size_t, len, unsigned *, prio, const struct timespec *, timeout)
743#endif
Andreas Schwab84946452020-11-12 12:45:16 +0100744#if defined(TARGET_NR_copy_file_range) && defined(__NR_copy_file_range)
745safe_syscall6(ssize_t, copy_file_range, int, infd, loff_t *, pinoff,
746 int, outfd, loff_t *, poutoff, size_t, length,
747 unsigned int, flags)
748#endif
749
Peter Maydell49ca6f32016-06-06 19:58:14 +0100750/* We do ioctl like this rather than via safe_syscall3 to preserve the
751 * "third argument might be integer or pointer or not present" behaviour of
752 * the libc function.
753 */
754#define safe_ioctl(...) safe_syscall(__NR_ioctl, __VA_ARGS__)
Peter Maydell435da5e2016-06-13 11:22:05 +0100755/* Similarly for fcntl. Note that callers must always:
756 * pass the F_GETLK64 etc constants rather than the unsuffixed F_GETLK
757 * use the flock64 struct rather than unsuffixed flock
758 * This will then work and use a 64-bit offset for both 32-bit and 64-bit hosts.
759 */
760#ifdef __NR_fcntl64
761#define safe_fcntl(...) safe_syscall(__NR_fcntl64, __VA_ARGS__)
762#else
763#define safe_fcntl(...) safe_syscall(__NR_fcntl, __VA_ARGS__)
764#endif
Timothy E Baldwin50afd022016-05-12 18:47:47 +0100765
Paul Burton8289d112014-06-22 11:25:33 +0100766static inline int host_to_target_sock_type(int host_type)
767{
768 int target_type;
769
770 switch (host_type & 0xf /* SOCK_TYPE_MASK */) {
771 case SOCK_DGRAM:
772 target_type = TARGET_SOCK_DGRAM;
773 break;
774 case SOCK_STREAM:
775 target_type = TARGET_SOCK_STREAM;
776 break;
777 default:
778 target_type = host_type & 0xf /* SOCK_TYPE_MASK */;
779 break;
780 }
781
782#if defined(SOCK_CLOEXEC)
783 if (host_type & SOCK_CLOEXEC) {
784 target_type |= TARGET_SOCK_CLOEXEC;
785 }
786#endif
787
788#if defined(SOCK_NONBLOCK)
789 if (host_type & SOCK_NONBLOCK) {
790 target_type |= TARGET_SOCK_NONBLOCK;
791 }
792#endif
793
794 return target_type;
795}
796
blueswir1992f48a2007-10-14 16:27:31 +0000797static abi_ulong target_brk;
798static abi_ulong target_original_brk;
vincent4d1de872011-06-14 21:56:33 +0000799static abi_ulong brk_page;
bellard31e31b82003-02-18 22:55:36 +0000800
blueswir1992f48a2007-10-14 16:27:31 +0000801void target_set_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000802{
blueswir14c1de732007-07-07 20:45:44 +0000803 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
vincent4d1de872011-06-14 21:56:33 +0000804 brk_page = HOST_PAGE_ALIGN(target_brk);
bellard31e31b82003-02-18 22:55:36 +0000805}
806
vincent4d1de872011-06-14 21:56:33 +0000807//#define DEBUGF_BRK(message, args...) do { fprintf(stderr, (message), ## args); } while (0)
808#define DEBUGF_BRK(message, args...)
809
ths0da46a62007-10-20 20:23:07 +0000810/* do_brk() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000811abi_long do_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000812{
blueswir1992f48a2007-10-14 16:27:31 +0000813 abi_long mapped_addr;
Peter Maydellef4330c2016-07-22 13:41:52 +0100814 abi_ulong new_alloc_size;
bellard31e31b82003-02-18 22:55:36 +0000815
Richard Hendersonee1bf832021-02-12 10:48:44 -0800816 /* brk pointers are always untagged */
817
Paul Brook3a0c6c42012-02-09 19:04:27 +0000818 DEBUGF_BRK("do_brk(" TARGET_ABI_FMT_lx ") -> ", new_brk);
ths3b46e622007-09-17 08:09:54 +0000819
vincent4d1de872011-06-14 21:56:33 +0000820 if (!new_brk) {
Paul Brook3a0c6c42012-02-09 19:04:27 +0000821 DEBUGF_BRK(TARGET_ABI_FMT_lx " (!new_brk)\n", target_brk);
vincent4d1de872011-06-14 21:56:33 +0000822 return target_brk;
823 }
824 if (new_brk < target_original_brk) {
Paul Brook3a0c6c42012-02-09 19:04:27 +0000825 DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk < target_original_brk)\n",
826 target_brk);
vincent4d1de872011-06-14 21:56:33 +0000827 return target_brk;
828 }
bellard31e31b82003-02-18 22:55:36 +0000829
vincent4d1de872011-06-14 21:56:33 +0000830 /* If the new brk is less than the highest page reserved to the
831 * target heap allocation, set it and we're almost done... */
832 if (new_brk <= brk_page) {
833 /* Heap contents are initialized to zero, as for anonymous
834 * mapped pages. */
835 if (new_brk > target_brk) {
Richard Henderson3e8f1622021-02-12 10:48:43 -0800836 memset(g2h_untagged(target_brk), 0, new_brk - target_brk);
vincent4d1de872011-06-14 21:56:33 +0000837 }
bellard31e31b82003-02-18 22:55:36 +0000838 target_brk = new_brk;
Paul Brook3a0c6c42012-02-09 19:04:27 +0000839 DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk <= brk_page)\n", target_brk);
Paolo Bonzini72e21db2018-12-13 23:37:36 +0100840 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000841 }
842
Peter Maydell00faf082011-04-18 16:34:24 +0100843 /* We need to allocate more memory after the brk... Note that
844 * we don't use MAP_FIXED because that will map over the top of
845 * any existing mapping (like the one with the host libc or qemu
846 * itself); instead we treat "mapped but at wrong address" as
847 * a failure and unmap again.
848 */
vincent4d1de872011-06-14 21:56:33 +0000849 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page);
ths5fafdf22007-09-16 21:08:06 +0000850 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
bellard54936002003-05-13 00:25:15 +0000851 PROT_READ|PROT_WRITE,
Peter Maydell00faf082011-04-18 16:34:24 +0100852 MAP_ANON|MAP_PRIVATE, 0, 0));
853
854 if (mapped_addr == brk_page) {
Cédric VINCENT70afc342011-08-26 10:56:50 +0200855 /* Heap contents are initialized to zero, as for anonymous
856 * mapped pages. Technically the new pages are already
857 * initialized to zero since they *are* anonymous mapped
858 * pages, however we have to take care with the contents that
859 * come from the remaining part of the previous page: it may
860 * contains garbage data due to a previous heap usage (grown
861 * then shrunken). */
Richard Henderson3e8f1622021-02-12 10:48:43 -0800862 memset(g2h_untagged(target_brk), 0, brk_page - target_brk);
Cédric VINCENT70afc342011-08-26 10:56:50 +0200863
Peter Maydell00faf082011-04-18 16:34:24 +0100864 target_brk = new_brk;
vincent4d1de872011-06-14 21:56:33 +0000865 brk_page = HOST_PAGE_ALIGN(target_brk);
Paul Brook3a0c6c42012-02-09 19:04:27 +0000866 DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr == brk_page)\n",
867 target_brk);
Peter Maydell00faf082011-04-18 16:34:24 +0100868 return target_brk;
869 } else if (mapped_addr != -1) {
870 /* Mapped but at wrong address, meaning there wasn't actually
871 * enough space for this brk.
872 */
873 target_munmap(mapped_addr, new_alloc_size);
874 mapped_addr = -1;
Paul Brook3a0c6c42012-02-09 19:04:27 +0000875 DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr != -1)\n", target_brk);
vincent4d1de872011-06-14 21:56:33 +0000876 }
877 else {
Paul Brook3a0c6c42012-02-09 19:04:27 +0000878 DEBUGF_BRK(TARGET_ABI_FMT_lx " (otherwise)\n", target_brk);
Peter Maydell00faf082011-04-18 16:34:24 +0100879 }
balrog7ab240a2008-04-26 12:17:34 +0000880
Richard Henderson7dd46c02010-05-03 10:07:49 -0700881#if defined(TARGET_ALPHA)
882 /* We (partially) emulate OSF/1 on Alpha, which requires we
883 return a proper errno, not an unchanged brk value. */
Peter Maydell00faf082011-04-18 16:34:24 +0100884 return -TARGET_ENOMEM;
Richard Henderson7dd46c02010-05-03 10:07:49 -0700885#endif
Peter Maydell00faf082011-04-18 16:34:24 +0100886 /* For everything else, return the previous break. */
balrog7ab240a2008-04-26 12:17:34 +0000887 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000888}
889
Alistair Francis859e8a82020-03-12 15:13:49 -0700890#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \
Filip Bozutae5ce9682020-08-25 00:30:49 +0200891 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
ths26edcf42007-12-09 02:25:24 +0000892static inline abi_long copy_from_user_fdset(fd_set *fds,
893 abi_ulong target_fds_addr,
894 int n)
bellard31e31b82003-02-18 22:55:36 +0000895{
ths26edcf42007-12-09 02:25:24 +0000896 int i, nw, j, k;
897 abi_ulong b, *target_fds;
898
Laurent Vivierb1b2db22016-05-31 18:36:02 +0200899 nw = DIV_ROUND_UP(n, TARGET_ABI_BITS);
ths26edcf42007-12-09 02:25:24 +0000900 if (!(target_fds = lock_user(VERIFY_READ,
901 target_fds_addr,
902 sizeof(abi_ulong) * nw,
903 1)))
904 return -TARGET_EFAULT;
905
906 FD_ZERO(fds);
907 k = 0;
908 for (i = 0; i < nw; i++) {
909 /* grab the abi_ulong */
910 __get_user(b, &target_fds[i]);
911 for (j = 0; j < TARGET_ABI_BITS; j++) {
912 /* check the bit inside the abi_ulong */
913 if ((b >> j) & 1)
914 FD_SET(k, fds);
915 k++;
bellard31e31b82003-02-18 22:55:36 +0000916 }
bellard31e31b82003-02-18 22:55:36 +0000917 }
ths26edcf42007-12-09 02:25:24 +0000918
919 unlock_user(target_fds, target_fds_addr, 0);
920
921 return 0;
bellard31e31b82003-02-18 22:55:36 +0000922}
923
Mike Frysinger055e0902011-06-03 17:01:49 -0400924static inline abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr,
925 abi_ulong target_fds_addr,
926 int n)
927{
928 if (target_fds_addr) {
929 if (copy_from_user_fdset(fds, target_fds_addr, n))
930 return -TARGET_EFAULT;
931 *fds_ptr = fds;
932 } else {
933 *fds_ptr = NULL;
934 }
935 return 0;
936}
937
ths26edcf42007-12-09 02:25:24 +0000938static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
939 const fd_set *fds,
940 int n)
bellard31e31b82003-02-18 22:55:36 +0000941{
bellard31e31b82003-02-18 22:55:36 +0000942 int i, nw, j, k;
blueswir1992f48a2007-10-14 16:27:31 +0000943 abi_long v;
ths26edcf42007-12-09 02:25:24 +0000944 abi_ulong *target_fds;
bellard31e31b82003-02-18 22:55:36 +0000945
Laurent Vivierb1b2db22016-05-31 18:36:02 +0200946 nw = DIV_ROUND_UP(n, TARGET_ABI_BITS);
ths26edcf42007-12-09 02:25:24 +0000947 if (!(target_fds = lock_user(VERIFY_WRITE,
948 target_fds_addr,
949 sizeof(abi_ulong) * nw,
950 0)))
951 return -TARGET_EFAULT;
952
953 k = 0;
954 for (i = 0; i < nw; i++) {
955 v = 0;
956 for (j = 0; j < TARGET_ABI_BITS; j++) {
Andreas Schwab9ab709b2013-04-09 01:02:34 +0000957 v |= ((abi_ulong)(FD_ISSET(k, fds) != 0) << j);
ths26edcf42007-12-09 02:25:24 +0000958 k++;
bellard31e31b82003-02-18 22:55:36 +0000959 }
ths26edcf42007-12-09 02:25:24 +0000960 __put_user(v, &target_fds[i]);
bellard31e31b82003-02-18 22:55:36 +0000961 }
ths26edcf42007-12-09 02:25:24 +0000962
963 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
964
965 return 0;
bellard31e31b82003-02-18 22:55:36 +0000966}
Alistair Francis859e8a82020-03-12 15:13:49 -0700967#endif
bellard31e31b82003-02-18 22:55:36 +0000968
bellardc596ed12003-07-13 17:32:31 +0000969#if defined(__alpha__)
970#define HOST_HZ 1024
971#else
972#define HOST_HZ 100
973#endif
974
blueswir1992f48a2007-10-14 16:27:31 +0000975static inline abi_long host_to_target_clock_t(long ticks)
bellardc596ed12003-07-13 17:32:31 +0000976{
977#if HOST_HZ == TARGET_HZ
978 return ticks;
979#else
980 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
981#endif
982}
983
bellard579a97f2007-11-11 14:26:47 +0000984static inline abi_long host_to_target_rusage(abi_ulong target_addr,
985 const struct rusage *rusage)
bellardb4091862003-05-16 15:39:34 +0000986{
pbrook53a59602006-03-25 19:31:22 +0000987 struct target_rusage *target_rusage;
988
bellard579a97f2007-11-11 14:26:47 +0000989 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
990 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200991 target_rusage->ru_utime.tv_sec = tswapal(rusage->ru_utime.tv_sec);
992 target_rusage->ru_utime.tv_usec = tswapal(rusage->ru_utime.tv_usec);
993 target_rusage->ru_stime.tv_sec = tswapal(rusage->ru_stime.tv_sec);
994 target_rusage->ru_stime.tv_usec = tswapal(rusage->ru_stime.tv_usec);
995 target_rusage->ru_maxrss = tswapal(rusage->ru_maxrss);
996 target_rusage->ru_ixrss = tswapal(rusage->ru_ixrss);
997 target_rusage->ru_idrss = tswapal(rusage->ru_idrss);
998 target_rusage->ru_isrss = tswapal(rusage->ru_isrss);
999 target_rusage->ru_minflt = tswapal(rusage->ru_minflt);
1000 target_rusage->ru_majflt = tswapal(rusage->ru_majflt);
1001 target_rusage->ru_nswap = tswapal(rusage->ru_nswap);
1002 target_rusage->ru_inblock = tswapal(rusage->ru_inblock);
1003 target_rusage->ru_oublock = tswapal(rusage->ru_oublock);
1004 target_rusage->ru_msgsnd = tswapal(rusage->ru_msgsnd);
1005 target_rusage->ru_msgrcv = tswapal(rusage->ru_msgrcv);
1006 target_rusage->ru_nsignals = tswapal(rusage->ru_nsignals);
1007 target_rusage->ru_nvcsw = tswapal(rusage->ru_nvcsw);
1008 target_rusage->ru_nivcsw = tswapal(rusage->ru_nivcsw);
pbrook53a59602006-03-25 19:31:22 +00001009 unlock_user_struct(target_rusage, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001010
1011 return 0;
bellardb4091862003-05-16 15:39:34 +00001012}
1013
Alistair Francis859e8a82020-03-12 15:13:49 -07001014#ifdef TARGET_NR_setrlimit
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001015static inline rlim_t target_to_host_rlim(abi_ulong target_rlim)
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001016{
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001017 abi_ulong target_rlim_swap;
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001018 rlim_t result;
1019
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001020 target_rlim_swap = tswapal(target_rlim);
1021 if (target_rlim_swap == TARGET_RLIM_INFINITY)
1022 return RLIM_INFINITY;
1023
1024 result = target_rlim_swap;
1025 if (target_rlim_swap != (rlim_t)result)
1026 return RLIM_INFINITY;
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001027
1028 return result;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001029}
Alistair Francis859e8a82020-03-12 15:13:49 -07001030#endif
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001031
Alistair Francis859e8a82020-03-12 15:13:49 -07001032#if defined(TARGET_NR_getrlimit) || defined(TARGET_NR_ugetrlimit)
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001033static inline abi_ulong host_to_target_rlim(rlim_t rlim)
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001034{
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001035 abi_ulong target_rlim_swap;
1036 abi_ulong result;
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001037
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001038 if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim)
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001039 target_rlim_swap = TARGET_RLIM_INFINITY;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001040 else
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001041 target_rlim_swap = rlim;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001042 result = tswapal(target_rlim_swap);
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001043
1044 return result;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001045}
Alistair Francis859e8a82020-03-12 15:13:49 -07001046#endif
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001047
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03001048static inline int target_to_host_resource(int code)
1049{
1050 switch (code) {
1051 case TARGET_RLIMIT_AS:
1052 return RLIMIT_AS;
1053 case TARGET_RLIMIT_CORE:
1054 return RLIMIT_CORE;
1055 case TARGET_RLIMIT_CPU:
1056 return RLIMIT_CPU;
1057 case TARGET_RLIMIT_DATA:
1058 return RLIMIT_DATA;
1059 case TARGET_RLIMIT_FSIZE:
1060 return RLIMIT_FSIZE;
1061 case TARGET_RLIMIT_LOCKS:
1062 return RLIMIT_LOCKS;
1063 case TARGET_RLIMIT_MEMLOCK:
1064 return RLIMIT_MEMLOCK;
1065 case TARGET_RLIMIT_MSGQUEUE:
1066 return RLIMIT_MSGQUEUE;
1067 case TARGET_RLIMIT_NICE:
1068 return RLIMIT_NICE;
1069 case TARGET_RLIMIT_NOFILE:
1070 return RLIMIT_NOFILE;
1071 case TARGET_RLIMIT_NPROC:
1072 return RLIMIT_NPROC;
1073 case TARGET_RLIMIT_RSS:
1074 return RLIMIT_RSS;
1075 case TARGET_RLIMIT_RTPRIO:
1076 return RLIMIT_RTPRIO;
Fabrice Fontainec3a28d72022-05-23 12:52:39 +02001077#ifdef RLIMIT_RTTIME
Serge Belyshev244fd082022-01-29 22:48:23 +03001078 case TARGET_RLIMIT_RTTIME:
1079 return RLIMIT_RTTIME;
Fabrice Fontainec3a28d72022-05-23 12:52:39 +02001080#endif
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03001081 case TARGET_RLIMIT_SIGPENDING:
1082 return RLIMIT_SIGPENDING;
1083 case TARGET_RLIMIT_STACK:
1084 return RLIMIT_STACK;
1085 default:
1086 return code;
1087 }
1088}
1089
ths788f5ec2007-12-09 02:37:05 +00001090static inline abi_long copy_from_user_timeval(struct timeval *tv,
1091 abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +00001092{
pbrook53a59602006-03-25 19:31:22 +00001093 struct target_timeval *target_tv;
1094
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001095 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) {
bellard579a97f2007-11-11 14:26:47 +00001096 return -TARGET_EFAULT;
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001097 }
ths788f5ec2007-12-09 02:37:05 +00001098
1099 __get_user(tv->tv_sec, &target_tv->tv_sec);
1100 __get_user(tv->tv_usec, &target_tv->tv_usec);
1101
1102 unlock_user_struct(target_tv, target_tv_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001103
1104 return 0;
bellard31e31b82003-02-18 22:55:36 +00001105}
1106
ths788f5ec2007-12-09 02:37:05 +00001107static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
1108 const struct timeval *tv)
bellard31e31b82003-02-18 22:55:36 +00001109{
pbrook53a59602006-03-25 19:31:22 +00001110 struct target_timeval *target_tv;
1111
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001112 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
bellard579a97f2007-11-11 14:26:47 +00001113 return -TARGET_EFAULT;
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001114 }
ths788f5ec2007-12-09 02:37:05 +00001115
1116 __put_user(tv->tv_sec, &target_tv->tv_sec);
1117 __put_user(tv->tv_usec, &target_tv->tv_usec);
1118
1119 unlock_user_struct(target_tv, target_tv_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001120
1121 return 0;
bellard31e31b82003-02-18 22:55:36 +00001122}
1123
Filip Bozuta6ac03b22020-08-24 21:21:15 +02001124#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
1125static inline abi_long copy_from_user_timeval64(struct timeval *tv,
1126 abi_ulong target_tv_addr)
1127{
1128 struct target__kernel_sock_timeval *target_tv;
1129
1130 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) {
1131 return -TARGET_EFAULT;
1132 }
1133
1134 __get_user(tv->tv_sec, &target_tv->tv_sec);
1135 __get_user(tv->tv_usec, &target_tv->tv_usec);
1136
1137 unlock_user_struct(target_tv, target_tv_addr, 0);
1138
1139 return 0;
1140}
1141#endif
1142
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001143static inline abi_long copy_to_user_timeval64(abi_ulong target_tv_addr,
Filip Bozuta6ac03b22020-08-24 21:21:15 +02001144 const struct timeval *tv)
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001145{
1146 struct target__kernel_sock_timeval *target_tv;
1147
1148 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
1149 return -TARGET_EFAULT;
1150 }
1151
1152 __put_user(tv->tv_sec, &target_tv->tv_sec);
1153 __put_user(tv->tv_usec, &target_tv->tv_usec);
1154
1155 unlock_user_struct(target_tv, target_tv_addr, 1);
1156
1157 return 0;
1158}
1159
Alistair Francis859e8a82020-03-12 15:13:49 -07001160#if defined(TARGET_NR_futex) || \
1161 defined(TARGET_NR_rt_sigtimedwait) || \
1162 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6) || \
1163 defined(TARGET_NR_nanosleep) || defined(TARGET_NR_clock_settime) || \
1164 defined(TARGET_NR_utimensat) || defined(TARGET_NR_mq_timedsend) || \
Matus Kyseld8c08b12020-06-26 14:46:11 +02001165 defined(TARGET_NR_mq_timedreceive) || defined(TARGET_NR_ipc) || \
Filip Bozuta2c86c902020-07-22 17:34:20 +02001166 defined(TARGET_NR_semop) || defined(TARGET_NR_semtimedop) || \
1167 defined(TARGET_NR_timer_settime) || \
1168 (defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD))
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001169static inline abi_long target_to_host_timespec(struct timespec *host_ts,
1170 abi_ulong target_addr)
1171{
1172 struct target_timespec *target_ts;
1173
1174 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) {
1175 return -TARGET_EFAULT;
1176 }
1177 __get_user(host_ts->tv_sec, &target_ts->tv_sec);
1178 __get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1179 unlock_user_struct(target_ts, target_addr, 0);
1180 return 0;
1181}
Alistair Francis859e8a82020-03-12 15:13:49 -07001182#endif
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001183
Filip Bozuta828cb3a2020-07-22 17:34:21 +02001184#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) || \
1185 defined(TARGET_NR_timer_settime64) || \
Filip Bozutad107e372020-08-24 21:37:52 +02001186 defined(TARGET_NR_mq_timedsend_time64) || \
1187 defined(TARGET_NR_mq_timedreceive_time64) || \
Filip Bozuta6ac03b22020-08-24 21:21:15 +02001188 (defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)) || \
Filip Bozutaddcbde12020-08-24 21:21:16 +02001189 defined(TARGET_NR_clock_nanosleep_time64) || \
Filip Bozutacac46eb2020-08-25 00:30:50 +02001190 defined(TARGET_NR_rt_sigtimedwait_time64) || \
1191 defined(TARGET_NR_utimensat) || \
1192 defined(TARGET_NR_utimensat_time64) || \
Filip Bozutae5ce9682020-08-25 00:30:49 +02001193 defined(TARGET_NR_semtimedop_time64) || \
1194 defined(TARGET_NR_pselect6_time64) || defined(TARGET_NR_ppoll_time64)
Alistair Francisc6c8d102020-03-12 15:13:53 -07001195static inline abi_long target_to_host_timespec64(struct timespec *host_ts,
1196 abi_ulong target_addr)
1197{
1198 struct target__kernel_timespec *target_ts;
1199
1200 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) {
1201 return -TARGET_EFAULT;
1202 }
1203 __get_user(host_ts->tv_sec, &target_ts->tv_sec);
1204 __get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
Laurent Vivier00576752020-08-27 09:04:49 +02001205 /* in 32bit mode, this drops the padding */
1206 host_ts->tv_nsec = (long)(abi_long)host_ts->tv_nsec;
Alistair Francisc6c8d102020-03-12 15:13:53 -07001207 unlock_user_struct(target_ts, target_addr, 0);
1208 return 0;
1209}
1210#endif
1211
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001212static inline abi_long host_to_target_timespec(abi_ulong target_addr,
1213 struct timespec *host_ts)
1214{
1215 struct target_timespec *target_ts;
1216
1217 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) {
1218 return -TARGET_EFAULT;
1219 }
1220 __put_user(host_ts->tv_sec, &target_ts->tv_sec);
1221 __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1222 unlock_user_struct(target_ts, target_addr, 1);
1223 return 0;
1224}
1225
1226static inline abi_long host_to_target_timespec64(abi_ulong target_addr,
1227 struct timespec *host_ts)
1228{
1229 struct target__kernel_timespec *target_ts;
1230
1231 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) {
1232 return -TARGET_EFAULT;
1233 }
1234 __put_user(host_ts->tv_sec, &target_ts->tv_sec);
1235 __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1236 unlock_user_struct(target_ts, target_addr, 1);
1237 return 0;
1238}
1239
Richard Hendersona52f5f82020-02-12 19:22:23 -08001240#if defined(TARGET_NR_gettimeofday)
1241static inline abi_long copy_to_user_timezone(abi_ulong target_tz_addr,
1242 struct timezone *tz)
1243{
1244 struct target_timezone *target_tz;
1245
1246 if (!lock_user_struct(VERIFY_WRITE, target_tz, target_tz_addr, 1)) {
1247 return -TARGET_EFAULT;
1248 }
1249
1250 __put_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
1251 __put_user(tz->tz_dsttime, &target_tz->tz_dsttime);
1252
1253 unlock_user_struct(target_tz, target_tz_addr, 1);
1254
1255 return 0;
1256}
1257#endif
1258
Alistair Francis859e8a82020-03-12 15:13:49 -07001259#if defined(TARGET_NR_settimeofday)
Paul Burtonef4467e2014-06-22 11:25:40 +01001260static inline abi_long copy_from_user_timezone(struct timezone *tz,
1261 abi_ulong target_tz_addr)
1262{
1263 struct target_timezone *target_tz;
1264
1265 if (!lock_user_struct(VERIFY_READ, target_tz, target_tz_addr, 1)) {
1266 return -TARGET_EFAULT;
1267 }
1268
1269 __get_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
1270 __get_user(tz->tz_dsttime, &target_tz->tz_dsttime);
1271
1272 unlock_user_struct(target_tz, target_tz_addr, 0);
1273
1274 return 0;
1275}
Alistair Francis859e8a82020-03-12 15:13:49 -07001276#endif
Paul Burtonef4467e2014-06-22 11:25:40 +01001277
Nathan Froyd8ec9cf82009-07-22 09:14:36 -07001278#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
1279#include <mqueue.h>
1280
aurel3224e10032009-04-15 16:11:43 +00001281static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr,
1282 abi_ulong target_mq_attr_addr)
1283{
1284 struct target_mq_attr *target_mq_attr;
1285
1286 if (!lock_user_struct(VERIFY_READ, target_mq_attr,
1287 target_mq_attr_addr, 1))
1288 return -TARGET_EFAULT;
1289
1290 __get_user(attr->mq_flags, &target_mq_attr->mq_flags);
1291 __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
1292 __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
1293 __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
1294
1295 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0);
1296
1297 return 0;
1298}
1299
1300static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
1301 const struct mq_attr *attr)
1302{
1303 struct target_mq_attr *target_mq_attr;
1304
1305 if (!lock_user_struct(VERIFY_WRITE, target_mq_attr,
1306 target_mq_attr_addr, 0))
1307 return -TARGET_EFAULT;
1308
1309 __put_user(attr->mq_flags, &target_mq_attr->mq_flags);
1310 __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
1311 __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
1312 __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
1313
1314 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1);
1315
1316 return 0;
1317}
Nathan Froyd8ec9cf82009-07-22 09:14:36 -07001318#endif
bellard31e31b82003-02-18 22:55:36 +00001319
Mike Frysinger055e0902011-06-03 17:01:49 -04001320#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect)
ths0da46a62007-10-20 20:23:07 +00001321/* do_select() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001322static abi_long do_select(int n,
ths26edcf42007-12-09 02:25:24 +00001323 abi_ulong rfd_addr, abi_ulong wfd_addr,
1324 abi_ulong efd_addr, abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +00001325{
1326 fd_set rfds, wfds, efds;
1327 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
Peter Maydell6df9d382016-05-12 18:47:51 +01001328 struct timeval tv;
1329 struct timespec ts, *ts_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00001330 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00001331
Mike Frysinger055e0902011-06-03 17:01:49 -04001332 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
1333 if (ret) {
1334 return ret;
pbrook53a59602006-03-25 19:31:22 +00001335 }
Mike Frysinger055e0902011-06-03 17:01:49 -04001336 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
1337 if (ret) {
1338 return ret;
pbrook53a59602006-03-25 19:31:22 +00001339 }
Mike Frysinger055e0902011-06-03 17:01:49 -04001340 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
1341 if (ret) {
1342 return ret;
pbrook53a59602006-03-25 19:31:22 +00001343 }
ths3b46e622007-09-17 08:09:54 +00001344
ths26edcf42007-12-09 02:25:24 +00001345 if (target_tv_addr) {
ths788f5ec2007-12-09 02:37:05 +00001346 if (copy_from_user_timeval(&tv, target_tv_addr))
1347 return -TARGET_EFAULT;
Peter Maydell6df9d382016-05-12 18:47:51 +01001348 ts.tv_sec = tv.tv_sec;
1349 ts.tv_nsec = tv.tv_usec * 1000;
1350 ts_ptr = &ts;
bellard31e31b82003-02-18 22:55:36 +00001351 } else {
Peter Maydell6df9d382016-05-12 18:47:51 +01001352 ts_ptr = NULL;
bellard31e31b82003-02-18 22:55:36 +00001353 }
ths26edcf42007-12-09 02:25:24 +00001354
Peter Maydell6df9d382016-05-12 18:47:51 +01001355 ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
1356 ts_ptr, NULL));
pbrook53a59602006-03-25 19:31:22 +00001357
ths26edcf42007-12-09 02:25:24 +00001358 if (!is_error(ret)) {
1359 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
1360 return -TARGET_EFAULT;
1361 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
1362 return -TARGET_EFAULT;
1363 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
1364 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00001365
Peter Maydell6df9d382016-05-12 18:47:51 +01001366 if (target_tv_addr) {
1367 tv.tv_sec = ts.tv_sec;
1368 tv.tv_usec = ts.tv_nsec / 1000;
1369 if (copy_to_user_timeval(target_tv_addr, &tv)) {
1370 return -TARGET_EFAULT;
1371 }
1372 }
bellard31e31b82003-02-18 22:55:36 +00001373 }
bellard579a97f2007-11-11 14:26:47 +00001374
bellard31e31b82003-02-18 22:55:36 +00001375 return ret;
1376}
Laurent Vivier5457dc92016-07-08 01:17:27 +02001377
1378#if defined(TARGET_WANT_OLD_SYS_SELECT)
1379static abi_long do_old_select(abi_ulong arg1)
1380{
1381 struct target_sel_arg_struct *sel;
1382 abi_ulong inp, outp, exp, tvp;
1383 long nsel;
1384
1385 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1)) {
1386 return -TARGET_EFAULT;
1387 }
1388
1389 nsel = tswapal(sel->n);
1390 inp = tswapal(sel->inp);
1391 outp = tswapal(sel->outp);
1392 exp = tswapal(sel->exp);
1393 tvp = tswapal(sel->tvp);
1394
1395 unlock_user_struct(sel, arg1, 0);
1396
1397 return do_select(nsel, inp, outp, exp, tvp);
1398}
1399#endif
Mike Frysinger055e0902011-06-03 17:01:49 -04001400#endif
bellard31e31b82003-02-18 22:55:36 +00001401
Filip Bozutae5ce9682020-08-25 00:30:49 +02001402#if defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
1403static abi_long do_pselect6(abi_long arg1, abi_long arg2, abi_long arg3,
1404 abi_long arg4, abi_long arg5, abi_long arg6,
1405 bool time64)
1406{
1407 abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr;
1408 fd_set rfds, wfds, efds;
1409 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
1410 struct timespec ts, *ts_ptr;
1411 abi_long ret;
1412
1413 /*
1414 * The 6th arg is actually two args smashed together,
1415 * so we cannot use the C library.
1416 */
Filip Bozutae5ce9682020-08-25 00:30:49 +02001417 struct {
1418 sigset_t *set;
1419 size_t size;
1420 } sig, *sig_ptr;
1421
1422 abi_ulong arg_sigset, arg_sigsize, *arg7;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001423
1424 n = arg1;
1425 rfd_addr = arg2;
1426 wfd_addr = arg3;
1427 efd_addr = arg4;
1428 ts_addr = arg5;
1429
1430 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
1431 if (ret) {
1432 return ret;
1433 }
1434 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
1435 if (ret) {
1436 return ret;
1437 }
1438 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
1439 if (ret) {
1440 return ret;
1441 }
1442
1443 /*
1444 * This takes a timespec, and not a timeval, so we cannot
1445 * use the do_select() helper ...
1446 */
1447 if (ts_addr) {
1448 if (time64) {
1449 if (target_to_host_timespec64(&ts, ts_addr)) {
1450 return -TARGET_EFAULT;
1451 }
1452 } else {
1453 if (target_to_host_timespec(&ts, ts_addr)) {
1454 return -TARGET_EFAULT;
1455 }
1456 }
1457 ts_ptr = &ts;
1458 } else {
1459 ts_ptr = NULL;
1460 }
1461
1462 /* Extract the two packed args for the sigset */
Richard Hendersoncb226032022-03-15 01:43:06 -07001463 sig_ptr = NULL;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001464 if (arg6) {
Filip Bozutae5ce9682020-08-25 00:30:49 +02001465 arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1);
1466 if (!arg7) {
1467 return -TARGET_EFAULT;
1468 }
1469 arg_sigset = tswapal(arg7[0]);
1470 arg_sigsize = tswapal(arg7[1]);
1471 unlock_user(arg7, arg6, 0);
1472
1473 if (arg_sigset) {
Richard Hendersoncb226032022-03-15 01:43:06 -07001474 ret = process_sigsuspend_mask(&sig.set, arg_sigset, arg_sigsize);
1475 if (ret != 0) {
1476 return ret;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001477 }
Richard Hendersoncb226032022-03-15 01:43:06 -07001478 sig_ptr = &sig;
1479 sig.size = SIGSET_T_SIZE;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001480 }
Filip Bozutae5ce9682020-08-25 00:30:49 +02001481 }
1482
1483 ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
1484 ts_ptr, sig_ptr));
1485
Richard Hendersoncb226032022-03-15 01:43:06 -07001486 if (sig_ptr) {
1487 finish_sigsuspend_mask(ret);
1488 }
1489
Filip Bozutae5ce9682020-08-25 00:30:49 +02001490 if (!is_error(ret)) {
1491 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n)) {
1492 return -TARGET_EFAULT;
1493 }
1494 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n)) {
1495 return -TARGET_EFAULT;
1496 }
1497 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n)) {
1498 return -TARGET_EFAULT;
1499 }
1500 if (time64) {
1501 if (ts_addr && host_to_target_timespec64(ts_addr, &ts)) {
1502 return -TARGET_EFAULT;
1503 }
1504 } else {
1505 if (ts_addr && host_to_target_timespec(ts_addr, &ts)) {
1506 return -TARGET_EFAULT;
1507 }
1508 }
1509 }
1510 return ret;
1511}
1512#endif
1513
1514#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll) || \
1515 defined(TARGET_NR_ppoll_time64)
1516static abi_long do_ppoll(abi_long arg1, abi_long arg2, abi_long arg3,
1517 abi_long arg4, abi_long arg5, bool ppoll, bool time64)
1518{
1519 struct target_pollfd *target_pfd;
1520 unsigned int nfds = arg2;
1521 struct pollfd *pfd;
1522 unsigned int i;
1523 abi_long ret;
1524
1525 pfd = NULL;
1526 target_pfd = NULL;
1527 if (nfds) {
1528 if (nfds > (INT_MAX / sizeof(struct target_pollfd))) {
1529 return -TARGET_EINVAL;
1530 }
1531 target_pfd = lock_user(VERIFY_WRITE, arg1,
1532 sizeof(struct target_pollfd) * nfds, 1);
1533 if (!target_pfd) {
1534 return -TARGET_EFAULT;
1535 }
1536
1537 pfd = alloca(sizeof(struct pollfd) * nfds);
1538 for (i = 0; i < nfds; i++) {
1539 pfd[i].fd = tswap32(target_pfd[i].fd);
1540 pfd[i].events = tswap16(target_pfd[i].events);
1541 }
1542 }
1543 if (ppoll) {
1544 struct timespec _timeout_ts, *timeout_ts = &_timeout_ts;
Richard Hendersondb36aa72022-03-15 01:43:08 -07001545 sigset_t *set = NULL;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001546
1547 if (arg3) {
1548 if (time64) {
1549 if (target_to_host_timespec64(timeout_ts, arg3)) {
1550 unlock_user(target_pfd, arg1, 0);
1551 return -TARGET_EFAULT;
1552 }
1553 } else {
1554 if (target_to_host_timespec(timeout_ts, arg3)) {
1555 unlock_user(target_pfd, arg1, 0);
1556 return -TARGET_EFAULT;
1557 }
1558 }
1559 } else {
1560 timeout_ts = NULL;
1561 }
1562
1563 if (arg4) {
Richard Hendersondb36aa72022-03-15 01:43:08 -07001564 ret = process_sigsuspend_mask(&set, arg4, arg5);
1565 if (ret != 0) {
Filip Bozutae5ce9682020-08-25 00:30:49 +02001566 unlock_user(target_pfd, arg1, 0);
Richard Hendersondb36aa72022-03-15 01:43:08 -07001567 return ret;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001568 }
Filip Bozutae5ce9682020-08-25 00:30:49 +02001569 }
1570
1571 ret = get_errno(safe_ppoll(pfd, nfds, timeout_ts,
1572 set, SIGSET_T_SIZE));
1573
Richard Hendersondb36aa72022-03-15 01:43:08 -07001574 if (set) {
1575 finish_sigsuspend_mask(ret);
1576 }
Filip Bozutae5ce9682020-08-25 00:30:49 +02001577 if (!is_error(ret) && arg3) {
1578 if (time64) {
1579 if (host_to_target_timespec64(arg3, timeout_ts)) {
1580 return -TARGET_EFAULT;
1581 }
1582 } else {
1583 if (host_to_target_timespec(arg3, timeout_ts)) {
1584 return -TARGET_EFAULT;
1585 }
1586 }
1587 }
Filip Bozutae5ce9682020-08-25 00:30:49 +02001588 } else {
1589 struct timespec ts, *pts;
1590
1591 if (arg3 >= 0) {
1592 /* Convert ms to secs, ns */
1593 ts.tv_sec = arg3 / 1000;
1594 ts.tv_nsec = (arg3 % 1000) * 1000000LL;
1595 pts = &ts;
1596 } else {
1597 /* -ve poll() timeout means "infinite" */
1598 pts = NULL;
1599 }
1600 ret = get_errno(safe_ppoll(pfd, nfds, pts, NULL, 0));
1601 }
1602
1603 if (!is_error(ret)) {
1604 for (i = 0; i < nfds; i++) {
1605 target_pfd[i].revents = tswap16(pfd[i].revents);
1606 }
1607 }
1608 unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds);
1609 return ret;
1610}
1611#endif
1612
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02001613static abi_long do_pipe(CPUArchState *cpu_env, abi_ulong pipedes,
Richard Hendersonfb41a662010-05-03 10:07:52 -07001614 int flags, int is_pipe2)
Riku Voipio099d6b02009-05-05 12:10:04 +03001615{
1616 int host_pipe[2];
1617 abi_long ret;
Helge Deller499d8052022-07-19 18:20:42 +02001618 ret = pipe2(host_pipe, flags);
Riku Voipio099d6b02009-05-05 12:10:04 +03001619
1620 if (is_error(ret))
1621 return get_errno(ret);
Richard Hendersonfb41a662010-05-03 10:07:52 -07001622
1623 /* Several targets have special calling conventions for the original
1624 pipe syscall, but didn't replicate this into the pipe2 syscall. */
1625 if (!is_pipe2) {
1626#if defined(TARGET_ALPHA)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02001627 cpu_env->ir[IR_A4] = host_pipe[1];
Richard Hendersonfb41a662010-05-03 10:07:52 -07001628 return host_pipe[0];
1629#elif defined(TARGET_MIPS)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02001630 cpu_env->active_tc.gpr[3] = host_pipe[1];
Richard Hendersonfb41a662010-05-03 10:07:52 -07001631 return host_pipe[0];
1632#elif defined(TARGET_SH4)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02001633 cpu_env->gregs[1] = host_pipe[1];
Richard Hendersonfb41a662010-05-03 10:07:52 -07001634 return host_pipe[0];
Peter Maydell82f05b62013-07-06 17:39:48 +01001635#elif defined(TARGET_SPARC)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02001636 cpu_env->regwptr[1] = host_pipe[1];
Peter Maydell82f05b62013-07-06 17:39:48 +01001637 return host_pipe[0];
takasi-y@ops.dti.ne.jp597c0212010-02-18 00:35:03 +09001638#endif
Richard Hendersonfb41a662010-05-03 10:07:52 -07001639 }
1640
Riku Voipio099d6b02009-05-05 12:10:04 +03001641 if (put_user_s32(host_pipe[0], pipedes)
Helge Deller6f200f52022-07-17 18:21:53 +02001642 || put_user_s32(host_pipe[1], pipedes + sizeof(abi_int)))
Riku Voipio099d6b02009-05-05 12:10:04 +03001643 return -TARGET_EFAULT;
Riku Voipio099d6b02009-05-05 12:10:04 +03001644 return get_errno(ret);
1645}
1646
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001647static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
1648 abi_ulong target_addr,
1649 socklen_t len)
1650{
1651 struct target_ip_mreqn *target_smreqn;
1652
1653 target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
1654 if (!target_smreqn)
1655 return -TARGET_EFAULT;
1656 mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
1657 mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
1658 if (len == sizeof(struct target_ip_mreqn))
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001659 mreqn->imr_ifindex = tswapal(target_smreqn->imr_ifindex);
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001660 unlock_user(target_smreqn, target_addr, 0);
1661
1662 return 0;
1663}
1664
Laurent Vivier7b36f782015-10-28 21:40:44 +01001665static inline abi_long target_to_host_sockaddr(int fd, struct sockaddr *addr,
bellard579a97f2007-11-11 14:26:47 +00001666 abi_ulong target_addr,
1667 socklen_t len)
bellard7854b052003-03-29 17:22:23 +00001668{
aurel32607175e2009-04-15 16:11:59 +00001669 const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
1670 sa_family_t sa_family;
pbrook53a59602006-03-25 19:31:22 +00001671 struct target_sockaddr *target_saddr;
1672
Laurent Vivier7b36f782015-10-28 21:40:44 +01001673 if (fd_trans_target_to_host_addr(fd)) {
1674 return fd_trans_target_to_host_addr(fd)(addr, target_addr, len);
1675 }
1676
bellard579a97f2007-11-11 14:26:47 +00001677 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
1678 if (!target_saddr)
1679 return -TARGET_EFAULT;
aurel32607175e2009-04-15 16:11:59 +00001680
1681 sa_family = tswap16(target_saddr->sa_family);
1682
1683 /* Oops. The caller might send a incomplete sun_path; sun_path
1684 * must be terminated by \0 (see the manual page), but
1685 * unfortunately it is quite common to specify sockaddr_un
1686 * length as "strlen(x->sun_path)" while it should be
1687 * "strlen(...) + 1". We'll fix that here if needed.
1688 * Linux kernel has a similar feature.
1689 */
1690
1691 if (sa_family == AF_UNIX) {
1692 if (len < unix_maxlen && len > 0) {
1693 char *cp = (char*)target_saddr;
1694
1695 if ( cp[len-1] && !cp[len] )
1696 len++;
1697 }
1698 if (len > unix_maxlen)
1699 len = unix_maxlen;
1700 }
1701
pbrook53a59602006-03-25 19:31:22 +00001702 memcpy(addr, target_saddr, len);
aurel32607175e2009-04-15 16:11:59 +00001703 addr->sa_family = sa_family;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02001704 if (sa_family == AF_NETLINK) {
1705 struct sockaddr_nl *nladdr;
1706
1707 nladdr = (struct sockaddr_nl *)addr;
1708 nladdr->nl_pid = tswap32(nladdr->nl_pid);
1709 nladdr->nl_groups = tswap32(nladdr->nl_groups);
1710 } else if (sa_family == AF_PACKET) {
Joakim Tjernlund33a29b52014-07-12 15:47:07 +02001711 struct target_sockaddr_ll *lladdr;
1712
1713 lladdr = (struct target_sockaddr_ll *)addr;
1714 lladdr->sll_ifindex = tswap32(lladdr->sll_ifindex);
1715 lladdr->sll_hatype = tswap16(lladdr->sll_hatype);
1716 }
pbrook53a59602006-03-25 19:31:22 +00001717 unlock_user(target_saddr, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001718
1719 return 0;
bellard7854b052003-03-29 17:22:23 +00001720}
1721
bellard579a97f2007-11-11 14:26:47 +00001722static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
1723 struct sockaddr *addr,
1724 socklen_t len)
bellard7854b052003-03-29 17:22:23 +00001725{
pbrook53a59602006-03-25 19:31:22 +00001726 struct target_sockaddr *target_saddr;
1727
Peter Maydella1e22192016-07-07 15:44:43 +01001728 if (len == 0) {
1729 return 0;
1730 }
Philippe Mathieu-Daudé68607102017-07-26 23:42:18 -03001731 assert(addr);
Peter Maydella1e22192016-07-07 15:44:43 +01001732
bellard579a97f2007-11-11 14:26:47 +00001733 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
1734 if (!target_saddr)
1735 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001736 memcpy(target_saddr, addr, len);
Peter Maydella1e22192016-07-07 15:44:43 +01001737 if (len >= offsetof(struct target_sockaddr, sa_family) +
1738 sizeof(target_saddr->sa_family)) {
1739 target_saddr->sa_family = tswap16(addr->sa_family);
1740 }
Philippe Mathieu-Daudéa47401b2019-10-21 13:48:52 +02001741 if (addr->sa_family == AF_NETLINK &&
1742 len >= sizeof(struct target_sockaddr_nl)) {
1743 struct target_sockaddr_nl *target_nl =
1744 (struct target_sockaddr_nl *)target_saddr;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02001745 target_nl->nl_pid = tswap32(target_nl->nl_pid);
1746 target_nl->nl_groups = tswap32(target_nl->nl_groups);
Laurent Viviera82ea932016-06-27 00:18:22 +02001747 } else if (addr->sa_family == AF_PACKET) {
1748 struct sockaddr_ll *target_ll = (struct sockaddr_ll *)target_saddr;
1749 target_ll->sll_ifindex = tswap32(target_ll->sll_ifindex);
1750 target_ll->sll_hatype = tswap16(target_ll->sll_hatype);
Helge Delleree1ac3a2017-02-18 23:31:30 +01001751 } else if (addr->sa_family == AF_INET6 &&
1752 len >= sizeof(struct target_sockaddr_in6)) {
1753 struct target_sockaddr_in6 *target_in6 =
1754 (struct target_sockaddr_in6 *)target_saddr;
1755 target_in6->sin6_scope_id = tswap16(target_in6->sin6_scope_id);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02001756 }
pbrook53a59602006-03-25 19:31:22 +00001757 unlock_user(target_saddr, target_addr, len);
bellard579a97f2007-11-11 14:26:47 +00001758
1759 return 0;
bellard7854b052003-03-29 17:22:23 +00001760}
1761
bellard5a4a8982007-11-11 17:39:18 +00001762static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
1763 struct target_msghdr *target_msgh)
bellard7854b052003-03-29 17:22:23 +00001764{
1765 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001766 abi_long msg_controllen;
1767 abi_ulong target_cmsg_addr;
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001768 struct target_cmsghdr *target_cmsg, *target_cmsg_start;
bellard7854b052003-03-29 17:22:23 +00001769 socklen_t space = 0;
bellard5a4a8982007-11-11 17:39:18 +00001770
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001771 msg_controllen = tswapal(target_msgh->msg_controllen);
bellard5a4a8982007-11-11 17:39:18 +00001772 if (msg_controllen < sizeof (struct target_cmsghdr))
1773 goto the_end;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001774 target_cmsg_addr = tswapal(target_msgh->msg_control);
bellard5a4a8982007-11-11 17:39:18 +00001775 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001776 target_cmsg_start = target_cmsg;
bellard5a4a8982007-11-11 17:39:18 +00001777 if (!target_cmsg)
1778 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001779
1780 while (cmsg && target_cmsg) {
1781 void *data = CMSG_DATA(cmsg);
1782 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1783
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001784 int len = tswapal(target_cmsg->cmsg_len)
Peter Maydellad762b92017-12-15 13:52:56 +00001785 - sizeof(struct target_cmsghdr);
bellard7854b052003-03-29 17:22:23 +00001786
1787 space += CMSG_SPACE(len);
1788 if (space > msgh->msg_controllen) {
1789 space -= CMSG_SPACE(len);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001790 /* This is a QEMU bug, since we allocated the payload
1791 * area ourselves (unlike overflow in host-to-target
1792 * conversion, which is just the guest giving us a buffer
1793 * that's too small). It can't happen for the payload types
1794 * we currently support; if it becomes an issue in future
1795 * we would need to improve our allocation strategy to
1796 * something more intelligent than "twice the size of the
1797 * target buffer we're reading from".
1798 */
Josh Kunz39be5352020-02-03 18:54:13 -08001799 qemu_log_mask(LOG_UNIMP,
1800 ("Unsupported ancillary data %d/%d: "
1801 "unhandled msg size\n"),
1802 tswap32(target_cmsg->cmsg_level),
1803 tswap32(target_cmsg->cmsg_type));
bellard7854b052003-03-29 17:22:23 +00001804 break;
1805 }
1806
Petar Jovanovicdbf4f792013-09-13 19:27:29 +02001807 if (tswap32(target_cmsg->cmsg_level) == TARGET_SOL_SOCKET) {
1808 cmsg->cmsg_level = SOL_SOCKET;
1809 } else {
1810 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
1811 }
bellard7854b052003-03-29 17:22:23 +00001812 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
1813 cmsg->cmsg_len = CMSG_LEN(len);
1814
Alex Suykov30b8b682014-12-23 07:52:58 +02001815 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +00001816 int *fd = (int *)data;
1817 int *target_fd = (int *)target_data;
1818 int i, numfds = len / sizeof(int);
1819
Peter Maydell876e23c2015-05-26 19:46:32 +01001820 for (i = 0; i < numfds; i++) {
1821 __get_user(fd[i], target_fd + i);
1822 }
Alex Suykov30b8b682014-12-23 07:52:58 +02001823 } else if (cmsg->cmsg_level == SOL_SOCKET
1824 && cmsg->cmsg_type == SCM_CREDENTIALS) {
1825 struct ucred *cred = (struct ucred *)data;
1826 struct target_ucred *target_cred =
1827 (struct target_ucred *)target_data;
1828
Peter Maydell876e23c2015-05-26 19:46:32 +01001829 __get_user(cred->pid, &target_cred->pid);
1830 __get_user(cred->uid, &target_cred->uid);
1831 __get_user(cred->gid, &target_cred->gid);
Helge Deller27404b62022-12-12 18:34:15 +01001832 } else if (cmsg->cmsg_level == SOL_ALG) {
1833 uint32_t *dst = (uint32_t *)data;
1834
1835 memcpy(dst, target_data, len);
1836 /* fix endianess of first 32-bit word */
1837 if (len >= sizeof(uint32_t)) {
1838 *dst = tswap32(*dst);
1839 }
Alex Suykov30b8b682014-12-23 07:52:58 +02001840 } else {
Josh Kunz39be5352020-02-03 18:54:13 -08001841 qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n",
1842 cmsg->cmsg_level, cmsg->cmsg_type);
Alex Suykov30b8b682014-12-23 07:52:58 +02001843 memcpy(data, target_data, len);
bellard7854b052003-03-29 17:22:23 +00001844 }
1845
1846 cmsg = CMSG_NXTHDR(msgh, cmsg);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001847 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg,
1848 target_cmsg_start);
bellard7854b052003-03-29 17:22:23 +00001849 }
bellard5a4a8982007-11-11 17:39:18 +00001850 unlock_user(target_cmsg, target_cmsg_addr, 0);
1851 the_end:
bellard7854b052003-03-29 17:22:23 +00001852 msgh->msg_controllen = space;
bellard5a4a8982007-11-11 17:39:18 +00001853 return 0;
bellard7854b052003-03-29 17:22:23 +00001854}
1855
bellard5a4a8982007-11-11 17:39:18 +00001856static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
1857 struct msghdr *msgh)
bellard7854b052003-03-29 17:22:23 +00001858{
1859 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001860 abi_long msg_controllen;
1861 abi_ulong target_cmsg_addr;
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001862 struct target_cmsghdr *target_cmsg, *target_cmsg_start;
bellard7854b052003-03-29 17:22:23 +00001863 socklen_t space = 0;
1864
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001865 msg_controllen = tswapal(target_msgh->msg_controllen);
bellard5a4a8982007-11-11 17:39:18 +00001866 if (msg_controllen < sizeof (struct target_cmsghdr))
1867 goto the_end;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001868 target_cmsg_addr = tswapal(target_msgh->msg_control);
bellard5a4a8982007-11-11 17:39:18 +00001869 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001870 target_cmsg_start = target_cmsg;
bellard5a4a8982007-11-11 17:39:18 +00001871 if (!target_cmsg)
1872 return -TARGET_EFAULT;
1873
bellard7854b052003-03-29 17:22:23 +00001874 while (cmsg && target_cmsg) {
1875 void *data = CMSG_DATA(cmsg);
1876 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1877
Peter Maydellad762b92017-12-15 13:52:56 +00001878 int len = cmsg->cmsg_len - sizeof(struct cmsghdr);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001879 int tgt_len, tgt_space;
bellard7854b052003-03-29 17:22:23 +00001880
Peter Maydellc2aeb252015-05-26 19:46:31 +01001881 /* We never copy a half-header but may copy half-data;
1882 * this is Linux's behaviour in put_cmsg(). Note that
1883 * truncation here is a guest problem (which we report
1884 * to the guest via the CTRUNC bit), unlike truncation
1885 * in target_to_host_cmsg, which is a QEMU bug.
1886 */
Peter Maydell71749702017-12-15 13:52:55 +00001887 if (msg_controllen < sizeof(struct target_cmsghdr)) {
Peter Maydellc2aeb252015-05-26 19:46:31 +01001888 target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
bellard7854b052003-03-29 17:22:23 +00001889 break;
1890 }
1891
Petar Jovanovicdbf4f792013-09-13 19:27:29 +02001892 if (cmsg->cmsg_level == SOL_SOCKET) {
1893 target_cmsg->cmsg_level = tswap32(TARGET_SOL_SOCKET);
1894 } else {
1895 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
1896 }
bellard7854b052003-03-29 17:22:23 +00001897 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
bellard7854b052003-03-29 17:22:23 +00001898
Peter Maydellc2aeb252015-05-26 19:46:31 +01001899 /* Payload types which need a different size of payload on
1900 * the target must adjust tgt_len here.
1901 */
Peter Maydell309786c2018-05-18 19:47:15 +01001902 tgt_len = len;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001903 switch (cmsg->cmsg_level) {
1904 case SOL_SOCKET:
1905 switch (cmsg->cmsg_type) {
1906 case SO_TIMESTAMP:
1907 tgt_len = sizeof(struct target_timeval);
1908 break;
1909 default:
1910 break;
1911 }
Peter Maydell309786c2018-05-18 19:47:15 +01001912 break;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001913 default:
1914 break;
1915 }
1916
Peter Maydell71749702017-12-15 13:52:55 +00001917 if (msg_controllen < TARGET_CMSG_LEN(tgt_len)) {
Peter Maydellc2aeb252015-05-26 19:46:31 +01001918 target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
Peter Maydell71749702017-12-15 13:52:55 +00001919 tgt_len = msg_controllen - sizeof(struct target_cmsghdr);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001920 }
1921
1922 /* We must now copy-and-convert len bytes of payload
1923 * into tgt_len bytes of destination space. Bear in mind
1924 * that in both source and destination we may be dealing
1925 * with a truncated value!
1926 */
Huw Davies52b65492014-04-17 14:02:47 +01001927 switch (cmsg->cmsg_level) {
1928 case SOL_SOCKET:
1929 switch (cmsg->cmsg_type) {
1930 case SCM_RIGHTS:
1931 {
1932 int *fd = (int *)data;
1933 int *target_fd = (int *)target_data;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001934 int i, numfds = tgt_len / sizeof(int);
bellard7854b052003-03-29 17:22:23 +00001935
Peter Maydell876e23c2015-05-26 19:46:32 +01001936 for (i = 0; i < numfds; i++) {
1937 __put_user(fd[i], target_fd + i);
1938 }
Huw Davies52b65492014-04-17 14:02:47 +01001939 break;
1940 }
1941 case SO_TIMESTAMP:
1942 {
1943 struct timeval *tv = (struct timeval *)data;
1944 struct target_timeval *target_tv =
1945 (struct target_timeval *)target_data;
Jing Huangaebf5bc2012-07-24 14:01:42 +00001946
Peter Maydellc2aeb252015-05-26 19:46:31 +01001947 if (len != sizeof(struct timeval) ||
1948 tgt_len != sizeof(struct target_timeval)) {
Huw Davies52b65492014-04-17 14:02:47 +01001949 goto unimplemented;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001950 }
Huw Davies52b65492014-04-17 14:02:47 +01001951
1952 /* copy struct timeval to target */
Peter Maydell876e23c2015-05-26 19:46:32 +01001953 __put_user(tv->tv_sec, &target_tv->tv_sec);
1954 __put_user(tv->tv_usec, &target_tv->tv_usec);
Huw Davies52b65492014-04-17 14:02:47 +01001955 break;
1956 }
Huw Davies4bc29752014-04-17 14:02:48 +01001957 case SCM_CREDENTIALS:
1958 {
1959 struct ucred *cred = (struct ucred *)data;
1960 struct target_ucred *target_cred =
1961 (struct target_ucred *)target_data;
1962
1963 __put_user(cred->pid, &target_cred->pid);
1964 __put_user(cred->uid, &target_cred->uid);
1965 __put_user(cred->gid, &target_cred->gid);
1966 break;
1967 }
Huw Davies52b65492014-04-17 14:02:47 +01001968 default:
1969 goto unimplemented;
1970 }
1971 break;
1972
Helge Delleree1ac3a2017-02-18 23:31:30 +01001973 case SOL_IP:
1974 switch (cmsg->cmsg_type) {
1975 case IP_TTL:
1976 {
1977 uint32_t *v = (uint32_t *)data;
1978 uint32_t *t_int = (uint32_t *)target_data;
1979
Peter Maydell71749702017-12-15 13:52:55 +00001980 if (len != sizeof(uint32_t) ||
1981 tgt_len != sizeof(uint32_t)) {
1982 goto unimplemented;
1983 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01001984 __put_user(*v, t_int);
1985 break;
1986 }
1987 case IP_RECVERR:
1988 {
1989 struct errhdr_t {
1990 struct sock_extended_err ee;
1991 struct sockaddr_in offender;
1992 };
1993 struct errhdr_t *errh = (struct errhdr_t *)data;
1994 struct errhdr_t *target_errh =
1995 (struct errhdr_t *)target_data;
1996
Peter Maydell71749702017-12-15 13:52:55 +00001997 if (len != sizeof(struct errhdr_t) ||
1998 tgt_len != sizeof(struct errhdr_t)) {
1999 goto unimplemented;
2000 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01002001 __put_user(errh->ee.ee_errno, &target_errh->ee.ee_errno);
2002 __put_user(errh->ee.ee_origin, &target_errh->ee.ee_origin);
2003 __put_user(errh->ee.ee_type, &target_errh->ee.ee_type);
2004 __put_user(errh->ee.ee_code, &target_errh->ee.ee_code);
2005 __put_user(errh->ee.ee_pad, &target_errh->ee.ee_pad);
2006 __put_user(errh->ee.ee_info, &target_errh->ee.ee_info);
2007 __put_user(errh->ee.ee_data, &target_errh->ee.ee_data);
2008 host_to_target_sockaddr((unsigned long) &target_errh->offender,
2009 (void *) &errh->offender, sizeof(errh->offender));
2010 break;
2011 }
2012 default:
2013 goto unimplemented;
2014 }
2015 break;
2016
2017 case SOL_IPV6:
2018 switch (cmsg->cmsg_type) {
2019 case IPV6_HOPLIMIT:
2020 {
2021 uint32_t *v = (uint32_t *)data;
2022 uint32_t *t_int = (uint32_t *)target_data;
2023
Peter Maydell71749702017-12-15 13:52:55 +00002024 if (len != sizeof(uint32_t) ||
2025 tgt_len != sizeof(uint32_t)) {
2026 goto unimplemented;
2027 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01002028 __put_user(*v, t_int);
2029 break;
2030 }
2031 case IPV6_RECVERR:
2032 {
2033 struct errhdr6_t {
2034 struct sock_extended_err ee;
2035 struct sockaddr_in6 offender;
2036 };
2037 struct errhdr6_t *errh = (struct errhdr6_t *)data;
2038 struct errhdr6_t *target_errh =
2039 (struct errhdr6_t *)target_data;
2040
Peter Maydell71749702017-12-15 13:52:55 +00002041 if (len != sizeof(struct errhdr6_t) ||
2042 tgt_len != sizeof(struct errhdr6_t)) {
2043 goto unimplemented;
2044 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01002045 __put_user(errh->ee.ee_errno, &target_errh->ee.ee_errno);
2046 __put_user(errh->ee.ee_origin, &target_errh->ee.ee_origin);
2047 __put_user(errh->ee.ee_type, &target_errh->ee.ee_type);
2048 __put_user(errh->ee.ee_code, &target_errh->ee.ee_code);
2049 __put_user(errh->ee.ee_pad, &target_errh->ee.ee_pad);
2050 __put_user(errh->ee.ee_info, &target_errh->ee.ee_info);
2051 __put_user(errh->ee.ee_data, &target_errh->ee.ee_data);
2052 host_to_target_sockaddr((unsigned long) &target_errh->offender,
2053 (void *) &errh->offender, sizeof(errh->offender));
2054 break;
2055 }
2056 default:
2057 goto unimplemented;
2058 }
2059 break;
2060
Huw Davies52b65492014-04-17 14:02:47 +01002061 default:
2062 unimplemented:
Josh Kunz39be5352020-02-03 18:54:13 -08002063 qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n",
2064 cmsg->cmsg_level, cmsg->cmsg_type);
Peter Maydellc2aeb252015-05-26 19:46:31 +01002065 memcpy(target_data, data, MIN(len, tgt_len));
2066 if (tgt_len > len) {
2067 memset(target_data + len, 0, tgt_len - len);
2068 }
bellard7854b052003-03-29 17:22:23 +00002069 }
2070
Peter Maydell71749702017-12-15 13:52:55 +00002071 target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(tgt_len));
2072 tgt_space = TARGET_CMSG_SPACE(tgt_len);
Peter Maydellc2aeb252015-05-26 19:46:31 +01002073 if (msg_controllen < tgt_space) {
2074 tgt_space = msg_controllen;
2075 }
2076 msg_controllen -= tgt_space;
2077 space += tgt_space;
bellard7854b052003-03-29 17:22:23 +00002078 cmsg = CMSG_NXTHDR(msgh, cmsg);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02002079 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg,
2080 target_cmsg_start);
bellard7854b052003-03-29 17:22:23 +00002081 }
bellard5a4a8982007-11-11 17:39:18 +00002082 unlock_user(target_cmsg, target_cmsg_addr, space);
2083 the_end:
Matthias Brauncbb21ee2011-08-12 19:57:41 +02002084 target_msgh->msg_controllen = tswapal(space);
bellard5a4a8982007-11-11 17:39:18 +00002085 return 0;
bellard7854b052003-03-29 17:22:23 +00002086}
2087
ths0da46a62007-10-20 20:23:07 +00002088/* do_setsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002089static abi_long do_setsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00002090 abi_ulong optval_addr, socklen_t optlen)
bellard7854b052003-03-29 17:22:23 +00002091{
blueswir1992f48a2007-10-14 16:27:31 +00002092 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +00002093 int val;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02002094 struct ip_mreqn *ip_mreq;
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02002095 struct ip_mreq_source *ip_mreq_source;
ths3b46e622007-09-17 08:09:54 +00002096
bellard8853f862004-02-22 14:57:26 +00002097 switch(level) {
2098 case SOL_TCP:
Shu-Chun Wengfe51b0a2020-12-18 11:32:11 -08002099 case SOL_UDP:
2100 /* TCP and UDP options all take an 'int' value. */
bellard7854b052003-03-29 17:22:23 +00002101 if (optlen < sizeof(uint32_t))
ths0da46a62007-10-20 20:23:07 +00002102 return -TARGET_EINVAL;
ths3b46e622007-09-17 08:09:54 +00002103
bellard2f619692007-11-16 10:46:05 +00002104 if (get_user_u32(val, optval_addr))
2105 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00002106 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
2107 break;
2108 case SOL_IP:
2109 switch(optname) {
bellard2efbe912005-07-23 15:10:20 +00002110 case IP_TOS:
2111 case IP_TTL:
bellard8853f862004-02-22 14:57:26 +00002112 case IP_HDRINCL:
bellard2efbe912005-07-23 15:10:20 +00002113 case IP_ROUTER_ALERT:
2114 case IP_RECVOPTS:
2115 case IP_RETOPTS:
2116 case IP_PKTINFO:
2117 case IP_MTU_DISCOVER:
2118 case IP_RECVERR:
Helge Delleree1ac3a2017-02-18 23:31:30 +01002119 case IP_RECVTTL:
bellard2efbe912005-07-23 15:10:20 +00002120 case IP_RECVTOS:
2121#ifdef IP_FREEBIND
2122 case IP_FREEBIND:
2123#endif
2124 case IP_MULTICAST_TTL:
2125 case IP_MULTICAST_LOOP:
bellard8853f862004-02-22 14:57:26 +00002126 val = 0;
2127 if (optlen >= sizeof(uint32_t)) {
bellard2f619692007-11-16 10:46:05 +00002128 if (get_user_u32(val, optval_addr))
2129 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00002130 } else if (optlen >= 1) {
bellard2f619692007-11-16 10:46:05 +00002131 if (get_user_u8(val, optval_addr))
2132 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00002133 }
2134 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
2135 break;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02002136 case IP_ADD_MEMBERSHIP:
2137 case IP_DROP_MEMBERSHIP:
2138 if (optlen < sizeof (struct target_ip_mreq) ||
2139 optlen > sizeof (struct target_ip_mreqn))
2140 return -TARGET_EINVAL;
2141
2142 ip_mreq = (struct ip_mreqn *) alloca(optlen);
2143 target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
2144 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen));
2145 break;
2146
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02002147 case IP_BLOCK_SOURCE:
2148 case IP_UNBLOCK_SOURCE:
2149 case IP_ADD_SOURCE_MEMBERSHIP:
2150 case IP_DROP_SOURCE_MEMBERSHIP:
2151 if (optlen != sizeof (struct target_ip_mreq_source))
2152 return -TARGET_EINVAL;
2153
2154 ip_mreq_source = lock_user(VERIFY_READ, optval_addr, optlen, 1);
Peter Maydell74e43b02021-08-09 16:54:24 +01002155 if (!ip_mreq_source) {
2156 return -TARGET_EFAULT;
2157 }
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02002158 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen));
2159 unlock_user (ip_mreq_source, optval_addr, 0);
2160 break;
2161
bellard8853f862004-02-22 14:57:26 +00002162 default:
2163 goto unimplemented;
2164 }
2165 break;
Laurent Vivier0d78b3b2013-08-30 01:46:43 +02002166 case SOL_IPV6:
2167 switch (optname) {
2168 case IPV6_MTU_DISCOVER:
2169 case IPV6_MTU:
2170 case IPV6_V6ONLY:
2171 case IPV6_RECVPKTINFO:
Helge Delleree1ac3a2017-02-18 23:31:30 +01002172 case IPV6_UNICAST_HOPS:
Laurent Vivier21749c42018-06-27 23:21:52 +02002173 case IPV6_MULTICAST_HOPS:
2174 case IPV6_MULTICAST_LOOP:
Helge Delleree1ac3a2017-02-18 23:31:30 +01002175 case IPV6_RECVERR:
2176 case IPV6_RECVHOPLIMIT:
2177 case IPV6_2292HOPLIMIT:
2178 case IPV6_CHECKSUM:
Helge Dellerb9cce6d2019-03-10 12:12:16 +01002179 case IPV6_ADDRFORM:
2180 case IPV6_2292PKTINFO:
2181 case IPV6_RECVTCLASS:
2182 case IPV6_RECVRTHDR:
2183 case IPV6_2292RTHDR:
2184 case IPV6_RECVHOPOPTS:
2185 case IPV6_2292HOPOPTS:
2186 case IPV6_RECVDSTOPTS:
2187 case IPV6_2292DSTOPTS:
2188 case IPV6_TCLASS:
Shu-Chun Weng22db1212020-12-18 11:32:12 -08002189 case IPV6_ADDR_PREFERENCES:
Helge Dellerb9cce6d2019-03-10 12:12:16 +01002190#ifdef IPV6_RECVPATHMTU
2191 case IPV6_RECVPATHMTU:
2192#endif
2193#ifdef IPV6_TRANSPARENT
2194 case IPV6_TRANSPARENT:
2195#endif
2196#ifdef IPV6_FREEBIND
2197 case IPV6_FREEBIND:
2198#endif
2199#ifdef IPV6_RECVORIGDSTADDR
2200 case IPV6_RECVORIGDSTADDR:
2201#endif
Laurent Vivier0d78b3b2013-08-30 01:46:43 +02002202 val = 0;
2203 if (optlen < sizeof(uint32_t)) {
2204 return -TARGET_EINVAL;
2205 }
2206 if (get_user_u32(val, optval_addr)) {
2207 return -TARGET_EFAULT;
2208 }
2209 ret = get_errno(setsockopt(sockfd, level, optname,
2210 &val, sizeof(val)));
2211 break;
Helge Delleree1ac3a2017-02-18 23:31:30 +01002212 case IPV6_PKTINFO:
2213 {
2214 struct in6_pktinfo pki;
2215
2216 if (optlen < sizeof(pki)) {
2217 return -TARGET_EINVAL;
2218 }
2219
2220 if (copy_from_user(&pki, optval_addr, sizeof(pki))) {
2221 return -TARGET_EFAULT;
2222 }
2223
2224 pki.ipi6_ifindex = tswap32(pki.ipi6_ifindex);
2225
2226 ret = get_errno(setsockopt(sockfd, level, optname,
2227 &pki, sizeof(pki)));
2228 break;
2229 }
Neng Chen22bf4ee2019-06-19 16:17:10 +02002230 case IPV6_ADD_MEMBERSHIP:
2231 case IPV6_DROP_MEMBERSHIP:
2232 {
2233 struct ipv6_mreq ipv6mreq;
2234
2235 if (optlen < sizeof(ipv6mreq)) {
2236 return -TARGET_EINVAL;
2237 }
2238
2239 if (copy_from_user(&ipv6mreq, optval_addr, sizeof(ipv6mreq))) {
2240 return -TARGET_EFAULT;
2241 }
2242
2243 ipv6mreq.ipv6mr_interface = tswap32(ipv6mreq.ipv6mr_interface);
2244
2245 ret = get_errno(setsockopt(sockfd, level, optname,
2246 &ipv6mreq, sizeof(ipv6mreq)));
2247 break;
2248 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01002249 default:
2250 goto unimplemented;
2251 }
2252 break;
2253 case SOL_ICMPV6:
2254 switch (optname) {
2255 case ICMPV6_FILTER:
2256 {
2257 struct icmp6_filter icmp6f;
2258
2259 if (optlen > sizeof(icmp6f)) {
2260 optlen = sizeof(icmp6f);
2261 }
2262
2263 if (copy_from_user(&icmp6f, optval_addr, optlen)) {
2264 return -TARGET_EFAULT;
2265 }
2266
2267 for (val = 0; val < 8; val++) {
2268 icmp6f.data[val] = tswap32(icmp6f.data[val]);
2269 }
2270
2271 ret = get_errno(setsockopt(sockfd, level, optname,
2272 &icmp6f, optlen));
2273 break;
2274 }
Laurent Vivier0d78b3b2013-08-30 01:46:43 +02002275 default:
2276 goto unimplemented;
2277 }
2278 break;
Jing Huang920394d2012-07-24 13:59:23 +00002279 case SOL_RAW:
2280 switch (optname) {
2281 case ICMP_FILTER:
Helge Delleree1ac3a2017-02-18 23:31:30 +01002282 case IPV6_CHECKSUM:
2283 /* those take an u32 value */
Jing Huang920394d2012-07-24 13:59:23 +00002284 if (optlen < sizeof(uint32_t)) {
2285 return -TARGET_EINVAL;
2286 }
2287
2288 if (get_user_u32(val, optval_addr)) {
2289 return -TARGET_EFAULT;
2290 }
2291 ret = get_errno(setsockopt(sockfd, level, optname,
2292 &val, sizeof(val)));
2293 break;
2294
2295 default:
2296 goto unimplemented;
2297 }
2298 break;
Yunqiang Suf31dddd2019-06-19 16:17:11 +02002299#if defined(SOL_ALG) && defined(ALG_SET_KEY) && defined(ALG_SET_AEAD_AUTHSIZE)
2300 case SOL_ALG:
2301 switch (optname) {
2302 case ALG_SET_KEY:
2303 {
2304 char *alg_key = g_malloc(optlen);
2305
2306 if (!alg_key) {
2307 return -TARGET_ENOMEM;
2308 }
2309 if (copy_from_user(alg_key, optval_addr, optlen)) {
2310 g_free(alg_key);
2311 return -TARGET_EFAULT;
2312 }
2313 ret = get_errno(setsockopt(sockfd, level, optname,
2314 alg_key, optlen));
2315 g_free(alg_key);
2316 break;
2317 }
2318 case ALG_SET_AEAD_AUTHSIZE:
2319 {
2320 ret = get_errno(setsockopt(sockfd, level, optname,
2321 NULL, optlen));
2322 break;
2323 }
2324 default:
2325 goto unimplemented;
2326 }
2327 break;
2328#endif
bellard3532fa72006-06-24 15:06:03 +00002329 case TARGET_SOL_SOCKET:
bellard8853f862004-02-22 14:57:26 +00002330 switch (optname) {
Laurent Vivier1b09aeb2013-01-01 08:24:11 +00002331 case TARGET_SO_RCVTIMEO:
2332 {
2333 struct timeval tv;
2334
2335 optname = SO_RCVTIMEO;
2336
2337set_timeout:
2338 if (optlen != sizeof(struct target_timeval)) {
2339 return -TARGET_EINVAL;
2340 }
2341
2342 if (copy_from_user_timeval(&tv, optval_addr)) {
2343 return -TARGET_EFAULT;
2344 }
2345
2346 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
2347 &tv, sizeof(tv)));
2348 return ret;
2349 }
2350 case TARGET_SO_SNDTIMEO:
2351 optname = SO_SNDTIMEO;
2352 goto set_timeout;
Laurent Vivierf57d4192013-08-30 01:46:41 +02002353 case TARGET_SO_ATTACH_FILTER:
2354 {
2355 struct target_sock_fprog *tfprog;
2356 struct target_sock_filter *tfilter;
2357 struct sock_fprog fprog;
2358 struct sock_filter *filter;
2359 int i;
2360
2361 if (optlen != sizeof(*tfprog)) {
2362 return -TARGET_EINVAL;
2363 }
2364 if (!lock_user_struct(VERIFY_READ, tfprog, optval_addr, 0)) {
2365 return -TARGET_EFAULT;
2366 }
2367 if (!lock_user_struct(VERIFY_READ, tfilter,
2368 tswapal(tfprog->filter), 0)) {
2369 unlock_user_struct(tfprog, optval_addr, 1);
2370 return -TARGET_EFAULT;
2371 }
2372
2373 fprog.len = tswap16(tfprog->len);
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05302374 filter = g_try_new(struct sock_filter, fprog.len);
Laurent Vivierf57d4192013-08-30 01:46:41 +02002375 if (filter == NULL) {
2376 unlock_user_struct(tfilter, tfprog->filter, 1);
2377 unlock_user_struct(tfprog, optval_addr, 1);
2378 return -TARGET_ENOMEM;
2379 }
2380 for (i = 0; i < fprog.len; i++) {
2381 filter[i].code = tswap16(tfilter[i].code);
2382 filter[i].jt = tfilter[i].jt;
2383 filter[i].jf = tfilter[i].jf;
2384 filter[i].k = tswap32(tfilter[i].k);
2385 }
2386 fprog.filter = filter;
2387
2388 ret = get_errno(setsockopt(sockfd, SOL_SOCKET,
2389 SO_ATTACH_FILTER, &fprog, sizeof(fprog)));
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05302390 g_free(filter);
Laurent Vivierf57d4192013-08-30 01:46:41 +02002391
2392 unlock_user_struct(tfilter, tfprog->filter, 1);
2393 unlock_user_struct(tfprog, optval_addr, 1);
2394 return ret;
2395 }
Joakim Tjernlund451aaf62014-07-12 15:47:06 +02002396 case TARGET_SO_BINDTODEVICE:
2397 {
2398 char *dev_ifname, *addr_ifname;
2399
2400 if (optlen > IFNAMSIZ - 1) {
2401 optlen = IFNAMSIZ - 1;
2402 }
2403 dev_ifname = lock_user(VERIFY_READ, optval_addr, optlen, 1);
2404 if (!dev_ifname) {
2405 return -TARGET_EFAULT;
2406 }
2407 optname = SO_BINDTODEVICE;
2408 addr_ifname = alloca(IFNAMSIZ);
2409 memcpy(addr_ifname, dev_ifname, optlen);
2410 addr_ifname[optlen] = 0;
Chen Gangfad6c582016-01-11 13:58:50 +08002411 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
2412 addr_ifname, optlen));
Joakim Tjernlund451aaf62014-07-12 15:47:06 +02002413 unlock_user (dev_ifname, optval_addr, 0);
2414 return ret;
2415 }
Carlo Marcelo Arenas Belón83eb6e52018-08-24 01:56:01 -07002416 case TARGET_SO_LINGER:
2417 {
2418 struct linger lg;
2419 struct target_linger *tlg;
2420
2421 if (optlen != sizeof(struct target_linger)) {
2422 return -TARGET_EINVAL;
2423 }
2424 if (!lock_user_struct(VERIFY_READ, tlg, optval_addr, 1)) {
2425 return -TARGET_EFAULT;
2426 }
2427 __get_user(lg.l_onoff, &tlg->l_onoff);
2428 __get_user(lg.l_linger, &tlg->l_linger);
2429 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, SO_LINGER,
2430 &lg, sizeof(lg)));
2431 unlock_user_struct(tlg, optval_addr, 0);
2432 return ret;
2433 }
bellard8853f862004-02-22 14:57:26 +00002434 /* Options with 'int' argument. */
bellard3532fa72006-06-24 15:06:03 +00002435 case TARGET_SO_DEBUG:
2436 optname = SO_DEBUG;
2437 break;
2438 case TARGET_SO_REUSEADDR:
2439 optname = SO_REUSEADDR;
2440 break;
Yunqiang Su113a9dd2018-10-30 13:55:08 +01002441#ifdef SO_REUSEPORT
2442 case TARGET_SO_REUSEPORT:
2443 optname = SO_REUSEPORT;
2444 break;
2445#endif
bellard3532fa72006-06-24 15:06:03 +00002446 case TARGET_SO_TYPE:
2447 optname = SO_TYPE;
2448 break;
2449 case TARGET_SO_ERROR:
2450 optname = SO_ERROR;
2451 break;
2452 case TARGET_SO_DONTROUTE:
2453 optname = SO_DONTROUTE;
2454 break;
2455 case TARGET_SO_BROADCAST:
2456 optname = SO_BROADCAST;
2457 break;
2458 case TARGET_SO_SNDBUF:
2459 optname = SO_SNDBUF;
2460 break;
Paul Burtond79b6cc2014-06-22 11:25:35 +01002461 case TARGET_SO_SNDBUFFORCE:
2462 optname = SO_SNDBUFFORCE;
2463 break;
bellard3532fa72006-06-24 15:06:03 +00002464 case TARGET_SO_RCVBUF:
2465 optname = SO_RCVBUF;
2466 break;
Paul Burtond79b6cc2014-06-22 11:25:35 +01002467 case TARGET_SO_RCVBUFFORCE:
2468 optname = SO_RCVBUFFORCE;
2469 break;
bellard3532fa72006-06-24 15:06:03 +00002470 case TARGET_SO_KEEPALIVE:
2471 optname = SO_KEEPALIVE;
2472 break;
2473 case TARGET_SO_OOBINLINE:
2474 optname = SO_OOBINLINE;
2475 break;
2476 case TARGET_SO_NO_CHECK:
2477 optname = SO_NO_CHECK;
2478 break;
2479 case TARGET_SO_PRIORITY:
2480 optname = SO_PRIORITY;
2481 break;
bellard5e83e8e2005-03-01 22:32:06 +00002482#ifdef SO_BSDCOMPAT
bellard3532fa72006-06-24 15:06:03 +00002483 case TARGET_SO_BSDCOMPAT:
2484 optname = SO_BSDCOMPAT;
2485 break;
bellard5e83e8e2005-03-01 22:32:06 +00002486#endif
bellard3532fa72006-06-24 15:06:03 +00002487 case TARGET_SO_PASSCRED:
2488 optname = SO_PASSCRED;
2489 break;
Paul Burton82d0fe62014-06-22 11:25:36 +01002490 case TARGET_SO_PASSSEC:
2491 optname = SO_PASSSEC;
2492 break;
bellard3532fa72006-06-24 15:06:03 +00002493 case TARGET_SO_TIMESTAMP:
2494 optname = SO_TIMESTAMP;
2495 break;
2496 case TARGET_SO_RCVLOWAT:
2497 optname = SO_RCVLOWAT;
2498 break;
bellard8853f862004-02-22 14:57:26 +00002499 default:
2500 goto unimplemented;
2501 }
bellard3532fa72006-06-24 15:06:03 +00002502 if (optlen < sizeof(uint32_t))
bellard2f619692007-11-16 10:46:05 +00002503 return -TARGET_EINVAL;
bellard3532fa72006-06-24 15:06:03 +00002504
bellard2f619692007-11-16 10:46:05 +00002505 if (get_user_u32(val, optval_addr))
2506 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00002507 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
bellard8853f862004-02-22 14:57:26 +00002508 break;
Josh Kunza2d86682019-10-29 15:43:10 -07002509#ifdef SOL_NETLINK
2510 case SOL_NETLINK:
2511 switch (optname) {
2512 case NETLINK_PKTINFO:
2513 case NETLINK_ADD_MEMBERSHIP:
2514 case NETLINK_DROP_MEMBERSHIP:
2515 case NETLINK_BROADCAST_ERROR:
2516 case NETLINK_NO_ENOBUFS:
2517#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2518 case NETLINK_LISTEN_ALL_NSID:
2519 case NETLINK_CAP_ACK:
2520#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2521#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
2522 case NETLINK_EXT_ACK:
2523#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2524#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
2525 case NETLINK_GET_STRICT_CHK:
2526#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2527 break;
2528 default:
2529 goto unimplemented;
2530 }
2531 val = 0;
2532 if (optlen < sizeof(uint32_t)) {
2533 return -TARGET_EINVAL;
2534 }
2535 if (get_user_u32(val, optval_addr)) {
2536 return -TARGET_EFAULT;
2537 }
2538 ret = get_errno(setsockopt(sockfd, SOL_NETLINK, optname, &val,
2539 sizeof(val)));
2540 break;
2541#endif /* SOL_NETLINK */
bellard7854b052003-03-29 17:22:23 +00002542 default:
bellard8853f862004-02-22 14:57:26 +00002543 unimplemented:
Josh Kunz39be5352020-02-03 18:54:13 -08002544 qemu_log_mask(LOG_UNIMP, "Unsupported setsockopt level=%d optname=%d\n",
2545 level, optname);
ths6fa13c12007-12-18 02:41:04 +00002546 ret = -TARGET_ENOPROTOOPT;
bellard7854b052003-03-29 17:22:23 +00002547 }
bellard8853f862004-02-22 14:57:26 +00002548 return ret;
bellard7854b052003-03-29 17:22:23 +00002549}
2550
ths0da46a62007-10-20 20:23:07 +00002551/* do_getsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002552static abi_long do_getsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00002553 abi_ulong optval_addr, abi_ulong optlen)
bellard7854b052003-03-29 17:22:23 +00002554{
blueswir1992f48a2007-10-14 16:27:31 +00002555 abi_long ret;
blueswir1b55266b2008-09-20 08:07:15 +00002556 int len, val;
2557 socklen_t lv;
bellard8853f862004-02-22 14:57:26 +00002558
2559 switch(level) {
bellard3532fa72006-06-24 15:06:03 +00002560 case TARGET_SOL_SOCKET:
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002561 level = SOL_SOCKET;
2562 switch (optname) {
2563 /* These don't just return a single integer */
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002564 case TARGET_SO_PEERNAME:
2565 goto unimplemented;
Andreas Schwab405dc4c2019-05-13 11:06:26 +02002566 case TARGET_SO_RCVTIMEO: {
2567 struct timeval tv;
2568 socklen_t tvlen;
2569
2570 optname = SO_RCVTIMEO;
2571
2572get_timeout:
2573 if (get_user_u32(len, optlen)) {
2574 return -TARGET_EFAULT;
2575 }
2576 if (len < 0) {
2577 return -TARGET_EINVAL;
2578 }
2579
2580 tvlen = sizeof(tv);
2581 ret = get_errno(getsockopt(sockfd, level, optname,
2582 &tv, &tvlen));
2583 if (ret < 0) {
2584 return ret;
2585 }
2586 if (len > sizeof(struct target_timeval)) {
2587 len = sizeof(struct target_timeval);
2588 }
2589 if (copy_to_user_timeval(optval_addr, &tv)) {
2590 return -TARGET_EFAULT;
2591 }
2592 if (put_user_u32(len, optlen)) {
2593 return -TARGET_EFAULT;
2594 }
2595 break;
2596 }
2597 case TARGET_SO_SNDTIMEO:
2598 optname = SO_SNDTIMEO;
2599 goto get_timeout;
Akos PASZTORY583359a2011-11-14 15:09:49 +02002600 case TARGET_SO_PEERCRED: {
2601 struct ucred cr;
2602 socklen_t crlen;
2603 struct target_ucred *tcr;
2604
2605 if (get_user_u32(len, optlen)) {
2606 return -TARGET_EFAULT;
2607 }
2608 if (len < 0) {
2609 return -TARGET_EINVAL;
2610 }
2611
2612 crlen = sizeof(cr);
2613 ret = get_errno(getsockopt(sockfd, level, SO_PEERCRED,
2614 &cr, &crlen));
2615 if (ret < 0) {
2616 return ret;
2617 }
2618 if (len > crlen) {
2619 len = crlen;
2620 }
2621 if (!lock_user_struct(VERIFY_WRITE, tcr, optval_addr, 0)) {
2622 return -TARGET_EFAULT;
2623 }
2624 __put_user(cr.pid, &tcr->pid);
2625 __put_user(cr.uid, &tcr->uid);
2626 __put_user(cr.gid, &tcr->gid);
2627 unlock_user_struct(tcr, optval_addr, 1);
2628 if (put_user_u32(len, optlen)) {
2629 return -TARGET_EFAULT;
2630 }
2631 break;
2632 }
Laurent Vivier6d485a52020-02-04 22:19:01 +01002633 case TARGET_SO_PEERSEC: {
2634 char *name;
2635
2636 if (get_user_u32(len, optlen)) {
2637 return -TARGET_EFAULT;
2638 }
2639 if (len < 0) {
2640 return -TARGET_EINVAL;
2641 }
2642 name = lock_user(VERIFY_WRITE, optval_addr, len, 0);
2643 if (!name) {
2644 return -TARGET_EFAULT;
2645 }
2646 lv = len;
2647 ret = get_errno(getsockopt(sockfd, level, SO_PEERSEC,
2648 name, &lv));
2649 if (put_user_u32(lv, optlen)) {
2650 ret = -TARGET_EFAULT;
2651 }
2652 unlock_user(name, optval_addr, lv);
2653 break;
2654 }
Carlo Marcelo Arenas Belón83eb6e52018-08-24 01:56:01 -07002655 case TARGET_SO_LINGER:
2656 {
2657 struct linger lg;
2658 socklen_t lglen;
2659 struct target_linger *tlg;
2660
2661 if (get_user_u32(len, optlen)) {
2662 return -TARGET_EFAULT;
2663 }
2664 if (len < 0) {
2665 return -TARGET_EINVAL;
2666 }
2667
2668 lglen = sizeof(lg);
2669 ret = get_errno(getsockopt(sockfd, level, SO_LINGER,
2670 &lg, &lglen));
2671 if (ret < 0) {
2672 return ret;
2673 }
2674 if (len > lglen) {
2675 len = lglen;
2676 }
2677 if (!lock_user_struct(VERIFY_WRITE, tlg, optval_addr, 0)) {
2678 return -TARGET_EFAULT;
2679 }
2680 __put_user(lg.l_onoff, &tlg->l_onoff);
2681 __put_user(lg.l_linger, &tlg->l_linger);
2682 unlock_user_struct(tlg, optval_addr, 1);
2683 if (put_user_u32(len, optlen)) {
2684 return -TARGET_EFAULT;
2685 }
2686 break;
2687 }
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002688 /* Options with 'int' argument. */
2689 case TARGET_SO_DEBUG:
2690 optname = SO_DEBUG;
2691 goto int_case;
2692 case TARGET_SO_REUSEADDR:
2693 optname = SO_REUSEADDR;
2694 goto int_case;
Yunqiang Su113a9dd2018-10-30 13:55:08 +01002695#ifdef SO_REUSEPORT
2696 case TARGET_SO_REUSEPORT:
2697 optname = SO_REUSEPORT;
2698 goto int_case;
2699#endif
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002700 case TARGET_SO_TYPE:
2701 optname = SO_TYPE;
2702 goto int_case;
2703 case TARGET_SO_ERROR:
2704 optname = SO_ERROR;
2705 goto int_case;
2706 case TARGET_SO_DONTROUTE:
2707 optname = SO_DONTROUTE;
2708 goto int_case;
2709 case TARGET_SO_BROADCAST:
2710 optname = SO_BROADCAST;
2711 goto int_case;
2712 case TARGET_SO_SNDBUF:
2713 optname = SO_SNDBUF;
2714 goto int_case;
2715 case TARGET_SO_RCVBUF:
2716 optname = SO_RCVBUF;
2717 goto int_case;
2718 case TARGET_SO_KEEPALIVE:
2719 optname = SO_KEEPALIVE;
2720 goto int_case;
2721 case TARGET_SO_OOBINLINE:
2722 optname = SO_OOBINLINE;
2723 goto int_case;
2724 case TARGET_SO_NO_CHECK:
2725 optname = SO_NO_CHECK;
2726 goto int_case;
2727 case TARGET_SO_PRIORITY:
2728 optname = SO_PRIORITY;
2729 goto int_case;
2730#ifdef SO_BSDCOMPAT
2731 case TARGET_SO_BSDCOMPAT:
2732 optname = SO_BSDCOMPAT;
2733 goto int_case;
2734#endif
2735 case TARGET_SO_PASSCRED:
2736 optname = SO_PASSCRED;
2737 goto int_case;
2738 case TARGET_SO_TIMESTAMP:
2739 optname = SO_TIMESTAMP;
2740 goto int_case;
2741 case TARGET_SO_RCVLOWAT:
2742 optname = SO_RCVLOWAT;
2743 goto int_case;
Paul Burtonaec1ca42014-06-22 11:25:34 +01002744 case TARGET_SO_ACCEPTCONN:
2745 optname = SO_ACCEPTCONN;
2746 goto int_case;
Jason A. Donenfeldec63e062021-02-04 16:39:25 +01002747 case TARGET_SO_PROTOCOL:
2748 optname = SO_PROTOCOL;
2749 goto int_case;
2750 case TARGET_SO_DOMAIN:
2751 optname = SO_DOMAIN;
2752 goto int_case;
bellard8853f862004-02-22 14:57:26 +00002753 default:
bellard2efbe912005-07-23 15:10:20 +00002754 goto int_case;
2755 }
2756 break;
2757 case SOL_TCP:
Shu-Chun Wengfe51b0a2020-12-18 11:32:11 -08002758 case SOL_UDP:
2759 /* TCP and UDP options all take an 'int' value. */
bellard2efbe912005-07-23 15:10:20 +00002760 int_case:
bellard2f619692007-11-16 10:46:05 +00002761 if (get_user_u32(len, optlen))
2762 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002763 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00002764 return -TARGET_EINVAL;
Mike Frysinger73160d92011-02-07 01:05:49 -05002765 lv = sizeof(lv);
bellard2efbe912005-07-23 15:10:20 +00002766 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2767 if (ret < 0)
2768 return ret;
Helge Dellercb88b7c2023-01-27 21:25:27 +01002769 switch (optname) {
2770 case SO_TYPE:
Paul Burton8289d112014-06-22 11:25:33 +01002771 val = host_to_target_sock_type(val);
Helge Dellercb88b7c2023-01-27 21:25:27 +01002772 break;
2773 case SO_ERROR:
2774 val = host_to_target_errno(val);
2775 break;
Paul Burton8289d112014-06-22 11:25:33 +01002776 }
bellard2efbe912005-07-23 15:10:20 +00002777 if (len > lv)
2778 len = lv;
bellard2f619692007-11-16 10:46:05 +00002779 if (len == 4) {
2780 if (put_user_u32(val, optval_addr))
2781 return -TARGET_EFAULT;
2782 } else {
2783 if (put_user_u8(val, optval_addr))
2784 return -TARGET_EFAULT;
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002785 }
bellard2f619692007-11-16 10:46:05 +00002786 if (put_user_u32(len, optlen))
2787 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002788 break;
2789 case SOL_IP:
2790 switch(optname) {
2791 case IP_TOS:
2792 case IP_TTL:
2793 case IP_HDRINCL:
2794 case IP_ROUTER_ALERT:
2795 case IP_RECVOPTS:
2796 case IP_RETOPTS:
2797 case IP_PKTINFO:
2798 case IP_MTU_DISCOVER:
2799 case IP_RECVERR:
2800 case IP_RECVTOS:
2801#ifdef IP_FREEBIND
2802 case IP_FREEBIND:
2803#endif
2804 case IP_MULTICAST_TTL:
2805 case IP_MULTICAST_LOOP:
bellard2f619692007-11-16 10:46:05 +00002806 if (get_user_u32(len, optlen))
2807 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00002808 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00002809 return -TARGET_EINVAL;
Mike Frysinger73160d92011-02-07 01:05:49 -05002810 lv = sizeof(lv);
bellard8853f862004-02-22 14:57:26 +00002811 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2812 if (ret < 0)
2813 return ret;
bellard2efbe912005-07-23 15:10:20 +00002814 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
bellard2efbe912005-07-23 15:10:20 +00002815 len = 1;
bellard2f619692007-11-16 10:46:05 +00002816 if (put_user_u32(len, optlen)
2817 || put_user_u8(val, optval_addr))
2818 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002819 } else {
bellard2efbe912005-07-23 15:10:20 +00002820 if (len > sizeof(int))
2821 len = sizeof(int);
bellard2f619692007-11-16 10:46:05 +00002822 if (put_user_u32(len, optlen)
2823 || put_user_u32(val, optval_addr))
2824 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002825 }
bellard8853f862004-02-22 14:57:26 +00002826 break;
bellard2efbe912005-07-23 15:10:20 +00002827 default:
thsc02f4992007-12-18 02:39:59 +00002828 ret = -TARGET_ENOPROTOOPT;
2829 break;
bellard8853f862004-02-22 14:57:26 +00002830 }
2831 break;
Tom Deseynbd8ed482018-12-13 14:06:11 +01002832 case SOL_IPV6:
2833 switch (optname) {
2834 case IPV6_MTU_DISCOVER:
2835 case IPV6_MTU:
2836 case IPV6_V6ONLY:
2837 case IPV6_RECVPKTINFO:
2838 case IPV6_UNICAST_HOPS:
2839 case IPV6_MULTICAST_HOPS:
2840 case IPV6_MULTICAST_LOOP:
2841 case IPV6_RECVERR:
2842 case IPV6_RECVHOPLIMIT:
2843 case IPV6_2292HOPLIMIT:
2844 case IPV6_CHECKSUM:
Helge Dellerb9cce6d2019-03-10 12:12:16 +01002845 case IPV6_ADDRFORM:
2846 case IPV6_2292PKTINFO:
2847 case IPV6_RECVTCLASS:
2848 case IPV6_RECVRTHDR:
2849 case IPV6_2292RTHDR:
2850 case IPV6_RECVHOPOPTS:
2851 case IPV6_2292HOPOPTS:
2852 case IPV6_RECVDSTOPTS:
2853 case IPV6_2292DSTOPTS:
2854 case IPV6_TCLASS:
Shu-Chun Weng22db1212020-12-18 11:32:12 -08002855 case IPV6_ADDR_PREFERENCES:
Helge Dellerb9cce6d2019-03-10 12:12:16 +01002856#ifdef IPV6_RECVPATHMTU
2857 case IPV6_RECVPATHMTU:
2858#endif
2859#ifdef IPV6_TRANSPARENT
2860 case IPV6_TRANSPARENT:
2861#endif
2862#ifdef IPV6_FREEBIND
2863 case IPV6_FREEBIND:
2864#endif
2865#ifdef IPV6_RECVORIGDSTADDR
2866 case IPV6_RECVORIGDSTADDR:
2867#endif
Tom Deseynbd8ed482018-12-13 14:06:11 +01002868 if (get_user_u32(len, optlen))
2869 return -TARGET_EFAULT;
2870 if (len < 0)
2871 return -TARGET_EINVAL;
2872 lv = sizeof(lv);
2873 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2874 if (ret < 0)
2875 return ret;
2876 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
2877 len = 1;
2878 if (put_user_u32(len, optlen)
2879 || put_user_u8(val, optval_addr))
2880 return -TARGET_EFAULT;
2881 } else {
2882 if (len > sizeof(int))
2883 len = sizeof(int);
2884 if (put_user_u32(len, optlen)
2885 || put_user_u32(val, optval_addr))
2886 return -TARGET_EFAULT;
2887 }
2888 break;
2889 default:
2890 ret = -TARGET_ENOPROTOOPT;
2891 break;
2892 }
2893 break;
Josh Kunza2d86682019-10-29 15:43:10 -07002894#ifdef SOL_NETLINK
2895 case SOL_NETLINK:
2896 switch (optname) {
2897 case NETLINK_PKTINFO:
2898 case NETLINK_BROADCAST_ERROR:
2899 case NETLINK_NO_ENOBUFS:
2900#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2901 case NETLINK_LISTEN_ALL_NSID:
2902 case NETLINK_CAP_ACK:
2903#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2904#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
2905 case NETLINK_EXT_ACK:
2906#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2907#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
2908 case NETLINK_GET_STRICT_CHK:
2909#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2910 if (get_user_u32(len, optlen)) {
2911 return -TARGET_EFAULT;
2912 }
2913 if (len != sizeof(val)) {
2914 return -TARGET_EINVAL;
2915 }
2916 lv = len;
2917 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2918 if (ret < 0) {
2919 return ret;
2920 }
2921 if (put_user_u32(lv, optlen)
2922 || put_user_u32(val, optval_addr)) {
2923 return -TARGET_EFAULT;
2924 }
2925 break;
2926#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2927 case NETLINK_LIST_MEMBERSHIPS:
2928 {
2929 uint32_t *results;
2930 int i;
2931 if (get_user_u32(len, optlen)) {
2932 return -TARGET_EFAULT;
2933 }
2934 if (len < 0) {
2935 return -TARGET_EINVAL;
2936 }
2937 results = lock_user(VERIFY_WRITE, optval_addr, len, 1);
Frédéric Fortier13e340c2021-03-28 14:01:35 -04002938 if (!results && len > 0) {
Josh Kunza2d86682019-10-29 15:43:10 -07002939 return -TARGET_EFAULT;
2940 }
2941 lv = len;
2942 ret = get_errno(getsockopt(sockfd, level, optname, results, &lv));
2943 if (ret < 0) {
2944 unlock_user(results, optval_addr, 0);
2945 return ret;
2946 }
2947 /* swap host endianess to target endianess. */
2948 for (i = 0; i < (len / sizeof(uint32_t)); i++) {
2949 results[i] = tswap32(results[i]);
2950 }
2951 if (put_user_u32(lv, optlen)) {
2952 return -TARGET_EFAULT;
2953 }
2954 unlock_user(results, optval_addr, 0);
2955 break;
2956 }
2957#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2958 default:
2959 goto unimplemented;
2960 }
Laurent Vivierc0cb8802019-11-12 11:50:55 +01002961 break;
Josh Kunza2d86682019-10-29 15:43:10 -07002962#endif /* SOL_NETLINK */
bellard8853f862004-02-22 14:57:26 +00002963 default:
2964 unimplemented:
Josh Kunz39be5352020-02-03 18:54:13 -08002965 qemu_log_mask(LOG_UNIMP,
2966 "getsockopt level=%d optname=%d not yet supported\n",
2967 level, optname);
thsc02f4992007-12-18 02:39:59 +00002968 ret = -TARGET_EOPNOTSUPP;
bellard8853f862004-02-22 14:57:26 +00002969 break;
2970 }
2971 return ret;
bellard7854b052003-03-29 17:22:23 +00002972}
2973
Max Filippov9ac22512018-04-04 17:30:41 -07002974/* Convert target low/high pair representing file offset into the host
2975 * low/high pair. This function doesn't handle offsets bigger than 64 bits
2976 * as the kernel doesn't handle them either.
2977 */
2978static void target_to_host_low_high(abi_ulong tlow,
2979 abi_ulong thigh,
2980 unsigned long *hlow,
2981 unsigned long *hhigh)
2982{
2983 uint64_t off = tlow |
2984 ((unsigned long long)thigh << TARGET_LONG_BITS / 2) <<
2985 TARGET_LONG_BITS / 2;
2986
2987 *hlow = off;
2988 *hhigh = (off >> HOST_LONG_BITS / 2) >> HOST_LONG_BITS / 2;
2989}
2990
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002991static struct iovec *lock_iovec(int type, abi_ulong target_addr,
Peter Maydelldab32b32016-07-15 14:57:26 +01002992 abi_ulong count, int copy)
pbrook53a59602006-03-25 19:31:22 +00002993{
2994 struct target_iovec *target_vec;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002995 struct iovec *vec;
2996 abi_ulong total_len, max_len;
balrogd732dcb2008-10-28 10:21:03 +00002997 int i;
Peter Maydell501bb4b2014-02-17 18:55:33 +00002998 int err = 0;
Tom Musta29560a62014-08-12 13:53:43 -05002999 bool bad_address = false;
pbrook53a59602006-03-25 19:31:22 +00003000
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003001 if (count == 0) {
3002 errno = 0;
3003 return NULL;
pbrook53a59602006-03-25 19:31:22 +00003004 }
Peter Maydelldab32b32016-07-15 14:57:26 +01003005 if (count > IOV_MAX) {
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003006 errno = EINVAL;
3007 return NULL;
3008 }
3009
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303010 vec = g_try_new0(struct iovec, count);
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003011 if (vec == NULL) {
3012 errno = ENOMEM;
3013 return NULL;
3014 }
3015
3016 target_vec = lock_user(VERIFY_READ, target_addr,
3017 count * sizeof(struct target_iovec), 1);
3018 if (target_vec == NULL) {
Peter Maydell501bb4b2014-02-17 18:55:33 +00003019 err = EFAULT;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003020 goto fail2;
3021 }
3022
3023 /* ??? If host page size > target page size, this will result in a
3024 value larger than what we can actually support. */
3025 max_len = 0x7fffffff & TARGET_PAGE_MASK;
3026 total_len = 0;
3027
3028 for (i = 0; i < count; i++) {
3029 abi_ulong base = tswapal(target_vec[i].iov_base);
3030 abi_long len = tswapal(target_vec[i].iov_len);
3031
3032 if (len < 0) {
Peter Maydell501bb4b2014-02-17 18:55:33 +00003033 err = EINVAL;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003034 goto fail;
3035 } else if (len == 0) {
3036 /* Zero length pointer is ignored. */
3037 vec[i].iov_base = 0;
3038 } else {
3039 vec[i].iov_base = lock_user(type, base, len, copy);
Tom Musta29560a62014-08-12 13:53:43 -05003040 /* If the first buffer pointer is bad, this is a fault. But
3041 * subsequent bad buffers will result in a partial write; this
3042 * is realized by filling the vector with null pointers and
3043 * zero lengths. */
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003044 if (!vec[i].iov_base) {
Tom Musta29560a62014-08-12 13:53:43 -05003045 if (i == 0) {
3046 err = EFAULT;
3047 goto fail;
3048 } else {
3049 bad_address = true;
3050 }
3051 }
3052 if (bad_address) {
3053 len = 0;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003054 }
3055 if (len > max_len - total_len) {
3056 len = max_len - total_len;
3057 }
3058 }
3059 vec[i].iov_len = len;
3060 total_len += len;
3061 }
3062
3063 unlock_user(target_vec, target_addr, 0);
3064 return vec;
3065
3066 fail:
Chen Gang S7eff5182015-01-23 18:01:09 +08003067 while (--i >= 0) {
3068 if (tswapal(target_vec[i].iov_len) > 0) {
3069 unlock_user(vec[i].iov_base, tswapal(target_vec[i].iov_base), 0);
3070 }
3071 }
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003072 unlock_user(target_vec, target_addr, 0);
Peter Maydell501bb4b2014-02-17 18:55:33 +00003073 fail2:
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303074 g_free(vec);
Peter Maydell501bb4b2014-02-17 18:55:33 +00003075 errno = err;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003076 return NULL;
pbrook53a59602006-03-25 19:31:22 +00003077}
3078
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003079static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
Peter Maydelldab32b32016-07-15 14:57:26 +01003080 abi_ulong count, int copy)
pbrook53a59602006-03-25 19:31:22 +00003081{
3082 struct target_iovec *target_vec;
pbrook53a59602006-03-25 19:31:22 +00003083 int i;
3084
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003085 target_vec = lock_user(VERIFY_READ, target_addr,
3086 count * sizeof(struct target_iovec), 1);
3087 if (target_vec) {
3088 for (i = 0; i < count; i++) {
3089 abi_ulong base = tswapal(target_vec[i].iov_base);
Chen Gang S71ec7ce2015-01-23 18:07:50 +08003090 abi_long len = tswapal(target_vec[i].iov_len);
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003091 if (len < 0) {
3092 break;
3093 }
balrogd732dcb2008-10-28 10:21:03 +00003094 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
3095 }
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003096 unlock_user(target_vec, target_addr, 0);
pbrook53a59602006-03-25 19:31:22 +00003097 }
bellard579a97f2007-11-11 14:26:47 +00003098
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303099 g_free(vec);
pbrook53a59602006-03-25 19:31:22 +00003100}
3101
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003102static inline int target_to_host_sock_type(int *type)
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003103{
3104 int host_type = 0;
3105 int target_type = *type;
3106
3107 switch (target_type & TARGET_SOCK_TYPE_MASK) {
3108 case TARGET_SOCK_DGRAM:
3109 host_type = SOCK_DGRAM;
3110 break;
3111 case TARGET_SOCK_STREAM:
3112 host_type = SOCK_STREAM;
3113 break;
3114 default:
3115 host_type = target_type & TARGET_SOCK_TYPE_MASK;
3116 break;
3117 }
3118 if (target_type & TARGET_SOCK_CLOEXEC) {
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003119#if defined(SOCK_CLOEXEC)
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003120 host_type |= SOCK_CLOEXEC;
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003121#else
3122 return -TARGET_EINVAL;
3123#endif
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003124 }
3125 if (target_type & TARGET_SOCK_NONBLOCK) {
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003126#if defined(SOCK_NONBLOCK)
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003127 host_type |= SOCK_NONBLOCK;
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003128#elif !defined(O_NONBLOCK)
3129 return -TARGET_EINVAL;
3130#endif
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003131 }
3132 *type = host_type;
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003133 return 0;
3134}
3135
3136/* Try to emulate socket type flags after socket creation. */
3137static int sock_flags_fixup(int fd, int target_type)
3138{
3139#if !defined(SOCK_NONBLOCK) && defined(O_NONBLOCK)
3140 if (target_type & TARGET_SOCK_NONBLOCK) {
3141 int flags = fcntl(fd, F_GETFL);
3142 if (fcntl(fd, F_SETFL, O_NONBLOCK | flags) == -1) {
3143 close(fd);
3144 return -TARGET_EINVAL;
3145 }
3146 }
3147#endif
3148 return fd;
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003149}
3150
ths0da46a62007-10-20 20:23:07 +00003151/* do_socket() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003152static abi_long do_socket(int domain, int type, int protocol)
bellard3532fa72006-06-24 15:06:03 +00003153{
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003154 int target_type = type;
3155 int ret;
3156
3157 ret = target_to_host_sock_type(&type);
3158 if (ret) {
3159 return ret;
3160 }
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003161
Laurent Vivier575b22b2016-06-02 22:14:15 +02003162 if (domain == PF_NETLINK && !(
3163#ifdef CONFIG_RTNETLINK
3164 protocol == NETLINK_ROUTE ||
3165#endif
3166 protocol == NETLINK_KOBJECT_UEVENT ||
3167 protocol == NETLINK_AUDIT)) {
Josh Kunz71e24432020-07-06 17:10:36 -07003168 return -TARGET_EPROTONOSUPPORT;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003169 }
Laurent Vivierff626f22015-10-28 21:40:42 +01003170
3171 if (domain == AF_PACKET ||
3172 (domain == AF_INET && type == SOCK_PACKET)) {
3173 protocol = tswap16(protocol);
3174 }
3175
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003176 ret = get_errno(socket(domain, type, protocol));
3177 if (ret >= 0) {
3178 ret = sock_flags_fixup(ret, target_type);
Laurent Vivier0cf22722015-10-28 21:40:45 +01003179 if (type == SOCK_PACKET) {
3180 /* Manage an obsolete case :
3181 * if socket type is SOCK_PACKET, bind by name
3182 */
3183 fd_trans_register(ret, &target_packet_trans);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003184 } else if (domain == PF_NETLINK) {
3185 switch (protocol) {
Laurent Vivier575b22b2016-06-02 22:14:15 +02003186#ifdef CONFIG_RTNETLINK
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003187 case NETLINK_ROUTE:
3188 fd_trans_register(ret, &target_netlink_route_trans);
3189 break;
Laurent Vivier575b22b2016-06-02 22:14:15 +02003190#endif
Laurent Vivierb2656202016-05-22 18:56:20 +02003191 case NETLINK_KOBJECT_UEVENT:
3192 /* nothing to do: messages are strings */
3193 break;
Laurent Vivier5ce9bb52016-05-22 18:56:21 +02003194 case NETLINK_AUDIT:
3195 fd_trans_register(ret, &target_netlink_audit_trans);
3196 break;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003197 default:
3198 g_assert_not_reached();
3199 }
Laurent Vivier0cf22722015-10-28 21:40:45 +01003200 }
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003201 }
3202 return ret;
bellard3532fa72006-06-24 15:06:03 +00003203}
3204
ths0da46a62007-10-20 20:23:07 +00003205/* do_bind() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003206static abi_long do_bind(int sockfd, abi_ulong target_addr,
3207 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00003208{
aurel328f7aeaf2009-01-30 19:47:57 +00003209 void *addr;
Arnaud Patard917507b2009-06-19 10:44:45 +03003210 abi_long ret;
aurel328f7aeaf2009-01-30 19:47:57 +00003211
Blue Swirl38724252010-09-18 05:53:14 +00003212 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003213 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003214 }
aurel328f7aeaf2009-01-30 19:47:57 +00003215
aurel32607175e2009-04-15 16:11:59 +00003216 addr = alloca(addrlen+1);
ths3b46e622007-09-17 08:09:54 +00003217
Laurent Vivier7b36f782015-10-28 21:40:44 +01003218 ret = target_to_host_sockaddr(sockfd, addr, target_addr, addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03003219 if (ret)
3220 return ret;
3221
bellard3532fa72006-06-24 15:06:03 +00003222 return get_errno(bind(sockfd, addr, addrlen));
3223}
3224
ths0da46a62007-10-20 20:23:07 +00003225/* do_connect() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003226static abi_long do_connect(int sockfd, abi_ulong target_addr,
3227 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00003228{
aurel328f7aeaf2009-01-30 19:47:57 +00003229 void *addr;
Arnaud Patard917507b2009-06-19 10:44:45 +03003230 abi_long ret;
aurel328f7aeaf2009-01-30 19:47:57 +00003231
Blue Swirl38724252010-09-18 05:53:14 +00003232 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003233 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003234 }
aurel328f7aeaf2009-01-30 19:47:57 +00003235
Joakim Tjernlund2dd08df2014-07-11 17:18:03 +02003236 addr = alloca(addrlen+1);
ths3b46e622007-09-17 08:09:54 +00003237
Laurent Vivier7b36f782015-10-28 21:40:44 +01003238 ret = target_to_host_sockaddr(sockfd, addr, target_addr, addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03003239 if (ret)
3240 return ret;
3241
Peter Maydell2a3c7612016-06-06 19:58:03 +01003242 return get_errno(safe_connect(sockfd, addr, addrlen));
bellard3532fa72006-06-24 15:06:03 +00003243}
3244
Alexander Graff19e00d2014-03-02 19:36:42 +00003245/* do_sendrecvmsg_locked() Must return target values and target errnos. */
3246static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
3247 int flags, int send)
bellard3532fa72006-06-24 15:06:03 +00003248{
balrog6de645c2008-10-28 10:26:29 +00003249 abi_long ret, len;
bellard3532fa72006-06-24 15:06:03 +00003250 struct msghdr msg;
Peter Maydelldab32b32016-07-15 14:57:26 +01003251 abi_ulong count;
bellard3532fa72006-06-24 15:06:03 +00003252 struct iovec *vec;
blueswir1992f48a2007-10-14 16:27:31 +00003253 abi_ulong target_vec;
bellard3532fa72006-06-24 15:06:03 +00003254
bellard3532fa72006-06-24 15:06:03 +00003255 if (msgp->msg_name) {
3256 msg.msg_namelen = tswap32(msgp->msg_namelen);
Joakim Tjernlund2dd08df2014-07-11 17:18:03 +02003257 msg.msg_name = alloca(msg.msg_namelen+1);
Laurent Vivier7b36f782015-10-28 21:40:44 +01003258 ret = target_to_host_sockaddr(fd, msg.msg_name,
3259 tswapal(msgp->msg_name),
3260 msg.msg_namelen);
Peter Maydell26a6fc92016-07-15 14:57:28 +01003261 if (ret == -TARGET_EFAULT) {
3262 /* For connected sockets msg_name and msg_namelen must
3263 * be ignored, so returning EFAULT immediately is wrong.
3264 * Instead, pass a bad msg_name to the host kernel, and
3265 * let it decide whether to return EFAULT or not.
3266 */
3267 msg.msg_name = (void *)-1;
3268 } else if (ret) {
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003269 goto out2;
Arnaud Patard917507b2009-06-19 10:44:45 +03003270 }
bellard3532fa72006-06-24 15:06:03 +00003271 } else {
3272 msg.msg_name = NULL;
3273 msg.msg_namelen = 0;
3274 }
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003275 msg.msg_controllen = 2 * tswapal(msgp->msg_controllen);
bellard3532fa72006-06-24 15:06:03 +00003276 msg.msg_control = alloca(msg.msg_controllen);
Jonas Schievink1d3d1b22018-07-12 00:12:44 +02003277 memset(msg.msg_control, 0, msg.msg_controllen);
3278
bellard3532fa72006-06-24 15:06:03 +00003279 msg.msg_flags = tswap32(msgp->msg_flags);
ths3b46e622007-09-17 08:09:54 +00003280
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003281 count = tswapal(msgp->msg_iovlen);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003282 target_vec = tswapal(msgp->msg_iov);
Peter Maydell97b07972016-07-15 14:57:27 +01003283
3284 if (count > IOV_MAX) {
3285 /* sendrcvmsg returns a different errno for this condition than
3286 * readv/writev, so we must catch it here before lock_iovec() does.
3287 */
3288 ret = -TARGET_EMSGSIZE;
3289 goto out2;
3290 }
3291
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003292 vec = lock_iovec(send ? VERIFY_READ : VERIFY_WRITE,
3293 target_vec, count, send);
3294 if (vec == NULL) {
3295 ret = -host_to_target_errno(errno);
Helge Deller3f0744f2022-12-12 18:34:16 +01003296 /* allow sending packet without any iov, e.g. with MSG_MORE flag */
3297 if (!send || ret) {
3298 goto out2;
3299 }
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003300 }
bellard3532fa72006-06-24 15:06:03 +00003301 msg.msg_iovlen = count;
3302 msg.msg_iov = vec;
ths3b46e622007-09-17 08:09:54 +00003303
bellard3532fa72006-06-24 15:06:03 +00003304 if (send) {
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003305 if (fd_trans_target_to_host_data(fd)) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003306 void *host_msg;
3307
3308 host_msg = g_malloc(msg.msg_iov->iov_len);
3309 memcpy(host_msg, msg.msg_iov->iov_base, msg.msg_iov->iov_len);
3310 ret = fd_trans_target_to_host_data(fd)(host_msg,
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003311 msg.msg_iov->iov_len);
Laurent Vivier7d61d892016-06-21 19:51:14 +02003312 if (ret >= 0) {
3313 msg.msg_iov->iov_base = host_msg;
3314 ret = get_errno(safe_sendmsg(fd, &msg, flags));
3315 }
3316 g_free(host_msg);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003317 } else {
3318 ret = target_to_host_cmsg(&msg, msgp);
Laurent Vivier7d61d892016-06-21 19:51:14 +02003319 if (ret == 0) {
3320 ret = get_errno(safe_sendmsg(fd, &msg, flags));
3321 }
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003322 }
bellard3532fa72006-06-24 15:06:03 +00003323 } else {
Peter Maydell66687532016-06-06 19:58:04 +01003324 ret = get_errno(safe_recvmsg(fd, &msg, flags));
balrog6de645c2008-10-28 10:26:29 +00003325 if (!is_error(ret)) {
3326 len = ret;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003327 if (fd_trans_host_to_target_data(fd)) {
3328 ret = fd_trans_host_to_target_data(fd)(msg.msg_iov->iov_base,
Laurent Vivier2a03d3e2018-08-20 19:15:54 +02003329 MIN(msg.msg_iov->iov_len, len));
Icenowy Zheng16c81dd2022-10-28 16:12:20 +08003330 }
3331 if (!is_error(ret)) {
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003332 ret = host_to_target_cmsg(msgp, &msg);
3333 }
Jing Huangca619062012-07-24 13:58:02 +00003334 if (!is_error(ret)) {
3335 msgp->msg_namelen = tswap32(msg.msg_namelen);
Andreas Schwab24894f32019-02-12 17:34:35 +01003336 msgp->msg_flags = tswap32(msg.msg_flags);
Peter Maydell26a6fc92016-07-15 14:57:28 +01003337 if (msg.msg_name != NULL && msg.msg_name != (void *)-1) {
Jing Huangca619062012-07-24 13:58:02 +00003338 ret = host_to_target_sockaddr(tswapal(msgp->msg_name),
3339 msg.msg_name, msg.msg_namelen);
3340 if (ret) {
3341 goto out;
3342 }
3343 }
3344
balrog6de645c2008-10-28 10:26:29 +00003345 ret = len;
Jing Huangca619062012-07-24 13:58:02 +00003346 }
balrog6de645c2008-10-28 10:26:29 +00003347 }
bellard3532fa72006-06-24 15:06:03 +00003348 }
Jing Huangca619062012-07-24 13:58:02 +00003349
3350out:
Helge Deller3f0744f2022-12-12 18:34:16 +01003351 if (vec) {
3352 unlock_iovec(vec, target_vec, count, !send);
3353 }
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003354out2:
Alexander Graff19e00d2014-03-02 19:36:42 +00003355 return ret;
3356}
3357
3358static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
3359 int flags, int send)
3360{
3361 abi_long ret;
3362 struct target_msghdr *msgp;
3363
3364 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
3365 msgp,
3366 target_msg,
3367 send ? 1 : 0)) {
3368 return -TARGET_EFAULT;
3369 }
3370 ret = do_sendrecvmsg_locked(fd, msgp, flags, send);
bellard579a97f2007-11-11 14:26:47 +00003371 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
bellard3532fa72006-06-24 15:06:03 +00003372 return ret;
3373}
3374
Alexander Graff19e00d2014-03-02 19:36:42 +00003375/* We don't rely on the C library to have sendmmsg/recvmmsg support,
3376 * so it might not have this *mmsg-specific flag either.
3377 */
3378#ifndef MSG_WAITFORONE
3379#define MSG_WAITFORONE 0x10000
3380#endif
3381
3382static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec,
3383 unsigned int vlen, unsigned int flags,
3384 int send)
3385{
3386 struct target_mmsghdr *mmsgp;
3387 abi_long ret = 0;
3388 int i;
3389
3390 if (vlen > UIO_MAXIOV) {
3391 vlen = UIO_MAXIOV;
3392 }
3393
3394 mmsgp = lock_user(VERIFY_WRITE, target_msgvec, sizeof(*mmsgp) * vlen, 1);
3395 if (!mmsgp) {
3396 return -TARGET_EFAULT;
3397 }
3398
3399 for (i = 0; i < vlen; i++) {
3400 ret = do_sendrecvmsg_locked(fd, &mmsgp[i].msg_hdr, flags, send);
3401 if (is_error(ret)) {
3402 break;
3403 }
3404 mmsgp[i].msg_len = tswap32(ret);
3405 /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
3406 if (flags & MSG_WAITFORONE) {
3407 flags |= MSG_DONTWAIT;
3408 }
3409 }
3410
3411 unlock_user(mmsgp, target_msgvec, sizeof(*mmsgp) * i);
3412
3413 /* Return number of datagrams sent if we sent any at all;
3414 * otherwise return the error.
3415 */
3416 if (i) {
3417 return i;
3418 }
3419 return ret;
3420}
Alexander Graff19e00d2014-03-02 19:36:42 +00003421
Peter Maydella94b4982013-02-08 04:35:04 +00003422/* do_accept4() Must return target values and target errnos. */
3423static abi_long do_accept4(int fd, abi_ulong target_addr,
3424 abi_ulong target_addrlen_addr, int flags)
pbrook1be9e1d2006-11-19 15:26:04 +00003425{
Andreas Schwabcd813362019-02-14 12:43:40 +01003426 socklen_t addrlen, ret_addrlen;
bellard2f619692007-11-16 10:46:05 +00003427 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00003428 abi_long ret;
Petar Jovanovicd25295d2014-03-31 17:41:23 +02003429 int host_flags;
3430
3431 host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
pbrook1be9e1d2006-11-19 15:26:04 +00003432
Peter Maydella94b4982013-02-08 04:35:04 +00003433 if (target_addr == 0) {
Peter Maydellff6dc132016-06-06 19:58:13 +01003434 return get_errno(safe_accept4(fd, NULL, NULL, host_flags));
Peter Maydella94b4982013-02-08 04:35:04 +00003435 }
Arnaud Patard917507b2009-06-19 10:44:45 +03003436
Matus Kysele554eb42020-09-30 17:16:16 +02003437 /* linux returns EFAULT if addrlen pointer is invalid */
bellard2f619692007-11-16 10:46:05 +00003438 if (get_user_u32(addrlen, target_addrlen_addr))
Matus Kysele554eb42020-09-30 17:16:16 +02003439 return -TARGET_EFAULT;
bellard2f619692007-11-16 10:46:05 +00003440
Blue Swirl38724252010-09-18 05:53:14 +00003441 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003442 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003443 }
aurel328f7aeaf2009-01-30 19:47:57 +00003444
Richard Hendersonc7169b02021-02-12 10:48:47 -08003445 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
Matus Kysele554eb42020-09-30 17:16:16 +02003446 return -TARGET_EFAULT;
Richard Hendersonc7169b02021-02-12 10:48:47 -08003447 }
Arnaud Patard917507b2009-06-19 10:44:45 +03003448
bellard2f619692007-11-16 10:46:05 +00003449 addr = alloca(addrlen);
3450
Andreas Schwabcd813362019-02-14 12:43:40 +01003451 ret_addrlen = addrlen;
3452 ret = get_errno(safe_accept4(fd, addr, &ret_addrlen, host_flags));
pbrook1be9e1d2006-11-19 15:26:04 +00003453 if (!is_error(ret)) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003454 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3455 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
bellard2f619692007-11-16 10:46:05 +00003456 ret = -TARGET_EFAULT;
Andreas Schwabcd813362019-02-14 12:43:40 +01003457 }
pbrook1be9e1d2006-11-19 15:26:04 +00003458 }
3459 return ret;
3460}
3461
ths0da46a62007-10-20 20:23:07 +00003462/* do_getpeername() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003463static abi_long do_getpeername(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00003464 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00003465{
Andreas Schwabcd813362019-02-14 12:43:40 +01003466 socklen_t addrlen, ret_addrlen;
bellard2f619692007-11-16 10:46:05 +00003467 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00003468 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003469
bellard2f619692007-11-16 10:46:05 +00003470 if (get_user_u32(addrlen, target_addrlen_addr))
3471 return -TARGET_EFAULT;
3472
Blue Swirl38724252010-09-18 05:53:14 +00003473 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003474 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003475 }
aurel328f7aeaf2009-01-30 19:47:57 +00003476
Richard Hendersonc7169b02021-02-12 10:48:47 -08003477 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
Arnaud Patard917507b2009-06-19 10:44:45 +03003478 return -TARGET_EFAULT;
Richard Hendersonc7169b02021-02-12 10:48:47 -08003479 }
Arnaud Patard917507b2009-06-19 10:44:45 +03003480
bellard2f619692007-11-16 10:46:05 +00003481 addr = alloca(addrlen);
3482
Andreas Schwabcd813362019-02-14 12:43:40 +01003483 ret_addrlen = addrlen;
3484 ret = get_errno(getpeername(fd, addr, &ret_addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003485 if (!is_error(ret)) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003486 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3487 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
bellard2f619692007-11-16 10:46:05 +00003488 ret = -TARGET_EFAULT;
Andreas Schwabcd813362019-02-14 12:43:40 +01003489 }
pbrook1be9e1d2006-11-19 15:26:04 +00003490 }
3491 return ret;
3492}
3493
ths0da46a62007-10-20 20:23:07 +00003494/* do_getsockname() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003495static abi_long do_getsockname(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00003496 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00003497{
Andreas Schwabcd813362019-02-14 12:43:40 +01003498 socklen_t addrlen, ret_addrlen;
bellard2f619692007-11-16 10:46:05 +00003499 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00003500 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003501
bellard2f619692007-11-16 10:46:05 +00003502 if (get_user_u32(addrlen, target_addrlen_addr))
3503 return -TARGET_EFAULT;
3504
Blue Swirl38724252010-09-18 05:53:14 +00003505 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003506 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003507 }
aurel328f7aeaf2009-01-30 19:47:57 +00003508
Richard Hendersonc7169b02021-02-12 10:48:47 -08003509 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
Arnaud Patard917507b2009-06-19 10:44:45 +03003510 return -TARGET_EFAULT;
Richard Hendersonc7169b02021-02-12 10:48:47 -08003511 }
Arnaud Patard917507b2009-06-19 10:44:45 +03003512
bellard2f619692007-11-16 10:46:05 +00003513 addr = alloca(addrlen);
3514
Andreas Schwabcd813362019-02-14 12:43:40 +01003515 ret_addrlen = addrlen;
3516 ret = get_errno(getsockname(fd, addr, &ret_addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003517 if (!is_error(ret)) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003518 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3519 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
bellard2f619692007-11-16 10:46:05 +00003520 ret = -TARGET_EFAULT;
Andreas Schwabcd813362019-02-14 12:43:40 +01003521 }
pbrook1be9e1d2006-11-19 15:26:04 +00003522 }
3523 return ret;
3524}
3525
ths0da46a62007-10-20 20:23:07 +00003526/* do_socketpair() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003527static abi_long do_socketpair(int domain, int type, int protocol,
bellard2f619692007-11-16 10:46:05 +00003528 abi_ulong target_tab_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00003529{
3530 int tab[2];
blueswir1992f48a2007-10-14 16:27:31 +00003531 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003532
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003533 target_to_host_sock_type(&type);
3534
pbrook1be9e1d2006-11-19 15:26:04 +00003535 ret = get_errno(socketpair(domain, type, protocol, tab));
3536 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00003537 if (put_user_s32(tab[0], target_tab_addr)
3538 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
3539 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00003540 }
3541 return ret;
3542}
3543
ths0da46a62007-10-20 20:23:07 +00003544/* do_sendto() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003545static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
3546 abi_ulong target_addr, socklen_t addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00003547{
3548 void *addr;
3549 void *host_msg;
Laurent Vivier7d61d892016-06-21 19:51:14 +02003550 void *copy_msg = NULL;
blueswir1992f48a2007-10-14 16:27:31 +00003551 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003552
Blue Swirl38724252010-09-18 05:53:14 +00003553 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003554 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003555 }
aurel328f7aeaf2009-01-30 19:47:57 +00003556
bellard579a97f2007-11-11 14:26:47 +00003557 host_msg = lock_user(VERIFY_READ, msg, len, 1);
3558 if (!host_msg)
3559 return -TARGET_EFAULT;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003560 if (fd_trans_target_to_host_data(fd)) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003561 copy_msg = host_msg;
3562 host_msg = g_malloc(len);
3563 memcpy(host_msg, copy_msg, len);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003564 ret = fd_trans_target_to_host_data(fd)(host_msg, len);
3565 if (ret < 0) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003566 goto fail;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003567 }
3568 }
pbrook1be9e1d2006-11-19 15:26:04 +00003569 if (target_addr) {
Joakim Tjernlund2dd08df2014-07-11 17:18:03 +02003570 addr = alloca(addrlen+1);
Laurent Vivier7b36f782015-10-28 21:40:44 +01003571 ret = target_to_host_sockaddr(fd, addr, target_addr, addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03003572 if (ret) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003573 goto fail;
Arnaud Patard917507b2009-06-19 10:44:45 +03003574 }
Peter Maydell66687532016-06-06 19:58:04 +01003575 ret = get_errno(safe_sendto(fd, host_msg, len, flags, addr, addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003576 } else {
Peter Maydell66687532016-06-06 19:58:04 +01003577 ret = get_errno(safe_sendto(fd, host_msg, len, flags, NULL, 0));
pbrook1be9e1d2006-11-19 15:26:04 +00003578 }
Laurent Vivier7d61d892016-06-21 19:51:14 +02003579fail:
3580 if (copy_msg) {
3581 g_free(host_msg);
3582 host_msg = copy_msg;
3583 }
pbrook1be9e1d2006-11-19 15:26:04 +00003584 unlock_user(host_msg, msg, 0);
3585 return ret;
3586}
3587
ths0da46a62007-10-20 20:23:07 +00003588/* do_recvfrom() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003589static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
3590 abi_ulong target_addr,
3591 abi_ulong target_addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00003592{
Andreas Schwabcd813362019-02-14 12:43:40 +01003593 socklen_t addrlen, ret_addrlen;
pbrook1be9e1d2006-11-19 15:26:04 +00003594 void *addr;
3595 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00003596 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003597
Zach Reizner4a1e6bc2021-03-26 22:11:16 -04003598 if (!msg) {
3599 host_msg = NULL;
3600 } else {
3601 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
3602 if (!host_msg) {
3603 return -TARGET_EFAULT;
3604 }
3605 }
pbrook1be9e1d2006-11-19 15:26:04 +00003606 if (target_addr) {
bellard2f619692007-11-16 10:46:05 +00003607 if (get_user_u32(addrlen, target_addrlen)) {
3608 ret = -TARGET_EFAULT;
3609 goto fail;
3610 }
Blue Swirl38724252010-09-18 05:53:14 +00003611 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003612 ret = -TARGET_EINVAL;
3613 goto fail;
3614 }
pbrook1be9e1d2006-11-19 15:26:04 +00003615 addr = alloca(addrlen);
Andreas Schwabcd813362019-02-14 12:43:40 +01003616 ret_addrlen = addrlen;
Peter Maydell66687532016-06-06 19:58:04 +01003617 ret = get_errno(safe_recvfrom(fd, host_msg, len, flags,
Andreas Schwabcd813362019-02-14 12:43:40 +01003618 addr, &ret_addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003619 } else {
3620 addr = NULL; /* To keep compiler quiet. */
Andreas Schwabcd813362019-02-14 12:43:40 +01003621 addrlen = 0; /* To keep compiler quiet. */
Peter Maydell66687532016-06-06 19:58:04 +01003622 ret = get_errno(safe_recvfrom(fd, host_msg, len, flags, NULL, 0));
pbrook1be9e1d2006-11-19 15:26:04 +00003623 }
3624 if (!is_error(ret)) {
Laurent Vivierc35e1f92016-06-21 19:51:15 +02003625 if (fd_trans_host_to_target_data(fd)) {
Laurent Vivier2a03d3e2018-08-20 19:15:54 +02003626 abi_long trans;
3627 trans = fd_trans_host_to_target_data(fd)(host_msg, MIN(ret, len));
3628 if (is_error(trans)) {
3629 ret = trans;
3630 goto fail;
3631 }
Laurent Vivierc35e1f92016-06-21 19:51:15 +02003632 }
pbrook1be9e1d2006-11-19 15:26:04 +00003633 if (target_addr) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003634 host_to_target_sockaddr(target_addr, addr,
3635 MIN(addrlen, ret_addrlen));
3636 if (put_user_u32(ret_addrlen, target_addrlen)) {
bellard2f619692007-11-16 10:46:05 +00003637 ret = -TARGET_EFAULT;
3638 goto fail;
3639 }
pbrook1be9e1d2006-11-19 15:26:04 +00003640 }
3641 unlock_user(host_msg, msg, len);
3642 } else {
bellard2f619692007-11-16 10:46:05 +00003643fail:
pbrook1be9e1d2006-11-19 15:26:04 +00003644 unlock_user(host_msg, msg, 0);
3645 }
3646 return ret;
3647}
3648
j_mayer32407102007-09-26 23:01:49 +00003649#ifdef TARGET_NR_socketcall
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003650/* do_socketcall() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003651static abi_long do_socketcall(int num, abi_ulong vptr)
bellard31e31b82003-02-18 22:55:36 +00003652{
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003653 static const unsigned nargs[] = { /* number of arguments per operation */
3654 [TARGET_SYS_SOCKET] = 3, /* domain, type, protocol */
3655 [TARGET_SYS_BIND] = 3, /* fd, addr, addrlen */
3656 [TARGET_SYS_CONNECT] = 3, /* fd, addr, addrlen */
3657 [TARGET_SYS_LISTEN] = 2, /* fd, backlog */
3658 [TARGET_SYS_ACCEPT] = 3, /* fd, addr, addrlen */
3659 [TARGET_SYS_GETSOCKNAME] = 3, /* fd, addr, addrlen */
3660 [TARGET_SYS_GETPEERNAME] = 3, /* fd, addr, addrlen */
3661 [TARGET_SYS_SOCKETPAIR] = 4, /* domain, type, protocol, tab */
3662 [TARGET_SYS_SEND] = 4, /* fd, msg, len, flags */
3663 [TARGET_SYS_RECV] = 4, /* fd, msg, len, flags */
3664 [TARGET_SYS_SENDTO] = 6, /* fd, msg, len, flags, addr, addrlen */
3665 [TARGET_SYS_RECVFROM] = 6, /* fd, msg, len, flags, addr, addrlen */
3666 [TARGET_SYS_SHUTDOWN] = 2, /* fd, how */
3667 [TARGET_SYS_SETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
3668 [TARGET_SYS_GETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
3669 [TARGET_SYS_SENDMSG] = 3, /* fd, msg, flags */
3670 [TARGET_SYS_RECVMSG] = 3, /* fd, msg, flags */
3671 [TARGET_SYS_ACCEPT4] = 4, /* fd, addr, addrlen, flags */
3672 [TARGET_SYS_RECVMMSG] = 4, /* fd, msgvec, vlen, flags */
3673 [TARGET_SYS_SENDMMSG] = 4, /* fd, msgvec, vlen, flags */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003674 };
3675 abi_long a[6]; /* max 6 args */
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003676 unsigned i;
bellard31e31b82003-02-18 22:55:36 +00003677
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003678 /* check the range of the first argument num */
3679 /* (TARGET_SYS_SENDMMSG is the highest among TARGET_SYS_xxx) */
3680 if (num < 1 || num > TARGET_SYS_SENDMMSG) {
3681 return -TARGET_EINVAL;
3682 }
3683 /* ensure we have space for args */
3684 if (nargs[num] > ARRAY_SIZE(a)) {
3685 return -TARGET_EINVAL;
3686 }
3687 /* collect the arguments in a[] according to nargs[] */
3688 for (i = 0; i < nargs[num]; ++i) {
3689 if (get_user_ual(a[i], vptr + i * sizeof(abi_long)) != 0) {
3690 return -TARGET_EFAULT;
André Hentschelb9d36eb2014-01-06 20:18:52 +01003691 }
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003692 }
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003693 /* now when we have the args, invoke the appropriate underlying function */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003694 switch (num) {
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003695 case TARGET_SYS_SOCKET: /* domain, type, protocol */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003696 return do_socket(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003697 case TARGET_SYS_BIND: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003698 return do_bind(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003699 case TARGET_SYS_CONNECT: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003700 return do_connect(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003701 case TARGET_SYS_LISTEN: /* sockfd, backlog */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003702 return get_errno(listen(a[0], a[1]));
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003703 case TARGET_SYS_ACCEPT: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003704 return do_accept4(a[0], a[1], a[2], 0);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003705 case TARGET_SYS_GETSOCKNAME: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003706 return do_getsockname(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003707 case TARGET_SYS_GETPEERNAME: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003708 return do_getpeername(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003709 case TARGET_SYS_SOCKETPAIR: /* domain, type, protocol, tab */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003710 return do_socketpair(a[0], a[1], a[2], a[3]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003711 case TARGET_SYS_SEND: /* sockfd, msg, len, flags */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003712 return do_sendto(a[0], a[1], a[2], a[3], 0, 0);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003713 case TARGET_SYS_RECV: /* sockfd, msg, len, flags */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003714 return do_recvfrom(a[0], a[1], a[2], a[3], 0, 0);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003715 case TARGET_SYS_SENDTO: /* sockfd, msg, len, flags, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003716 return do_sendto(a[0], a[1], a[2], a[3], a[4], a[5]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003717 case TARGET_SYS_RECVFROM: /* sockfd, msg, len, flags, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003718 return do_recvfrom(a[0], a[1], a[2], a[3], a[4], a[5]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003719 case TARGET_SYS_SHUTDOWN: /* sockfd, how */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003720 return get_errno(shutdown(a[0], a[1]));
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003721 case TARGET_SYS_SETSOCKOPT: /* sockfd, level, optname, optval, optlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003722 return do_setsockopt(a[0], a[1], a[2], a[3], a[4]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003723 case TARGET_SYS_GETSOCKOPT: /* sockfd, level, optname, optval, optlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003724 return do_getsockopt(a[0], a[1], a[2], a[3], a[4]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003725 case TARGET_SYS_SENDMSG: /* sockfd, msg, flags */
3726 return do_sendrecvmsg(a[0], a[1], a[2], 1);
3727 case TARGET_SYS_RECVMSG: /* sockfd, msg, flags */
3728 return do_sendrecvmsg(a[0], a[1], a[2], 0);
3729 case TARGET_SYS_ACCEPT4: /* sockfd, addr, addrlen, flags */
3730 return do_accept4(a[0], a[1], a[2], a[3]);
3731 case TARGET_SYS_RECVMMSG: /* sockfd, msgvec, vlen, flags */
3732 return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0);
3733 case TARGET_SYS_SENDMMSG: /* sockfd, msgvec, vlen, flags */
3734 return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 1);
bellard31e31b82003-02-18 22:55:36 +00003735 default:
Josh Kunz39be5352020-02-03 18:54:13 -08003736 qemu_log_mask(LOG_UNIMP, "Unsupported socketcall: %d\n", num);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003737 return -TARGET_EINVAL;
bellard31e31b82003-02-18 22:55:36 +00003738 }
bellard31e31b82003-02-18 22:55:36 +00003739}
j_mayer32407102007-09-26 23:01:49 +00003740#endif
bellard31e31b82003-02-18 22:55:36 +00003741
bellard8853f862004-02-22 14:57:26 +00003742#define N_SHM_REGIONS 32
3743
3744static struct shm_region {
Peter Maydellb6e17872016-02-09 15:57:11 +00003745 abi_ulong start;
3746 abi_ulong size;
3747 bool in_use;
bellard8853f862004-02-22 14:57:26 +00003748} shm_regions[N_SHM_REGIONS];
3749
Peter Maydell005eb2a2016-07-15 16:50:47 +01003750#ifndef TARGET_SEMID64_DS
3751/* asm-generic version of this struct */
3752struct target_semid64_ds
ths3eb6b042007-06-03 14:26:27 +00003753{
3754 struct target_ipc_perm sem_perm;
blueswir1992f48a2007-10-14 16:27:31 +00003755 abi_ulong sem_otime;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003756#if TARGET_ABI_BITS == 32
blueswir1992f48a2007-10-14 16:27:31 +00003757 abi_ulong __unused1;
Tom Musta03527342014-08-12 13:53:32 -05003758#endif
blueswir1992f48a2007-10-14 16:27:31 +00003759 abi_ulong sem_ctime;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003760#if TARGET_ABI_BITS == 32
blueswir1992f48a2007-10-14 16:27:31 +00003761 abi_ulong __unused2;
Tom Musta03527342014-08-12 13:53:32 -05003762#endif
blueswir1992f48a2007-10-14 16:27:31 +00003763 abi_ulong sem_nsems;
3764 abi_ulong __unused3;
3765 abi_ulong __unused4;
ths3eb6b042007-06-03 14:26:27 +00003766};
Peter Maydell005eb2a2016-07-15 16:50:47 +01003767#endif
ths3eb6b042007-06-03 14:26:27 +00003768
bellard579a97f2007-11-11 14:26:47 +00003769static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
3770 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00003771{
3772 struct target_ipc_perm *target_ip;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003773 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003774
bellard579a97f2007-11-11 14:26:47 +00003775 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
3776 return -TARGET_EFAULT;
Michael S. Tsirkine8bbe362009-09-30 18:56:44 +00003777 target_ip = &(target_sd->sem_perm);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003778 host_ip->__key = tswap32(target_ip->__key);
3779 host_ip->uid = tswap32(target_ip->uid);
3780 host_ip->gid = tswap32(target_ip->gid);
3781 host_ip->cuid = tswap32(target_ip->cuid);
3782 host_ip->cgid = tswap32(target_ip->cgid);
3783#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
3784 host_ip->mode = tswap32(target_ip->mode);
3785#else
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003786 host_ip->mode = tswap16(target_ip->mode);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003787#endif
3788#if defined(TARGET_PPC)
3789 host_ip->__seq = tswap32(target_ip->__seq);
3790#else
3791 host_ip->__seq = tswap16(target_ip->__seq);
3792#endif
ths3eb6b042007-06-03 14:26:27 +00003793 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00003794 return 0;
ths3eb6b042007-06-03 14:26:27 +00003795}
3796
bellard579a97f2007-11-11 14:26:47 +00003797static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
3798 struct ipc_perm *host_ip)
ths3eb6b042007-06-03 14:26:27 +00003799{
3800 struct target_ipc_perm *target_ip;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003801 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003802
bellard579a97f2007-11-11 14:26:47 +00003803 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3804 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00003805 target_ip = &(target_sd->sem_perm);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003806 target_ip->__key = tswap32(host_ip->__key);
3807 target_ip->uid = tswap32(host_ip->uid);
3808 target_ip->gid = tswap32(host_ip->gid);
3809 target_ip->cuid = tswap32(host_ip->cuid);
3810 target_ip->cgid = tswap32(host_ip->cgid);
3811#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
3812 target_ip->mode = tswap32(host_ip->mode);
3813#else
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003814 target_ip->mode = tswap16(host_ip->mode);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003815#endif
3816#if defined(TARGET_PPC)
3817 target_ip->__seq = tswap32(host_ip->__seq);
3818#else
3819 target_ip->__seq = tswap16(host_ip->__seq);
3820#endif
ths3eb6b042007-06-03 14:26:27 +00003821 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00003822 return 0;
ths3eb6b042007-06-03 14:26:27 +00003823}
3824
bellard579a97f2007-11-11 14:26:47 +00003825static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
3826 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00003827{
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_READ, target_sd, target_addr, 1))
3831 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00003832 if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
3833 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003834 host_sd->sem_nsems = tswapal(target_sd->sem_nsems);
3835 host_sd->sem_otime = tswapal(target_sd->sem_otime);
3836 host_sd->sem_ctime = tswapal(target_sd->sem_ctime);
ths3eb6b042007-06-03 14:26:27 +00003837 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00003838 return 0;
ths3eb6b042007-06-03 14:26:27 +00003839}
3840
bellard579a97f2007-11-11 14:26:47 +00003841static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
3842 struct semid_ds *host_sd)
ths3eb6b042007-06-03 14:26:27 +00003843{
Peter Maydell005eb2a2016-07-15 16:50:47 +01003844 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003845
bellard579a97f2007-11-11 14:26:47 +00003846 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3847 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00003848 if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
Dong Xu Wang3a931132011-11-29 16:52:38 +08003849 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003850 target_sd->sem_nsems = tswapal(host_sd->sem_nsems);
3851 target_sd->sem_otime = tswapal(host_sd->sem_otime);
3852 target_sd->sem_ctime = tswapal(host_sd->sem_ctime);
ths3eb6b042007-06-03 14:26:27 +00003853 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00003854 return 0;
ths3eb6b042007-06-03 14:26:27 +00003855}
3856
aurel32e5289082009-04-18 16:16:12 +00003857struct target_seminfo {
3858 int semmap;
3859 int semmni;
3860 int semmns;
3861 int semmnu;
3862 int semmsl;
3863 int semopm;
3864 int semume;
3865 int semusz;
3866 int semvmx;
3867 int semaem;
3868};
3869
3870static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
3871 struct seminfo *host_seminfo)
3872{
3873 struct target_seminfo *target_seminfo;
3874 if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
3875 return -TARGET_EFAULT;
3876 __put_user(host_seminfo->semmap, &target_seminfo->semmap);
3877 __put_user(host_seminfo->semmni, &target_seminfo->semmni);
3878 __put_user(host_seminfo->semmns, &target_seminfo->semmns);
3879 __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
3880 __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
3881 __put_user(host_seminfo->semopm, &target_seminfo->semopm);
3882 __put_user(host_seminfo->semume, &target_seminfo->semume);
3883 __put_user(host_seminfo->semusz, &target_seminfo->semusz);
3884 __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
3885 __put_user(host_seminfo->semaem, &target_seminfo->semaem);
3886 unlock_user_struct(target_seminfo, target_addr, 1);
3887 return 0;
3888}
3889
thsfa294812007-02-02 22:05:00 +00003890union semun {
3891 int val;
ths3eb6b042007-06-03 14:26:27 +00003892 struct semid_ds *buf;
thsfa294812007-02-02 22:05:00 +00003893 unsigned short *array;
aurel32e5289082009-04-18 16:16:12 +00003894 struct seminfo *__buf;
thsfa294812007-02-02 22:05:00 +00003895};
3896
ths3eb6b042007-06-03 14:26:27 +00003897union target_semun {
3898 int val;
aurel32e5289082009-04-18 16:16:12 +00003899 abi_ulong buf;
3900 abi_ulong array;
3901 abi_ulong __buf;
ths3eb6b042007-06-03 14:26:27 +00003902};
3903
aurel32e5289082009-04-18 16:16:12 +00003904static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
3905 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00003906{
aurel32e5289082009-04-18 16:16:12 +00003907 int nsems;
3908 unsigned short *array;
3909 union semun semun;
3910 struct semid_ds semid_ds;
3911 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00003912
aurel32e5289082009-04-18 16:16:12 +00003913 semun.buf = &semid_ds;
3914
3915 ret = semctl(semid, 0, IPC_STAT, semun);
3916 if (ret == -1)
3917 return get_errno(ret);
3918
3919 nsems = semid_ds.sem_nsems;
3920
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303921 *host_array = g_try_new(unsigned short, nsems);
Peter Maydell69d4c702014-02-17 18:55:34 +00003922 if (!*host_array) {
3923 return -TARGET_ENOMEM;
3924 }
aurel32e5289082009-04-18 16:16:12 +00003925 array = lock_user(VERIFY_READ, target_addr,
3926 nsems*sizeof(unsigned short), 1);
Peter Maydell69d4c702014-02-17 18:55:34 +00003927 if (!array) {
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303928 g_free(*host_array);
aurel32e5289082009-04-18 16:16:12 +00003929 return -TARGET_EFAULT;
Peter Maydell69d4c702014-02-17 18:55:34 +00003930 }
aurel32e5289082009-04-18 16:16:12 +00003931
3932 for(i=0; i<nsems; i++) {
3933 __get_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00003934 }
aurel32e5289082009-04-18 16:16:12 +00003935 unlock_user(array, target_addr, 0);
3936
bellard579a97f2007-11-11 14:26:47 +00003937 return 0;
ths3eb6b042007-06-03 14:26:27 +00003938}
3939
aurel32e5289082009-04-18 16:16:12 +00003940static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
3941 unsigned short **host_array)
ths3eb6b042007-06-03 14:26:27 +00003942{
aurel32e5289082009-04-18 16:16:12 +00003943 int nsems;
3944 unsigned short *array;
3945 union semun semun;
3946 struct semid_ds semid_ds;
3947 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00003948
aurel32e5289082009-04-18 16:16:12 +00003949 semun.buf = &semid_ds;
3950
3951 ret = semctl(semid, 0, IPC_STAT, semun);
3952 if (ret == -1)
3953 return get_errno(ret);
3954
3955 nsems = semid_ds.sem_nsems;
3956
3957 array = lock_user(VERIFY_WRITE, target_addr,
3958 nsems*sizeof(unsigned short), 0);
3959 if (!array)
3960 return -TARGET_EFAULT;
3961
3962 for(i=0; i<nsems; i++) {
3963 __put_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00003964 }
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303965 g_free(*host_array);
aurel32e5289082009-04-18 16:16:12 +00003966 unlock_user(array, target_addr, 1);
3967
bellard579a97f2007-11-11 14:26:47 +00003968 return 0;
ths3eb6b042007-06-03 14:26:27 +00003969}
3970
aurel32e5289082009-04-18 16:16:12 +00003971static inline abi_long do_semctl(int semid, int semnum, int cmd,
Stefan Weild1c002b2015-02-08 15:40:58 +01003972 abi_ulong target_arg)
ths3eb6b042007-06-03 14:26:27 +00003973{
Stefan Weild1c002b2015-02-08 15:40:58 +01003974 union target_semun target_su = { .buf = target_arg };
ths3eb6b042007-06-03 14:26:27 +00003975 union semun arg;
3976 struct semid_ds dsarg;
vibi sreenivasan7b8118e2009-06-19 13:34:39 +05303977 unsigned short *array = NULL;
aurel32e5289082009-04-18 16:16:12 +00003978 struct seminfo seminfo;
3979 abi_long ret = -TARGET_EINVAL;
3980 abi_long err;
3981 cmd &= 0xff;
ths3eb6b042007-06-03 14:26:27 +00003982
3983 switch( cmd ) {
3984 case GETVAL:
ths3eb6b042007-06-03 14:26:27 +00003985 case SETVAL:
Tom Musta5464bae2014-08-12 13:53:34 -05003986 /* In 64 bit cross-endian situations, we will erroneously pick up
3987 * the wrong half of the union for the "val" element. To rectify
3988 * this, the entire 8-byte structure is byteswapped, followed by
3989 * a swap of the 4 byte val field. In other cases, the data is
3990 * already in proper host byte order. */
3991 if (sizeof(target_su.val) != (sizeof(target_su.buf))) {
3992 target_su.buf = tswapal(target_su.buf);
3993 arg.val = tswap32(target_su.val);
3994 } else {
3995 arg.val = target_su.val;
3996 }
aurel32e5289082009-04-18 16:16:12 +00003997 ret = get_errno(semctl(semid, semnum, cmd, arg));
ths3eb6b042007-06-03 14:26:27 +00003998 break;
3999 case GETALL:
ths3eb6b042007-06-03 14:26:27 +00004000 case SETALL:
aurel32e5289082009-04-18 16:16:12 +00004001 err = target_to_host_semarray(semid, &array, target_su.array);
4002 if (err)
4003 return err;
4004 arg.array = array;
4005 ret = get_errno(semctl(semid, semnum, cmd, arg));
4006 err = host_to_target_semarray(semid, target_su.array, &array);
4007 if (err)
4008 return err;
ths3eb6b042007-06-03 14:26:27 +00004009 break;
4010 case IPC_STAT:
ths3eb6b042007-06-03 14:26:27 +00004011 case IPC_SET:
aurel32e5289082009-04-18 16:16:12 +00004012 case SEM_STAT:
4013 err = target_to_host_semid_ds(&dsarg, target_su.buf);
4014 if (err)
4015 return err;
4016 arg.buf = &dsarg;
4017 ret = get_errno(semctl(semid, semnum, cmd, arg));
4018 err = host_to_target_semid_ds(target_su.buf, &dsarg);
4019 if (err)
4020 return err;
ths3eb6b042007-06-03 14:26:27 +00004021 break;
aurel32e5289082009-04-18 16:16:12 +00004022 case IPC_INFO:
4023 case SEM_INFO:
4024 arg.__buf = &seminfo;
4025 ret = get_errno(semctl(semid, semnum, cmd, arg));
4026 err = host_to_target_seminfo(target_su.__buf, &seminfo);
4027 if (err)
4028 return err;
4029 break;
4030 case IPC_RMID:
4031 case GETPID:
4032 case GETNCNT:
4033 case GETZCNT:
4034 ret = get_errno(semctl(semid, semnum, cmd, NULL));
4035 break;
ths3eb6b042007-06-03 14:26:27 +00004036 }
4037
4038 return ret;
4039}
4040
aurel32e5289082009-04-18 16:16:12 +00004041struct target_sembuf {
4042 unsigned short sem_num;
4043 short sem_op;
4044 short sem_flg;
4045};
4046
4047static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
4048 abi_ulong target_addr,
4049 unsigned nsops)
4050{
4051 struct target_sembuf *target_sembuf;
4052 int i;
4053
4054 target_sembuf = lock_user(VERIFY_READ, target_addr,
4055 nsops*sizeof(struct target_sembuf), 1);
4056 if (!target_sembuf)
4057 return -TARGET_EFAULT;
4058
4059 for(i=0; i<nsops; i++) {
4060 __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
4061 __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
4062 __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
4063 }
4064
4065 unlock_user(target_sembuf, target_addr, 0);
4066
4067 return 0;
4068}
4069
Matus Kyseld8c08b12020-06-26 14:46:11 +02004070#if defined(TARGET_NR_ipc) || defined(TARGET_NR_semop) || \
Filip Bozutacac46eb2020-08-25 00:30:50 +02004071 defined(TARGET_NR_semtimedop) || defined(TARGET_NR_semtimedop_time64)
Matus Kyseld8c08b12020-06-26 14:46:11 +02004072
4073/*
4074 * This macro is required to handle the s390 variants, which passes the
4075 * arguments in a different order than default.
4076 */
4077#ifdef __s390x__
4078#define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
4079 (__nsops), (__timeout), (__sops)
4080#else
4081#define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
4082 (__nsops), 0, (__sops), (__timeout)
4083#endif
4084
4085static inline abi_long do_semtimedop(int semid,
4086 abi_long ptr,
4087 unsigned nsops,
Filip Bozutacac46eb2020-08-25 00:30:50 +02004088 abi_long timeout, bool time64)
aurel32e5289082009-04-18 16:16:12 +00004089{
Filip Bozuta0a7ec842020-08-18 20:07:22 +02004090 struct sembuf *sops;
Matus Kyseld8c08b12020-06-26 14:46:11 +02004091 struct timespec ts, *pts = NULL;
Laurent Vivier524fa342019-05-29 10:48:04 +02004092 abi_long ret;
aurel32e5289082009-04-18 16:16:12 +00004093
Matus Kyseld8c08b12020-06-26 14:46:11 +02004094 if (timeout) {
4095 pts = &ts;
Filip Bozutacac46eb2020-08-25 00:30:50 +02004096 if (time64) {
4097 if (target_to_host_timespec64(pts, timeout)) {
4098 return -TARGET_EFAULT;
4099 }
4100 } else {
4101 if (target_to_host_timespec(pts, timeout)) {
4102 return -TARGET_EFAULT;
4103 }
Matus Kyseld8c08b12020-06-26 14:46:11 +02004104 }
4105 }
4106
Filip Bozuta0a7ec842020-08-18 20:07:22 +02004107 if (nsops > TARGET_SEMOPM) {
4108 return -TARGET_E2BIG;
4109 }
4110
4111 sops = g_new(struct sembuf, nsops);
4112
4113 if (target_to_host_sembuf(sops, ptr, nsops)) {
4114 g_free(sops);
aurel32e5289082009-04-18 16:16:12 +00004115 return -TARGET_EFAULT;
Filip Bozuta0a7ec842020-08-18 20:07:22 +02004116 }
aurel32e5289082009-04-18 16:16:12 +00004117
Laurent Vivier524fa342019-05-29 10:48:04 +02004118 ret = -TARGET_ENOSYS;
4119#ifdef __NR_semtimedop
Matus Kyseld8c08b12020-06-26 14:46:11 +02004120 ret = get_errno(safe_semtimedop(semid, sops, nsops, pts));
Laurent Vivier524fa342019-05-29 10:48:04 +02004121#endif
4122#ifdef __NR_ipc
4123 if (ret == -TARGET_ENOSYS) {
Matus Kyseld8c08b12020-06-26 14:46:11 +02004124 ret = get_errno(safe_ipc(IPCOP_semtimedop, semid,
4125 SEMTIMEDOP_IPC_ARGS(nsops, sops, (long)pts)));
Laurent Vivier524fa342019-05-29 10:48:04 +02004126 }
4127#endif
Filip Bozuta0a7ec842020-08-18 20:07:22 +02004128 g_free(sops);
Laurent Vivier524fa342019-05-29 10:48:04 +02004129 return ret;
aurel32e5289082009-04-18 16:16:12 +00004130}
Matus Kyseld8c08b12020-06-26 14:46:11 +02004131#endif
aurel32e5289082009-04-18 16:16:12 +00004132
ths1bc012f2007-06-03 14:27:49 +00004133struct target_msqid_ds
4134{
aurel321c54ff92008-10-13 21:08:44 +00004135 struct target_ipc_perm msg_perm;
4136 abi_ulong msg_stime;
4137#if TARGET_ABI_BITS == 32
4138 abi_ulong __unused1;
4139#endif
4140 abi_ulong msg_rtime;
4141#if TARGET_ABI_BITS == 32
4142 abi_ulong __unused2;
4143#endif
4144 abi_ulong msg_ctime;
4145#if TARGET_ABI_BITS == 32
4146 abi_ulong __unused3;
4147#endif
4148 abi_ulong __msg_cbytes;
4149 abi_ulong msg_qnum;
4150 abi_ulong msg_qbytes;
4151 abi_ulong msg_lspid;
4152 abi_ulong msg_lrpid;
4153 abi_ulong __unused4;
4154 abi_ulong __unused5;
ths1bc012f2007-06-03 14:27:49 +00004155};
4156
bellard579a97f2007-11-11 14:26:47 +00004157static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
4158 abi_ulong target_addr)
ths1bc012f2007-06-03 14:27:49 +00004159{
4160 struct target_msqid_ds *target_md;
4161
bellard579a97f2007-11-11 14:26:47 +00004162 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
4163 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00004164 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
4165 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02004166 host_md->msg_stime = tswapal(target_md->msg_stime);
4167 host_md->msg_rtime = tswapal(target_md->msg_rtime);
4168 host_md->msg_ctime = tswapal(target_md->msg_ctime);
4169 host_md->__msg_cbytes = tswapal(target_md->__msg_cbytes);
4170 host_md->msg_qnum = tswapal(target_md->msg_qnum);
4171 host_md->msg_qbytes = tswapal(target_md->msg_qbytes);
4172 host_md->msg_lspid = tswapal(target_md->msg_lspid);
4173 host_md->msg_lrpid = tswapal(target_md->msg_lrpid);
ths1bc012f2007-06-03 14:27:49 +00004174 unlock_user_struct(target_md, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00004175 return 0;
ths1bc012f2007-06-03 14:27:49 +00004176}
4177
bellard579a97f2007-11-11 14:26:47 +00004178static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
4179 struct msqid_ds *host_md)
ths1bc012f2007-06-03 14:27:49 +00004180{
4181 struct target_msqid_ds *target_md;
4182
bellard579a97f2007-11-11 14:26:47 +00004183 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
4184 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00004185 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
4186 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02004187 target_md->msg_stime = tswapal(host_md->msg_stime);
4188 target_md->msg_rtime = tswapal(host_md->msg_rtime);
4189 target_md->msg_ctime = tswapal(host_md->msg_ctime);
4190 target_md->__msg_cbytes = tswapal(host_md->__msg_cbytes);
4191 target_md->msg_qnum = tswapal(host_md->msg_qnum);
4192 target_md->msg_qbytes = tswapal(host_md->msg_qbytes);
4193 target_md->msg_lspid = tswapal(host_md->msg_lspid);
4194 target_md->msg_lrpid = tswapal(host_md->msg_lrpid);
ths1bc012f2007-06-03 14:27:49 +00004195 unlock_user_struct(target_md, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00004196 return 0;
ths1bc012f2007-06-03 14:27:49 +00004197}
4198
aurel321c54ff92008-10-13 21:08:44 +00004199struct target_msginfo {
4200 int msgpool;
4201 int msgmap;
4202 int msgmax;
4203 int msgmnb;
4204 int msgmni;
4205 int msgssz;
4206 int msgtql;
4207 unsigned short int msgseg;
4208};
4209
4210static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
4211 struct msginfo *host_msginfo)
4212{
4213 struct target_msginfo *target_msginfo;
4214 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
4215 return -TARGET_EFAULT;
4216 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
4217 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
4218 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
4219 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
4220 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
4221 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
4222 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
4223 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
4224 unlock_user_struct(target_msginfo, target_addr, 1);
aurel3200b229a2008-10-24 13:12:52 +00004225 return 0;
aurel321c54ff92008-10-13 21:08:44 +00004226}
4227
4228static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
ths1bc012f2007-06-03 14:27:49 +00004229{
4230 struct msqid_ds dsarg;
aurel321c54ff92008-10-13 21:08:44 +00004231 struct msginfo msginfo;
4232 abi_long ret = -TARGET_EINVAL;
4233
4234 cmd &= 0xff;
4235
4236 switch (cmd) {
ths1bc012f2007-06-03 14:27:49 +00004237 case IPC_STAT:
4238 case IPC_SET:
aurel321c54ff92008-10-13 21:08:44 +00004239 case MSG_STAT:
4240 if (target_to_host_msqid_ds(&dsarg,ptr))
4241 return -TARGET_EFAULT;
4242 ret = get_errno(msgctl(msgid, cmd, &dsarg));
4243 if (host_to_target_msqid_ds(ptr,&dsarg))
4244 return -TARGET_EFAULT;
4245 break;
4246 case IPC_RMID:
4247 ret = get_errno(msgctl(msgid, cmd, NULL));
4248 break;
4249 case IPC_INFO:
4250 case MSG_INFO:
4251 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
4252 if (host_to_target_msginfo(ptr, &msginfo))
4253 return -TARGET_EFAULT;
4254 break;
ths1bc012f2007-06-03 14:27:49 +00004255 }
aurel321c54ff92008-10-13 21:08:44 +00004256
ths1bc012f2007-06-03 14:27:49 +00004257 return ret;
4258}
4259
4260struct target_msgbuf {
aurel321c54ff92008-10-13 21:08:44 +00004261 abi_long mtype;
4262 char mtext[1];
ths1bc012f2007-06-03 14:27:49 +00004263};
4264
blueswir1992f48a2007-10-14 16:27:31 +00004265static inline abi_long do_msgsnd(int msqid, abi_long msgp,
Tom Mustaedcc5f92014-08-12 13:53:37 -05004266 ssize_t msgsz, int msgflg)
ths1bc012f2007-06-03 14:27:49 +00004267{
4268 struct target_msgbuf *target_mb;
4269 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00004270 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00004271
Tom Mustaedcc5f92014-08-12 13:53:37 -05004272 if (msgsz < 0) {
4273 return -TARGET_EINVAL;
4274 }
4275
bellard579a97f2007-11-11 14:26:47 +00004276 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
4277 return -TARGET_EFAULT;
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304278 host_mb = g_try_malloc(msgsz + sizeof(long));
zhanghailiang29e03fc2014-08-14 15:29:18 +08004279 if (!host_mb) {
4280 unlock_user_struct(target_mb, msgp, 0);
4281 return -TARGET_ENOMEM;
4282 }
Matthias Brauncbb21ee2011-08-12 19:57:41 +02004283 host_mb->mtype = (abi_long) tswapal(target_mb->mtype);
aurel321c54ff92008-10-13 21:08:44 +00004284 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
Laurent Vivier524fa342019-05-29 10:48:04 +02004285 ret = -TARGET_ENOSYS;
4286#ifdef __NR_msgsnd
Peter Maydell89f9fe42016-06-06 19:58:05 +01004287 ret = get_errno(safe_msgsnd(msqid, host_mb, msgsz, msgflg));
Laurent Vivier524fa342019-05-29 10:48:04 +02004288#endif
4289#ifdef __NR_ipc
4290 if (ret == -TARGET_ENOSYS) {
Matus Kyseld8c08b12020-06-26 14:46:11 +02004291#ifdef __s390x__
4292 ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg,
4293 host_mb));
4294#else
Laurent Vivier524fa342019-05-29 10:48:04 +02004295 ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg,
4296 host_mb, 0));
Matus Kyseld8c08b12020-06-26 14:46:11 +02004297#endif
Laurent Vivier524fa342019-05-29 10:48:04 +02004298 }
4299#endif
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304300 g_free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00004301 unlock_user_struct(target_mb, msgp, 0);
4302
4303 return ret;
4304}
4305
Matus Kyseld8c08b12020-06-26 14:46:11 +02004306#ifdef __NR_ipc
4307#if defined(__sparc__)
4308/* SPARC for msgrcv it does not use the kludge on final 2 arguments. */
4309#define MSGRCV_ARGS(__msgp, __msgtyp) __msgp, __msgtyp
4310#elif defined(__s390x__)
4311/* The s390 sys_ipc variant has only five parameters. */
4312#define MSGRCV_ARGS(__msgp, __msgtyp) \
4313 ((long int[]){(long int)__msgp, __msgtyp})
4314#else
4315#define MSGRCV_ARGS(__msgp, __msgtyp) \
4316 ((long int[]){(long int)__msgp, __msgtyp}), 0
4317#endif
4318#endif
4319
blueswir1992f48a2007-10-14 16:27:31 +00004320static inline abi_long do_msgrcv(int msqid, abi_long msgp,
Peter Maydell99874f62016-05-20 19:00:56 +01004321 ssize_t msgsz, abi_long msgtyp,
blueswir1992f48a2007-10-14 16:27:31 +00004322 int msgflg)
ths1bc012f2007-06-03 14:27:49 +00004323{
4324 struct target_msgbuf *target_mb;
bellard579a97f2007-11-11 14:26:47 +00004325 char *target_mtext;
ths1bc012f2007-06-03 14:27:49 +00004326 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00004327 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00004328
Peter Maydell99874f62016-05-20 19:00:56 +01004329 if (msgsz < 0) {
4330 return -TARGET_EINVAL;
4331 }
4332
bellard579a97f2007-11-11 14:26:47 +00004333 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
4334 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00004335
Peter Maydell415d8472016-05-20 19:00:57 +01004336 host_mb = g_try_malloc(msgsz + sizeof(long));
4337 if (!host_mb) {
4338 ret = -TARGET_ENOMEM;
4339 goto end;
4340 }
Laurent Vivier524fa342019-05-29 10:48:04 +02004341 ret = -TARGET_ENOSYS;
4342#ifdef __NR_msgrcv
Peter Maydell89f9fe42016-06-06 19:58:05 +01004343 ret = get_errno(safe_msgrcv(msqid, host_mb, msgsz, msgtyp, msgflg));
Laurent Vivier524fa342019-05-29 10:48:04 +02004344#endif
4345#ifdef __NR_ipc
4346 if (ret == -TARGET_ENOSYS) {
4347 ret = get_errno(safe_ipc(IPCOP_CALL(1, IPCOP_msgrcv), msqid, msgsz,
Matus Kyseld8c08b12020-06-26 14:46:11 +02004348 msgflg, MSGRCV_ARGS(host_mb, msgtyp)));
Laurent Vivier524fa342019-05-29 10:48:04 +02004349 }
4350#endif
aurel321c54ff92008-10-13 21:08:44 +00004351
bellard579a97f2007-11-11 14:26:47 +00004352 if (ret > 0) {
4353 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
4354 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
4355 if (!target_mtext) {
4356 ret = -TARGET_EFAULT;
4357 goto end;
4358 }
aurel321c54ff92008-10-13 21:08:44 +00004359 memcpy(target_mb->mtext, host_mb->mtext, ret);
bellard579a97f2007-11-11 14:26:47 +00004360 unlock_user(target_mtext, target_mtext_addr, ret);
4361 }
aurel321c54ff92008-10-13 21:08:44 +00004362
Matthias Brauncbb21ee2011-08-12 19:57:41 +02004363 target_mb->mtype = tswapal(host_mb->mtype);
ths1bc012f2007-06-03 14:27:49 +00004364
bellard579a97f2007-11-11 14:26:47 +00004365end:
4366 if (target_mb)
4367 unlock_user_struct(target_mb, msgp, 1);
Jim Meyering0d07fe42012-08-22 13:55:53 +02004368 g_free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00004369 return ret;
4370}
4371
Riku Voipio88a8c982009-04-03 10:42:00 +03004372static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
4373 abi_ulong target_addr)
4374{
4375 struct target_shmid_ds *target_sd;
4376
4377 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
4378 return -TARGET_EFAULT;
4379 if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
4380 return -TARGET_EFAULT;
4381 __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
4382 __get_user(host_sd->shm_atime, &target_sd->shm_atime);
4383 __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
4384 __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
4385 __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
4386 __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
4387 __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
4388 unlock_user_struct(target_sd, target_addr, 0);
4389 return 0;
4390}
4391
4392static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
4393 struct shmid_ds *host_sd)
4394{
4395 struct target_shmid_ds *target_sd;
4396
4397 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
4398 return -TARGET_EFAULT;
4399 if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
4400 return -TARGET_EFAULT;
4401 __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
4402 __put_user(host_sd->shm_atime, &target_sd->shm_atime);
4403 __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
4404 __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
4405 __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
4406 __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
4407 __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
4408 unlock_user_struct(target_sd, target_addr, 1);
4409 return 0;
4410}
4411
4412struct target_shminfo {
4413 abi_ulong shmmax;
4414 abi_ulong shmmin;
4415 abi_ulong shmmni;
4416 abi_ulong shmseg;
4417 abi_ulong shmall;
4418};
4419
4420static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
4421 struct shminfo *host_shminfo)
4422{
4423 struct target_shminfo *target_shminfo;
4424 if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
4425 return -TARGET_EFAULT;
4426 __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
4427 __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
4428 __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
4429 __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
4430 __put_user(host_shminfo->shmall, &target_shminfo->shmall);
4431 unlock_user_struct(target_shminfo, target_addr, 1);
4432 return 0;
4433}
4434
4435struct target_shm_info {
4436 int used_ids;
4437 abi_ulong shm_tot;
4438 abi_ulong shm_rss;
4439 abi_ulong shm_swp;
4440 abi_ulong swap_attempts;
4441 abi_ulong swap_successes;
4442};
4443
4444static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
4445 struct shm_info *host_shm_info)
4446{
4447 struct target_shm_info *target_shm_info;
4448 if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
4449 return -TARGET_EFAULT;
4450 __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
4451 __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
4452 __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
4453 __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
4454 __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
4455 __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
4456 unlock_user_struct(target_shm_info, target_addr, 1);
4457 return 0;
4458}
4459
4460static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
4461{
4462 struct shmid_ds dsarg;
4463 struct shminfo shminfo;
4464 struct shm_info shm_info;
4465 abi_long ret = -TARGET_EINVAL;
4466
4467 cmd &= 0xff;
4468
4469 switch(cmd) {
4470 case IPC_STAT:
4471 case IPC_SET:
4472 case SHM_STAT:
4473 if (target_to_host_shmid_ds(&dsarg, buf))
4474 return -TARGET_EFAULT;
4475 ret = get_errno(shmctl(shmid, cmd, &dsarg));
4476 if (host_to_target_shmid_ds(buf, &dsarg))
4477 return -TARGET_EFAULT;
4478 break;
4479 case IPC_INFO:
4480 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
4481 if (host_to_target_shminfo(buf, &shminfo))
4482 return -TARGET_EFAULT;
4483 break;
4484 case SHM_INFO:
4485 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
4486 if (host_to_target_shm_info(buf, &shm_info))
4487 return -TARGET_EFAULT;
4488 break;
4489 case IPC_RMID:
4490 case SHM_LOCK:
4491 case SHM_UNLOCK:
4492 ret = get_errno(shmctl(shmid, cmd, NULL));
4493 break;
4494 }
4495
4496 return ret;
4497}
4498
Peter Maydellee8e7612016-07-11 16:48:11 +01004499#ifndef TARGET_FORCE_SHMLBA
4500/* For most architectures, SHMLBA is the same as the page size;
4501 * some architectures have larger values, in which case they should
4502 * define TARGET_FORCE_SHMLBA and provide a target_shmlba() function.
4503 * This corresponds to the kernel arch code defining __ARCH_FORCE_SHMLBA
4504 * and defining its own value for SHMLBA.
4505 *
4506 * The kernel also permits SHMLBA to be set by the architecture to a
4507 * value larger than the page size without setting __ARCH_FORCE_SHMLBA;
4508 * this means that addresses are rounded to the large size if
4509 * SHM_RND is set but addresses not aligned to that size are not rejected
4510 * as long as they are at least page-aligned. Since the only architecture
4511 * which uses this is ia64 this code doesn't provide for that oddity.
4512 */
4513static inline abi_ulong target_shmlba(CPUArchState *cpu_env)
4514{
4515 return TARGET_PAGE_SIZE;
4516}
4517#endif
4518
4519static inline abi_ulong do_shmat(CPUArchState *cpu_env,
4520 int shmid, abi_ulong shmaddr, int shmflg)
Riku Voipio88a8c982009-04-03 10:42:00 +03004521{
Richard Henderson228168c2021-06-11 23:08:28 -07004522 CPUState *cpu = env_cpu(cpu_env);
Riku Voipio88a8c982009-04-03 10:42:00 +03004523 abi_long raddr;
4524 void *host_raddr;
4525 struct shmid_ds shm_info;
4526 int i,ret;
Peter Maydellee8e7612016-07-11 16:48:11 +01004527 abi_ulong shmlba;
Riku Voipio88a8c982009-04-03 10:42:00 +03004528
Richard Hendersonee1bf832021-02-12 10:48:44 -08004529 /* shmat pointers are always untagged */
4530
Riku Voipio88a8c982009-04-03 10:42:00 +03004531 /* find out the length of the shared memory segment */
4532 ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
4533 if (is_error(ret)) {
4534 /* can't get length, bail out */
4535 return ret;
4536 }
4537
Peter Maydellee8e7612016-07-11 16:48:11 +01004538 shmlba = target_shmlba(cpu_env);
4539
4540 if (shmaddr & (shmlba - 1)) {
4541 if (shmflg & SHM_RND) {
4542 shmaddr &= ~(shmlba - 1);
4543 } else {
4544 return -TARGET_EINVAL;
4545 }
4546 }
Richard Henderson46b12f42021-02-12 10:48:46 -08004547 if (!guest_range_valid_untagged(shmaddr, shm_info.shm_segsz)) {
Max Filippovebf9a362018-03-07 13:50:10 -08004548 return -TARGET_EINVAL;
4549 }
Peter Maydellee8e7612016-07-11 16:48:11 +01004550
Riku Voipio88a8c982009-04-03 10:42:00 +03004551 mmap_lock();
4552
Richard Henderson228168c2021-06-11 23:08:28 -07004553 /*
4554 * We're mapping shared memory, so ensure we generate code for parallel
4555 * execution and flush old translations. This will work up to the level
4556 * supported by the host -- anything that requires EXCP_ATOMIC will not
4557 * be atomic with respect to an external process.
4558 */
4559 if (!(cpu->tcg_cflags & CF_PARALLEL)) {
4560 cpu->tcg_cflags |= CF_PARALLEL;
4561 tb_flush(cpu);
4562 }
4563
Riku Voipio88a8c982009-04-03 10:42:00 +03004564 if (shmaddr)
Richard Henderson3e8f1622021-02-12 10:48:43 -08004565 host_raddr = shmat(shmid, (void *)g2h_untagged(shmaddr), shmflg);
Riku Voipio88a8c982009-04-03 10:42:00 +03004566 else {
4567 abi_ulong mmap_start;
4568
Richard Henderson30ab9ef2019-05-19 13:19:52 -07004569 /* In order to use the host shmat, we need to honor host SHMLBA. */
4570 mmap_start = mmap_find_vma(0, shm_info.shm_segsz, MAX(SHMLBA, shmlba));
Riku Voipio88a8c982009-04-03 10:42:00 +03004571
4572 if (mmap_start == -1) {
4573 errno = ENOMEM;
4574 host_raddr = (void *)-1;
4575 } else
Richard Henderson3e8f1622021-02-12 10:48:43 -08004576 host_raddr = shmat(shmid, g2h_untagged(mmap_start),
4577 shmflg | SHM_REMAP);
Riku Voipio88a8c982009-04-03 10:42:00 +03004578 }
4579
4580 if (host_raddr == (void *)-1) {
4581 mmap_unlock();
4582 return get_errno((long)host_raddr);
4583 }
4584 raddr=h2g((unsigned long)host_raddr);
4585
4586 page_set_flags(raddr, raddr + shm_info.shm_segsz,
Richard Hendersond9c58582021-02-12 10:48:32 -08004587 PAGE_VALID | PAGE_RESET | PAGE_READ |
4588 (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
Riku Voipio88a8c982009-04-03 10:42:00 +03004589
4590 for (i = 0; i < N_SHM_REGIONS; i++) {
Peter Maydellb6e17872016-02-09 15:57:11 +00004591 if (!shm_regions[i].in_use) {
4592 shm_regions[i].in_use = true;
Riku Voipio88a8c982009-04-03 10:42:00 +03004593 shm_regions[i].start = raddr;
4594 shm_regions[i].size = shm_info.shm_segsz;
4595 break;
4596 }
4597 }
4598
4599 mmap_unlock();
4600 return raddr;
4601
4602}
4603
4604static inline abi_long do_shmdt(abi_ulong shmaddr)
4605{
4606 int i;
Max Filippov3c5f6a52018-02-28 14:16:04 -08004607 abi_long rv;
4608
Richard Hendersonee1bf832021-02-12 10:48:44 -08004609 /* shmdt pointers are always untagged */
4610
Max Filippov3c5f6a52018-02-28 14:16:04 -08004611 mmap_lock();
Riku Voipio88a8c982009-04-03 10:42:00 +03004612
4613 for (i = 0; i < N_SHM_REGIONS; ++i) {
Peter Maydellb6e17872016-02-09 15:57:11 +00004614 if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
4615 shm_regions[i].in_use = false;
takasi-y@ops.dti.ne.jpe00ac242010-04-11 02:09:57 +09004616 page_set_flags(shmaddr, shmaddr + shm_regions[i].size, 0);
Riku Voipio88a8c982009-04-03 10:42:00 +03004617 break;
4618 }
4619 }
Richard Henderson3e8f1622021-02-12 10:48:43 -08004620 rv = get_errno(shmdt(g2h_untagged(shmaddr)));
Riku Voipio88a8c982009-04-03 10:42:00 +03004621
Max Filippov3c5f6a52018-02-28 14:16:04 -08004622 mmap_unlock();
4623
4624 return rv;
Riku Voipio88a8c982009-04-03 10:42:00 +03004625}
4626
aurel321c54ff92008-10-13 21:08:44 +00004627#ifdef TARGET_NR_ipc
pbrook53a59602006-03-25 19:31:22 +00004628/* ??? This only works with linear mappings. */
ths0da46a62007-10-20 20:23:07 +00004629/* do_ipc() must return target values and target errnos. */
Peter Maydellee8e7612016-07-11 16:48:11 +01004630static abi_long do_ipc(CPUArchState *cpu_env,
4631 unsigned int call, abi_long first,
Tom Musta37ed0952014-08-12 13:53:35 -05004632 abi_long second, abi_long third,
blueswir1992f48a2007-10-14 16:27:31 +00004633 abi_long ptr, abi_long fifth)
bellard8853f862004-02-22 14:57:26 +00004634{
4635 int version;
blueswir1992f48a2007-10-14 16:27:31 +00004636 abi_long ret = 0;
bellard8853f862004-02-22 14:57:26 +00004637
4638 version = call >> 16;
4639 call &= 0xffff;
4640
4641 switch (call) {
thsfa294812007-02-02 22:05:00 +00004642 case IPCOP_semop:
Filip Bozutacac46eb2020-08-25 00:30:50 +02004643 ret = do_semtimedop(first, ptr, second, 0, false);
Matus Kyseld8c08b12020-06-26 14:46:11 +02004644 break;
4645 case IPCOP_semtimedop:
4646 /*
4647 * The s390 sys_ipc variant has only five parameters instead of six
4648 * (as for default variant) and the only difference is the handling of
4649 * SEMTIMEDOP where on s390 the third parameter is used as a pointer
4650 * to a struct timespec where the generic variant uses fifth parameter.
4651 */
4652#if defined(TARGET_S390X)
Filip Bozutacac46eb2020-08-25 00:30:50 +02004653 ret = do_semtimedop(first, ptr, second, third, TARGET_ABI_BITS == 64);
Matus Kyseld8c08b12020-06-26 14:46:11 +02004654#else
Filip Bozutacac46eb2020-08-25 00:30:50 +02004655 ret = do_semtimedop(first, ptr, second, fifth, TARGET_ABI_BITS == 64);
Matus Kyseld8c08b12020-06-26 14:46:11 +02004656#endif
thsfa294812007-02-02 22:05:00 +00004657 break;
4658
4659 case IPCOP_semget:
4660 ret = get_errno(semget(first, second, third));
4661 break;
4662
Tom Musta5d2fa8e2014-08-12 13:53:33 -05004663 case IPCOP_semctl: {
4664 /* The semun argument to semctl is passed by value, so dereference the
4665 * ptr argument. */
4666 abi_ulong atptr;
Tom Musta37ed0952014-08-12 13:53:35 -05004667 get_user_ual(atptr, ptr);
Stefan Weild1c002b2015-02-08 15:40:58 +01004668 ret = do_semctl(first, second, third, atptr);
thsfa294812007-02-02 22:05:00 +00004669 break;
Tom Musta5d2fa8e2014-08-12 13:53:33 -05004670 }
thsd96372e2007-02-02 22:05:44 +00004671
aurel321c54ff92008-10-13 21:08:44 +00004672 case IPCOP_msgget:
4673 ret = get_errno(msgget(first, second));
4674 break;
thsd96372e2007-02-02 22:05:44 +00004675
aurel321c54ff92008-10-13 21:08:44 +00004676 case IPCOP_msgsnd:
4677 ret = do_msgsnd(first, ptr, second, third);
4678 break;
thsd96372e2007-02-02 22:05:44 +00004679
aurel321c54ff92008-10-13 21:08:44 +00004680 case IPCOP_msgctl:
4681 ret = do_msgctl(first, second, ptr);
4682 break;
thsd96372e2007-02-02 22:05:44 +00004683
aurel321c54ff92008-10-13 21:08:44 +00004684 case IPCOP_msgrcv:
4685 switch (version) {
4686 case 0:
4687 {
4688 struct target_ipc_kludge {
4689 abi_long msgp;
4690 abi_long msgtyp;
4691 } *tmp;
thsd96372e2007-02-02 22:05:44 +00004692
aurel321c54ff92008-10-13 21:08:44 +00004693 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
4694 ret = -TARGET_EFAULT;
4695 break;
ths1bc012f2007-06-03 14:27:49 +00004696 }
aurel321c54ff92008-10-13 21:08:44 +00004697
Laurent Vivier79dd77d2012-12-20 11:00:11 +00004698 ret = do_msgrcv(first, tswapal(tmp->msgp), second, tswapal(tmp->msgtyp), third);
aurel321c54ff92008-10-13 21:08:44 +00004699
4700 unlock_user_struct(tmp, ptr, 0);
4701 break;
4702 }
4703 default:
4704 ret = do_msgrcv(first, ptr, second, fifth, third);
4705 }
4706 break;
thsd96372e2007-02-02 22:05:44 +00004707
bellard8853f862004-02-22 14:57:26 +00004708 case IPCOP_shmat:
Riku Voipio88a8c982009-04-03 10:42:00 +03004709 switch (version) {
4710 default:
bellard5a4a8982007-11-11 17:39:18 +00004711 {
4712 abi_ulong raddr;
Peter Maydellee8e7612016-07-11 16:48:11 +01004713 raddr = do_shmat(cpu_env, first, ptr, second);
Riku Voipio88a8c982009-04-03 10:42:00 +03004714 if (is_error(raddr))
4715 return get_errno(raddr);
bellard2f619692007-11-16 10:46:05 +00004716 if (put_user_ual(raddr, third))
bellard5a4a8982007-11-11 17:39:18 +00004717 return -TARGET_EFAULT;
Riku Voipio88a8c982009-04-03 10:42:00 +03004718 break;
4719 }
4720 case 1:
4721 ret = -TARGET_EINVAL;
4722 break;
bellard5a4a8982007-11-11 17:39:18 +00004723 }
bellard8853f862004-02-22 14:57:26 +00004724 break;
4725 case IPCOP_shmdt:
Riku Voipio88a8c982009-04-03 10:42:00 +03004726 ret = do_shmdt(ptr);
bellard8853f862004-02-22 14:57:26 +00004727 break;
4728
4729 case IPCOP_shmget:
4730 /* IPC_* flag values are the same on all linux platforms */
4731 ret = get_errno(shmget(first, second, third));
4732 break;
4733
4734 /* IPC_* and SHM_* command values are the same on all linux platforms */
4735 case IPCOP_shmctl:
Petar Jovanovica2926782013-10-30 14:46:32 +01004736 ret = do_shmctl(first, second, ptr);
bellard8853f862004-02-22 14:57:26 +00004737 break;
4738 default:
Josh Kunz39be5352020-02-03 18:54:13 -08004739 qemu_log_mask(LOG_UNIMP, "Unsupported ipc call: %d (version %d)\n",
4740 call, version);
ths0da46a62007-10-20 20:23:07 +00004741 ret = -TARGET_ENOSYS;
bellard8853f862004-02-22 14:57:26 +00004742 break;
4743 }
4744 return ret;
4745}
j_mayer32407102007-09-26 23:01:49 +00004746#endif
bellard8853f862004-02-22 14:57:26 +00004747
bellard31e31b82003-02-18 22:55:36 +00004748/* kernel structure types definitions */
bellard31e31b82003-02-18 22:55:36 +00004749
Blue Swirl001faf32009-05-13 17:53:17 +00004750#define STRUCT(name, ...) STRUCT_ ## name,
bellard31e31b82003-02-18 22:55:36 +00004751#define STRUCT_SPECIAL(name) STRUCT_ ## name,
4752enum {
4753#include "syscall_types.h"
Alexander Graf8be656b2015-05-06 23:47:32 +02004754STRUCT_MAX
bellard31e31b82003-02-18 22:55:36 +00004755};
4756#undef STRUCT
4757#undef STRUCT_SPECIAL
4758
Blue Swirl001faf32009-05-13 17:53:17 +00004759#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
bellard31e31b82003-02-18 22:55:36 +00004760#define STRUCT_SPECIAL(name)
4761#include "syscall_types.h"
4762#undef STRUCT
4763#undef STRUCT_SPECIAL
4764
bellard31e31b82003-02-18 22:55:36 +00004765#define MAX_STRUCT_SIZE 4096
4766
Peter Maydelldace20d2011-01-10 13:11:24 +00004767#ifdef CONFIG_FIEMAP
Peter Maydell285da2b2011-01-06 15:04:18 +00004768/* So fiemap access checks don't overflow on 32 bit systems.
4769 * This is very slightly smaller than the limit imposed by
4770 * the underlying kernel.
4771 */
4772#define FIEMAP_MAX_EXTENTS ((UINT_MAX - sizeof(struct fiemap)) \
4773 / sizeof(struct fiemap_extent))
4774
4775static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004776 int fd, int cmd, abi_long arg)
Peter Maydell285da2b2011-01-06 15:04:18 +00004777{
4778 /* The parameter for this ioctl is a struct fiemap followed
4779 * by an array of struct fiemap_extent whose size is set
4780 * in fiemap->fm_extent_count. The array is filled in by the
4781 * ioctl.
4782 */
4783 int target_size_in, target_size_out;
4784 struct fiemap *fm;
4785 const argtype *arg_type = ie->arg_type;
4786 const argtype extent_arg_type[] = { MK_STRUCT(STRUCT_fiemap_extent) };
4787 void *argptr, *p;
4788 abi_long ret;
4789 int i, extent_size = thunk_type_size(extent_arg_type, 0);
4790 uint32_t outbufsz;
4791 int free_fm = 0;
4792
4793 assert(arg_type[0] == TYPE_PTR);
4794 assert(ie->access == IOC_RW);
4795 arg_type++;
4796 target_size_in = thunk_type_size(arg_type, 0);
4797 argptr = lock_user(VERIFY_READ, arg, target_size_in, 1);
4798 if (!argptr) {
4799 return -TARGET_EFAULT;
4800 }
4801 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4802 unlock_user(argptr, arg, 0);
4803 fm = (struct fiemap *)buf_temp;
4804 if (fm->fm_extent_count > FIEMAP_MAX_EXTENTS) {
4805 return -TARGET_EINVAL;
4806 }
4807
4808 outbufsz = sizeof (*fm) +
4809 (sizeof(struct fiemap_extent) * fm->fm_extent_count);
4810
4811 if (outbufsz > MAX_STRUCT_SIZE) {
4812 /* We can't fit all the extents into the fixed size buffer.
4813 * Allocate one that is large enough and use it instead.
4814 */
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304815 fm = g_try_malloc(outbufsz);
Peter Maydell285da2b2011-01-06 15:04:18 +00004816 if (!fm) {
4817 return -TARGET_ENOMEM;
4818 }
4819 memcpy(fm, buf_temp, sizeof(struct fiemap));
4820 free_fm = 1;
4821 }
Peter Maydell49ca6f32016-06-06 19:58:14 +01004822 ret = get_errno(safe_ioctl(fd, ie->host_cmd, fm));
Peter Maydell285da2b2011-01-06 15:04:18 +00004823 if (!is_error(ret)) {
4824 target_size_out = target_size_in;
4825 /* An extent_count of 0 means we were only counting the extents
4826 * so there are no structs to copy
4827 */
4828 if (fm->fm_extent_count != 0) {
4829 target_size_out += fm->fm_mapped_extents * extent_size;
4830 }
4831 argptr = lock_user(VERIFY_WRITE, arg, target_size_out, 0);
4832 if (!argptr) {
4833 ret = -TARGET_EFAULT;
4834 } else {
4835 /* Convert the struct fiemap */
4836 thunk_convert(argptr, fm, arg_type, THUNK_TARGET);
4837 if (fm->fm_extent_count != 0) {
4838 p = argptr + target_size_in;
4839 /* ...and then all the struct fiemap_extents */
4840 for (i = 0; i < fm->fm_mapped_extents; i++) {
4841 thunk_convert(p, &fm->fm_extents[i], extent_arg_type,
4842 THUNK_TARGET);
4843 p += extent_size;
4844 }
4845 }
4846 unlock_user(argptr, arg, target_size_out);
4847 }
4848 }
4849 if (free_fm) {
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304850 g_free(fm);
Peter Maydell285da2b2011-01-06 15:04:18 +00004851 }
4852 return ret;
4853}
Peter Maydelldace20d2011-01-10 13:11:24 +00004854#endif
Peter Maydell285da2b2011-01-06 15:04:18 +00004855
Laurent Vivier059c2f22011-03-30 00:12:12 +02004856static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004857 int fd, int cmd, abi_long arg)
Laurent Vivier059c2f22011-03-30 00:12:12 +02004858{
4859 const argtype *arg_type = ie->arg_type;
4860 int target_size;
4861 void *argptr;
4862 int ret;
4863 struct ifconf *host_ifconf;
4864 uint32_t outbufsz;
4865 const argtype ifreq_arg_type[] = { MK_STRUCT(STRUCT_sockaddr_ifreq) };
Stefan4df7b7f2021-01-09 19:59:42 +01004866 const argtype ifreq_max_type[] = { MK_STRUCT(STRUCT_ifmap_ifreq) };
Laurent Vivier059c2f22011-03-30 00:12:12 +02004867 int target_ifreq_size;
4868 int nb_ifreq;
4869 int free_buf = 0;
4870 int i;
4871 int target_ifc_len;
4872 abi_long target_ifc_buf;
4873 int host_ifc_len;
4874 char *host_ifc_buf;
4875
4876 assert(arg_type[0] == TYPE_PTR);
4877 assert(ie->access == IOC_RW);
4878
4879 arg_type++;
4880 target_size = thunk_type_size(arg_type, 0);
4881
4882 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4883 if (!argptr)
4884 return -TARGET_EFAULT;
4885 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4886 unlock_user(argptr, arg, 0);
4887
4888 host_ifconf = (struct ifconf *)(unsigned long)buf_temp;
Laurent Vivier059c2f22011-03-30 00:12:12 +02004889 target_ifc_buf = (abi_long)(unsigned long)host_ifconf->ifc_buf;
Stefan4df7b7f2021-01-09 19:59:42 +01004890 target_ifreq_size = thunk_type_size(ifreq_max_type, 0);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004891
Kan Li22e4a2672018-10-24 20:13:03 +00004892 if (target_ifc_buf != 0) {
4893 target_ifc_len = host_ifconf->ifc_len;
4894 nb_ifreq = target_ifc_len / target_ifreq_size;
4895 host_ifc_len = nb_ifreq * sizeof(struct ifreq);
4896
4897 outbufsz = sizeof(*host_ifconf) + host_ifc_len;
4898 if (outbufsz > MAX_STRUCT_SIZE) {
4899 /*
4900 * We can't fit all the extents into the fixed size buffer.
4901 * Allocate one that is large enough and use it instead.
4902 */
Ahmed Abouzied7a5626a2022-01-04 16:38:41 +02004903 host_ifconf = g_try_malloc(outbufsz);
Kan Li22e4a2672018-10-24 20:13:03 +00004904 if (!host_ifconf) {
4905 return -TARGET_ENOMEM;
4906 }
4907 memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf));
4908 free_buf = 1;
Laurent Vivier059c2f22011-03-30 00:12:12 +02004909 }
Kan Li22e4a2672018-10-24 20:13:03 +00004910 host_ifc_buf = (char *)host_ifconf + sizeof(*host_ifconf);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004911
Kan Li22e4a2672018-10-24 20:13:03 +00004912 host_ifconf->ifc_len = host_ifc_len;
4913 } else {
4914 host_ifc_buf = NULL;
4915 }
Laurent Vivier059c2f22011-03-30 00:12:12 +02004916 host_ifconf->ifc_buf = host_ifc_buf;
4917
Peter Maydell49ca6f32016-06-06 19:58:14 +01004918 ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_ifconf));
Laurent Vivier059c2f22011-03-30 00:12:12 +02004919 if (!is_error(ret)) {
4920 /* convert host ifc_len to target ifc_len */
4921
4922 nb_ifreq = host_ifconf->ifc_len / sizeof(struct ifreq);
4923 target_ifc_len = nb_ifreq * target_ifreq_size;
4924 host_ifconf->ifc_len = target_ifc_len;
4925
4926 /* restore target ifc_buf */
4927
4928 host_ifconf->ifc_buf = (char *)(unsigned long)target_ifc_buf;
4929
4930 /* copy struct ifconf to target user */
4931
4932 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
4933 if (!argptr)
4934 return -TARGET_EFAULT;
4935 thunk_convert(argptr, host_ifconf, arg_type, THUNK_TARGET);
4936 unlock_user(argptr, arg, target_size);
4937
Kan Li22e4a2672018-10-24 20:13:03 +00004938 if (target_ifc_buf != 0) {
4939 /* copy ifreq[] to target user */
4940 argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0);
4941 for (i = 0; i < nb_ifreq ; i++) {
4942 thunk_convert(argptr + i * target_ifreq_size,
4943 host_ifc_buf + i * sizeof(struct ifreq),
4944 ifreq_arg_type, THUNK_TARGET);
4945 }
4946 unlock_user(argptr, target_ifc_buf, target_ifc_len);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004947 }
Laurent Vivier059c2f22011-03-30 00:12:12 +02004948 }
4949
4950 if (free_buf) {
Ahmed Abouzied7a5626a2022-01-04 16:38:41 +02004951 g_free(host_ifconf);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004952 }
4953
4954 return ret;
4955}
4956
Cortland Tölvaa1333672018-10-08 09:35:21 -07004957#if defined(CONFIG_USBFS)
4958#if HOST_LONG_BITS > 64
4959#error USBDEVFS thunks do not support >64 bit hosts yet.
4960#endif
4961struct live_urb {
4962 uint64_t target_urb_adr;
4963 uint64_t target_buf_adr;
4964 char *target_buf_ptr;
4965 struct usbdevfs_urb host_urb;
4966};
4967
4968static GHashTable *usbdevfs_urb_hashtable(void)
4969{
4970 static GHashTable *urb_hashtable;
4971
4972 if (!urb_hashtable) {
4973 urb_hashtable = g_hash_table_new(g_int64_hash, g_int64_equal);
4974 }
4975 return urb_hashtable;
4976}
4977
4978static void urb_hashtable_insert(struct live_urb *urb)
4979{
4980 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
4981 g_hash_table_insert(urb_hashtable, urb, urb);
4982}
4983
4984static struct live_urb *urb_hashtable_lookup(uint64_t target_urb_adr)
4985{
4986 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
4987 return g_hash_table_lookup(urb_hashtable, &target_urb_adr);
4988}
4989
4990static void urb_hashtable_remove(struct live_urb *urb)
4991{
4992 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
4993 g_hash_table_remove(urb_hashtable, urb);
4994}
4995
4996static abi_long
4997do_ioctl_usbdevfs_reapurb(const IOCTLEntry *ie, uint8_t *buf_temp,
4998 int fd, int cmd, abi_long arg)
4999{
5000 const argtype usbfsurb_arg_type[] = { MK_STRUCT(STRUCT_usbdevfs_urb) };
5001 const argtype ptrvoid_arg_type[] = { TYPE_PTRVOID, 0, 0 };
5002 struct live_urb *lurb;
5003 void *argptr;
5004 uint64_t hurb;
5005 int target_size;
5006 uintptr_t target_urb_adr;
5007 abi_long ret;
5008
5009 target_size = thunk_type_size(usbfsurb_arg_type, THUNK_TARGET);
5010
5011 memset(buf_temp, 0, sizeof(uint64_t));
5012 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
5013 if (is_error(ret)) {
5014 return ret;
5015 }
5016
5017 memcpy(&hurb, buf_temp, sizeof(uint64_t));
5018 lurb = (void *)((uintptr_t)hurb - offsetof(struct live_urb, host_urb));
5019 if (!lurb->target_urb_adr) {
5020 return -TARGET_EFAULT;
5021 }
5022 urb_hashtable_remove(lurb);
5023 unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr,
5024 lurb->host_urb.buffer_length);
5025 lurb->target_buf_ptr = NULL;
5026
5027 /* restore the guest buffer pointer */
5028 lurb->host_urb.buffer = (void *)(uintptr_t)lurb->target_buf_adr;
5029
5030 /* update the guest urb struct */
5031 argptr = lock_user(VERIFY_WRITE, lurb->target_urb_adr, target_size, 0);
5032 if (!argptr) {
5033 g_free(lurb);
5034 return -TARGET_EFAULT;
5035 }
5036 thunk_convert(argptr, &lurb->host_urb, usbfsurb_arg_type, THUNK_TARGET);
5037 unlock_user(argptr, lurb->target_urb_adr, target_size);
5038
5039 target_size = thunk_type_size(ptrvoid_arg_type, THUNK_TARGET);
5040 /* write back the urb handle */
5041 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5042 if (!argptr) {
5043 g_free(lurb);
5044 return -TARGET_EFAULT;
5045 }
5046
5047 /* GHashTable uses 64-bit keys but thunk_convert expects uintptr_t */
5048 target_urb_adr = lurb->target_urb_adr;
5049 thunk_convert(argptr, &target_urb_adr, ptrvoid_arg_type, THUNK_TARGET);
5050 unlock_user(argptr, arg, target_size);
5051
5052 g_free(lurb);
5053 return ret;
5054}
5055
5056static abi_long
5057do_ioctl_usbdevfs_discardurb(const IOCTLEntry *ie,
5058 uint8_t *buf_temp __attribute__((unused)),
5059 int fd, int cmd, abi_long arg)
5060{
5061 struct live_urb *lurb;
5062
5063 /* map target address back to host URB with metadata. */
5064 lurb = urb_hashtable_lookup(arg);
5065 if (!lurb) {
5066 return -TARGET_EFAULT;
5067 }
5068 return get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
5069}
5070
5071static abi_long
5072do_ioctl_usbdevfs_submiturb(const IOCTLEntry *ie, uint8_t *buf_temp,
5073 int fd, int cmd, abi_long arg)
5074{
5075 const argtype *arg_type = ie->arg_type;
5076 int target_size;
5077 abi_long ret;
5078 void *argptr;
5079 int rw_dir;
5080 struct live_urb *lurb;
5081
5082 /*
5083 * each submitted URB needs to map to a unique ID for the
5084 * kernel, and that unique ID needs to be a pointer to
5085 * host memory. hence, we need to malloc for each URB.
5086 * isochronous transfers have a variable length struct.
5087 */
5088 arg_type++;
5089 target_size = thunk_type_size(arg_type, THUNK_TARGET);
5090
5091 /* construct host copy of urb and metadata */
Markus Armbrusterb21e2382022-03-15 15:41:56 +01005092 lurb = g_try_new0(struct live_urb, 1);
Cortland Tölvaa1333672018-10-08 09:35:21 -07005093 if (!lurb) {
5094 return -TARGET_ENOMEM;
5095 }
5096
5097 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5098 if (!argptr) {
5099 g_free(lurb);
5100 return -TARGET_EFAULT;
5101 }
5102 thunk_convert(&lurb->host_urb, argptr, arg_type, THUNK_HOST);
5103 unlock_user(argptr, arg, 0);
5104
5105 lurb->target_urb_adr = arg;
5106 lurb->target_buf_adr = (uintptr_t)lurb->host_urb.buffer;
5107
5108 /* buffer space used depends on endpoint type so lock the entire buffer */
5109 /* control type urbs should check the buffer contents for true direction */
5110 rw_dir = lurb->host_urb.endpoint & USB_DIR_IN ? VERIFY_WRITE : VERIFY_READ;
5111 lurb->target_buf_ptr = lock_user(rw_dir, lurb->target_buf_adr,
5112 lurb->host_urb.buffer_length, 1);
5113 if (lurb->target_buf_ptr == NULL) {
5114 g_free(lurb);
5115 return -TARGET_EFAULT;
5116 }
5117
5118 /* update buffer pointer in host copy */
5119 lurb->host_urb.buffer = lurb->target_buf_ptr;
5120
5121 ret = get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
5122 if (is_error(ret)) {
5123 unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr, 0);
5124 g_free(lurb);
5125 } else {
5126 urb_hashtable_insert(lurb);
5127 }
5128
5129 return ret;
5130}
5131#endif /* CONFIG_USBFS */
5132
Alexander Graf56e904e2012-01-31 18:42:06 +01005133static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
Laurent Vivier45c874e2015-06-16 00:35:28 +02005134 int cmd, abi_long arg)
Alexander Graf56e904e2012-01-31 18:42:06 +01005135{
5136 void *argptr;
5137 struct dm_ioctl *host_dm;
5138 abi_long guest_data;
5139 uint32_t guest_data_size;
5140 int target_size;
5141 const argtype *arg_type = ie->arg_type;
5142 abi_long ret;
5143 void *big_buf = NULL;
5144 char *host_data;
5145
5146 arg_type++;
5147 target_size = thunk_type_size(arg_type, 0);
5148 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5149 if (!argptr) {
5150 ret = -TARGET_EFAULT;
5151 goto out;
5152 }
5153 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5154 unlock_user(argptr, arg, 0);
5155
5156 /* buf_temp is too small, so fetch things into a bigger buffer */
5157 big_buf = g_malloc0(((struct dm_ioctl*)buf_temp)->data_size * 2);
5158 memcpy(big_buf, buf_temp, target_size);
5159 buf_temp = big_buf;
5160 host_dm = big_buf;
5161
5162 guest_data = arg + host_dm->data_start;
5163 if ((guest_data - arg) < 0) {
Peter Maydellf9757b12016-07-12 13:02:14 +01005164 ret = -TARGET_EINVAL;
Alexander Graf56e904e2012-01-31 18:42:06 +01005165 goto out;
5166 }
5167 guest_data_size = host_dm->data_size - host_dm->data_start;
5168 host_data = (char*)host_dm + host_dm->data_start;
5169
5170 argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1);
Peter Maydell32112152016-07-12 13:02:13 +01005171 if (!argptr) {
5172 ret = -TARGET_EFAULT;
5173 goto out;
5174 }
5175
Alexander Graf56e904e2012-01-31 18:42:06 +01005176 switch (ie->host_cmd) {
5177 case DM_REMOVE_ALL:
5178 case DM_LIST_DEVICES:
5179 case DM_DEV_CREATE:
5180 case DM_DEV_REMOVE:
5181 case DM_DEV_SUSPEND:
5182 case DM_DEV_STATUS:
5183 case DM_DEV_WAIT:
5184 case DM_TABLE_STATUS:
5185 case DM_TABLE_CLEAR:
5186 case DM_TABLE_DEPS:
5187 case DM_LIST_VERSIONS:
5188 /* no input data */
5189 break;
5190 case DM_DEV_RENAME:
5191 case DM_DEV_SET_GEOMETRY:
5192 /* data contains only strings */
5193 memcpy(host_data, argptr, guest_data_size);
5194 break;
5195 case DM_TARGET_MSG:
5196 memcpy(host_data, argptr, guest_data_size);
5197 *(uint64_t*)host_data = tswap64(*(uint64_t*)argptr);
5198 break;
5199 case DM_TABLE_LOAD:
5200 {
5201 void *gspec = argptr;
5202 void *cur_data = host_data;
5203 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
5204 int spec_size = thunk_type_size(arg_type, 0);
5205 int i;
5206
5207 for (i = 0; i < host_dm->target_count; i++) {
5208 struct dm_target_spec *spec = cur_data;
5209 uint32_t next;
5210 int slen;
5211
5212 thunk_convert(spec, gspec, arg_type, THUNK_HOST);
5213 slen = strlen((char*)gspec + spec_size) + 1;
5214 next = spec->next;
5215 spec->next = sizeof(*spec) + slen;
5216 strcpy((char*)&spec[1], gspec + spec_size);
5217 gspec += next;
5218 cur_data += spec->next;
5219 }
5220 break;
5221 }
5222 default:
5223 ret = -TARGET_EINVAL;
Chen Gang Sdec04732015-01-25 08:00:42 +08005224 unlock_user(argptr, guest_data, 0);
Alexander Graf56e904e2012-01-31 18:42:06 +01005225 goto out;
5226 }
5227 unlock_user(argptr, guest_data, 0);
5228
Peter Maydell49ca6f32016-06-06 19:58:14 +01005229 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
Alexander Graf56e904e2012-01-31 18:42:06 +01005230 if (!is_error(ret)) {
5231 guest_data = arg + host_dm->data_start;
5232 guest_data_size = host_dm->data_size - host_dm->data_start;
5233 argptr = lock_user(VERIFY_WRITE, guest_data, guest_data_size, 0);
5234 switch (ie->host_cmd) {
5235 case DM_REMOVE_ALL:
5236 case DM_DEV_CREATE:
5237 case DM_DEV_REMOVE:
5238 case DM_DEV_RENAME:
5239 case DM_DEV_SUSPEND:
5240 case DM_DEV_STATUS:
5241 case DM_TABLE_LOAD:
5242 case DM_TABLE_CLEAR:
5243 case DM_TARGET_MSG:
5244 case DM_DEV_SET_GEOMETRY:
5245 /* no return data */
5246 break;
5247 case DM_LIST_DEVICES:
5248 {
5249 struct dm_name_list *nl = (void*)host_dm + host_dm->data_start;
5250 uint32_t remaining_data = guest_data_size;
5251 void *cur_data = argptr;
5252 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
5253 int nl_size = 12; /* can't use thunk_size due to alignment */
5254
5255 while (1) {
5256 uint32_t next = nl->next;
5257 if (next) {
5258 nl->next = nl_size + (strlen(nl->name) + 1);
5259 }
5260 if (remaining_data < nl->next) {
5261 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5262 break;
5263 }
5264 thunk_convert(cur_data, nl, arg_type, THUNK_TARGET);
5265 strcpy(cur_data + nl_size, nl->name);
5266 cur_data += nl->next;
5267 remaining_data -= nl->next;
5268 if (!next) {
5269 break;
5270 }
5271 nl = (void*)nl + next;
5272 }
5273 break;
5274 }
5275 case DM_DEV_WAIT:
5276 case DM_TABLE_STATUS:
5277 {
5278 struct dm_target_spec *spec = (void*)host_dm + host_dm->data_start;
5279 void *cur_data = argptr;
5280 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
5281 int spec_size = thunk_type_size(arg_type, 0);
5282 int i;
5283
5284 for (i = 0; i < host_dm->target_count; i++) {
5285 uint32_t next = spec->next;
5286 int slen = strlen((char*)&spec[1]) + 1;
5287 spec->next = (cur_data - argptr) + spec_size + slen;
5288 if (guest_data_size < spec->next) {
5289 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5290 break;
5291 }
5292 thunk_convert(cur_data, spec, arg_type, THUNK_TARGET);
5293 strcpy(cur_data + spec_size, (char*)&spec[1]);
5294 cur_data = argptr + spec->next;
5295 spec = (void*)host_dm + host_dm->data_start + next;
5296 }
5297 break;
5298 }
5299 case DM_TABLE_DEPS:
5300 {
5301 void *hdata = (void*)host_dm + host_dm->data_start;
5302 int count = *(uint32_t*)hdata;
5303 uint64_t *hdev = hdata + 8;
5304 uint64_t *gdev = argptr + 8;
5305 int i;
5306
5307 *(uint32_t*)argptr = tswap32(count);
5308 for (i = 0; i < count; i++) {
5309 *gdev = tswap64(*hdev);
5310 gdev++;
5311 hdev++;
5312 }
5313 break;
5314 }
5315 case DM_LIST_VERSIONS:
5316 {
5317 struct dm_target_versions *vers = (void*)host_dm + host_dm->data_start;
5318 uint32_t remaining_data = guest_data_size;
5319 void *cur_data = argptr;
5320 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_versions) };
5321 int vers_size = thunk_type_size(arg_type, 0);
5322
5323 while (1) {
5324 uint32_t next = vers->next;
5325 if (next) {
5326 vers->next = vers_size + (strlen(vers->name) + 1);
5327 }
5328 if (remaining_data < vers->next) {
5329 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5330 break;
5331 }
5332 thunk_convert(cur_data, vers, arg_type, THUNK_TARGET);
5333 strcpy(cur_data + vers_size, vers->name);
5334 cur_data += vers->next;
5335 remaining_data -= vers->next;
5336 if (!next) {
5337 break;
5338 }
5339 vers = (void*)vers + next;
5340 }
5341 break;
5342 }
5343 default:
Chen Gang Sdec04732015-01-25 08:00:42 +08005344 unlock_user(argptr, guest_data, 0);
Alexander Graf56e904e2012-01-31 18:42:06 +01005345 ret = -TARGET_EINVAL;
5346 goto out;
5347 }
5348 unlock_user(argptr, guest_data, guest_data_size);
5349
5350 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5351 if (!argptr) {
5352 ret = -TARGET_EFAULT;
5353 goto out;
5354 }
5355 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5356 unlock_user(argptr, arg, target_size);
5357 }
5358out:
Stefan Weilad11ad72012-09-04 22:14:19 +02005359 g_free(big_buf);
Alexander Graf56e904e2012-01-31 18:42:06 +01005360 return ret;
5361}
5362
Alexander Grafa59b5e32014-08-22 13:15:50 +02005363static abi_long do_ioctl_blkpg(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
Laurent Vivier45c874e2015-06-16 00:35:28 +02005364 int cmd, abi_long arg)
Alexander Grafa59b5e32014-08-22 13:15:50 +02005365{
5366 void *argptr;
5367 int target_size;
5368 const argtype *arg_type = ie->arg_type;
5369 const argtype part_arg_type[] = { MK_STRUCT(STRUCT_blkpg_partition) };
5370 abi_long ret;
5371
5372 struct blkpg_ioctl_arg *host_blkpg = (void*)buf_temp;
5373 struct blkpg_partition host_part;
5374
5375 /* Read and convert blkpg */
5376 arg_type++;
5377 target_size = thunk_type_size(arg_type, 0);
5378 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5379 if (!argptr) {
5380 ret = -TARGET_EFAULT;
5381 goto out;
5382 }
5383 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5384 unlock_user(argptr, arg, 0);
5385
5386 switch (host_blkpg->op) {
5387 case BLKPG_ADD_PARTITION:
5388 case BLKPG_DEL_PARTITION:
5389 /* payload is struct blkpg_partition */
5390 break;
5391 default:
5392 /* Unknown opcode */
5393 ret = -TARGET_EINVAL;
5394 goto out;
5395 }
5396
5397 /* Read and convert blkpg->data */
5398 arg = (abi_long)(uintptr_t)host_blkpg->data;
5399 target_size = thunk_type_size(part_arg_type, 0);
5400 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5401 if (!argptr) {
5402 ret = -TARGET_EFAULT;
5403 goto out;
5404 }
5405 thunk_convert(&host_part, argptr, part_arg_type, THUNK_HOST);
5406 unlock_user(argptr, arg, 0);
5407
5408 /* Swizzle the data pointer to our local copy and call! */
5409 host_blkpg->data = &host_part;
Peter Maydell49ca6f32016-06-06 19:58:14 +01005410 ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_blkpg));
Alexander Grafa59b5e32014-08-22 13:15:50 +02005411
5412out:
5413 return ret;
5414}
5415
Laurent Vivier7ff7b662013-07-02 14:04:12 +01005416static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02005417 int fd, int cmd, abi_long arg)
Laurent Vivier7ff7b662013-07-02 14:04:12 +01005418{
5419 const argtype *arg_type = ie->arg_type;
5420 const StructEntry *se;
5421 const argtype *field_types;
5422 const int *dst_offsets, *src_offsets;
5423 int target_size;
5424 void *argptr;
Marc-André Lureaub78c5222019-03-05 16:15:00 +01005425 abi_ulong *target_rt_dev_ptr = NULL;
5426 unsigned long *host_rt_dev_ptr = NULL;
Laurent Vivier7ff7b662013-07-02 14:04:12 +01005427 abi_long ret;
5428 int i;
5429
5430 assert(ie->access == IOC_W);
5431 assert(*arg_type == TYPE_PTR);
5432 arg_type++;
5433 assert(*arg_type == TYPE_STRUCT);
5434 target_size = thunk_type_size(arg_type, 0);
5435 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5436 if (!argptr) {
5437 return -TARGET_EFAULT;
5438 }
5439 arg_type++;
5440 assert(*arg_type == (int)STRUCT_rtentry);
5441 se = struct_entries + *arg_type++;
5442 assert(se->convert[0] == NULL);
5443 /* convert struct here to be able to catch rt_dev string */
5444 field_types = se->field_types;
5445 dst_offsets = se->field_offsets[THUNK_HOST];
5446 src_offsets = se->field_offsets[THUNK_TARGET];
5447 for (i = 0; i < se->nb_fields; i++) {
5448 if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) {
5449 assert(*field_types == TYPE_PTRVOID);
Markus Armbruster3d558332022-11-23 14:38:11 +01005450 target_rt_dev_ptr = argptr + src_offsets[i];
Laurent Vivier7ff7b662013-07-02 14:04:12 +01005451 host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]);
5452 if (*target_rt_dev_ptr != 0) {
5453 *host_rt_dev_ptr = (unsigned long)lock_user_string(
5454 tswapal(*target_rt_dev_ptr));
5455 if (!*host_rt_dev_ptr) {
5456 unlock_user(argptr, arg, 0);
5457 return -TARGET_EFAULT;
5458 }
5459 } else {
5460 *host_rt_dev_ptr = 0;
5461 }
5462 field_types++;
5463 continue;
5464 }
5465 field_types = thunk_convert(buf_temp + dst_offsets[i],
5466 argptr + src_offsets[i],
5467 field_types, THUNK_HOST);
5468 }
5469 unlock_user(argptr, arg, 0);
5470
Peter Maydell49ca6f32016-06-06 19:58:14 +01005471 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
Marc-André Lureaub78c5222019-03-05 16:15:00 +01005472
5473 assert(host_rt_dev_ptr != NULL);
5474 assert(target_rt_dev_ptr != NULL);
Laurent Vivier7ff7b662013-07-02 14:04:12 +01005475 if (*host_rt_dev_ptr != 0) {
5476 unlock_user((void *)*host_rt_dev_ptr,
5477 *target_rt_dev_ptr, 0);
5478 }
5479 return ret;
5480}
5481
Paul Burtonca56f5b2014-06-22 11:25:47 +01005482static abi_long do_ioctl_kdsigaccept(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02005483 int fd, int cmd, abi_long arg)
Paul Burtonca56f5b2014-06-22 11:25:47 +01005484{
5485 int sig = target_to_host_signal(arg);
Peter Maydell49ca6f32016-06-06 19:58:14 +01005486 return get_errno(safe_ioctl(fd, ie->host_cmd, sig));
Paul Burtonca56f5b2014-06-22 11:25:47 +01005487}
5488
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02005489static abi_long do_ioctl_SIOCGSTAMP(const IOCTLEntry *ie, uint8_t *buf_temp,
5490 int fd, int cmd, abi_long arg)
5491{
5492 struct timeval tv;
5493 abi_long ret;
5494
5495 ret = get_errno(safe_ioctl(fd, SIOCGSTAMP, &tv));
5496 if (is_error(ret)) {
5497 return ret;
5498 }
5499
5500 if (cmd == (int)TARGET_SIOCGSTAMP_OLD) {
5501 if (copy_to_user_timeval(arg, &tv)) {
5502 return -TARGET_EFAULT;
5503 }
5504 } else {
5505 if (copy_to_user_timeval64(arg, &tv)) {
5506 return -TARGET_EFAULT;
5507 }
5508 }
5509
5510 return ret;
5511}
5512
5513static abi_long do_ioctl_SIOCGSTAMPNS(const IOCTLEntry *ie, uint8_t *buf_temp,
5514 int fd, int cmd, abi_long arg)
5515{
5516 struct timespec ts;
5517 abi_long ret;
5518
5519 ret = get_errno(safe_ioctl(fd, SIOCGSTAMPNS, &ts));
5520 if (is_error(ret)) {
5521 return ret;
5522 }
5523
5524 if (cmd == (int)TARGET_SIOCGSTAMPNS_OLD) {
5525 if (host_to_target_timespec(arg, &ts)) {
5526 return -TARGET_EFAULT;
5527 }
5528 } else{
5529 if (host_to_target_timespec64(arg, &ts)) {
5530 return -TARGET_EFAULT;
5531 }
5532 }
5533
5534 return ret;
5535}
5536
Andreas Schwab2b74f622018-01-29 11:47:06 +01005537#ifdef TIOCGPTPEER
5538static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry *ie, uint8_t *buf_temp,
5539 int fd, int cmd, abi_long arg)
5540{
5541 int flags = target_to_host_bitmask(arg, fcntl_flags_tbl);
5542 return get_errno(safe_ioctl(fd, ie->host_cmd, flags));
5543}
5544#endif
5545
Chen Gange865b972020-06-05 09:32:21 +08005546#ifdef HAVE_DRM_H
5547
5548static void unlock_drm_version(struct drm_version *host_ver,
5549 struct target_drm_version *target_ver,
5550 bool copy)
5551{
5552 unlock_user(host_ver->name, target_ver->name,
5553 copy ? host_ver->name_len : 0);
5554 unlock_user(host_ver->date, target_ver->date,
5555 copy ? host_ver->date_len : 0);
5556 unlock_user(host_ver->desc, target_ver->desc,
5557 copy ? host_ver->desc_len : 0);
5558}
5559
5560static inline abi_long target_to_host_drmversion(struct drm_version *host_ver,
5561 struct target_drm_version *target_ver)
5562{
5563 memset(host_ver, 0, sizeof(*host_ver));
5564
5565 __get_user(host_ver->name_len, &target_ver->name_len);
5566 if (host_ver->name_len) {
5567 host_ver->name = lock_user(VERIFY_WRITE, target_ver->name,
5568 target_ver->name_len, 0);
5569 if (!host_ver->name) {
5570 return -EFAULT;
5571 }
5572 }
5573
5574 __get_user(host_ver->date_len, &target_ver->date_len);
5575 if (host_ver->date_len) {
5576 host_ver->date = lock_user(VERIFY_WRITE, target_ver->date,
5577 target_ver->date_len, 0);
5578 if (!host_ver->date) {
5579 goto err;
5580 }
5581 }
5582
5583 __get_user(host_ver->desc_len, &target_ver->desc_len);
5584 if (host_ver->desc_len) {
5585 host_ver->desc = lock_user(VERIFY_WRITE, target_ver->desc,
5586 target_ver->desc_len, 0);
5587 if (!host_ver->desc) {
5588 goto err;
5589 }
5590 }
5591
5592 return 0;
5593err:
5594 unlock_drm_version(host_ver, target_ver, false);
5595 return -EFAULT;
5596}
5597
5598static inline void host_to_target_drmversion(
5599 struct target_drm_version *target_ver,
5600 struct drm_version *host_ver)
5601{
5602 __put_user(host_ver->version_major, &target_ver->version_major);
5603 __put_user(host_ver->version_minor, &target_ver->version_minor);
5604 __put_user(host_ver->version_patchlevel, &target_ver->version_patchlevel);
5605 __put_user(host_ver->name_len, &target_ver->name_len);
5606 __put_user(host_ver->date_len, &target_ver->date_len);
5607 __put_user(host_ver->desc_len, &target_ver->desc_len);
5608 unlock_drm_version(host_ver, target_ver, true);
5609}
5610
5611static abi_long do_ioctl_drm(const IOCTLEntry *ie, uint8_t *buf_temp,
5612 int fd, int cmd, abi_long arg)
5613{
5614 struct drm_version *ver;
5615 struct target_drm_version *target_ver;
5616 abi_long ret;
5617
5618 switch (ie->host_cmd) {
5619 case DRM_IOCTL_VERSION:
5620 if (!lock_user_struct(VERIFY_WRITE, target_ver, arg, 0)) {
5621 return -TARGET_EFAULT;
5622 }
5623 ver = (struct drm_version *)buf_temp;
5624 ret = target_to_host_drmversion(ver, target_ver);
5625 if (!is_error(ret)) {
5626 ret = get_errno(safe_ioctl(fd, ie->host_cmd, ver));
5627 if (is_error(ret)) {
5628 unlock_drm_version(ver, target_ver, false);
5629 } else {
5630 host_to_target_drmversion(target_ver, ver);
5631 }
5632 }
5633 unlock_user_struct(target_ver, arg, 0);
5634 return ret;
5635 }
5636 return -TARGET_ENOSYS;
5637}
5638
Chen Gang913b03c2020-08-02 21:39:38 +08005639static abi_long do_ioctl_drm_i915_getparam(const IOCTLEntry *ie,
5640 struct drm_i915_getparam *gparam,
5641 int fd, abi_long arg)
5642{
5643 abi_long ret;
5644 int value;
5645 struct target_drm_i915_getparam *target_gparam;
5646
5647 if (!lock_user_struct(VERIFY_READ, target_gparam, arg, 0)) {
5648 return -TARGET_EFAULT;
5649 }
5650
5651 __get_user(gparam->param, &target_gparam->param);
5652 gparam->value = &value;
5653 ret = get_errno(safe_ioctl(fd, ie->host_cmd, gparam));
5654 put_user_s32(value, target_gparam->value);
5655
5656 unlock_user_struct(target_gparam, arg, 0);
5657 return ret;
5658}
5659
5660static abi_long do_ioctl_drm_i915(const IOCTLEntry *ie, uint8_t *buf_temp,
5661 int fd, int cmd, abi_long arg)
5662{
5663 switch (ie->host_cmd) {
5664 case DRM_IOCTL_I915_GETPARAM:
5665 return do_ioctl_drm_i915_getparam(ie,
5666 (struct drm_i915_getparam *)buf_temp,
5667 fd, arg);
5668 default:
5669 return -TARGET_ENOSYS;
5670 }
5671}
5672
Chen Gange865b972020-06-05 09:32:21 +08005673#endif
5674
Shu-Chun Weng6addf062020-09-28 18:48:01 -07005675static abi_long do_ioctl_TUNSETTXFILTER(const IOCTLEntry *ie, uint8_t *buf_temp,
5676 int fd, int cmd, abi_long arg)
5677{
5678 struct tun_filter *filter = (struct tun_filter *)buf_temp;
5679 struct tun_filter *target_filter;
5680 char *target_addr;
5681
5682 assert(ie->access == IOC_W);
5683
5684 target_filter = lock_user(VERIFY_READ, arg, sizeof(*target_filter), 1);
5685 if (!target_filter) {
5686 return -TARGET_EFAULT;
5687 }
5688 filter->flags = tswap16(target_filter->flags);
5689 filter->count = tswap16(target_filter->count);
5690 unlock_user(target_filter, arg, 0);
5691
5692 if (filter->count) {
5693 if (offsetof(struct tun_filter, addr) + filter->count * ETH_ALEN >
5694 MAX_STRUCT_SIZE) {
5695 return -TARGET_EFAULT;
5696 }
5697
5698 target_addr = lock_user(VERIFY_READ,
5699 arg + offsetof(struct tun_filter, addr),
5700 filter->count * ETH_ALEN, 1);
5701 if (!target_addr) {
5702 return -TARGET_EFAULT;
5703 }
5704 memcpy(filter->addr, target_addr, filter->count * ETH_ALEN);
5705 unlock_user(target_addr, arg + offsetof(struct tun_filter, addr), 0);
5706 }
5707
5708 return get_errno(safe_ioctl(fd, ie->host_cmd, filter));
5709}
5710
Filip Bozuta79482e592020-06-19 14:47:27 +02005711IOCTLEntry ioctl_entries[] = {
Blue Swirl001faf32009-05-13 17:53:17 +00005712#define IOCTL(cmd, access, ...) \
Peter Maydelld2ef05b2011-01-06 15:04:17 +00005713 { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
5714#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
5715 { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
Helge Deller8cb762f2016-12-06 16:24:03 +01005716#define IOCTL_IGNORE(cmd) \
5717 { TARGET_ ## cmd, 0, #cmd },
bellard31e31b82003-02-18 22:55:36 +00005718#include "ioctls.h"
5719 { 0, 0, },
5720};
5721
pbrook53a59602006-03-25 19:31:22 +00005722/* ??? Implement proper locking for ioctls. */
ths0da46a62007-10-20 20:23:07 +00005723/* do_ioctl() Must return target values and target errnos. */
Laurent Vivier45c874e2015-06-16 00:35:28 +02005724static abi_long do_ioctl(int fd, int cmd, abi_long arg)
bellard31e31b82003-02-18 22:55:36 +00005725{
5726 const IOCTLEntry *ie;
5727 const argtype *arg_type;
blueswir1992f48a2007-10-14 16:27:31 +00005728 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00005729 uint8_t buf_temp[MAX_STRUCT_SIZE];
pbrook53a59602006-03-25 19:31:22 +00005730 int target_size;
5731 void *argptr;
bellard31e31b82003-02-18 22:55:36 +00005732
5733 ie = ioctl_entries;
5734 for(;;) {
5735 if (ie->target_cmd == 0) {
Josh Kunz39be5352020-02-03 18:54:13 -08005736 qemu_log_mask(
5737 LOG_UNIMP, "Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
ths0da46a62007-10-20 20:23:07 +00005738 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00005739 }
5740 if (ie->target_cmd == cmd)
5741 break;
5742 ie++;
5743 }
5744 arg_type = ie->arg_type;
Peter Maydelld2ef05b2011-01-06 15:04:17 +00005745 if (ie->do_ioctl) {
5746 return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
Helge Deller8cb762f2016-12-06 16:24:03 +01005747 } else if (!ie->host_cmd) {
5748 /* Some architectures define BSD ioctls in their headers
5749 that are not implemented in Linux. */
5750 return -TARGET_ENOSYS;
Peter Maydelld2ef05b2011-01-06 15:04:17 +00005751 }
5752
bellard31e31b82003-02-18 22:55:36 +00005753 switch(arg_type[0]) {
5754 case TYPE_NULL:
5755 /* no argument */
Peter Maydell49ca6f32016-06-06 19:58:14 +01005756 ret = get_errno(safe_ioctl(fd, ie->host_cmd));
bellard31e31b82003-02-18 22:55:36 +00005757 break;
5758 case TYPE_PTRVOID:
5759 case TYPE_INT:
Filip Bozutac858e532020-01-15 20:36:47 +01005760 case TYPE_LONG:
5761 case TYPE_ULONG:
Peter Maydell49ca6f32016-06-06 19:58:14 +01005762 ret = get_errno(safe_ioctl(fd, ie->host_cmd, arg));
bellard31e31b82003-02-18 22:55:36 +00005763 break;
5764 case TYPE_PTR:
5765 arg_type++;
pbrook53a59602006-03-25 19:31:22 +00005766 target_size = thunk_type_size(arg_type, 0);
bellard31e31b82003-02-18 22:55:36 +00005767 switch(ie->access) {
5768 case IOC_R:
Peter Maydell49ca6f32016-06-06 19:58:14 +01005769 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
bellard31e31b82003-02-18 22:55:36 +00005770 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005771 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5772 if (!argptr)
5773 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005774 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5775 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00005776 }
5777 break;
5778 case IOC_W:
bellard579a97f2007-11-11 14:26:47 +00005779 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5780 if (!argptr)
5781 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005782 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5783 unlock_user(argptr, arg, 0);
Peter Maydell49ca6f32016-06-06 19:58:14 +01005784 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
bellard31e31b82003-02-18 22:55:36 +00005785 break;
5786 default:
5787 case IOC_RW:
bellard579a97f2007-11-11 14:26:47 +00005788 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5789 if (!argptr)
5790 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005791 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5792 unlock_user(argptr, arg, 0);
Peter Maydell49ca6f32016-06-06 19:58:14 +01005793 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
bellard31e31b82003-02-18 22:55:36 +00005794 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005795 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5796 if (!argptr)
5797 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005798 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5799 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00005800 }
5801 break;
5802 }
5803 break;
5804 default:
Josh Kunz39be5352020-02-03 18:54:13 -08005805 qemu_log_mask(LOG_UNIMP,
5806 "Unsupported ioctl type: cmd=0x%04lx type=%d\n",
5807 (long)cmd, arg_type[0]);
ths0da46a62007-10-20 20:23:07 +00005808 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00005809 break;
5810 }
5811 return ret;
5812}
5813
blueswir1b39bc502008-10-05 10:51:10 +00005814static const bitmask_transtbl iflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00005815 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
5816 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
5817 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
5818 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
5819 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
5820 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
5821 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
5822 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
5823 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
5824 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
5825 { TARGET_IXON, TARGET_IXON, IXON, IXON },
5826 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
5827 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
5828 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
Filip Bozutac218b4e2020-07-23 23:02:32 +02005829 { TARGET_IUTF8, TARGET_IUTF8, IUTF8, IUTF8},
bellard31e31b82003-02-18 22:55:36 +00005830 { 0, 0, 0, 0 }
5831};
5832
blueswir1b39bc502008-10-05 10:51:10 +00005833static const bitmask_transtbl oflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00005834 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
5835 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
5836 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
5837 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
5838 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
5839 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
5840 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
5841 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
5842 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
5843 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
5844 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
5845 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
5846 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
5847 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
5848 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
5849 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
5850 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
5851 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
5852 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
5853 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
5854 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
5855 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
5856 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
5857 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
5858 { 0, 0, 0, 0 }
5859};
5860
blueswir1b39bc502008-10-05 10:51:10 +00005861static const bitmask_transtbl cflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00005862 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
5863 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
5864 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
5865 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
5866 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
5867 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
5868 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
5869 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
5870 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
5871 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
5872 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
5873 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
5874 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
5875 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
5876 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
5877 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
5878 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
5879 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
5880 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
5881 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
5882 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
5883 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
5884 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
5885 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
5886 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
5887 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
5888 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
5889 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
5890 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
5891 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
5892 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
5893 { 0, 0, 0, 0 }
5894};
5895
blueswir1b39bc502008-10-05 10:51:10 +00005896static const bitmask_transtbl lflag_tbl[] = {
Filip Bozutac218b4e2020-07-23 23:02:32 +02005897 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
5898 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
5899 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
5900 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
5901 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
5902 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
5903 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
5904 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
5905 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
5906 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
5907 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
5908 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
5909 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
5910 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
5911 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
5912 { TARGET_EXTPROC, TARGET_EXTPROC, EXTPROC, EXTPROC},
5913 { 0, 0, 0, 0 }
bellard31e31b82003-02-18 22:55:36 +00005914};
5915
5916static void target_to_host_termios (void *dst, const void *src)
5917{
5918 struct host_termios *host = dst;
5919 const struct target_termios *target = src;
ths3b46e622007-09-17 08:09:54 +00005920
ths5fafdf22007-09-16 21:08:06 +00005921 host->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00005922 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00005923 host->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00005924 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00005925 host->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00005926 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00005927 host->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00005928 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
5929 host->c_line = target->c_line;
ths3b46e622007-09-17 08:09:54 +00005930
Arnaud Patard44607122009-04-21 17:39:08 +03005931 memset(host->c_cc, 0, sizeof(host->c_cc));
ths5fafdf22007-09-16 21:08:06 +00005932 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
5933 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
ths3b46e622007-09-17 08:09:54 +00005934 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
ths5fafdf22007-09-16 21:08:06 +00005935 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
ths3b46e622007-09-17 08:09:54 +00005936 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
ths5fafdf22007-09-16 21:08:06 +00005937 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
ths3b46e622007-09-17 08:09:54 +00005938 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
ths5fafdf22007-09-16 21:08:06 +00005939 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
ths3b46e622007-09-17 08:09:54 +00005940 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
ths5fafdf22007-09-16 21:08:06 +00005941 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
5942 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
ths3b46e622007-09-17 08:09:54 +00005943 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
5944 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
5945 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
5946 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
5947 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
ths5fafdf22007-09-16 21:08:06 +00005948 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
bellard31e31b82003-02-18 22:55:36 +00005949}
ths3b46e622007-09-17 08:09:54 +00005950
bellard31e31b82003-02-18 22:55:36 +00005951static void host_to_target_termios (void *dst, const void *src)
5952{
5953 struct target_termios *target = dst;
5954 const struct host_termios *host = src;
5955
ths5fafdf22007-09-16 21:08:06 +00005956 target->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00005957 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00005958 target->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00005959 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00005960 target->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00005961 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00005962 target->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00005963 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
5964 target->c_line = host->c_line;
ths3b46e622007-09-17 08:09:54 +00005965
Arnaud Patard44607122009-04-21 17:39:08 +03005966 memset(target->c_cc, 0, sizeof(target->c_cc));
bellard31e31b82003-02-18 22:55:36 +00005967 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
5968 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
5969 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
5970 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
5971 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
5972 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
5973 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
5974 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
5975 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
5976 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
5977 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
5978 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
5979 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
5980 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
5981 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
5982 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
5983 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
5984}
5985
blueswir18e853dc2008-10-05 10:49:32 +00005986static const StructEntry struct_termios_def = {
bellard31e31b82003-02-18 22:55:36 +00005987 .convert = { host_to_target_termios, target_to_host_termios },
5988 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
5989 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
Filip Bozuta888468d2020-07-23 23:02:33 +02005990 .print = print_termios,
bellard31e31b82003-02-18 22:55:36 +00005991};
5992
Philippe Mathieu-Daudé180d4ef2021-05-17 07:52:43 +02005993static const bitmask_transtbl mmap_flags_tbl[] = {
Helge Deller541e1692017-10-31 13:53:58 +01005994 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
5995 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
5996 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
5997 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS,
5998 MAP_ANONYMOUS, MAP_ANONYMOUS },
5999 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN,
6000 MAP_GROWSDOWN, MAP_GROWSDOWN },
6001 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE,
6002 MAP_DENYWRITE, MAP_DENYWRITE },
6003 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE,
6004 MAP_EXECUTABLE, MAP_EXECUTABLE },
6005 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
6006 { TARGET_MAP_NORESERVE, TARGET_MAP_NORESERVE,
6007 MAP_NORESERVE, MAP_NORESERVE },
6008 { TARGET_MAP_HUGETLB, TARGET_MAP_HUGETLB, MAP_HUGETLB, MAP_HUGETLB },
6009 /* MAP_STACK had been ignored by the kernel for quite some time.
6010 Recognize it for the target insofar as we do not want to pass
6011 it through to the host. */
6012 { TARGET_MAP_STACK, TARGET_MAP_STACK, 0, 0 },
6013 { 0, 0, 0, 0 }
bellard5286db72003-06-05 00:57:30 +00006014};
6015
Laurent Vivier9d12f792020-03-10 11:33:55 +01006016/*
6017 * NOTE: TARGET_ABI32 is defined for TARGET_I386 (but not for TARGET_X86_64)
6018 * TARGET_I386 is defined if TARGET_X86_64 is defined
6019 */
bellard2ab83ea2003-06-15 19:56:46 +00006020#if defined(TARGET_I386)
bellard6dbad632003-03-16 18:05:05 +00006021
6022/* NOTE: there is really one LDT for all the threads */
blueswir1b1d8e522008-10-26 13:43:07 +00006023static uint8_t *ldt_table;
bellard6dbad632003-03-16 18:05:05 +00006024
bellard03acab62007-11-11 14:57:14 +00006025static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00006026{
6027 int size;
pbrook53a59602006-03-25 19:31:22 +00006028 void *p;
bellard6dbad632003-03-16 18:05:05 +00006029
6030 if (!ldt_table)
6031 return 0;
6032 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
6033 if (size > bytecount)
6034 size = bytecount;
bellard579a97f2007-11-11 14:26:47 +00006035 p = lock_user(VERIFY_WRITE, ptr, size, 0);
6036 if (!p)
bellard03acab62007-11-11 14:57:14 +00006037 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00006038 /* ??? Should this by byteswapped? */
pbrook53a59602006-03-25 19:31:22 +00006039 memcpy(p, ldt_table, size);
6040 unlock_user(p, ptr, size);
bellard6dbad632003-03-16 18:05:05 +00006041 return size;
6042}
6043
6044/* XXX: add locking support */
bellard03acab62007-11-11 14:57:14 +00006045static abi_long write_ldt(CPUX86State *env,
6046 abi_ulong ptr, unsigned long bytecount, int oldmode)
bellard6dbad632003-03-16 18:05:05 +00006047{
6048 struct target_modify_ldt_ldt_s ldt_info;
pbrook53a59602006-03-25 19:31:22 +00006049 struct target_modify_ldt_ldt_s *target_ldt_info;
bellard6dbad632003-03-16 18:05:05 +00006050 int seg_32bit, contents, read_exec_only, limit_in_pages;
bellard8d18e892007-11-14 15:18:40 +00006051 int seg_not_present, useable, lm;
bellard6dbad632003-03-16 18:05:05 +00006052 uint32_t *lp, entry_1, entry_2;
6053
6054 if (bytecount != sizeof(ldt_info))
bellard03acab62007-11-11 14:57:14 +00006055 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +00006056 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
bellard03acab62007-11-11 14:57:14 +00006057 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00006058 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02006059 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
pbrook53a59602006-03-25 19:31:22 +00006060 ldt_info.limit = tswap32(target_ldt_info->limit);
6061 ldt_info.flags = tswap32(target_ldt_info->flags);
6062 unlock_user_struct(target_ldt_info, ptr, 0);
ths3b46e622007-09-17 08:09:54 +00006063
bellard6dbad632003-03-16 18:05:05 +00006064 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
bellard03acab62007-11-11 14:57:14 +00006065 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00006066 seg_32bit = ldt_info.flags & 1;
6067 contents = (ldt_info.flags >> 1) & 3;
6068 read_exec_only = (ldt_info.flags >> 3) & 1;
6069 limit_in_pages = (ldt_info.flags >> 4) & 1;
6070 seg_not_present = (ldt_info.flags >> 5) & 1;
6071 useable = (ldt_info.flags >> 6) & 1;
bellard8d18e892007-11-14 15:18:40 +00006072#ifdef TARGET_ABI32
6073 lm = 0;
6074#else
6075 lm = (ldt_info.flags >> 7) & 1;
6076#endif
bellard6dbad632003-03-16 18:05:05 +00006077 if (contents == 3) {
6078 if (oldmode)
bellard03acab62007-11-11 14:57:14 +00006079 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00006080 if (seg_not_present == 0)
bellard03acab62007-11-11 14:57:14 +00006081 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00006082 }
6083 /* allocate the LDT */
6084 if (!ldt_table) {
balroge4415702008-11-10 02:55:33 +00006085 env->ldt.base = target_mmap(0,
6086 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
6087 PROT_READ|PROT_WRITE,
6088 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
6089 if (env->ldt.base == -1)
bellard03acab62007-11-11 14:57:14 +00006090 return -TARGET_ENOMEM;
Richard Henderson3e8f1622021-02-12 10:48:43 -08006091 memset(g2h_untagged(env->ldt.base), 0,
balroge4415702008-11-10 02:55:33 +00006092 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
bellard6dbad632003-03-16 18:05:05 +00006093 env->ldt.limit = 0xffff;
Richard Henderson3e8f1622021-02-12 10:48:43 -08006094 ldt_table = g2h_untagged(env->ldt.base);
bellard6dbad632003-03-16 18:05:05 +00006095 }
6096
6097 /* NOTE: same code as Linux kernel */
6098 /* Allow LDTs to be cleared by the user. */
6099 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
6100 if (oldmode ||
6101 (contents == 0 &&
6102 read_exec_only == 1 &&
6103 seg_32bit == 0 &&
6104 limit_in_pages == 0 &&
6105 seg_not_present == 1 &&
6106 useable == 0 )) {
6107 entry_1 = 0;
6108 entry_2 = 0;
6109 goto install;
6110 }
6111 }
ths3b46e622007-09-17 08:09:54 +00006112
bellard6dbad632003-03-16 18:05:05 +00006113 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
6114 (ldt_info.limit & 0x0ffff);
6115 entry_2 = (ldt_info.base_addr & 0xff000000) |
6116 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
6117 (ldt_info.limit & 0xf0000) |
6118 ((read_exec_only ^ 1) << 9) |
6119 (contents << 10) |
6120 ((seg_not_present ^ 1) << 15) |
6121 (seg_32bit << 22) |
6122 (limit_in_pages << 23) |
bellard8d18e892007-11-14 15:18:40 +00006123 (lm << 21) |
bellard6dbad632003-03-16 18:05:05 +00006124 0x7000;
6125 if (!oldmode)
6126 entry_2 |= (useable << 20);
bellard14ae3ba2003-05-27 23:25:06 +00006127
bellard6dbad632003-03-16 18:05:05 +00006128 /* Install the new entry ... */
6129install:
6130 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
6131 lp[0] = tswap32(entry_1);
6132 lp[1] = tswap32(entry_2);
6133 return 0;
6134}
6135
6136/* specific and weird i386 syscalls */
blueswir18fcd3692008-08-17 20:26:25 +00006137static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
6138 unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00006139{
bellard03acab62007-11-11 14:57:14 +00006140 abi_long ret;
ths3b46e622007-09-17 08:09:54 +00006141
bellard6dbad632003-03-16 18:05:05 +00006142 switch (func) {
6143 case 0:
6144 ret = read_ldt(ptr, bytecount);
6145 break;
6146 case 1:
6147 ret = write_ldt(env, ptr, bytecount, 1);
6148 break;
6149 case 0x11:
6150 ret = write_ldt(env, ptr, bytecount, 0);
6151 break;
bellard03acab62007-11-11 14:57:14 +00006152 default:
6153 ret = -TARGET_ENOSYS;
6154 break;
bellard6dbad632003-03-16 18:05:05 +00006155 }
6156 return ret;
6157}
bellard1b6b0292003-03-22 17:31:38 +00006158
Laurent Vivier9d12f792020-03-10 11:33:55 +01006159#if defined(TARGET_ABI32)
Alexander Grafbc22eb42013-07-16 18:44:58 +01006160abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00006161{
Richard Henderson3e8f1622021-02-12 10:48:43 -08006162 uint64_t *gdt_table = g2h_untagged(env->gdt.base);
bellard8d18e892007-11-14 15:18:40 +00006163 struct target_modify_ldt_ldt_s ldt_info;
6164 struct target_modify_ldt_ldt_s *target_ldt_info;
6165 int seg_32bit, contents, read_exec_only, limit_in_pages;
6166 int seg_not_present, useable, lm;
6167 uint32_t *lp, entry_1, entry_2;
6168 int i;
6169
6170 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
6171 if (!target_ldt_info)
6172 return -TARGET_EFAULT;
6173 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02006174 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
bellard8d18e892007-11-14 15:18:40 +00006175 ldt_info.limit = tswap32(target_ldt_info->limit);
6176 ldt_info.flags = tswap32(target_ldt_info->flags);
6177 if (ldt_info.entry_number == -1) {
6178 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
6179 if (gdt_table[i] == 0) {
6180 ldt_info.entry_number = i;
6181 target_ldt_info->entry_number = tswap32(i);
6182 break;
6183 }
6184 }
6185 }
6186 unlock_user_struct(target_ldt_info, ptr, 1);
6187
6188 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
6189 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
6190 return -TARGET_EINVAL;
6191 seg_32bit = ldt_info.flags & 1;
6192 contents = (ldt_info.flags >> 1) & 3;
6193 read_exec_only = (ldt_info.flags >> 3) & 1;
6194 limit_in_pages = (ldt_info.flags >> 4) & 1;
6195 seg_not_present = (ldt_info.flags >> 5) & 1;
6196 useable = (ldt_info.flags >> 6) & 1;
6197#ifdef TARGET_ABI32
6198 lm = 0;
6199#else
6200 lm = (ldt_info.flags >> 7) & 1;
6201#endif
6202
6203 if (contents == 3) {
6204 if (seg_not_present == 0)
6205 return -TARGET_EINVAL;
6206 }
6207
6208 /* NOTE: same code as Linux kernel */
6209 /* Allow LDTs to be cleared by the user. */
6210 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
6211 if ((contents == 0 &&
6212 read_exec_only == 1 &&
6213 seg_32bit == 0 &&
6214 limit_in_pages == 0 &&
6215 seg_not_present == 1 &&
6216 useable == 0 )) {
6217 entry_1 = 0;
6218 entry_2 = 0;
6219 goto install;
6220 }
6221 }
6222
6223 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
6224 (ldt_info.limit & 0x0ffff);
6225 entry_2 = (ldt_info.base_addr & 0xff000000) |
6226 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
6227 (ldt_info.limit & 0xf0000) |
6228 ((read_exec_only ^ 1) << 9) |
6229 (contents << 10) |
6230 ((seg_not_present ^ 1) << 15) |
6231 (seg_32bit << 22) |
6232 (limit_in_pages << 23) |
6233 (useable << 20) |
6234 (lm << 21) |
6235 0x7000;
6236
6237 /* Install the new entry ... */
6238install:
6239 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
6240 lp[0] = tswap32(entry_1);
6241 lp[1] = tswap32(entry_2);
6242 return 0;
6243}
6244
blueswir18fcd3692008-08-17 20:26:25 +00006245static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00006246{
6247 struct target_modify_ldt_ldt_s *target_ldt_info;
Richard Henderson3e8f1622021-02-12 10:48:43 -08006248 uint64_t *gdt_table = g2h_untagged(env->gdt.base);
bellard8d18e892007-11-14 15:18:40 +00006249 uint32_t base_addr, limit, flags;
6250 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
6251 int seg_not_present, useable, lm;
6252 uint32_t *lp, entry_1, entry_2;
6253
6254 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
6255 if (!target_ldt_info)
6256 return -TARGET_EFAULT;
6257 idx = tswap32(target_ldt_info->entry_number);
6258 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
6259 idx > TARGET_GDT_ENTRY_TLS_MAX) {
6260 unlock_user_struct(target_ldt_info, ptr, 1);
6261 return -TARGET_EINVAL;
6262 }
6263 lp = (uint32_t *)(gdt_table + idx);
6264 entry_1 = tswap32(lp[0]);
6265 entry_2 = tswap32(lp[1]);
6266
6267 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
6268 contents = (entry_2 >> 10) & 3;
6269 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
6270 seg_32bit = (entry_2 >> 22) & 1;
6271 limit_in_pages = (entry_2 >> 23) & 1;
6272 useable = (entry_2 >> 20) & 1;
6273#ifdef TARGET_ABI32
6274 lm = 0;
6275#else
6276 lm = (entry_2 >> 21) & 1;
6277#endif
6278 flags = (seg_32bit << 0) | (contents << 1) |
6279 (read_exec_only << 3) | (limit_in_pages << 4) |
6280 (seg_not_present << 5) | (useable << 6) | (lm << 7);
6281 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
6282 base_addr = (entry_1 >> 16) |
6283 (entry_2 & 0xff000000) |
6284 ((entry_2 & 0xff) << 16);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02006285 target_ldt_info->base_addr = tswapal(base_addr);
bellard8d18e892007-11-14 15:18:40 +00006286 target_ldt_info->limit = tswap32(limit);
6287 target_ldt_info->flags = tswap32(flags);
6288 unlock_user_struct(target_ldt_info, ptr, 1);
6289 return 0;
6290}
6291
Laurent Vivier9d12f792020-03-10 11:33:55 +01006292abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
6293{
Helge Deller538fabc2020-04-25 00:00:33 +02006294 return -TARGET_ENOSYS;
Laurent Vivier9d12f792020-03-10 11:33:55 +01006295}
6296#else
Peter Maydell2667e712013-07-16 18:44:59 +01006297abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
bellardd2fd1af2007-11-14 18:08:56 +00006298{
Juan Quintela1add8692011-06-16 17:37:09 +01006299 abi_long ret = 0;
bellardd2fd1af2007-11-14 18:08:56 +00006300 abi_ulong val;
6301 int idx;
Juan Quintela1add8692011-06-16 17:37:09 +01006302
bellardd2fd1af2007-11-14 18:08:56 +00006303 switch(code) {
6304 case TARGET_ARCH_SET_GS:
6305 case TARGET_ARCH_SET_FS:
6306 if (code == TARGET_ARCH_SET_GS)
6307 idx = R_GS;
6308 else
6309 idx = R_FS;
6310 cpu_x86_load_seg(env, idx, 0);
6311 env->segs[idx].base = addr;
6312 break;
6313 case TARGET_ARCH_GET_GS:
6314 case TARGET_ARCH_GET_FS:
6315 if (code == TARGET_ARCH_GET_GS)
6316 idx = R_GS;
6317 else
6318 idx = R_FS;
6319 val = env->segs[idx].base;
6320 if (put_user(val, addr, abi_ulong))
Juan Quintela1add8692011-06-16 17:37:09 +01006321 ret = -TARGET_EFAULT;
bellardd2fd1af2007-11-14 18:08:56 +00006322 break;
6323 default:
6324 ret = -TARGET_EINVAL;
6325 break;
6326 }
Juan Quintela1add8692011-06-16 17:37:09 +01006327 return ret;
bellardd2fd1af2007-11-14 18:08:56 +00006328}
Laurent Vivier9d12f792020-03-10 11:33:55 +01006329#endif /* defined(TARGET_ABI32 */
bellard2ab83ea2003-06-15 19:56:46 +00006330#endif /* defined(TARGET_I386) */
6331
Richard Henderson87e9bf22021-12-27 07:01:22 -08006332/*
6333 * These constants are generic. Supply any that are missing from the host.
6334 */
6335#ifndef PR_SET_NAME
6336# define PR_SET_NAME 15
6337# define PR_GET_NAME 16
6338#endif
6339#ifndef PR_SET_FP_MODE
6340# define PR_SET_FP_MODE 45
6341# define PR_GET_FP_MODE 46
6342# define PR_FP_MODE_FR (1 << 0)
6343# define PR_FP_MODE_FRE (1 << 1)
6344#endif
6345#ifndef PR_SVE_SET_VL
6346# define PR_SVE_SET_VL 50
6347# define PR_SVE_GET_VL 51
6348# define PR_SVE_VL_LEN_MASK 0xffff
6349# define PR_SVE_VL_INHERIT (1 << 17)
6350#endif
6351#ifndef PR_PAC_RESET_KEYS
6352# define PR_PAC_RESET_KEYS 54
6353# define PR_PAC_APIAKEY (1 << 0)
6354# define PR_PAC_APIBKEY (1 << 1)
6355# define PR_PAC_APDAKEY (1 << 2)
6356# define PR_PAC_APDBKEY (1 << 3)
6357# define PR_PAC_APGAKEY (1 << 4)
6358#endif
6359#ifndef PR_SET_TAGGED_ADDR_CTRL
6360# define PR_SET_TAGGED_ADDR_CTRL 55
6361# define PR_GET_TAGGED_ADDR_CTRL 56
6362# define PR_TAGGED_ADDR_ENABLE (1UL << 0)
6363#endif
6364#ifndef PR_MTE_TCF_SHIFT
6365# define PR_MTE_TCF_SHIFT 1
6366# define PR_MTE_TCF_NONE (0UL << PR_MTE_TCF_SHIFT)
6367# define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT)
6368# define PR_MTE_TCF_ASYNC (2UL << PR_MTE_TCF_SHIFT)
6369# define PR_MTE_TCF_MASK (3UL << PR_MTE_TCF_SHIFT)
6370# define PR_MTE_TAG_SHIFT 3
6371# define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT)
6372#endif
Richard Henderson220717a2021-12-27 07:01:23 -08006373#ifndef PR_SET_IO_FLUSHER
6374# define PR_SET_IO_FLUSHER 57
6375# define PR_GET_IO_FLUSHER 58
6376#endif
6377#ifndef PR_SET_SYSCALL_USER_DISPATCH
6378# define PR_SET_SYSCALL_USER_DISPATCH 59
6379#endif
Richard Henderson24d87c12022-07-08 20:45:37 +05306380#ifndef PR_SME_SET_VL
6381# define PR_SME_SET_VL 63
6382# define PR_SME_GET_VL 64
6383# define PR_SME_VL_LEN_MASK 0xffff
6384# define PR_SME_VL_INHERIT (1 << 17)
6385#endif
Richard Henderson87e9bf22021-12-27 07:01:22 -08006386
6387#include "target_prctl.h"
6388
6389static abi_long do_prctl_inval0(CPUArchState *env)
6390{
6391 return -TARGET_EINVAL;
6392}
6393
6394static abi_long do_prctl_inval1(CPUArchState *env, abi_long arg2)
6395{
6396 return -TARGET_EINVAL;
6397}
6398
6399#ifndef do_prctl_get_fp_mode
6400#define do_prctl_get_fp_mode do_prctl_inval0
6401#endif
6402#ifndef do_prctl_set_fp_mode
6403#define do_prctl_set_fp_mode do_prctl_inval1
6404#endif
Richard Hendersonfd72f5d2022-07-08 20:45:36 +05306405#ifndef do_prctl_sve_get_vl
6406#define do_prctl_sve_get_vl do_prctl_inval0
Richard Henderson87e9bf22021-12-27 07:01:22 -08006407#endif
Richard Hendersonfd72f5d2022-07-08 20:45:36 +05306408#ifndef do_prctl_sve_set_vl
6409#define do_prctl_sve_set_vl do_prctl_inval1
Richard Henderson87e9bf22021-12-27 07:01:22 -08006410#endif
6411#ifndef do_prctl_reset_keys
6412#define do_prctl_reset_keys do_prctl_inval1
6413#endif
6414#ifndef do_prctl_set_tagged_addr_ctrl
6415#define do_prctl_set_tagged_addr_ctrl do_prctl_inval1
6416#endif
6417#ifndef do_prctl_get_tagged_addr_ctrl
6418#define do_prctl_get_tagged_addr_ctrl do_prctl_inval0
6419#endif
Richard Henderson6e8dcac2021-12-27 07:01:24 -08006420#ifndef do_prctl_get_unalign
6421#define do_prctl_get_unalign do_prctl_inval1
6422#endif
6423#ifndef do_prctl_set_unalign
6424#define do_prctl_set_unalign do_prctl_inval1
6425#endif
Richard Henderson24d87c12022-07-08 20:45:37 +05306426#ifndef do_prctl_sme_get_vl
6427#define do_prctl_sme_get_vl do_prctl_inval0
6428#endif
6429#ifndef do_prctl_sme_set_vl
6430#define do_prctl_sme_set_vl do_prctl_inval1
6431#endif
Richard Henderson87e9bf22021-12-27 07:01:22 -08006432
6433static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
6434 abi_long arg3, abi_long arg4, abi_long arg5)
6435{
6436 abi_long ret;
6437
6438 switch (option) {
6439 case PR_GET_PDEATHSIG:
6440 {
6441 int deathsig;
6442 ret = get_errno(prctl(PR_GET_PDEATHSIG, &deathsig,
6443 arg3, arg4, arg5));
Richard Henderson1edebb32022-01-06 14:57:36 -08006444 if (!is_error(ret) &&
6445 put_user_s32(host_to_target_signal(deathsig), arg2)) {
Richard Henderson87e9bf22021-12-27 07:01:22 -08006446 return -TARGET_EFAULT;
6447 }
6448 return ret;
6449 }
Richard Hendersonf746c652022-01-06 14:57:37 -08006450 case PR_SET_PDEATHSIG:
6451 return get_errno(prctl(PR_SET_PDEATHSIG, target_to_host_signal(arg2),
6452 arg3, arg4, arg5));
Richard Henderson87e9bf22021-12-27 07:01:22 -08006453 case PR_GET_NAME:
6454 {
6455 void *name = lock_user(VERIFY_WRITE, arg2, 16, 1);
6456 if (!name) {
6457 return -TARGET_EFAULT;
6458 }
6459 ret = get_errno(prctl(PR_GET_NAME, (uintptr_t)name,
6460 arg3, arg4, arg5));
6461 unlock_user(name, arg2, 16);
6462 return ret;
6463 }
6464 case PR_SET_NAME:
6465 {
6466 void *name = lock_user(VERIFY_READ, arg2, 16, 1);
6467 if (!name) {
6468 return -TARGET_EFAULT;
6469 }
6470 ret = get_errno(prctl(PR_SET_NAME, (uintptr_t)name,
6471 arg3, arg4, arg5));
6472 unlock_user(name, arg2, 0);
6473 return ret;
6474 }
6475 case PR_GET_FP_MODE:
6476 return do_prctl_get_fp_mode(env);
6477 case PR_SET_FP_MODE:
6478 return do_prctl_set_fp_mode(env, arg2);
6479 case PR_SVE_GET_VL:
Richard Hendersonfd72f5d2022-07-08 20:45:36 +05306480 return do_prctl_sve_get_vl(env);
Richard Henderson87e9bf22021-12-27 07:01:22 -08006481 case PR_SVE_SET_VL:
Richard Hendersonfd72f5d2022-07-08 20:45:36 +05306482 return do_prctl_sve_set_vl(env, arg2);
Richard Henderson24d87c12022-07-08 20:45:37 +05306483 case PR_SME_GET_VL:
6484 return do_prctl_sme_get_vl(env);
6485 case PR_SME_SET_VL:
6486 return do_prctl_sme_set_vl(env, arg2);
Richard Henderson87e9bf22021-12-27 07:01:22 -08006487 case PR_PAC_RESET_KEYS:
6488 if (arg3 || arg4 || arg5) {
6489 return -TARGET_EINVAL;
6490 }
6491 return do_prctl_reset_keys(env, arg2);
6492 case PR_SET_TAGGED_ADDR_CTRL:
6493 if (arg3 || arg4 || arg5) {
6494 return -TARGET_EINVAL;
6495 }
6496 return do_prctl_set_tagged_addr_ctrl(env, arg2);
6497 case PR_GET_TAGGED_ADDR_CTRL:
6498 if (arg2 || arg3 || arg4 || arg5) {
6499 return -TARGET_EINVAL;
6500 }
6501 return do_prctl_get_tagged_addr_ctrl(env);
Richard Henderson220717a2021-12-27 07:01:23 -08006502
Richard Henderson6e8dcac2021-12-27 07:01:24 -08006503 case PR_GET_UNALIGN:
6504 return do_prctl_get_unalign(env, arg2);
6505 case PR_SET_UNALIGN:
6506 return do_prctl_set_unalign(env, arg2);
6507
Richard Henderson4f4e5562022-01-06 14:57:38 -08006508 case PR_CAP_AMBIENT:
6509 case PR_CAPBSET_READ:
6510 case PR_CAPBSET_DROP:
Richard Henderson220717a2021-12-27 07:01:23 -08006511 case PR_GET_DUMPABLE:
6512 case PR_SET_DUMPABLE:
6513 case PR_GET_KEEPCAPS:
6514 case PR_SET_KEEPCAPS:
Richard Henderson4f4e5562022-01-06 14:57:38 -08006515 case PR_GET_SECUREBITS:
6516 case PR_SET_SECUREBITS:
Richard Henderson220717a2021-12-27 07:01:23 -08006517 case PR_GET_TIMING:
6518 case PR_SET_TIMING:
6519 case PR_GET_TIMERSLACK:
6520 case PR_SET_TIMERSLACK:
6521 case PR_MCE_KILL:
6522 case PR_MCE_KILL_GET:
6523 case PR_GET_NO_NEW_PRIVS:
6524 case PR_SET_NO_NEW_PRIVS:
6525 case PR_GET_IO_FLUSHER:
6526 case PR_SET_IO_FLUSHER:
6527 /* Some prctl options have no pointer arguments and we can pass on. */
6528 return get_errno(prctl(option, arg2, arg3, arg4, arg5));
6529
6530 case PR_GET_CHILD_SUBREAPER:
6531 case PR_SET_CHILD_SUBREAPER:
6532 case PR_GET_SPECULATION_CTRL:
6533 case PR_SET_SPECULATION_CTRL:
6534 case PR_GET_TID_ADDRESS:
6535 /* TODO */
6536 return -TARGET_EINVAL;
6537
6538 case PR_GET_FPEXC:
6539 case PR_SET_FPEXC:
6540 /* Was used for SPE on PowerPC. */
6541 return -TARGET_EINVAL;
6542
6543 case PR_GET_ENDIAN:
6544 case PR_SET_ENDIAN:
6545 case PR_GET_FPEMU:
6546 case PR_SET_FPEMU:
6547 case PR_SET_MM:
Richard Henderson87e9bf22021-12-27 07:01:22 -08006548 case PR_GET_SECCOMP:
6549 case PR_SET_SECCOMP:
Richard Henderson220717a2021-12-27 07:01:23 -08006550 case PR_SET_SYSCALL_USER_DISPATCH:
6551 case PR_GET_THP_DISABLE:
6552 case PR_SET_THP_DISABLE:
6553 case PR_GET_TSC:
6554 case PR_SET_TSC:
Richard Henderson220717a2021-12-27 07:01:23 -08006555 /* Disable to prevent the target disabling stuff we need. */
Richard Henderson87e9bf22021-12-27 07:01:22 -08006556 return -TARGET_EINVAL;
Richard Henderson220717a2021-12-27 07:01:23 -08006557
Richard Henderson87e9bf22021-12-27 07:01:22 -08006558 default:
Richard Henderson220717a2021-12-27 07:01:23 -08006559 qemu_log_mask(LOG_UNIMP, "Unsupported prctl: " TARGET_ABI_FMT_ld "\n",
6560 option);
6561 return -TARGET_EINVAL;
Richard Henderson87e9bf22021-12-27 07:01:22 -08006562 }
6563}
6564
Riku Voipio05098a92011-03-04 15:27:29 +02006565#define NEW_STACK_SIZE 0x40000
pbrookd865bab2008-06-07 22:12:17 +00006566
pbrookd865bab2008-06-07 22:12:17 +00006567
6568static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
6569typedef struct {
Andreas Färber9349b4f2012-03-14 01:38:32 +01006570 CPUArchState *env;
pbrookd865bab2008-06-07 22:12:17 +00006571 pthread_mutex_t mutex;
6572 pthread_cond_t cond;
6573 pthread_t thread;
6574 uint32_t tid;
6575 abi_ulong child_tidptr;
6576 abi_ulong parent_tidptr;
6577 sigset_t sigmask;
6578} new_thread_info;
6579
6580static void *clone_func(void *arg)
6581{
6582 new_thread_info *info = arg;
Andreas Färber9349b4f2012-03-14 01:38:32 +01006583 CPUArchState *env;
Andreas Färber0d342822012-12-17 07:12:13 +01006584 CPUState *cpu;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03006585 TaskState *ts;
pbrookd865bab2008-06-07 22:12:17 +00006586
Emilio G. Cota70903762015-08-23 20:23:41 -04006587 rcu_register_thread();
Emilio G. Cota3468b592017-07-19 18:57:58 -04006588 tcg_register_thread();
pbrookd865bab2008-06-07 22:12:17 +00006589 env = info->env;
Richard Henderson29a0af62019-03-22 16:07:18 -07006590 cpu = env_cpu(env);
Andreas Färbera2247f82013-06-09 19:47:04 +02006591 thread_cpu = cpu;
Andreas Färber0429a972013-08-26 18:14:44 +02006592 ts = (TaskState *)cpu->opaque;
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +00006593 info->tid = sys_gettid();
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03006594 task_settid(ts);
pbrookd865bab2008-06-07 22:12:17 +00006595 if (info->child_tidptr)
6596 put_user_u32(info->tid, info->child_tidptr);
6597 if (info->parent_tidptr)
6598 put_user_u32(info->tid, info->parent_tidptr);
Richard Henderson5ebdd772019-03-14 13:10:53 -07006599 qemu_guest_random_seed_thread_part2(cpu->random_seed);
pbrookd865bab2008-06-07 22:12:17 +00006600 /* Enable signals. */
6601 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
6602 /* Signal to the parent that we're ready. */
6603 pthread_mutex_lock(&info->mutex);
6604 pthread_cond_broadcast(&info->cond);
6605 pthread_mutex_unlock(&info->mutex);
Emilio G. Cotaa4dd3d52017-10-18 18:01:41 -04006606 /* Wait until the parent has finished initializing the tls state. */
pbrookd865bab2008-06-07 22:12:17 +00006607 pthread_mutex_lock(&clone_lock);
6608 pthread_mutex_unlock(&clone_lock);
6609 cpu_loop(env);
6610 /* never exits */
6611 return NULL;
6612}
bellard1b6b0292003-03-22 17:31:38 +00006613
ths0da46a62007-10-20 20:23:07 +00006614/* do_fork() Must return host values and target errnos (unlike most
6615 do_*() functions). */
Andreas Färber9349b4f2012-03-14 01:38:32 +01006616static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
pbrookd865bab2008-06-07 22:12:17 +00006617 abi_ulong parent_tidptr, target_ulong newtls,
6618 abi_ulong child_tidptr)
bellard1b6b0292003-03-22 17:31:38 +00006619{
Richard Henderson29a0af62019-03-22 16:07:18 -07006620 CPUState *cpu = env_cpu(env);
bellard1b6b0292003-03-22 17:31:38 +00006621 int ret;
bellard5cd43932003-03-29 16:54:36 +00006622 TaskState *ts;
Andreas Färber0429a972013-08-26 18:14:44 +02006623 CPUState *new_cpu;
Andreas Färber9349b4f2012-03-14 01:38:32 +01006624 CPUArchState *new_env;
pbrookd865bab2008-06-07 22:12:17 +00006625 sigset_t sigmask;
ths3b46e622007-09-17 08:09:54 +00006626
Peter Maydell5ea2fc82016-08-02 18:41:27 +01006627 flags &= ~CLONE_IGNORED_FLAGS;
6628
balrog436d1242008-09-21 02:39:45 +00006629 /* Emulate vfork() with fork() */
6630 if (flags & CLONE_VFORK)
6631 flags &= ~(CLONE_VFORK | CLONE_VM);
6632
bellard1b6b0292003-03-22 17:31:38 +00006633 if (flags & CLONE_VM) {
Andreas Färber0429a972013-08-26 18:14:44 +02006634 TaskState *parent_ts = (TaskState *)cpu->opaque;
pbrookd865bab2008-06-07 22:12:17 +00006635 new_thread_info info;
6636 pthread_attr_t attr;
Peter Maydell24cb36a2013-07-16 18:45:00 +01006637
Peter Maydell5ea2fc82016-08-02 18:41:27 +01006638 if (((flags & CLONE_THREAD_FLAGS) != CLONE_THREAD_FLAGS) ||
6639 (flags & CLONE_INVALID_THREAD_FLAGS)) {
6640 return -TARGET_EINVAL;
6641 }
6642
Markus Armbrusterc78d65e2015-09-14 13:53:03 +02006643 ts = g_new0(TaskState, 1);
pbrook624f7972008-05-31 16:11:38 +00006644 init_task_state(ts);
Max Filippov73a988d2018-03-30 06:19:58 -07006645
6646 /* Grab a mutex so that thread setup appears atomic. */
6647 pthread_mutex_lock(&clone_lock);
6648
Richard Henderson6cc9d672021-03-01 19:21:08 -08006649 /*
6650 * If this is our first additional thread, we need to ensure we
6651 * generate code for parallel execution and flush old translations.
6652 * Do this now so that the copy gets CF_PARALLEL too.
6653 */
6654 if (!(cpu->tcg_cflags & CF_PARALLEL)) {
6655 cpu->tcg_cflags |= CF_PARALLEL;
6656 tb_flush(cpu);
6657 }
6658
bellard1b6b0292003-03-22 17:31:38 +00006659 /* we create a new CPU instance. */
thsc5be9f02007-02-28 20:20:53 +00006660 new_env = cpu_copy(env);
pbrook6e68e072008-05-30 17:22:15 +00006661 /* Init regs that differ from the parent. */
Richard Henderson608999d2019-11-06 12:33:15 +01006662 cpu_clone_regs_child(new_env, newsp, flags);
Richard Henderson07a6ecf2019-11-06 12:33:16 +01006663 cpu_clone_regs_parent(env, flags);
Richard Henderson29a0af62019-03-22 16:07:18 -07006664 new_cpu = env_cpu(new_env);
Andreas Färber0429a972013-08-26 18:14:44 +02006665 new_cpu->opaque = ts;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03006666 ts->bprm = parent_ts->bprm;
6667 ts->info = parent_ts->info;
Peter Maydell3d3efba2016-05-27 15:51:49 +01006668 ts->signal_mask = parent_ts->signal_mask;
pbrookd865bab2008-06-07 22:12:17 +00006669
Peter Maydell7cfbd382016-08-02 18:41:26 +01006670 if (flags & CLONE_CHILD_CLEARTID) {
pbrookc2764712009-03-07 15:24:59 +00006671 ts->child_tidptr = child_tidptr;
6672 }
6673
Peter Maydell7cfbd382016-08-02 18:41:26 +01006674 if (flags & CLONE_SETTLS) {
pbrookd865bab2008-06-07 22:12:17 +00006675 cpu_set_tls (new_env, newtls);
Peter Maydell7cfbd382016-08-02 18:41:26 +01006676 }
pbrookd865bab2008-06-07 22:12:17 +00006677
pbrookd865bab2008-06-07 22:12:17 +00006678 memset(&info, 0, sizeof(info));
6679 pthread_mutex_init(&info.mutex, NULL);
6680 pthread_mutex_lock(&info.mutex);
6681 pthread_cond_init(&info.cond, NULL);
6682 info.env = new_env;
Peter Maydell7cfbd382016-08-02 18:41:26 +01006683 if (flags & CLONE_CHILD_SETTID) {
pbrookd865bab2008-06-07 22:12:17 +00006684 info.child_tidptr = child_tidptr;
Peter Maydell7cfbd382016-08-02 18:41:26 +01006685 }
6686 if (flags & CLONE_PARENT_SETTID) {
pbrookd865bab2008-06-07 22:12:17 +00006687 info.parent_tidptr = parent_tidptr;
Peter Maydell7cfbd382016-08-02 18:41:26 +01006688 }
pbrookd865bab2008-06-07 22:12:17 +00006689
6690 ret = pthread_attr_init(&attr);
Nathan Froyd48e15fc2010-10-29 07:48:57 -07006691 ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE);
6692 ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pbrookd865bab2008-06-07 22:12:17 +00006693 /* It is not safe to deliver signals until the child has finished
6694 initializing, so temporarily block all signals. */
6695 sigfillset(&sigmask);
6696 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
Richard Henderson5ebdd772019-03-14 13:10:53 -07006697 cpu->random_seed = qemu_guest_random_seed_thread_part1();
pbrookd865bab2008-06-07 22:12:17 +00006698
6699 ret = pthread_create(&info.thread, &attr, clone_func, &info);
pbrookc2764712009-03-07 15:24:59 +00006700 /* TODO: Free new CPU state if thread creation failed. */
pbrookd865bab2008-06-07 22:12:17 +00006701
6702 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
6703 pthread_attr_destroy(&attr);
6704 if (ret == 0) {
6705 /* Wait for the child to initialize. */
6706 pthread_cond_wait(&info.cond, &info.mutex);
6707 ret = info.tid;
pbrookd865bab2008-06-07 22:12:17 +00006708 } else {
6709 ret = -1;
6710 }
6711 pthread_mutex_unlock(&info.mutex);
6712 pthread_cond_destroy(&info.cond);
6713 pthread_mutex_destroy(&info.mutex);
6714 pthread_mutex_unlock(&clone_lock);
bellard1b6b0292003-03-22 17:31:38 +00006715 } else {
6716 /* if no CLONE_VM, we consider it is a fork */
Peter Maydell5ea2fc82016-08-02 18:41:27 +01006717 if (flags & CLONE_INVALID_FORK_FLAGS) {
6718 return -TARGET_EINVAL;
6719 }
6720
6721 /* We can't support custom termination signals */
6722 if ((flags & CSIGNAL) != TARGET_SIGCHLD) {
Timothy E Baldwin93b4eff2015-08-31 00:26:21 +01006723 return -TARGET_EINVAL;
6724 }
Timothy E Baldwin7d92d342016-05-27 15:51:58 +01006725
6726 if (block_signals()) {
Richard Hendersonaf254a22021-11-22 19:47:33 +01006727 return -QEMU_ERESTARTSYS;
Timothy E Baldwin7d92d342016-05-27 15:51:58 +01006728 }
6729
pbrookd865bab2008-06-07 22:12:17 +00006730 fork_start();
bellard1b6b0292003-03-22 17:31:38 +00006731 ret = fork();
pbrookd865bab2008-06-07 22:12:17 +00006732 if (ret == 0) {
aurel322b1319c2008-12-18 22:44:04 +00006733 /* Child Process. */
Richard Henderson608999d2019-11-06 12:33:15 +01006734 cpu_clone_regs_child(env, newsp, flags);
pbrookd865bab2008-06-07 22:12:17 +00006735 fork_end(1);
aurel322b1319c2008-12-18 22:44:04 +00006736 /* There is a race condition here. The parent process could
6737 theoretically read the TID in the child process before the child
6738 tid is set. This would require using either ptrace
6739 (not implemented) or having *_tidptr to point at a shared memory
6740 mapping. We can't repeat the spinlock hack used above because
6741 the child process gets its own copy of the lock. */
pbrookd865bab2008-06-07 22:12:17 +00006742 if (flags & CLONE_CHILD_SETTID)
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +00006743 put_user_u32(sys_gettid(), child_tidptr);
pbrookd865bab2008-06-07 22:12:17 +00006744 if (flags & CLONE_PARENT_SETTID)
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +00006745 put_user_u32(sys_gettid(), parent_tidptr);
Andreas Färber0429a972013-08-26 18:14:44 +02006746 ts = (TaskState *)cpu->opaque;
pbrookd865bab2008-06-07 22:12:17 +00006747 if (flags & CLONE_SETTLS)
6748 cpu_set_tls (env, newtls);
pbrookc2764712009-03-07 15:24:59 +00006749 if (flags & CLONE_CHILD_CLEARTID)
6750 ts->child_tidptr = child_tidptr;
pbrookd865bab2008-06-07 22:12:17 +00006751 } else {
Richard Henderson07a6ecf2019-11-06 12:33:16 +01006752 cpu_clone_regs_parent(env, flags);
pbrookd865bab2008-06-07 22:12:17 +00006753 fork_end(0);
6754 }
bellard1b6b0292003-03-22 17:31:38 +00006755 }
6756 return ret;
6757}
6758
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006759/* warning : doesn't handle linux specific flags... */
6760static int target_to_host_fcntl_cmd(int cmd)
6761{
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006762 int ret;
6763
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006764 switch(cmd) {
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006765 case TARGET_F_DUPFD:
6766 case TARGET_F_GETFD:
6767 case TARGET_F_SETFD:
6768 case TARGET_F_GETFL:
6769 case TARGET_F_SETFL:
Andreas Schwab2d92c682020-05-25 09:59:28 +02006770 case TARGET_F_OFD_GETLK:
6771 case TARGET_F_OFD_SETLK:
6772 case TARGET_F_OFD_SETLKW:
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006773 ret = cmd;
6774 break;
6775 case TARGET_F_GETLK:
6776 ret = F_GETLK64;
6777 break;
6778 case TARGET_F_SETLK:
6779 ret = F_SETLK64;
6780 break;
6781 case TARGET_F_SETLKW:
6782 ret = F_SETLKW64;
6783 break;
6784 case TARGET_F_GETOWN:
6785 ret = F_GETOWN;
6786 break;
6787 case TARGET_F_SETOWN:
6788 ret = F_SETOWN;
6789 break;
6790 case TARGET_F_GETSIG:
6791 ret = F_GETSIG;
6792 break;
6793 case TARGET_F_SETSIG:
6794 ret = F_SETSIG;
6795 break;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006796#if TARGET_ABI_BITS == 32
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006797 case TARGET_F_GETLK64:
6798 ret = F_GETLK64;
6799 break;
6800 case TARGET_F_SETLK64:
6801 ret = F_SETLK64;
6802 break;
6803 case TARGET_F_SETLKW64:
6804 ret = F_SETLKW64;
6805 break;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006806#endif
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006807 case TARGET_F_SETLEASE:
6808 ret = F_SETLEASE;
6809 break;
6810 case TARGET_F_GETLEASE:
6811 ret = F_GETLEASE;
6812 break;
malcfbd5de92009-09-06 06:31:59 +04006813#ifdef F_DUPFD_CLOEXEC
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006814 case TARGET_F_DUPFD_CLOEXEC:
6815 ret = F_DUPFD_CLOEXEC;
6816 break;
malcfbd5de92009-09-06 06:31:59 +04006817#endif
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006818 case TARGET_F_NOTIFY:
6819 ret = F_NOTIFY;
6820 break;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006821#ifdef F_GETOWN_EX
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006822 case TARGET_F_GETOWN_EX:
6823 ret = F_GETOWN_EX;
6824 break;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006825#endif
6826#ifdef F_SETOWN_EX
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006827 case TARGET_F_SETOWN_EX:
6828 ret = F_SETOWN_EX;
6829 break;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006830#endif
Peter Maydellddf31aa2016-06-30 17:33:49 +01006831#ifdef F_SETPIPE_SZ
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006832 case TARGET_F_SETPIPE_SZ:
6833 ret = F_SETPIPE_SZ;
6834 break;
6835 case TARGET_F_GETPIPE_SZ:
6836 ret = F_GETPIPE_SZ;
6837 break;
Peter Maydellddf31aa2016-06-30 17:33:49 +01006838#endif
Shu-Chun Weng2bb963f2020-12-18 11:32:10 -08006839#ifdef F_ADD_SEALS
6840 case TARGET_F_ADD_SEALS:
6841 ret = F_ADD_SEALS;
6842 break;
6843 case TARGET_F_GET_SEALS:
6844 ret = F_GET_SEALS;
6845 break;
6846#endif
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006847 default:
6848 ret = -TARGET_EINVAL;
6849 break;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006850 }
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006851
6852#if defined(__powerpc64__)
6853 /* On PPC64, glibc headers has the F_*LK* defined to 12, 13 and 14 and
6854 * is not supported by kernel. The glibc fcntl call actually adjusts
6855 * them to 5, 6 and 7 before making the syscall(). Since we make the
6856 * syscall directly, adjust to what is supported by the kernel.
6857 */
6858 if (ret >= F_GETLK64 && ret <= F_SETLKW64) {
6859 ret -= F_GETLK64 - 5;
6860 }
6861#endif
6862
6863 return ret;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006864}
6865
Laurent Vivierae68ad92018-05-10 01:11:21 +02006866#define FLOCK_TRANSTBL \
6867 switch (type) { \
6868 TRANSTBL_CONVERT(F_RDLCK); \
6869 TRANSTBL_CONVERT(F_WRLCK); \
6870 TRANSTBL_CONVERT(F_UNLCK); \
Laurent Vivierae68ad92018-05-10 01:11:21 +02006871 }
6872
6873static int target_to_host_flock(int type)
6874{
6875#define TRANSTBL_CONVERT(a) case TARGET_##a: return a
6876 FLOCK_TRANSTBL
6877#undef TRANSTBL_CONVERT
6878 return -TARGET_EINVAL;
6879}
6880
6881static int host_to_target_flock(int type)
6882{
6883#define TRANSTBL_CONVERT(a) case a: return TARGET_##a
6884 FLOCK_TRANSTBL
6885#undef TRANSTBL_CONVERT
6886 /* if we don't know how to convert the value coming
6887 * from the host we copy to the target field as-is
6888 */
6889 return type;
6890}
Laurent Vivier2ba7f732013-01-10 21:42:48 +01006891
Peter Maydell213d3e92016-06-13 11:22:05 +01006892static inline abi_long copy_from_user_flock(struct flock64 *fl,
6893 abi_ulong target_flock_addr)
6894{
6895 struct target_flock *target_fl;
Laurent Vivierae68ad92018-05-10 01:11:21 +02006896 int l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006897
6898 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
6899 return -TARGET_EFAULT;
6900 }
6901
6902 __get_user(l_type, &target_fl->l_type);
Laurent Vivierae68ad92018-05-10 01:11:21 +02006903 l_type = target_to_host_flock(l_type);
6904 if (l_type < 0) {
6905 return l_type;
6906 }
6907 fl->l_type = l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006908 __get_user(fl->l_whence, &target_fl->l_whence);
6909 __get_user(fl->l_start, &target_fl->l_start);
6910 __get_user(fl->l_len, &target_fl->l_len);
6911 __get_user(fl->l_pid, &target_fl->l_pid);
6912 unlock_user_struct(target_fl, target_flock_addr, 0);
6913 return 0;
6914}
6915
6916static inline abi_long copy_to_user_flock(abi_ulong target_flock_addr,
6917 const struct flock64 *fl)
6918{
6919 struct target_flock *target_fl;
6920 short l_type;
6921
6922 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
6923 return -TARGET_EFAULT;
6924 }
6925
Laurent Vivierae68ad92018-05-10 01:11:21 +02006926 l_type = host_to_target_flock(fl->l_type);
Peter Maydell213d3e92016-06-13 11:22:05 +01006927 __put_user(l_type, &target_fl->l_type);
6928 __put_user(fl->l_whence, &target_fl->l_whence);
6929 __put_user(fl->l_start, &target_fl->l_start);
6930 __put_user(fl->l_len, &target_fl->l_len);
6931 __put_user(fl->l_pid, &target_fl->l_pid);
6932 unlock_user_struct(target_fl, target_flock_addr, 1);
6933 return 0;
6934}
6935
6936typedef abi_long from_flock64_fn(struct flock64 *fl, abi_ulong target_addr);
6937typedef abi_long to_flock64_fn(abi_ulong target_addr, const struct flock64 *fl);
6938
6939#if defined(TARGET_ARM) && TARGET_ABI_BITS == 32
Richard Hendersonffe81d42022-01-06 20:25:59 -08006940struct target_oabi_flock64 {
6941 abi_short l_type;
6942 abi_short l_whence;
6943 abi_llong l_start;
6944 abi_llong l_len;
6945 abi_int l_pid;
6946} QEMU_PACKED;
6947
Laurent Vivier7f254c52018-05-02 23:57:30 +02006948static inline abi_long copy_from_user_oabi_flock64(struct flock64 *fl,
Peter Maydell213d3e92016-06-13 11:22:05 +01006949 abi_ulong target_flock_addr)
6950{
Laurent Vivier7f254c52018-05-02 23:57:30 +02006951 struct target_oabi_flock64 *target_fl;
Laurent Vivierae68ad92018-05-10 01:11:21 +02006952 int l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006953
6954 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
6955 return -TARGET_EFAULT;
6956 }
6957
6958 __get_user(l_type, &target_fl->l_type);
Laurent Vivierae68ad92018-05-10 01:11:21 +02006959 l_type = target_to_host_flock(l_type);
6960 if (l_type < 0) {
6961 return l_type;
6962 }
6963 fl->l_type = l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006964 __get_user(fl->l_whence, &target_fl->l_whence);
6965 __get_user(fl->l_start, &target_fl->l_start);
6966 __get_user(fl->l_len, &target_fl->l_len);
6967 __get_user(fl->l_pid, &target_fl->l_pid);
6968 unlock_user_struct(target_fl, target_flock_addr, 0);
6969 return 0;
6970}
6971
Laurent Vivier7f254c52018-05-02 23:57:30 +02006972static inline abi_long copy_to_user_oabi_flock64(abi_ulong target_flock_addr,
Peter Maydell213d3e92016-06-13 11:22:05 +01006973 const struct flock64 *fl)
6974{
Laurent Vivier7f254c52018-05-02 23:57:30 +02006975 struct target_oabi_flock64 *target_fl;
Peter Maydell213d3e92016-06-13 11:22:05 +01006976 short l_type;
6977
6978 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
6979 return -TARGET_EFAULT;
6980 }
6981
Laurent Vivierae68ad92018-05-10 01:11:21 +02006982 l_type = host_to_target_flock(fl->l_type);
Peter Maydell213d3e92016-06-13 11:22:05 +01006983 __put_user(l_type, &target_fl->l_type);
6984 __put_user(fl->l_whence, &target_fl->l_whence);
6985 __put_user(fl->l_start, &target_fl->l_start);
6986 __put_user(fl->l_len, &target_fl->l_len);
6987 __put_user(fl->l_pid, &target_fl->l_pid);
6988 unlock_user_struct(target_fl, target_flock_addr, 1);
6989 return 0;
6990}
6991#endif
6992
6993static inline abi_long copy_from_user_flock64(struct flock64 *fl,
6994 abi_ulong target_flock_addr)
6995{
6996 struct target_flock64 *target_fl;
Laurent Vivierae68ad92018-05-10 01:11:21 +02006997 int l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006998
6999 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
7000 return -TARGET_EFAULT;
7001 }
7002
7003 __get_user(l_type, &target_fl->l_type);
Laurent Vivierae68ad92018-05-10 01:11:21 +02007004 l_type = target_to_host_flock(l_type);
7005 if (l_type < 0) {
7006 return l_type;
7007 }
7008 fl->l_type = l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01007009 __get_user(fl->l_whence, &target_fl->l_whence);
7010 __get_user(fl->l_start, &target_fl->l_start);
7011 __get_user(fl->l_len, &target_fl->l_len);
7012 __get_user(fl->l_pid, &target_fl->l_pid);
7013 unlock_user_struct(target_fl, target_flock_addr, 0);
7014 return 0;
7015}
7016
7017static inline abi_long copy_to_user_flock64(abi_ulong target_flock_addr,
7018 const struct flock64 *fl)
7019{
7020 struct target_flock64 *target_fl;
7021 short l_type;
7022
7023 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
7024 return -TARGET_EFAULT;
7025 }
7026
Laurent Vivierae68ad92018-05-10 01:11:21 +02007027 l_type = host_to_target_flock(fl->l_type);
Peter Maydell213d3e92016-06-13 11:22:05 +01007028 __put_user(l_type, &target_fl->l_type);
7029 __put_user(fl->l_whence, &target_fl->l_whence);
7030 __put_user(fl->l_start, &target_fl->l_start);
7031 __put_user(fl->l_len, &target_fl->l_len);
7032 __put_user(fl->l_pid, &target_fl->l_pid);
7033 unlock_user_struct(target_fl, target_flock_addr, 1);
7034 return 0;
7035}
7036
blueswir1992f48a2007-10-14 16:27:31 +00007037static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
bellard7775e9e2003-05-14 22:46:48 +00007038{
ths43f238d2007-01-05 20:55:49 +00007039 struct flock64 fl64;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01007040#ifdef F_GETOWN_EX
7041 struct f_owner_ex fox;
7042 struct target_f_owner_ex *target_fox;
7043#endif
blueswir1992f48a2007-10-14 16:27:31 +00007044 abi_long ret;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007045 int host_cmd = target_to_host_fcntl_cmd(cmd);
7046
7047 if (host_cmd == -TARGET_EINVAL)
7048 return host_cmd;
pbrook53a59602006-03-25 19:31:22 +00007049
bellard7775e9e2003-05-14 22:46:48 +00007050 switch(cmd) {
7051 case TARGET_F_GETLK:
Peter Maydell213d3e92016-06-13 11:22:05 +01007052 ret = copy_from_user_flock(&fl64, arg);
7053 if (ret) {
7054 return ret;
7055 }
Peter Maydell435da5e2016-06-13 11:22:05 +01007056 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00007057 if (ret == 0) {
Peter Maydell213d3e92016-06-13 11:22:05 +01007058 ret = copy_to_user_flock(arg, &fl64);
bellard7775e9e2003-05-14 22:46:48 +00007059 }
7060 break;
ths3b46e622007-09-17 08:09:54 +00007061
bellard7775e9e2003-05-14 22:46:48 +00007062 case TARGET_F_SETLK:
7063 case TARGET_F_SETLKW:
Peter Maydell213d3e92016-06-13 11:22:05 +01007064 ret = copy_from_user_flock(&fl64, arg);
7065 if (ret) {
7066 return ret;
7067 }
Peter Maydell435da5e2016-06-13 11:22:05 +01007068 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00007069 break;
ths3b46e622007-09-17 08:09:54 +00007070
bellard7775e9e2003-05-14 22:46:48 +00007071 case TARGET_F_GETLK64:
Andreas Schwab2d92c682020-05-25 09:59:28 +02007072 case TARGET_F_OFD_GETLK:
Peter Maydell213d3e92016-06-13 11:22:05 +01007073 ret = copy_from_user_flock64(&fl64, arg);
7074 if (ret) {
7075 return ret;
7076 }
Peter Maydell435da5e2016-06-13 11:22:05 +01007077 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
ths43f238d2007-01-05 20:55:49 +00007078 if (ret == 0) {
Peter Maydell213d3e92016-06-13 11:22:05 +01007079 ret = copy_to_user_flock64(arg, &fl64);
ths43f238d2007-01-05 20:55:49 +00007080 }
bellard9ee1fa22007-11-11 15:11:19 +00007081 break;
bellard7775e9e2003-05-14 22:46:48 +00007082 case TARGET_F_SETLK64:
7083 case TARGET_F_SETLKW64:
Andreas Schwab2d92c682020-05-25 09:59:28 +02007084 case TARGET_F_OFD_SETLK:
7085 case TARGET_F_OFD_SETLKW:
Peter Maydell213d3e92016-06-13 11:22:05 +01007086 ret = copy_from_user_flock64(&fl64, arg);
7087 if (ret) {
7088 return ret;
7089 }
Peter Maydell435da5e2016-06-13 11:22:05 +01007090 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00007091 break;
7092
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007093 case TARGET_F_GETFL:
Peter Maydell435da5e2016-06-13 11:22:05 +01007094 ret = get_errno(safe_fcntl(fd, host_cmd, arg));
bellard9ee1fa22007-11-11 15:11:19 +00007095 if (ret >= 0) {
7096 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
7097 }
bellardffa65c32004-01-04 23:57:22 +00007098 break;
7099
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007100 case TARGET_F_SETFL:
Peter Maydell435da5e2016-06-13 11:22:05 +01007101 ret = get_errno(safe_fcntl(fd, host_cmd,
7102 target_to_host_bitmask(arg,
7103 fcntl_flags_tbl)));
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007104 break;
7105
Andreas Schwab8d5d3002014-03-07 15:24:08 +01007106#ifdef F_GETOWN_EX
7107 case TARGET_F_GETOWN_EX:
Peter Maydell435da5e2016-06-13 11:22:05 +01007108 ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
Andreas Schwab8d5d3002014-03-07 15:24:08 +01007109 if (ret >= 0) {
7110 if (!lock_user_struct(VERIFY_WRITE, target_fox, arg, 0))
7111 return -TARGET_EFAULT;
7112 target_fox->type = tswap32(fox.type);
7113 target_fox->pid = tswap32(fox.pid);
7114 unlock_user_struct(target_fox, arg, 1);
7115 }
7116 break;
7117#endif
7118
7119#ifdef F_SETOWN_EX
7120 case TARGET_F_SETOWN_EX:
7121 if (!lock_user_struct(VERIFY_READ, target_fox, arg, 1))
7122 return -TARGET_EFAULT;
7123 fox.type = tswap32(target_fox->type);
7124 fox.pid = tswap32(target_fox->pid);
7125 unlock_user_struct(target_fox, arg, 0);
Peter Maydell435da5e2016-06-13 11:22:05 +01007126 ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
Andreas Schwab8d5d3002014-03-07 15:24:08 +01007127 break;
7128#endif
7129
Timothy Baldwina7b4c9b2020-07-29 21:06:44 +01007130 case TARGET_F_SETSIG:
7131 ret = get_errno(safe_fcntl(fd, host_cmd, target_to_host_signal(arg)));
7132 break;
7133
7134 case TARGET_F_GETSIG:
7135 ret = host_to_target_signal(get_errno(safe_fcntl(fd, host_cmd, arg)));
7136 break;
7137
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007138 case TARGET_F_SETOWN:
7139 case TARGET_F_GETOWN:
Ulrich Hecht7e22e542009-07-24 19:10:27 +02007140 case TARGET_F_SETLEASE:
7141 case TARGET_F_GETLEASE:
Peter Maydell7e3b92e2016-06-20 15:50:37 +01007142 case TARGET_F_SETPIPE_SZ:
7143 case TARGET_F_GETPIPE_SZ:
Shu-Chun Weng2bb963f2020-12-18 11:32:10 -08007144 case TARGET_F_ADD_SEALS:
7145 case TARGET_F_GET_SEALS:
Peter Maydell435da5e2016-06-13 11:22:05 +01007146 ret = get_errno(safe_fcntl(fd, host_cmd, arg));
bellardffa65c32004-01-04 23:57:22 +00007147 break;
7148
bellard7775e9e2003-05-14 22:46:48 +00007149 default:
Peter Maydell435da5e2016-06-13 11:22:05 +01007150 ret = get_errno(safe_fcntl(fd, cmd, arg));
bellard7775e9e2003-05-14 22:46:48 +00007151 break;
7152 }
7153 return ret;
7154}
7155
bellard67867302003-11-23 17:05:30 +00007156#ifdef USE_UID16
bellard7775e9e2003-05-14 22:46:48 +00007157
bellard67867302003-11-23 17:05:30 +00007158static inline int high2lowuid(int uid)
7159{
7160 if (uid > 65535)
7161 return 65534;
7162 else
7163 return uid;
7164}
7165
7166static inline int high2lowgid(int gid)
7167{
7168 if (gid > 65535)
7169 return 65534;
7170 else
7171 return gid;
7172}
7173
7174static inline int low2highuid(int uid)
7175{
7176 if ((int16_t)uid == -1)
7177 return -1;
7178 else
7179 return uid;
7180}
7181
7182static inline int low2highgid(int gid)
7183{
7184 if ((int16_t)gid == -1)
7185 return -1;
7186 else
7187 return gid;
7188}
Riku Voipio0c866a72011-04-18 15:23:06 +03007189static inline int tswapid(int id)
7190{
7191 return tswap16(id);
7192}
Peter Maydell76ca3102014-03-02 19:36:41 +00007193
7194#define put_user_id(x, gaddr) put_user_u16(x, gaddr)
7195
Riku Voipio0c866a72011-04-18 15:23:06 +03007196#else /* !USE_UID16 */
7197static inline int high2lowuid(int uid)
7198{
7199 return uid;
7200}
7201static inline int high2lowgid(int gid)
7202{
7203 return gid;
7204}
7205static inline int low2highuid(int uid)
7206{
7207 return uid;
7208}
7209static inline int low2highgid(int gid)
7210{
7211 return gid;
7212}
7213static inline int tswapid(int id)
7214{
7215 return tswap32(id);
7216}
Peter Maydell76ca3102014-03-02 19:36:41 +00007217
7218#define put_user_id(x, gaddr) put_user_u32(x, gaddr)
7219
bellard67867302003-11-23 17:05:30 +00007220#endif /* USE_UID16 */
bellard1b6b0292003-03-22 17:31:38 +00007221
Peter Maydellfd6f7792016-03-01 16:33:02 +00007222/* We must do direct syscalls for setting UID/GID, because we want to
7223 * implement the Linux system call semantics of "change only for this thread",
7224 * not the libc/POSIX semantics of "change for all threads in process".
7225 * (See http://ewontfix.com/17/ for more details.)
7226 * We use the 32-bit version of the syscalls if present; if it is not
7227 * then either the host architecture supports 32-bit UIDs natively with
7228 * the standard syscall, or the 16-bit UID is the best we can do.
7229 */
7230#ifdef __NR_setuid32
7231#define __NR_sys_setuid __NR_setuid32
7232#else
7233#define __NR_sys_setuid __NR_setuid
7234#endif
7235#ifdef __NR_setgid32
7236#define __NR_sys_setgid __NR_setgid32
7237#else
7238#define __NR_sys_setgid __NR_setgid
7239#endif
7240#ifdef __NR_setresuid32
7241#define __NR_sys_setresuid __NR_setresuid32
7242#else
7243#define __NR_sys_setresuid __NR_setresuid
7244#endif
7245#ifdef __NR_setresgid32
7246#define __NR_sys_setresgid __NR_setresgid32
7247#else
7248#define __NR_sys_setresgid __NR_setresgid
7249#endif
7250
7251_syscall1(int, sys_setuid, uid_t, uid)
7252_syscall1(int, sys_setgid, gid_t, gid)
7253_syscall3(int, sys_setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
7254_syscall3(int, sys_setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
7255
bellard31e31b82003-02-18 22:55:36 +00007256void syscall_init(void)
7257{
bellard2ab83ea2003-06-15 19:56:46 +00007258 IOCTLEntry *ie;
7259 const argtype *arg_type;
7260 int size;
7261
Alexander Graf8be656b2015-05-06 23:47:32 +02007262 thunk_init(STRUCT_MAX);
7263
Blue Swirl001faf32009-05-13 17:53:17 +00007264#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
ths5fafdf22007-09-16 21:08:06 +00007265#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
bellard31e31b82003-02-18 22:55:36 +00007266#include "syscall_types.h"
7267#undef STRUCT
7268#undef STRUCT_SPECIAL
bellard2ab83ea2003-06-15 19:56:46 +00007269
7270 /* we patch the ioctl size if necessary. We rely on the fact that
7271 no ioctl has all the bits at '1' in the size field */
7272 ie = ioctl_entries;
7273 while (ie->target_cmd != 0) {
7274 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
7275 TARGET_IOC_SIZEMASK) {
7276 arg_type = ie->arg_type;
7277 if (arg_type[0] != TYPE_PTR) {
ths5fafdf22007-09-16 21:08:06 +00007278 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00007279 ie->target_cmd);
7280 exit(1);
7281 }
7282 arg_type++;
7283 size = thunk_type_size(arg_type, 0);
ths5fafdf22007-09-16 21:08:06 +00007284 ie->target_cmd = (ie->target_cmd &
bellard2ab83ea2003-06-15 19:56:46 +00007285 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
7286 (size << TARGET_IOC_SIZESHIFT);
7287 }
thsb92c47c2007-11-01 00:07:38 +00007288
bellard2ab83ea2003-06-15 19:56:46 +00007289 /* automatic consistency check if same arch */
balrog872ea0c2008-09-21 02:31:19 +00007290#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
7291 (defined(__x86_64__) && defined(TARGET_X86_64))
7292 if (unlikely(ie->target_cmd != ie->host_cmd)) {
7293 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
7294 ie->name, ie->target_cmd, ie->host_cmd);
bellard2ab83ea2003-06-15 19:56:46 +00007295 }
7296#endif
7297 ie++;
7298 }
bellard31e31b82003-02-18 22:55:36 +00007299}
bellardc573ff62004-01-04 15:51:36 +00007300
pbrookce4defa2006-02-09 16:49:55 +00007301#ifdef TARGET_NR_truncate64
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02007302static inline abi_long target_truncate64(CPUArchState *cpu_env, const char *arg1,
blueswir1992f48a2007-10-14 16:27:31 +00007303 abi_long arg2,
7304 abi_long arg3,
7305 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00007306{
James Clarke8bf8e9d2017-09-15 20:33:13 +01007307 if (regpairs_aligned(cpu_env, TARGET_NR_truncate64)) {
pbrookce4defa2006-02-09 16:49:55 +00007308 arg2 = arg3;
7309 arg3 = arg4;
Riku Voipio48e515d2011-07-12 15:40:51 +03007310 }
pbrookce4defa2006-02-09 16:49:55 +00007311 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
7312}
7313#endif
7314
7315#ifdef TARGET_NR_ftruncate64
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02007316static inline abi_long target_ftruncate64(CPUArchState *cpu_env, abi_long arg1,
blueswir1992f48a2007-10-14 16:27:31 +00007317 abi_long arg2,
7318 abi_long arg3,
7319 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00007320{
James Clarke8bf8e9d2017-09-15 20:33:13 +01007321 if (regpairs_aligned(cpu_env, TARGET_NR_ftruncate64)) {
pbrookce4defa2006-02-09 16:49:55 +00007322 arg2 = arg3;
7323 arg3 = arg4;
Riku Voipio48e515d2011-07-12 15:40:51 +03007324 }
pbrookce4defa2006-02-09 16:49:55 +00007325 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
7326}
7327#endif
7328
Alistair Francis859e8a82020-03-12 15:13:49 -07007329#if defined(TARGET_NR_timer_settime) || \
7330 (defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD))
Filip Bozuta2c86c902020-07-22 17:34:20 +02007331static inline abi_long target_to_host_itimerspec(struct itimerspec *host_its,
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007332 abi_ulong target_addr)
7333{
Filip Bozuta2c86c902020-07-22 17:34:20 +02007334 if (target_to_host_timespec(&host_its->it_interval, target_addr +
7335 offsetof(struct target_itimerspec,
7336 it_interval)) ||
7337 target_to_host_timespec(&host_its->it_value, target_addr +
7338 offsetof(struct target_itimerspec,
7339 it_value))) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007340 return -TARGET_EFAULT;
7341 }
7342
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007343 return 0;
7344}
Alistair Francis859e8a82020-03-12 15:13:49 -07007345#endif
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007346
Filip Bozuta828cb3a2020-07-22 17:34:21 +02007347#if defined(TARGET_NR_timer_settime64) || \
7348 (defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD))
7349static inline abi_long target_to_host_itimerspec64(struct itimerspec *host_its,
7350 abi_ulong target_addr)
7351{
7352 if (target_to_host_timespec64(&host_its->it_interval, target_addr +
7353 offsetof(struct target__kernel_itimerspec,
7354 it_interval)) ||
7355 target_to_host_timespec64(&host_its->it_value, target_addr +
7356 offsetof(struct target__kernel_itimerspec,
7357 it_value))) {
7358 return -TARGET_EFAULT;
7359 }
7360
7361 return 0;
7362}
7363#endif
7364
Alistair Francis859e8a82020-03-12 15:13:49 -07007365#if ((defined(TARGET_NR_timerfd_gettime) || \
7366 defined(TARGET_NR_timerfd_settime)) && defined(CONFIG_TIMERFD)) || \
Filip Bozuta2c86c902020-07-22 17:34:20 +02007367 defined(TARGET_NR_timer_gettime) || defined(TARGET_NR_timer_settime)
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007368static inline abi_long host_to_target_itimerspec(abi_ulong target_addr,
Filip Bozuta2c86c902020-07-22 17:34:20 +02007369 struct itimerspec *host_its)
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007370{
Filip Bozuta2c86c902020-07-22 17:34:20 +02007371 if (host_to_target_timespec(target_addr + offsetof(struct target_itimerspec,
7372 it_interval),
7373 &host_its->it_interval) ||
7374 host_to_target_timespec(target_addr + offsetof(struct target_itimerspec,
7375 it_value),
7376 &host_its->it_value)) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007377 return -TARGET_EFAULT;
7378 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007379 return 0;
7380}
Alistair Francis859e8a82020-03-12 15:13:49 -07007381#endif
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007382
Filip Bozuta828cb3a2020-07-22 17:34:21 +02007383#if ((defined(TARGET_NR_timerfd_gettime64) || \
7384 defined(TARGET_NR_timerfd_settime64)) && defined(CONFIG_TIMERFD)) || \
7385 defined(TARGET_NR_timer_gettime64) || defined(TARGET_NR_timer_settime64)
7386static inline abi_long host_to_target_itimerspec64(abi_ulong target_addr,
7387 struct itimerspec *host_its)
7388{
7389 if (host_to_target_timespec64(target_addr +
7390 offsetof(struct target__kernel_itimerspec,
7391 it_interval),
7392 &host_its->it_interval) ||
7393 host_to_target_timespec64(target_addr +
7394 offsetof(struct target__kernel_itimerspec,
7395 it_value),
7396 &host_its->it_value)) {
7397 return -TARGET_EFAULT;
7398 }
7399 return 0;
7400}
7401#endif
7402
Alistair Francis859e8a82020-03-12 15:13:49 -07007403#if defined(TARGET_NR_adjtimex) || \
7404 (defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME))
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +02007405static inline abi_long target_to_host_timex(struct timex *host_tx,
7406 abi_long target_addr)
7407{
7408 struct target_timex *target_tx;
7409
7410 if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) {
7411 return -TARGET_EFAULT;
7412 }
7413
7414 __get_user(host_tx->modes, &target_tx->modes);
7415 __get_user(host_tx->offset, &target_tx->offset);
7416 __get_user(host_tx->freq, &target_tx->freq);
7417 __get_user(host_tx->maxerror, &target_tx->maxerror);
7418 __get_user(host_tx->esterror, &target_tx->esterror);
7419 __get_user(host_tx->status, &target_tx->status);
7420 __get_user(host_tx->constant, &target_tx->constant);
7421 __get_user(host_tx->precision, &target_tx->precision);
7422 __get_user(host_tx->tolerance, &target_tx->tolerance);
7423 __get_user(host_tx->time.tv_sec, &target_tx->time.tv_sec);
7424 __get_user(host_tx->time.tv_usec, &target_tx->time.tv_usec);
7425 __get_user(host_tx->tick, &target_tx->tick);
7426 __get_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7427 __get_user(host_tx->jitter, &target_tx->jitter);
7428 __get_user(host_tx->shift, &target_tx->shift);
7429 __get_user(host_tx->stabil, &target_tx->stabil);
7430 __get_user(host_tx->jitcnt, &target_tx->jitcnt);
7431 __get_user(host_tx->calcnt, &target_tx->calcnt);
7432 __get_user(host_tx->errcnt, &target_tx->errcnt);
7433 __get_user(host_tx->stbcnt, &target_tx->stbcnt);
7434 __get_user(host_tx->tai, &target_tx->tai);
7435
7436 unlock_user_struct(target_tx, target_addr, 0);
7437 return 0;
7438}
7439
7440static inline abi_long host_to_target_timex(abi_long target_addr,
7441 struct timex *host_tx)
7442{
7443 struct target_timex *target_tx;
7444
7445 if (!lock_user_struct(VERIFY_WRITE, target_tx, target_addr, 0)) {
7446 return -TARGET_EFAULT;
7447 }
7448
7449 __put_user(host_tx->modes, &target_tx->modes);
7450 __put_user(host_tx->offset, &target_tx->offset);
7451 __put_user(host_tx->freq, &target_tx->freq);
7452 __put_user(host_tx->maxerror, &target_tx->maxerror);
7453 __put_user(host_tx->esterror, &target_tx->esterror);
7454 __put_user(host_tx->status, &target_tx->status);
7455 __put_user(host_tx->constant, &target_tx->constant);
7456 __put_user(host_tx->precision, &target_tx->precision);
7457 __put_user(host_tx->tolerance, &target_tx->tolerance);
7458 __put_user(host_tx->time.tv_sec, &target_tx->time.tv_sec);
7459 __put_user(host_tx->time.tv_usec, &target_tx->time.tv_usec);
7460 __put_user(host_tx->tick, &target_tx->tick);
7461 __put_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7462 __put_user(host_tx->jitter, &target_tx->jitter);
7463 __put_user(host_tx->shift, &target_tx->shift);
7464 __put_user(host_tx->stabil, &target_tx->stabil);
7465 __put_user(host_tx->jitcnt, &target_tx->jitcnt);
7466 __put_user(host_tx->calcnt, &target_tx->calcnt);
7467 __put_user(host_tx->errcnt, &target_tx->errcnt);
7468 __put_user(host_tx->stbcnt, &target_tx->stbcnt);
7469 __put_user(host_tx->tai, &target_tx->tai);
7470
7471 unlock_user_struct(target_tx, target_addr, 1);
7472 return 0;
7473}
Alistair Francis859e8a82020-03-12 15:13:49 -07007474#endif
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +02007475
Filip Bozuta6ac03b22020-08-24 21:21:15 +02007476
7477#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
7478static inline abi_long target_to_host_timex64(struct timex *host_tx,
7479 abi_long target_addr)
7480{
7481 struct target__kernel_timex *target_tx;
7482
7483 if (copy_from_user_timeval64(&host_tx->time, target_addr +
7484 offsetof(struct target__kernel_timex,
7485 time))) {
7486 return -TARGET_EFAULT;
7487 }
7488
7489 if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) {
7490 return -TARGET_EFAULT;
7491 }
7492
7493 __get_user(host_tx->modes, &target_tx->modes);
7494 __get_user(host_tx->offset, &target_tx->offset);
7495 __get_user(host_tx->freq, &target_tx->freq);
7496 __get_user(host_tx->maxerror, &target_tx->maxerror);
7497 __get_user(host_tx->esterror, &target_tx->esterror);
7498 __get_user(host_tx->status, &target_tx->status);
7499 __get_user(host_tx->constant, &target_tx->constant);
7500 __get_user(host_tx->precision, &target_tx->precision);
7501 __get_user(host_tx->tolerance, &target_tx->tolerance);
7502 __get_user(host_tx->tick, &target_tx->tick);
7503 __get_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7504 __get_user(host_tx->jitter, &target_tx->jitter);
7505 __get_user(host_tx->shift, &target_tx->shift);
7506 __get_user(host_tx->stabil, &target_tx->stabil);
7507 __get_user(host_tx->jitcnt, &target_tx->jitcnt);
7508 __get_user(host_tx->calcnt, &target_tx->calcnt);
7509 __get_user(host_tx->errcnt, &target_tx->errcnt);
7510 __get_user(host_tx->stbcnt, &target_tx->stbcnt);
7511 __get_user(host_tx->tai, &target_tx->tai);
7512
7513 unlock_user_struct(target_tx, target_addr, 0);
7514 return 0;
7515}
7516
7517static inline abi_long host_to_target_timex64(abi_long target_addr,
7518 struct timex *host_tx)
7519{
7520 struct target__kernel_timex *target_tx;
7521
7522 if (copy_to_user_timeval64(target_addr +
7523 offsetof(struct target__kernel_timex, time),
7524 &host_tx->time)) {
7525 return -TARGET_EFAULT;
7526 }
7527
7528 if (!lock_user_struct(VERIFY_WRITE, target_tx, target_addr, 0)) {
7529 return -TARGET_EFAULT;
7530 }
7531
7532 __put_user(host_tx->modes, &target_tx->modes);
7533 __put_user(host_tx->offset, &target_tx->offset);
7534 __put_user(host_tx->freq, &target_tx->freq);
7535 __put_user(host_tx->maxerror, &target_tx->maxerror);
7536 __put_user(host_tx->esterror, &target_tx->esterror);
7537 __put_user(host_tx->status, &target_tx->status);
7538 __put_user(host_tx->constant, &target_tx->constant);
7539 __put_user(host_tx->precision, &target_tx->precision);
7540 __put_user(host_tx->tolerance, &target_tx->tolerance);
7541 __put_user(host_tx->tick, &target_tx->tick);
7542 __put_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7543 __put_user(host_tx->jitter, &target_tx->jitter);
7544 __put_user(host_tx->shift, &target_tx->shift);
7545 __put_user(host_tx->stabil, &target_tx->stabil);
7546 __put_user(host_tx->jitcnt, &target_tx->jitcnt);
7547 __put_user(host_tx->calcnt, &target_tx->calcnt);
7548 __put_user(host_tx->errcnt, &target_tx->errcnt);
7549 __put_user(host_tx->stbcnt, &target_tx->stbcnt);
7550 __put_user(host_tx->tai, &target_tx->tai);
7551
7552 unlock_user_struct(target_tx, target_addr, 1);
7553 return 0;
7554}
7555#endif
7556
Michael Forney96ff7582021-05-25 20:55:56 -07007557#ifndef HAVE_SIGEV_NOTIFY_THREAD_ID
7558#define sigev_notify_thread_id _sigev_un._tid
7559#endif
7560
Peter Maydellc0659762014-08-09 15:42:32 +01007561static inline abi_long target_to_host_sigevent(struct sigevent *host_sevp,
7562 abi_ulong target_addr)
7563{
7564 struct target_sigevent *target_sevp;
7565
7566 if (!lock_user_struct(VERIFY_READ, target_sevp, target_addr, 1)) {
7567 return -TARGET_EFAULT;
7568 }
7569
7570 /* This union is awkward on 64 bit systems because it has a 32 bit
7571 * integer and a pointer in it; we follow the conversion approach
7572 * used for handling sigval types in signal.c so the guest should get
7573 * the correct value back even if we did a 64 bit byteswap and it's
7574 * using the 32 bit integer.
7575 */
7576 host_sevp->sigev_value.sival_ptr =
7577 (void *)(uintptr_t)tswapal(target_sevp->sigev_value.sival_ptr);
7578 host_sevp->sigev_signo =
7579 target_to_host_signal(tswap32(target_sevp->sigev_signo));
7580 host_sevp->sigev_notify = tswap32(target_sevp->sigev_notify);
Michael Forney96ff7582021-05-25 20:55:56 -07007581 host_sevp->sigev_notify_thread_id = tswap32(target_sevp->_sigev_un._tid);
Peter Maydellc0659762014-08-09 15:42:32 +01007582
7583 unlock_user_struct(target_sevp, target_addr, 1);
7584 return 0;
7585}
7586
Tom Musta6f6a4032014-08-12 13:53:42 -05007587#if defined(TARGET_NR_mlockall)
7588static inline int target_to_host_mlockall_arg(int arg)
7589{
7590 int result = 0;
7591
Filip Bozuta02e5d7d2020-08-11 18:45:51 +02007592 if (arg & TARGET_MCL_CURRENT) {
Tom Musta6f6a4032014-08-12 13:53:42 -05007593 result |= MCL_CURRENT;
7594 }
Filip Bozuta02e5d7d2020-08-11 18:45:51 +02007595 if (arg & TARGET_MCL_FUTURE) {
Tom Musta6f6a4032014-08-12 13:53:42 -05007596 result |= MCL_FUTURE;
7597 }
Filip Bozuta02e5d7d2020-08-11 18:45:51 +02007598#ifdef MCL_ONFAULT
7599 if (arg & TARGET_MCL_ONFAULT) {
7600 result |= MCL_ONFAULT;
7601 }
7602#endif
7603
Tom Musta6f6a4032014-08-12 13:53:42 -05007604 return result;
7605}
7606#endif
7607
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02007608#if (defined(TARGET_NR_stat64) || defined(TARGET_NR_lstat64) || \
7609 defined(TARGET_NR_fstat64) || defined(TARGET_NR_fstatat64) || \
7610 defined(TARGET_NR_newfstatat))
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02007611static inline abi_long host_to_target_stat64(CPUArchState *cpu_env,
balrog6a24a772008-09-20 02:23:36 +00007612 abi_ulong target_addr,
7613 struct stat *host_st)
7614{
Alexander Graf09701192013-09-03 20:12:15 +01007615#if defined(TARGET_ARM) && defined(TARGET_ABI32)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02007616 if (cpu_env->eabi) {
balrog6a24a772008-09-20 02:23:36 +00007617 struct target_eabi_stat64 *target_st;
7618
7619 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
7620 return -TARGET_EFAULT;
7621 memset(target_st, 0, sizeof(struct target_eabi_stat64));
7622 __put_user(host_st->st_dev, &target_st->st_dev);
7623 __put_user(host_st->st_ino, &target_st->st_ino);
7624#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
7625 __put_user(host_st->st_ino, &target_st->__st_ino);
7626#endif
7627 __put_user(host_st->st_mode, &target_st->st_mode);
7628 __put_user(host_st->st_nlink, &target_st->st_nlink);
7629 __put_user(host_st->st_uid, &target_st->st_uid);
7630 __put_user(host_st->st_gid, &target_st->st_gid);
7631 __put_user(host_st->st_rdev, &target_st->st_rdev);
7632 __put_user(host_st->st_size, &target_st->st_size);
7633 __put_user(host_st->st_blksize, &target_st->st_blksize);
7634 __put_user(host_st->st_blocks, &target_st->st_blocks);
7635 __put_user(host_st->st_atime, &target_st->target_st_atime);
7636 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
7637 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
Michael Forneyfebf6fa2021-05-25 20:55:31 -07007638#ifdef HAVE_STRUCT_STAT_ST_ATIM
Chen-Yu Tsai5f992db2019-05-23 00:21:47 +08007639 __put_user(host_st->st_atim.tv_nsec, &target_st->target_st_atime_nsec);
7640 __put_user(host_st->st_mtim.tv_nsec, &target_st->target_st_mtime_nsec);
7641 __put_user(host_st->st_ctim.tv_nsec, &target_st->target_st_ctime_nsec);
7642#endif
balrog6a24a772008-09-20 02:23:36 +00007643 unlock_user_struct(target_st, target_addr, 1);
7644 } else
7645#endif
7646 {
Stefan Weil20d155b2013-10-30 22:52:24 +01007647#if defined(TARGET_HAS_STRUCT_STAT64)
balrog6a24a772008-09-20 02:23:36 +00007648 struct target_stat64 *target_st;
Stefan Weil20d155b2013-10-30 22:52:24 +01007649#else
7650 struct target_stat *target_st;
aurel329d33b762009-04-08 23:07:05 +00007651#endif
balrog6a24a772008-09-20 02:23:36 +00007652
7653 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
7654 return -TARGET_EFAULT;
aurel329d33b762009-04-08 23:07:05 +00007655 memset(target_st, 0, sizeof(*target_st));
balrog6a24a772008-09-20 02:23:36 +00007656 __put_user(host_st->st_dev, &target_st->st_dev);
7657 __put_user(host_st->st_ino, &target_st->st_ino);
7658#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
7659 __put_user(host_st->st_ino, &target_st->__st_ino);
7660#endif
7661 __put_user(host_st->st_mode, &target_st->st_mode);
7662 __put_user(host_st->st_nlink, &target_st->st_nlink);
7663 __put_user(host_st->st_uid, &target_st->st_uid);
7664 __put_user(host_st->st_gid, &target_st->st_gid);
7665 __put_user(host_st->st_rdev, &target_st->st_rdev);
7666 /* XXX: better use of kernel struct */
7667 __put_user(host_st->st_size, &target_st->st_size);
7668 __put_user(host_st->st_blksize, &target_st->st_blksize);
7669 __put_user(host_st->st_blocks, &target_st->st_blocks);
7670 __put_user(host_st->st_atime, &target_st->target_st_atime);
7671 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
7672 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
Michael Forneyfebf6fa2021-05-25 20:55:31 -07007673#ifdef HAVE_STRUCT_STAT_ST_ATIM
Chen-Yu Tsai5f992db2019-05-23 00:21:47 +08007674 __put_user(host_st->st_atim.tv_nsec, &target_st->target_st_atime_nsec);
7675 __put_user(host_st->st_mtim.tv_nsec, &target_st->target_st_mtime_nsec);
7676 __put_user(host_st->st_ctim.tv_nsec, &target_st->target_st_ctime_nsec);
7677#endif
balrog6a24a772008-09-20 02:23:36 +00007678 unlock_user_struct(target_st, target_addr, 1);
7679 }
7680
7681 return 0;
7682}
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02007683#endif
balrog6a24a772008-09-20 02:23:36 +00007684
Aleksandar Rikaloefa92182019-06-28 12:43:34 +02007685#if defined(TARGET_NR_statx) && defined(__NR_statx)
7686static inline abi_long host_to_target_statx(struct target_statx *host_stx,
7687 abi_ulong target_addr)
7688{
7689 struct target_statx *target_stx;
7690
7691 if (!lock_user_struct(VERIFY_WRITE, target_stx, target_addr, 0)) {
7692 return -TARGET_EFAULT;
7693 }
7694 memset(target_stx, 0, sizeof(*target_stx));
7695
7696 __put_user(host_stx->stx_mask, &target_stx->stx_mask);
7697 __put_user(host_stx->stx_blksize, &target_stx->stx_blksize);
7698 __put_user(host_stx->stx_attributes, &target_stx->stx_attributes);
7699 __put_user(host_stx->stx_nlink, &target_stx->stx_nlink);
7700 __put_user(host_stx->stx_uid, &target_stx->stx_uid);
7701 __put_user(host_stx->stx_gid, &target_stx->stx_gid);
7702 __put_user(host_stx->stx_mode, &target_stx->stx_mode);
7703 __put_user(host_stx->stx_ino, &target_stx->stx_ino);
7704 __put_user(host_stx->stx_size, &target_stx->stx_size);
7705 __put_user(host_stx->stx_blocks, &target_stx->stx_blocks);
7706 __put_user(host_stx->stx_attributes_mask, &target_stx->stx_attributes_mask);
7707 __put_user(host_stx->stx_atime.tv_sec, &target_stx->stx_atime.tv_sec);
7708 __put_user(host_stx->stx_atime.tv_nsec, &target_stx->stx_atime.tv_nsec);
Ariadne Conilld1e26702019-11-22 11:40:40 -06007709 __put_user(host_stx->stx_btime.tv_sec, &target_stx->stx_btime.tv_sec);
7710 __put_user(host_stx->stx_btime.tv_nsec, &target_stx->stx_btime.tv_nsec);
7711 __put_user(host_stx->stx_ctime.tv_sec, &target_stx->stx_ctime.tv_sec);
7712 __put_user(host_stx->stx_ctime.tv_nsec, &target_stx->stx_ctime.tv_nsec);
7713 __put_user(host_stx->stx_mtime.tv_sec, &target_stx->stx_mtime.tv_sec);
7714 __put_user(host_stx->stx_mtime.tv_nsec, &target_stx->stx_mtime.tv_nsec);
Aleksandar Rikaloefa92182019-06-28 12:43:34 +02007715 __put_user(host_stx->stx_rdev_major, &target_stx->stx_rdev_major);
7716 __put_user(host_stx->stx_rdev_minor, &target_stx->stx_rdev_minor);
7717 __put_user(host_stx->stx_dev_major, &target_stx->stx_dev_major);
7718 __put_user(host_stx->stx_dev_minor, &target_stx->stx_dev_minor);
7719
7720 unlock_user_struct(target_stx, target_addr, 1);
7721
7722 return 0;
7723}
7724#endif
7725
Alistair Francis14690292020-03-18 15:47:01 -07007726static int do_sys_futex(int *uaddr, int op, int val,
7727 const struct timespec *timeout, int *uaddr2,
7728 int val3)
7729{
7730#if HOST_LONG_BITS == 64
7731#if defined(__NR_futex)
7732 /* always a 64-bit time_t, it doesn't define _time64 version */
7733 return sys_futex(uaddr, op, val, timeout, uaddr2, val3);
7734
7735#endif
7736#else /* HOST_LONG_BITS == 64 */
7737#if defined(__NR_futex_time64)
7738 if (sizeof(timeout->tv_sec) == 8) {
7739 /* _time64 function on 32bit arch */
7740 return sys_futex_time64(uaddr, op, val, timeout, uaddr2, val3);
7741 }
7742#endif
7743#if defined(__NR_futex)
7744 /* old function on 32bit arch */
7745 return sys_futex(uaddr, op, val, timeout, uaddr2, val3);
7746#endif
7747#endif /* HOST_LONG_BITS == 64 */
7748 g_assert_not_reached();
7749}
7750
7751static int do_safe_futex(int *uaddr, int op, int val,
7752 const struct timespec *timeout, int *uaddr2,
7753 int val3)
7754{
7755#if HOST_LONG_BITS == 64
7756#if defined(__NR_futex)
7757 /* always a 64-bit time_t, it doesn't define _time64 version */
7758 return get_errno(safe_futex(uaddr, op, val, timeout, uaddr2, val3));
7759#endif
7760#else /* HOST_LONG_BITS == 64 */
7761#if defined(__NR_futex_time64)
7762 if (sizeof(timeout->tv_sec) == 8) {
7763 /* _time64 function on 32bit arch */
7764 return get_errno(safe_futex_time64(uaddr, op, val, timeout, uaddr2,
7765 val3));
7766 }
7767#endif
7768#if defined(__NR_futex)
7769 /* old function on 32bit arch */
7770 return get_errno(safe_futex(uaddr, op, val, timeout, uaddr2, val3));
7771#endif
7772#endif /* HOST_LONG_BITS == 64 */
7773 return -TARGET_ENOSYS;
7774}
Aleksandar Rikaloefa92182019-06-28 12:43:34 +02007775
pbrookbd0c5662008-05-29 14:34:11 +00007776/* ??? Using host futex calls even when target atomic operations
7777 are not really atomic probably breaks things. However implementing
7778 futexes locally would make futexes shared between multiple processes
7779 tricky. However they're probably useless because guest atomic
7780 operations won't work either. */
Richard Henderson0fbc0f82022-08-28 19:09:59 -07007781#if defined(TARGET_NR_futex) || defined(TARGET_NR_futex_time64)
7782static int do_futex(CPUState *cpu, bool time64, target_ulong uaddr,
7783 int op, int val, target_ulong timeout,
7784 target_ulong uaddr2, int val3)
pbrookbd0c5662008-05-29 14:34:11 +00007785{
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007786 struct timespec ts, *pts = NULL;
7787 void *haddr2 = NULL;
Nathan Froyda16aae02009-08-03 08:43:29 -07007788 int base_op;
pbrookbd0c5662008-05-29 14:34:11 +00007789
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007790 /* We assume FUTEX_* constants are the same on both host and target. */
Martin Mohringa29ccd62009-05-04 21:34:56 +03007791#ifdef FUTEX_CMD_MASK
Nathan Froyda16aae02009-08-03 08:43:29 -07007792 base_op = op & FUTEX_CMD_MASK;
Martin Mohringa29ccd62009-05-04 21:34:56 +03007793#else
Nathan Froyda16aae02009-08-03 08:43:29 -07007794 base_op = op;
Martin Mohringa29ccd62009-05-04 21:34:56 +03007795#endif
Nathan Froyda16aae02009-08-03 08:43:29 -07007796 switch (base_op) {
pbrookbd0c5662008-05-29 14:34:11 +00007797 case FUTEX_WAIT:
John Rigbycce246e2013-02-23 16:14:07 -07007798 case FUTEX_WAIT_BITSET:
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007799 val = tswap32(val);
7800 break;
Richard Hendersonc72a90d2022-08-28 19:10:03 -07007801 case FUTEX_WAIT_REQUEUE_PI:
7802 val = tswap32(val);
7803 haddr2 = g2h(cpu, uaddr2);
7804 break;
7805 case FUTEX_LOCK_PI:
7806 case FUTEX_LOCK_PI2:
7807 break;
pbrookbd0c5662008-05-29 14:34:11 +00007808 case FUTEX_WAKE:
Richard Hendersona6180f82022-08-28 19:10:01 -07007809 case FUTEX_WAKE_BITSET:
Richard Hendersonc72a90d2022-08-28 19:10:03 -07007810 case FUTEX_TRYLOCK_PI:
7811 case FUTEX_UNLOCK_PI:
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007812 timeout = 0;
7813 break;
pbrookbd0c5662008-05-29 14:34:11 +00007814 case FUTEX_FD:
Richard Henderson0f946732022-08-28 19:10:02 -07007815 val = target_to_host_signal(val);
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007816 timeout = 0;
7817 break;
pbrookbd0c5662008-05-29 14:34:11 +00007818 case FUTEX_CMP_REQUEUE:
Richard Hendersonc72a90d2022-08-28 19:10:03 -07007819 case FUTEX_CMP_REQUEUE_PI:
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007820 val3 = tswap32(val3);
7821 /* fall through */
7822 case FUTEX_REQUEUE:
Nathan Froyda16aae02009-08-03 08:43:29 -07007823 case FUTEX_WAKE_OP:
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007824 /*
7825 * For these, the 4th argument is not TIMEOUT, but VAL2.
7826 * But the prototype of do_safe_futex takes a pointer, so
7827 * insert casts to satisfy the compiler. We do not need
7828 * to tswap VAL2 since it's not compared to guest memory.
7829 */
7830 pts = (struct timespec *)(uintptr_t)timeout;
7831 timeout = 0;
7832 haddr2 = g2h(cpu, uaddr2);
7833 break;
pbrookbd0c5662008-05-29 14:34:11 +00007834 default:
7835 return -TARGET_ENOSYS;
7836 }
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007837 if (timeout) {
7838 pts = &ts;
7839 if (time64
7840 ? target_to_host_timespec64(pts, timeout)
7841 : target_to_host_timespec(pts, timeout)) {
7842 return -TARGET_EFAULT;
7843 }
7844 }
7845 return do_safe_futex(g2h(cpu, uaddr), op, val, pts, haddr2, val3);
pbrookbd0c5662008-05-29 14:34:11 +00007846}
Alistair Francis859e8a82020-03-12 15:13:49 -07007847#endif
Alistair Francis14690292020-03-18 15:47:01 -07007848
Laurent Vivier0f0426f2015-09-01 22:27:33 +02007849#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
7850static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname,
7851 abi_long handle, abi_long mount_id,
7852 abi_long flags)
7853{
7854 struct file_handle *target_fh;
7855 struct file_handle *fh;
7856 int mid = 0;
7857 abi_long ret;
7858 char *name;
7859 unsigned int size, total_size;
7860
7861 if (get_user_s32(size, handle)) {
7862 return -TARGET_EFAULT;
7863 }
7864
7865 name = lock_user_string(pathname);
7866 if (!name) {
7867 return -TARGET_EFAULT;
7868 }
7869
7870 total_size = sizeof(struct file_handle) + size;
7871 target_fh = lock_user(VERIFY_WRITE, handle, total_size, 0);
7872 if (!target_fh) {
7873 unlock_user(name, pathname, 0);
7874 return -TARGET_EFAULT;
7875 }
7876
7877 fh = g_malloc0(total_size);
7878 fh->handle_bytes = size;
7879
7880 ret = get_errno(name_to_handle_at(dirfd, path(name), fh, &mid, flags));
7881 unlock_user(name, pathname, 0);
7882
7883 /* man name_to_handle_at(2):
7884 * Other than the use of the handle_bytes field, the caller should treat
7885 * the file_handle structure as an opaque data type
7886 */
7887
7888 memcpy(target_fh, fh, total_size);
7889 target_fh->handle_bytes = tswap32(fh->handle_bytes);
7890 target_fh->handle_type = tswap32(fh->handle_type);
7891 g_free(fh);
7892 unlock_user(target_fh, handle, total_size);
7893
7894 if (put_user_s32(mid, mount_id)) {
7895 return -TARGET_EFAULT;
7896 }
7897
7898 return ret;
7899
7900}
7901#endif
7902
7903#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
7904static abi_long do_open_by_handle_at(abi_long mount_fd, abi_long handle,
7905 abi_long flags)
7906{
7907 struct file_handle *target_fh;
7908 struct file_handle *fh;
7909 unsigned int size, total_size;
7910 abi_long ret;
7911
7912 if (get_user_s32(size, handle)) {
7913 return -TARGET_EFAULT;
7914 }
7915
7916 total_size = sizeof(struct file_handle) + size;
7917 target_fh = lock_user(VERIFY_READ, handle, total_size, 1);
7918 if (!target_fh) {
7919 return -TARGET_EFAULT;
7920 }
7921
Thomas Huthe9d49d52015-10-09 17:56:38 +02007922 fh = g_memdup(target_fh, total_size);
Laurent Vivier0f0426f2015-09-01 22:27:33 +02007923 fh->handle_bytes = size;
7924 fh->handle_type = tswap32(target_fh->handle_type);
7925
7926 ret = get_errno(open_by_handle_at(mount_fd, fh,
7927 target_to_host_bitmask(flags, fcntl_flags_tbl)));
7928
7929 g_free(fh);
7930
7931 unlock_user(target_fh, handle, total_size);
7932
7933 return ret;
7934}
7935#endif
pbrookbd0c5662008-05-29 14:34:11 +00007936
Laurent Viviere36800c2015-10-02 14:48:09 +02007937#if defined(TARGET_NR_signalfd) || defined(TARGET_NR_signalfd4)
7938
Laurent Viviere36800c2015-10-02 14:48:09 +02007939static abi_long do_signalfd4(int fd, abi_long mask, int flags)
7940{
7941 int host_flags;
7942 target_sigset_t *target_mask;
7943 sigset_t host_mask;
7944 abi_long ret;
7945
Helge Deller78721302021-02-10 07:12:14 +01007946 if (flags & ~(TARGET_O_NONBLOCK_MASK | TARGET_O_CLOEXEC)) {
Laurent Viviere36800c2015-10-02 14:48:09 +02007947 return -TARGET_EINVAL;
7948 }
7949 if (!lock_user_struct(VERIFY_READ, target_mask, mask, 1)) {
7950 return -TARGET_EFAULT;
7951 }
7952
7953 target_to_host_sigset(&host_mask, target_mask);
7954
7955 host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
7956
7957 ret = get_errno(signalfd(fd, &host_mask, host_flags));
7958 if (ret >= 0) {
7959 fd_trans_register(ret, &target_signalfd_trans);
7960 }
7961
7962 unlock_user_struct(target_mask, mask, 0);
7963
7964 return ret;
7965}
7966#endif
7967
pbrook1d9d8b52009-04-16 15:17:02 +00007968/* Map host to target signal numbers for the wait family of syscalls.
7969 Assume all other status bits are the same. */
Richard Hendersona05c6402012-09-15 11:34:20 -07007970int host_to_target_waitstatus(int status)
pbrook1d9d8b52009-04-16 15:17:02 +00007971{
7972 if (WIFSIGNALED(status)) {
7973 return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
7974 }
7975 if (WIFSTOPPED(status)) {
7976 return (host_to_target_signal(WSTOPSIG(status)) << 8)
7977 | (status & 0xff);
7978 }
7979 return status;
7980}
7981
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02007982static int open_self_cmdline(CPUArchState *cpu_env, int fd)
Wim Vander Schelden76b94242014-06-18 11:02:39 +02007983{
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02007984 CPUState *cpu = env_cpu(cpu_env);
Andreas Schwab58de8b92017-03-20 12:31:55 +01007985 struct linux_binprm *bprm = ((TaskState *)cpu->opaque)->bprm;
7986 int i;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02007987
Andreas Schwab58de8b92017-03-20 12:31:55 +01007988 for (i = 0; i < bprm->argc; i++) {
7989 size_t len = strlen(bprm->argv[i]) + 1;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02007990
Andreas Schwab58de8b92017-03-20 12:31:55 +01007991 if (write(fd, bprm->argv[i], len) != len) {
Wim Vander Schelden76b94242014-06-18 11:02:39 +02007992 return -1;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02007993 }
7994 }
7995
Andreas Schwab58de8b92017-03-20 12:31:55 +01007996 return 0;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02007997}
7998
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02007999static int open_self_maps(CPUArchState *cpu_env, int fd)
Alexander Graf36c08d42011-11-02 20:23:24 +01008000{
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02008001 CPUState *cpu = env_cpu(cpu_env);
Andreas Färber0429a972013-08-26 18:14:44 +02008002 TaskState *ts = cpu->opaque;
Alex Bennée01ef6b92020-04-03 20:11:46 +01008003 GSList *map_info = read_self_maps();
8004 GSList *s;
Alex Bennéebb551732020-04-03 20:11:47 +01008005 int count;
Alexander Graf36c08d42011-11-02 20:23:24 +01008006
Alex Bennée01ef6b92020-04-03 20:11:46 +01008007 for (s = map_info; s; s = g_slist_next(s)) {
8008 MapInfo *e = (MapInfo *) s->data;
Alexander Graf1a49ef22012-05-01 16:30:28 +01008009
Alex Bennée01ef6b92020-04-03 20:11:46 +01008010 if (h2g_valid(e->start)) {
8011 unsigned long min = e->start;
8012 unsigned long max = e->end;
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04008013 int flags = page_get_flags(h2g(min));
Alex Bennée01ef6b92020-04-03 20:11:46 +01008014 const char *path;
8015
8016 max = h2g_valid(max - 1) ?
Richard Henderson3e8f1622021-02-12 10:48:43 -08008017 max : (uintptr_t) g2h_untagged(GUEST_ADDR_MAX) + 1;
Alex Bennée01ef6b92020-04-03 20:11:46 +01008018
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04008019 if (page_check_range(h2g(min), max - min, flags) == -1) {
8020 continue;
8021 }
Alex Bennée01ef6b92020-04-03 20:11:46 +01008022
Helge Deller0a3346b2022-09-24 13:44:59 +02008023#ifdef TARGET_HPPA
8024 if (h2g(max) == ts->info->stack_limit) {
8025#else
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04008026 if (h2g(min) == ts->info->stack_limit) {
Helge Deller0a3346b2022-09-24 13:44:59 +02008027#endif
Alex Bennéebb551732020-04-03 20:11:47 +01008028 path = "[stack]";
Alex Bennée01ef6b92020-04-03 20:11:46 +01008029 } else {
8030 path = e->path;
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04008031 }
Alex Bennée01ef6b92020-04-03 20:11:46 +01008032
Alex Bennéebb551732020-04-03 20:11:47 +01008033 count = dprintf(fd, TARGET_ABI_FMT_ptr "-" TARGET_ABI_FMT_ptr
8034 " %c%c%c%c %08" PRIx64 " %s %"PRId64,
8035 h2g(min), h2g(max - 1) + 1,
Nicolas Surbayrole08f3a962021-03-08 10:19:59 +01008036 (flags & PAGE_READ) ? 'r' : '-',
8037 (flags & PAGE_WRITE_ORG) ? 'w' : '-',
8038 (flags & PAGE_EXEC) ? 'x' : '-',
Andrey Kazmine13685a2021-12-27 15:50:48 +03008039 e->is_priv ? 'p' : 's',
Alex Bennéebb551732020-04-03 20:11:47 +01008040 (uint64_t) e->offset, e->dev, e->inode);
8041 if (path) {
8042 dprintf(fd, "%*s%s\n", 73 - count, "", path);
8043 } else {
8044 dprintf(fd, "\n");
8045 }
Alexander Graf1a49ef22012-05-01 16:30:28 +01008046 }
8047 }
8048
Alex Bennée01ef6b92020-04-03 20:11:46 +01008049 free_self_maps(map_info);
8050
Richard Hendersonbf02adc2020-02-12 19:22:22 -08008051#ifdef TARGET_VSYSCALL_PAGE
8052 /*
8053 * We only support execution from the vsyscall page.
8054 * This is as if CONFIG_LEGACY_VSYSCALL_XONLY=y from v5.3.
8055 */
Alex Bennéebb551732020-04-03 20:11:47 +01008056 count = dprintf(fd, TARGET_FMT_lx "-" TARGET_FMT_lx
8057 " --xp 00000000 00:00 0",
8058 TARGET_VSYSCALL_PAGE, TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE);
8059 dprintf(fd, "%*s%s\n", 73 - count, "", "[vsyscall]");
Richard Hendersonbf02adc2020-02-12 19:22:22 -08008060#endif
8061
Alexander Graf36c08d42011-11-02 20:23:24 +01008062 return 0;
8063}
8064
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008065static int open_self_stat(CPUArchState *cpu_env, int fd)
Alexander Graf480b8e72011-11-02 20:23:25 +01008066{
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02008067 CPUState *cpu = env_cpu(cpu_env);
Andreas Färber0429a972013-08-26 18:14:44 +02008068 TaskState *ts = cpu->opaque;
Alex Bennée7ad4d5a2020-04-14 21:06:23 +01008069 g_autoptr(GString) buf = g_string_new(NULL);
Alexander Graf480b8e72011-11-02 20:23:25 +01008070 int i;
8071
8072 for (i = 0; i < 44; i++) {
Alex Bennée7ad4d5a2020-04-14 21:06:23 +01008073 if (i == 0) {
8074 /* pid */
8075 g_string_printf(buf, FMT_pid " ", getpid());
8076 } else if (i == 1) {
8077 /* app name */
8078 gchar *bin = g_strrstr(ts->bprm->argv[0], "/");
8079 bin = bin ? bin + 1 : ts->bprm->argv[0];
8080 g_string_printf(buf, "(%.15s) ", bin);
Andreas Schwab7aa9fe32021-06-21 11:32:59 +02008081 } else if (i == 3) {
8082 /* ppid */
8083 g_string_printf(buf, FMT_pid " ", getppid());
Cameron Esfahanieb33cda2022-01-27 16:12:51 -08008084 } else if (i == 21) {
8085 /* starttime */
8086 g_string_printf(buf, "%" PRIu64 " ", ts->start_boottime);
Alex Bennée7ad4d5a2020-04-14 21:06:23 +01008087 } else if (i == 27) {
8088 /* stack bottom */
8089 g_string_printf(buf, TARGET_ABI_FMT_ld " ", ts->info->start_stack);
8090 } else {
8091 /* for the rest, there is MasterCard */
8092 g_string_printf(buf, "0%c", i == 43 ? '\n' : ' ');
8093 }
Alexander Graf480b8e72011-11-02 20:23:25 +01008094
Alex Bennée7ad4d5a2020-04-14 21:06:23 +01008095 if (write(fd, buf->str, buf->len) != buf->len) {
8096 return -1;
8097 }
Alexander Graf480b8e72011-11-02 20:23:25 +01008098 }
8099
8100 return 0;
8101}
8102
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008103static int open_self_auxv(CPUArchState *cpu_env, int fd)
Alexander Graf257450e2011-11-02 20:23:26 +01008104{
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02008105 CPUState *cpu = env_cpu(cpu_env);
Andreas Färber0429a972013-08-26 18:14:44 +02008106 TaskState *ts = cpu->opaque;
Alexander Graf257450e2011-11-02 20:23:26 +01008107 abi_ulong auxv = ts->info->saved_auxv;
8108 abi_ulong len = ts->info->auxv_len;
8109 char *ptr;
8110
8111 /*
8112 * Auxiliary vector is stored in target process stack.
8113 * read in whole auxv vector and copy it to file
8114 */
8115 ptr = lock_user(VERIFY_READ, auxv, len, 0);
8116 if (ptr != NULL) {
8117 while (len > 0) {
8118 ssize_t r;
8119 r = write(fd, ptr, len);
8120 if (r <= 0) {
8121 break;
8122 }
8123 len -= r;
8124 ptr += r;
8125 }
8126 lseek(fd, 0, SEEK_SET);
8127 unlock_user(ptr, auxv, len);
8128 }
8129
8130 return 0;
8131}
8132
Andreas Schwab463d8e72013-07-02 14:04:12 +01008133static int is_proc_myself(const char *filename, const char *entry)
8134{
8135 if (!strncmp(filename, "/proc/", strlen("/proc/"))) {
8136 filename += strlen("/proc/");
8137 if (!strncmp(filename, "self/", strlen("self/"))) {
8138 filename += strlen("self/");
8139 } else if (*filename >= '1' && *filename <= '9') {
8140 char myself[80];
8141 snprintf(myself, sizeof(myself), "%d/", getpid());
8142 if (!strncmp(filename, myself, strlen(myself))) {
8143 filename += strlen(myself);
8144 } else {
8145 return 0;
8146 }
8147 } else {
8148 return 0;
8149 }
8150 if (!strcmp(filename, entry)) {
8151 return 1;
8152 }
8153 }
8154 return 0;
8155}
8156
Helge Dellerbd5ccd62022-10-24 22:18:09 +02008157static void excp_dump_file(FILE *logfile, CPUArchState *env,
8158 const char *fmt, int code)
8159{
8160 if (logfile) {
8161 CPUState *cs = env_cpu(env);
8162
8163 fprintf(logfile, fmt, code);
8164 fprintf(logfile, "Failing executable: %s\n", exec_path);
8165 cpu_dump_state(cs, logfile, 0);
8166 open_self_maps(env, fileno(logfile));
8167 }
8168}
8169
8170void target_exception_dump(CPUArchState *env, const char *fmt, int code)
8171{
8172 /* dump to console */
8173 excp_dump_file(stderr, env, fmt, code);
8174
8175 /* dump to log file */
8176 if (qemu_log_separate()) {
8177 FILE *logfile = qemu_log_trylock();
8178
8179 excp_dump_file(logfile, env, fmt, code);
8180 qemu_log_unlock(logfile);
8181 }
8182}
8183
Marc-André Lureauee3eb3a2022-03-23 19:57:18 +04008184#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN || \
Helge Deller93a56612020-04-24 23:06:48 +02008185 defined(TARGET_SPARC) || defined(TARGET_M68K) || defined(TARGET_HPPA)
Laurent Vivierde6b9932013-08-30 01:46:40 +02008186static int is_proc(const char *filename, const char *entry)
8187{
8188 return strcmp(filename, entry) == 0;
8189}
Laurent Vivierfff69382019-05-17 15:31:48 +02008190#endif
Laurent Vivierde6b9932013-08-30 01:46:40 +02008191
Marc-André Lureauee3eb3a2022-03-23 19:57:18 +04008192#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008193static int open_net_route(CPUArchState *cpu_env, int fd)
Laurent Vivierde6b9932013-08-30 01:46:40 +02008194{
8195 FILE *fp;
8196 char *line = NULL;
8197 size_t len = 0;
8198 ssize_t read;
8199
8200 fp = fopen("/proc/net/route", "r");
8201 if (fp == NULL) {
Peter Maydella3ca7bb2016-05-12 18:47:26 +01008202 return -1;
Laurent Vivierde6b9932013-08-30 01:46:40 +02008203 }
8204
8205 /* read header */
8206
8207 read = getline(&line, &len, fp);
8208 dprintf(fd, "%s", line);
8209
8210 /* read routes */
8211
8212 while ((read = getline(&line, &len, fp)) != -1) {
8213 char iface[16];
8214 uint32_t dest, gw, mask;
8215 unsigned int flags, refcnt, use, metric, mtu, window, irtt;
Peter Maydell9d0bd0c2019-02-05 17:42:07 +00008216 int fields;
8217
8218 fields = sscanf(line,
8219 "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
8220 iface, &dest, &gw, &flags, &refcnt, &use, &metric,
8221 &mask, &mtu, &window, &irtt);
8222 if (fields != 11) {
8223 continue;
8224 }
Laurent Vivierde6b9932013-08-30 01:46:40 +02008225 dprintf(fd, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
8226 iface, tswap32(dest), tswap32(gw), flags, refcnt, use,
8227 metric, tswap32(mask), mtu, window, irtt);
8228 }
8229
8230 free(line);
8231 fclose(fp);
8232
8233 return 0;
8234}
8235#endif
8236
Laurent Vivierfff69382019-05-17 15:31:48 +02008237#if defined(TARGET_SPARC)
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008238static int open_cpuinfo(CPUArchState *cpu_env, int fd)
Laurent Vivierfff69382019-05-17 15:31:48 +02008239{
8240 dprintf(fd, "type\t\t: sun4u\n");
8241 return 0;
8242}
8243#endif
8244
Helge Deller93a56612020-04-24 23:06:48 +02008245#if defined(TARGET_HPPA)
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008246static int open_cpuinfo(CPUArchState *cpu_env, int fd)
Helge Deller93a56612020-04-24 23:06:48 +02008247{
Helge Dellere0174af2023-01-27 21:10:49 +01008248 int i, num_cpus;
8249
8250 num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
8251 for (i = 0; i < num_cpus; i++) {
8252 dprintf(fd, "processor\t: %d\n", i);
8253 dprintf(fd, "cpu family\t: PA-RISC 1.1e\n");
8254 dprintf(fd, "cpu\t\t: PA7300LC (PCX-L2)\n");
8255 dprintf(fd, "capabilities\t: os32\n");
8256 dprintf(fd, "model\t\t: 9000/778/B160L - "
8257 "Merlin L2 160 QEMU (9000/778/B160L)\n\n");
8258 }
Helge Deller93a56612020-04-24 23:06:48 +02008259 return 0;
8260}
8261#endif
8262
Laurent Vivier4ab67132019-05-17 15:31:49 +02008263#if defined(TARGET_M68K)
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008264static int open_hardware(CPUArchState *cpu_env, int fd)
Laurent Vivier4ab67132019-05-17 15:31:49 +02008265{
8266 dprintf(fd, "Model:\t\tqemu-m68k\n");
8267 return 0;
8268}
8269#endif
8270
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008271static int do_openat(CPUArchState *cpu_env, int dirfd, const char *pathname, int flags, mode_t mode)
Alexander Graf3be14d02011-11-02 20:23:23 +01008272{
8273 struct fake_open {
8274 const char *filename;
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008275 int (*fill)(CPUArchState *cpu_env, int fd);
Laurent Vivierde6b9932013-08-30 01:46:40 +02008276 int (*cmp)(const char *s1, const char *s2);
Alexander Graf3be14d02011-11-02 20:23:23 +01008277 };
8278 const struct fake_open *fake_open;
8279 static const struct fake_open fakes[] = {
Laurent Vivierde6b9932013-08-30 01:46:40 +02008280 { "maps", open_self_maps, is_proc_myself },
8281 { "stat", open_self_stat, is_proc_myself },
8282 { "auxv", open_self_auxv, is_proc_myself },
Wim Vander Schelden76b94242014-06-18 11:02:39 +02008283 { "cmdline", open_self_cmdline, is_proc_myself },
Marc-André Lureauee3eb3a2022-03-23 19:57:18 +04008284#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN
Laurent Vivierde6b9932013-08-30 01:46:40 +02008285 { "/proc/net/route", open_net_route, is_proc },
8286#endif
Helge Deller93a56612020-04-24 23:06:48 +02008287#if defined(TARGET_SPARC) || defined(TARGET_HPPA)
Laurent Vivierfff69382019-05-17 15:31:48 +02008288 { "/proc/cpuinfo", open_cpuinfo, is_proc },
8289#endif
Laurent Vivier4ab67132019-05-17 15:31:49 +02008290#if defined(TARGET_M68K)
8291 { "/proc/hardware", open_hardware, is_proc },
8292#endif
Laurent Vivierde6b9932013-08-30 01:46:40 +02008293 { NULL, NULL, NULL }
Alexander Graf3be14d02011-11-02 20:23:23 +01008294 };
8295
Maxim Ostapenkoaa07f5e2014-05-02 11:17:07 +03008296 if (is_proc_myself(pathname, "exe")) {
Laurent Vivier00ed8a32022-09-27 14:43:57 +02008297 return safe_openat(dirfd, exec_path, flags, mode);
Maxim Ostapenkoaa07f5e2014-05-02 11:17:07 +03008298 }
8299
Alexander Graf3be14d02011-11-02 20:23:23 +01008300 for (fake_open = fakes; fake_open->filename; fake_open++) {
Laurent Vivierde6b9932013-08-30 01:46:40 +02008301 if (fake_open->cmp(pathname, fake_open->filename)) {
Alexander Graf3be14d02011-11-02 20:23:23 +01008302 break;
8303 }
8304 }
8305
8306 if (fake_open->filename) {
8307 const char *tmpdir;
8308 char filename[PATH_MAX];
8309 int fd, r;
8310
Rainer Müller5b63de62022-07-29 17:49:51 +02008311 fd = memfd_create("qemu-open", 0);
Alexander Graf3be14d02011-11-02 20:23:23 +01008312 if (fd < 0) {
Rainer Müller5b63de62022-07-29 17:49:51 +02008313 if (errno != ENOSYS) {
8314 return fd;
8315 }
8316 /* create temporary file to map stat to */
8317 tmpdir = getenv("TMPDIR");
8318 if (!tmpdir)
8319 tmpdir = "/tmp";
8320 snprintf(filename, sizeof(filename), "%s/qemu-open.XXXXXX", tmpdir);
8321 fd = mkstemp(filename);
8322 if (fd < 0) {
8323 return fd;
8324 }
8325 unlink(filename);
Alexander Graf3be14d02011-11-02 20:23:23 +01008326 }
Alexander Graf3be14d02011-11-02 20:23:23 +01008327
8328 if ((r = fake_open->fill(cpu_env, fd))) {
Peter Maydella3ca7bb2016-05-12 18:47:26 +01008329 int e = errno;
Alexander Graf3be14d02011-11-02 20:23:23 +01008330 close(fd);
Peter Maydella3ca7bb2016-05-12 18:47:26 +01008331 errno = e;
Alexander Graf3be14d02011-11-02 20:23:23 +01008332 return r;
8333 }
8334 lseek(fd, 0, SEEK_SET);
8335
8336 return fd;
8337 }
8338
Timothy E Baldwinc10a0732016-05-12 18:47:48 +01008339 return safe_openat(dirfd, path(pathname), flags, mode);
Alexander Graf3be14d02011-11-02 20:23:23 +01008340}
8341
Drew DeVault55bbe4d2022-11-04 18:36:32 +01008342static int do_execveat(CPUArchState *cpu_env, int dirfd,
Drew DeVault156e1f62022-11-04 18:36:31 +01008343 abi_long pathname, abi_long guest_argp,
Drew DeVault55bbe4d2022-11-04 18:36:32 +01008344 abi_long guest_envp, int flags)
Drew DeVault156e1f62022-11-04 18:36:31 +01008345{
8346 int ret;
8347 char **argp, **envp;
8348 int argc, envc;
8349 abi_ulong gp;
8350 abi_ulong addr;
8351 char **q;
8352 void *p;
8353
8354 argc = 0;
8355
8356 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
8357 if (get_user_ual(addr, gp)) {
8358 return -TARGET_EFAULT;
8359 }
8360 if (!addr) {
8361 break;
8362 }
8363 argc++;
8364 }
8365 envc = 0;
8366 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
8367 if (get_user_ual(addr, gp)) {
8368 return -TARGET_EFAULT;
8369 }
8370 if (!addr) {
8371 break;
8372 }
8373 envc++;
8374 }
8375
8376 argp = g_new0(char *, argc + 1);
8377 envp = g_new0(char *, envc + 1);
8378
8379 for (gp = guest_argp, q = argp; gp; gp += sizeof(abi_ulong), q++) {
8380 if (get_user_ual(addr, gp)) {
8381 goto execve_efault;
8382 }
8383 if (!addr) {
8384 break;
8385 }
8386 *q = lock_user_string(addr);
8387 if (!*q) {
8388 goto execve_efault;
8389 }
8390 }
8391 *q = NULL;
8392
8393 for (gp = guest_envp, q = envp; gp; gp += sizeof(abi_ulong), q++) {
8394 if (get_user_ual(addr, gp)) {
8395 goto execve_efault;
8396 }
8397 if (!addr) {
8398 break;
8399 }
8400 *q = lock_user_string(addr);
8401 if (!*q) {
8402 goto execve_efault;
8403 }
8404 }
8405 *q = NULL;
8406
8407 /*
8408 * Although execve() is not an interruptible syscall it is
8409 * a special case where we must use the safe_syscall wrapper:
8410 * if we allow a signal to happen before we make the host
8411 * syscall then we will 'lose' it, because at the point of
8412 * execve the process leaves QEMU's control. So we use the
8413 * safe syscall wrapper to ensure that we either take the
8414 * signal as a guest signal, or else it does not happen
8415 * before the execve completes and makes it the other
8416 * program's problem.
8417 */
8418 p = lock_user_string(pathname);
8419 if (!p) {
8420 goto execve_efault;
8421 }
8422
8423 if (is_proc_myself(p, "exe")) {
Drew DeVault55bbe4d2022-11-04 18:36:32 +01008424 ret = get_errno(safe_execveat(dirfd, exec_path, argp, envp, flags));
Drew DeVault156e1f62022-11-04 18:36:31 +01008425 } else {
Drew DeVault55bbe4d2022-11-04 18:36:32 +01008426 ret = get_errno(safe_execveat(dirfd, p, argp, envp, flags));
Drew DeVault156e1f62022-11-04 18:36:31 +01008427 }
8428
8429 unlock_user(p, pathname, 0);
8430
8431 goto execve_end;
8432
8433execve_efault:
8434 ret = -TARGET_EFAULT;
8435
8436execve_end:
8437 for (gp = guest_argp, q = argp; *q; gp += sizeof(abi_ulong), q++) {
8438 if (get_user_ual(addr, gp) || !addr) {
8439 break;
8440 }
8441 unlock_user(*q, addr, 0);
8442 }
8443 for (gp = guest_envp, q = envp; *q; gp += sizeof(abi_ulong), q++) {
8444 if (get_user_ual(addr, gp) || !addr) {
8445 break;
8446 }
8447 unlock_user(*q, addr, 0);
8448 }
8449
8450 g_free(argp);
8451 g_free(envp);
8452 return ret;
8453}
8454
Alexander Grafaecc8862014-11-10 21:33:03 +01008455#define TIMER_MAGIC 0x0caf0000
8456#define TIMER_MAGIC_MASK 0xffff0000
8457
8458/* Convert QEMU provided timer ID back to internal 16bit index format */
8459static target_timer_t get_timer_id(abi_long arg)
8460{
8461 target_timer_t timerid = arg;
8462
8463 if ((timerid & TIMER_MAGIC_MASK) != TIMER_MAGIC) {
8464 return -TARGET_EINVAL;
8465 }
8466
8467 timerid &= 0xffff;
8468
8469 if (timerid >= ARRAY_SIZE(g_posix_timers)) {
8470 return -TARGET_EINVAL;
8471 }
8472
8473 return timerid;
8474}
8475
Samuel Thibault2e0a8712018-01-09 21:16:43 +01008476static int target_to_host_cpu_mask(unsigned long *host_mask,
8477 size_t host_size,
8478 abi_ulong target_addr,
8479 size_t target_size)
8480{
8481 unsigned target_bits = sizeof(abi_ulong) * 8;
8482 unsigned host_bits = sizeof(*host_mask) * 8;
8483 abi_ulong *target_mask;
8484 unsigned i, j;
8485
8486 assert(host_size >= target_size);
8487
8488 target_mask = lock_user(VERIFY_READ, target_addr, target_size, 1);
8489 if (!target_mask) {
8490 return -TARGET_EFAULT;
8491 }
8492 memset(host_mask, 0, host_size);
8493
8494 for (i = 0 ; i < target_size / sizeof(abi_ulong); i++) {
8495 unsigned bit = i * target_bits;
8496 abi_ulong val;
8497
8498 __get_user(val, &target_mask[i]);
8499 for (j = 0; j < target_bits; j++, bit++) {
8500 if (val & (1UL << j)) {
8501 host_mask[bit / host_bits] |= 1UL << (bit % host_bits);
8502 }
8503 }
8504 }
8505
8506 unlock_user(target_mask, target_addr, 0);
8507 return 0;
8508}
8509
8510static int host_to_target_cpu_mask(const unsigned long *host_mask,
8511 size_t host_size,
8512 abi_ulong target_addr,
8513 size_t target_size)
8514{
8515 unsigned target_bits = sizeof(abi_ulong) * 8;
8516 unsigned host_bits = sizeof(*host_mask) * 8;
8517 abi_ulong *target_mask;
8518 unsigned i, j;
8519
8520 assert(host_size >= target_size);
8521
8522 target_mask = lock_user(VERIFY_WRITE, target_addr, target_size, 0);
8523 if (!target_mask) {
8524 return -TARGET_EFAULT;
8525 }
8526
8527 for (i = 0 ; i < target_size / sizeof(abi_ulong); i++) {
8528 unsigned bit = i * target_bits;
8529 abi_ulong val = 0;
8530
8531 for (j = 0; j < target_bits; j++, bit++) {
8532 if (host_mask[bit / host_bits] & (1UL << (bit % host_bits))) {
8533 val |= 1UL << j;
8534 }
8535 }
8536 __put_user(val, &target_mask[i]);
8537 }
8538
8539 unlock_user(target_mask, target_addr, target_size);
8540 return 0;
8541}
8542
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008543#ifdef TARGET_NR_getdents
Richard Hendersonaee14c72021-11-14 11:35:39 +01008544static int do_getdents(abi_long dirfd, abi_long arg2, abi_long count)
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008545{
Richard Hendersonaee14c72021-11-14 11:35:39 +01008546 g_autofree void *hdirp = NULL;
8547 void *tdirp;
8548 int hlen, hoff, toff;
8549 int hreclen, treclen;
8550 off64_t prev_diroff = 0;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008551
Richard Hendersonaee14c72021-11-14 11:35:39 +01008552 hdirp = g_try_malloc(count);
8553 if (!hdirp) {
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008554 return -TARGET_ENOMEM;
8555 }
8556
Richard Hendersonaee14c72021-11-14 11:35:39 +01008557#ifdef EMULATE_GETDENTS_WITH_GETDENTS
8558 hlen = sys_getdents(dirfd, hdirp, count);
8559#else
8560 hlen = sys_getdents64(dirfd, hdirp, count);
8561#endif
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008562
Richard Hendersonaee14c72021-11-14 11:35:39 +01008563 hlen = get_errno(hlen);
8564 if (is_error(hlen)) {
8565 return hlen;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008566 }
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008567
Richard Hendersonaee14c72021-11-14 11:35:39 +01008568 tdirp = lock_user(VERIFY_WRITE, arg2, count, 0);
8569 if (!tdirp) {
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008570 return -TARGET_EFAULT;
8571 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008572
8573 for (hoff = toff = 0; hoff < hlen; hoff += hreclen, toff += treclen) {
8574#ifdef EMULATE_GETDENTS_WITH_GETDENTS
8575 struct linux_dirent *hde = hdirp + hoff;
8576#else
8577 struct linux_dirent64 *hde = hdirp + hoff;
8578#endif
8579 struct target_dirent *tde = tdirp + toff;
8580 int namelen;
8581 uint8_t type;
8582
8583 namelen = strlen(hde->d_name);
8584 hreclen = hde->d_reclen;
8585 treclen = offsetof(struct target_dirent, d_name) + namelen + 2;
8586 treclen = QEMU_ALIGN_UP(treclen, __alignof(struct target_dirent));
8587
8588 if (toff + treclen > count) {
8589 /*
8590 * If the host struct is smaller than the target struct, or
8591 * requires less alignment and thus packs into less space,
8592 * then the host can return more entries than we can pass
8593 * on to the guest.
8594 */
8595 if (toff == 0) {
8596 toff = -TARGET_EINVAL; /* result buffer is too small */
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008597 break;
8598 }
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008599 /*
Richard Hendersonaee14c72021-11-14 11:35:39 +01008600 * Return what we have, resetting the file pointer to the
8601 * location of the first record not returned.
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008602 */
Richard Hendersonaee14c72021-11-14 11:35:39 +01008603 lseek64(dirfd, prev_diroff, SEEK_SET);
8604 break;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008605 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008606
8607 prev_diroff = hde->d_off;
8608 tde->d_ino = tswapal(hde->d_ino);
8609 tde->d_off = tswapal(hde->d_off);
8610 tde->d_reclen = tswap16(treclen);
8611 memcpy(tde->d_name, hde->d_name, namelen + 1);
8612
8613 /*
8614 * The getdents type is in what was formerly a padding byte at the
8615 * end of the structure.
8616 */
8617#ifdef EMULATE_GETDENTS_WITH_GETDENTS
8618 type = *((uint8_t *)hde + hreclen - 1);
8619#else
8620 type = hde->d_type;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008621#endif
Richard Hendersonaee14c72021-11-14 11:35:39 +01008622 *((uint8_t *)tde + treclen - 1) = type;
8623 }
8624
8625 unlock_user(tdirp, arg2, toff);
8626 return toff;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008627}
8628#endif /* TARGET_NR_getdents */
8629
8630#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
Richard Hendersonaee14c72021-11-14 11:35:39 +01008631static int do_getdents64(abi_long dirfd, abi_long arg2, abi_long count)
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008632{
Richard Hendersonaee14c72021-11-14 11:35:39 +01008633 g_autofree void *hdirp = NULL;
8634 void *tdirp;
8635 int hlen, hoff, toff;
8636 int hreclen, treclen;
8637 off64_t prev_diroff = 0;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008638
Richard Hendersonaee14c72021-11-14 11:35:39 +01008639 hdirp = g_try_malloc(count);
8640 if (!hdirp) {
8641 return -TARGET_ENOMEM;
8642 }
8643
8644 hlen = get_errno(sys_getdents64(dirfd, hdirp, count));
8645 if (is_error(hlen)) {
8646 return hlen;
8647 }
8648
8649 tdirp = lock_user(VERIFY_WRITE, arg2, count, 0);
8650 if (!tdirp) {
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008651 return -TARGET_EFAULT;
8652 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008653
8654 for (hoff = toff = 0; hoff < hlen; hoff += hreclen, toff += treclen) {
8655 struct linux_dirent64 *hde = hdirp + hoff;
8656 struct target_dirent64 *tde = tdirp + toff;
8657 int namelen;
8658
8659 namelen = strlen(hde->d_name) + 1;
8660 hreclen = hde->d_reclen;
8661 treclen = offsetof(struct target_dirent64, d_name) + namelen;
8662 treclen = QEMU_ALIGN_UP(treclen, __alignof(struct target_dirent64));
8663
8664 if (toff + treclen > count) {
8665 /*
8666 * If the host struct is smaller than the target struct, or
8667 * requires less alignment and thus packs into less space,
8668 * then the host can return more entries than we can pass
8669 * on to the guest.
8670 */
8671 if (toff == 0) {
8672 toff = -TARGET_EINVAL; /* result buffer is too small */
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008673 break;
8674 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008675 /*
8676 * Return what we have, resetting the file pointer to the
8677 * location of the first record not returned.
8678 */
8679 lseek64(dirfd, prev_diroff, SEEK_SET);
8680 break;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008681 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008682
8683 prev_diroff = hde->d_off;
8684 tde->d_ino = tswap64(hde->d_ino);
8685 tde->d_off = tswap64(hde->d_off);
8686 tde->d_reclen = tswap16(treclen);
8687 tde->d_type = hde->d_type;
8688 memcpy(tde->d_name, hde->d_name, namelen);
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008689 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008690
8691 unlock_user(tdirp, arg2, toff);
8692 return toff;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008693}
8694#endif /* TARGET_NR_getdents64 */
8695
YAMAMOTO Takashie10fbe82021-05-31 14:50:12 +09008696#if defined(TARGET_NR_pivot_root) && defined(__NR_pivot_root)
8697_syscall2(int, pivot_root, const char *, new_root, const char *, put_old)
8698#endif
8699
Richard Hendersondc1ce182018-08-18 12:01:04 -07008700/* This is an internal helper for do_syscall so that it is easier
8701 * to have a single return point, so that actions, such as logging
8702 * of syscall results, can be performed.
8703 * All errnos that do_syscall() returns must be -TARGET_<errcode>.
8704 */
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008705static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
Richard Hendersondc1ce182018-08-18 12:01:04 -07008706 abi_long arg2, abi_long arg3, abi_long arg4,
8707 abi_long arg5, abi_long arg6, abi_long arg7,
8708 abi_long arg8)
bellard31e31b82003-02-18 22:55:36 +00008709{
Richard Henderson29a0af62019-03-22 16:07:18 -07008710 CPUState *cpu = env_cpu(cpu_env);
blueswir1992f48a2007-10-14 16:27:31 +00008711 abi_long ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008712#if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) \
8713 || defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64) \
Aleksandar Rikaloefa92182019-06-28 12:43:34 +02008714 || defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64) \
8715 || defined(TARGET_NR_statx)
bellard31e31b82003-02-18 22:55:36 +00008716 struct stat st;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008717#endif
8718#if defined(TARGET_NR_statfs) || defined(TARGET_NR_statfs64) \
8719 || defined(TARGET_NR_fstatfs)
bellard56c8f682005-11-28 22:28:41 +00008720 struct statfs stfs;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008721#endif
pbrook53a59602006-03-25 19:31:22 +00008722 void *p;
ths3b46e622007-09-17 08:09:54 +00008723
bellard31e31b82003-02-18 22:55:36 +00008724 switch(num) {
8725 case TARGET_NR_exit:
Andreas Färber9b056fc2013-06-24 23:53:10 +02008726 /* In old applications this may be used to implement _exit(2).
zhaolichang6f9ff552020-09-17 15:50:25 +08008727 However in threaded applications it is used for thread termination,
Andreas Färber9b056fc2013-06-24 23:53:10 +02008728 and _exit_group is used for application termination.
8729 Do thread termination if we have more then one thread. */
Timothy E Baldwina0995882016-05-27 15:51:56 +01008730
8731 if (block_signals()) {
Richard Hendersonaf254a22021-11-22 19:47:33 +01008732 return -QEMU_ERESTARTSYS;
Timothy E Baldwina0995882016-05-27 15:51:56 +01008733 }
8734
Alex Bennée1f81ce92020-05-20 15:05:39 +01008735 pthread_mutex_lock(&clone_lock);
Alex Bennéedd1f6342016-09-30 22:31:01 +01008736
Andreas Färberbdc44642013-06-24 23:50:24 +02008737 if (CPU_NEXT(first_cpu)) {
Alex Bennée1f81ce92020-05-20 15:05:39 +01008738 TaskState *ts = cpu->opaque;
pbrookc2764712009-03-07 15:24:59 +00008739
Richard Henderson6490d9a2023-01-24 10:10:19 -10008740 if (ts->child_tidptr) {
8741 put_user_u32(0, ts->child_tidptr);
8742 do_sys_futex(g2h(cpu, ts->child_tidptr),
8743 FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
8744 }
8745
8746 object_unparent(OBJECT(cpu));
Alex Bennée1f81ce92020-05-20 15:05:39 +01008747 object_unref(OBJECT(cpu));
8748 /*
8749 * At this point the CPU should be unrealized and removed
8750 * from cpu lists. We can clean-up the rest of the thread
8751 * data without the lock held.
8752 */
Alex Bennéedd1f6342016-09-30 22:31:01 +01008753
Alex Bennée1f81ce92020-05-20 15:05:39 +01008754 pthread_mutex_unlock(&clone_lock);
Alex Bennéedd1f6342016-09-30 22:31:01 +01008755
Andreas Färbera2247f82013-06-09 19:47:04 +02008756 thread_cpu = NULL;
Andreas Färber9b056fc2013-06-24 23:53:10 +02008757 g_free(ts);
Emilio G. Cota70903762015-08-23 20:23:41 -04008758 rcu_unregister_thread();
Andreas Färber9b056fc2013-06-24 23:53:10 +02008759 pthread_exit(NULL);
8760 }
Alex Bennéedd1f6342016-09-30 22:31:01 +01008761
Alex Bennée1f81ce92020-05-20 15:05:39 +01008762 pthread_mutex_unlock(&clone_lock);
Alex Bennée708b6a62018-06-22 17:09:10 +01008763 preexit_cleanup(cpu_env, arg1);
pbrookc2764712009-03-07 15:24:59 +00008764 _exit(arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008765 return 0; /* avoid warning */
bellard31e31b82003-02-18 22:55:36 +00008766 case TARGET_NR_read:
Andreas Schwabba584f12019-03-05 17:45:05 +01008767 if (arg2 == 0 && arg3 == 0) {
8768 return get_errno(safe_read(arg1, 0, 0));
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008769 } else {
aurel3238d840e2009-01-30 19:48:17 +00008770 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008771 return -TARGET_EFAULT;
Timothy E Baldwin50afd022016-05-12 18:47:47 +01008772 ret = get_errno(safe_read(arg1, p, arg3));
Laurent Viviere36800c2015-10-02 14:48:09 +02008773 if (ret >= 0 &&
Laurent Vivier5d4d3662015-10-28 21:40:43 +01008774 fd_trans_host_to_target_data(arg1)) {
8775 ret = fd_trans_host_to_target_data(arg1)(p, ret);
Laurent Viviere36800c2015-10-02 14:48:09 +02008776 }
aurel3238d840e2009-01-30 19:48:17 +00008777 unlock_user(p, arg2, ret);
8778 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008779 return ret;
bellard31e31b82003-02-18 22:55:36 +00008780 case TARGET_NR_write:
Tony Garnock-Jones58cfa6c2018-09-08 19:22:05 +01008781 if (arg2 == 0 && arg3 == 0) {
8782 return get_errno(safe_write(arg1, 0, 0));
8783 }
bellard579a97f2007-11-11 14:26:47 +00008784 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008785 return -TARGET_EFAULT;
Laurent Vivier04b9bcf2017-03-01 10:37:47 +01008786 if (fd_trans_target_to_host_data(arg1)) {
8787 void *copy = g_malloc(arg3);
8788 memcpy(copy, p, arg3);
8789 ret = fd_trans_target_to_host_data(arg1)(copy, arg3);
8790 if (ret >= 0) {
8791 ret = get_errno(safe_write(arg1, copy, ret));
8792 }
8793 g_free(copy);
8794 } else {
8795 ret = get_errno(safe_write(arg1, p, arg3));
8796 }
pbrook53a59602006-03-25 19:31:22 +00008797 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008798 return ret;
8799
Chen Gang704eff62015-08-21 05:37:33 +08008800#ifdef TARGET_NR_open
bellard31e31b82003-02-18 22:55:36 +00008801 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00008802 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008803 return -TARGET_EFAULT;
Riku Voipio0b2effd2014-08-06 10:36:37 +03008804 ret = get_errno(do_openat(cpu_env, AT_FDCWD, p,
8805 target_to_host_bitmask(arg2, fcntl_flags_tbl),
8806 arg3));
Laurent Viviere36800c2015-10-02 14:48:09 +02008807 fd_trans_unregister(ret);
pbrook53a59602006-03-25 19:31:22 +00008808 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008809 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008810#endif
ths82424832007-09-24 09:21:55 +00008811 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00008812 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008813 return -TARGET_EFAULT;
Riku Voipio0b2effd2014-08-06 10:36:37 +03008814 ret = get_errno(do_openat(cpu_env, arg1, p,
8815 target_to_host_bitmask(arg3, fcntl_flags_tbl),
8816 arg4));
Laurent Viviere36800c2015-10-02 14:48:09 +02008817 fd_trans_unregister(ret);
bellard579a97f2007-11-11 14:26:47 +00008818 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008819 return ret;
Laurent Vivier0f0426f2015-09-01 22:27:33 +02008820#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
8821 case TARGET_NR_name_to_handle_at:
8822 ret = do_name_to_handle_at(arg1, arg2, arg3, arg4, arg5);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008823 return ret;
Laurent Vivier0f0426f2015-09-01 22:27:33 +02008824#endif
8825#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
8826 case TARGET_NR_open_by_handle_at:
8827 ret = do_open_by_handle_at(arg1, arg2, arg3);
Laurent Viviere36800c2015-10-02 14:48:09 +02008828 fd_trans_unregister(ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008829 return ret;
Laurent Vivier0f0426f2015-09-01 22:27:33 +02008830#endif
Helge Dellercc054c62022-09-18 21:45:46 +02008831#if defined(__NR_pidfd_open) && defined(TARGET_NR_pidfd_open)
8832 case TARGET_NR_pidfd_open:
8833 return get_errno(pidfd_open(arg1, arg2));
8834#endif
8835#if defined(__NR_pidfd_send_signal) && defined(TARGET_NR_pidfd_send_signal)
8836 case TARGET_NR_pidfd_send_signal:
8837 {
Laurent Vivier46187d72022-10-05 18:38:26 +02008838 siginfo_t uinfo, *puinfo;
Helge Dellercc054c62022-09-18 21:45:46 +02008839
Laurent Vivier46187d72022-10-05 18:38:26 +02008840 if (arg3) {
8841 p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
8842 if (!p) {
8843 return -TARGET_EFAULT;
8844 }
8845 target_to_host_siginfo(&uinfo, p);
8846 unlock_user(p, arg3, 0);
8847 puinfo = &uinfo;
8848 } else {
8849 puinfo = NULL;
Helge Dellercc054c62022-09-18 21:45:46 +02008850 }
Helge Dellercc054c62022-09-18 21:45:46 +02008851 ret = get_errno(pidfd_send_signal(arg1, target_to_host_signal(arg2),
Laurent Vivier46187d72022-10-05 18:38:26 +02008852 puinfo, arg4));
Helge Dellercc054c62022-09-18 21:45:46 +02008853 }
8854 return ret;
8855#endif
8856#if defined(__NR_pidfd_getfd) && defined(TARGET_NR_pidfd_getfd)
8857 case TARGET_NR_pidfd_getfd:
8858 return get_errno(pidfd_getfd(arg1, arg2, arg3));
8859#endif
bellard31e31b82003-02-18 22:55:36 +00008860 case TARGET_NR_close:
Laurent Viviere36800c2015-10-02 14:48:09 +02008861 fd_trans_unregister(arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008862 return get_errno(close(arg1));
Helge Delleraf804f32022-10-25 04:34:14 +02008863#if defined(__NR_close_range) && defined(TARGET_NR_close_range)
8864 case TARGET_NR_close_range:
8865 ret = get_errno(sys_close_range(arg1, arg2, arg3));
8866 if (ret == 0 && !(arg3 & CLOSE_RANGE_CLOEXEC)) {
8867 abi_long fd, maxfd;
8868 maxfd = MIN(arg2, target_fd_max);
8869 for (fd = arg1; fd < maxfd; fd++) {
8870 fd_trans_unregister(fd);
8871 }
8872 }
8873 return ret;
8874#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008875
bellard31e31b82003-02-18 22:55:36 +00008876 case TARGET_NR_brk:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008877 return do_brk(arg1);
Chen Gang704eff62015-08-21 05:37:33 +08008878#ifdef TARGET_NR_fork
bellard31e31b82003-02-18 22:55:36 +00008879 case TARGET_NR_fork:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008880 return get_errno(do_fork(cpu_env, TARGET_SIGCHLD, 0, 0, 0, 0));
Chen Gang704eff62015-08-21 05:37:33 +08008881#endif
thse5febef2007-04-01 18:31:35 +00008882#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00008883 case TARGET_NR_waitpid:
8884 {
pbrook53a59602006-03-25 19:31:22 +00008885 int status;
Timothy E Baldwin4af80a32016-05-12 18:47:49 +01008886 ret = get_errno(safe_wait4(arg1, &status, arg3, 0));
Alexander Graf53795572011-11-24 00:44:43 +01008887 if (!is_error(ret) && arg2 && ret
pbrook1d9d8b52009-04-16 15:17:02 +00008888 && put_user_s32(host_to_target_waitstatus(status), arg2))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008889 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00008890 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008891 return ret;
thse5febef2007-04-01 18:31:35 +00008892#endif
pbrookf0cbb612008-05-30 18:20:05 +00008893#ifdef TARGET_NR_waitid
8894 case TARGET_NR_waitid:
8895 {
8896 siginfo_t info;
8897 info.si_pid = 0;
Timothy E Baldwin4af80a32016-05-12 18:47:49 +01008898 ret = get_errno(safe_waitid(arg1, arg2, &info, arg4, NULL));
pbrookf0cbb612008-05-30 18:20:05 +00008899 if (!is_error(ret) && arg3 && info.si_pid != 0) {
Anthony Liguoric227f092009-10-01 16:12:16 -05008900 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008901 return -TARGET_EFAULT;
pbrookf0cbb612008-05-30 18:20:05 +00008902 host_to_target_siginfo(p, &info);
Anthony Liguoric227f092009-10-01 16:12:16 -05008903 unlock_user(p, arg3, sizeof(target_siginfo_t));
pbrookf0cbb612008-05-30 18:20:05 +00008904 }
8905 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008906 return ret;
pbrookf0cbb612008-05-30 18:20:05 +00008907#endif
j_mayer7a3148a2007-04-05 07:13:51 +00008908#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00008909 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00008910 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008911 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008912 ret = get_errno(creat(p, arg2));
Laurent Viviere36800c2015-10-02 14:48:09 +02008913 fd_trans_unregister(ret);
pbrook53a59602006-03-25 19:31:22 +00008914 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008915 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00008916#endif
Chen Gang704eff62015-08-21 05:37:33 +08008917#ifdef TARGET_NR_link
bellard31e31b82003-02-18 22:55:36 +00008918 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00008919 {
8920 void * p2;
8921 p = lock_user_string(arg1);
8922 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00008923 if (!p || !p2)
8924 ret = -TARGET_EFAULT;
8925 else
8926 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00008927 unlock_user(p2, arg2, 0);
8928 unlock_user(p, arg1, 0);
8929 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008930 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008931#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01008932#if defined(TARGET_NR_linkat)
ths64f0ce42007-09-24 09:25:06 +00008933 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00008934 {
8935 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00008936 if (!arg2 || !arg4)
Richard Henderson2852aaf2018-08-18 12:01:06 -07008937 return -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00008938 p = lock_user_string(arg2);
8939 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00008940 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00008941 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00008942 else
Peter Maydellc0d472b2013-06-12 16:20:21 +01008943 ret = get_errno(linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00008944 unlock_user(p, arg2, 0);
8945 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00008946 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008947 return ret;
ths64f0ce42007-09-24 09:25:06 +00008948#endif
Chen Gang704eff62015-08-21 05:37:33 +08008949#ifdef TARGET_NR_unlink
bellard31e31b82003-02-18 22:55:36 +00008950 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00008951 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008952 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008953 ret = get_errno(unlink(p));
8954 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008955 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008956#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01008957#if defined(TARGET_NR_unlinkat)
ths8170f562007-09-24 09:24:11 +00008958 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00008959 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008960 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01008961 ret = get_errno(unlinkat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00008962 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008963 return ret;
balrogb7d35e62007-12-12 00:40:24 +00008964#endif
Drew DeVault55bbe4d2022-11-04 18:36:32 +01008965 case TARGET_NR_execveat:
8966 return do_execveat(cpu_env, arg1, arg2, arg3, arg4, arg5);
bellard31e31b82003-02-18 22:55:36 +00008967 case TARGET_NR_execve:
Drew DeVault55bbe4d2022-11-04 18:36:32 +01008968 return do_execveat(cpu_env, AT_FDCWD, arg1, arg2, arg3, 0);
bellard31e31b82003-02-18 22:55:36 +00008969 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00008970 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008971 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008972 ret = get_errno(chdir(p));
8973 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008974 return ret;
bellarda315a142005-01-30 22:59:18 +00008975#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00008976 case TARGET_NR_time:
8977 {
pbrook53a59602006-03-25 19:31:22 +00008978 time_t host_time;
8979 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00008980 if (!is_error(ret)
8981 && arg1
8982 && put_user_sal(host_time, arg1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008983 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00008984 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008985 return ret;
bellarda315a142005-01-30 22:59:18 +00008986#endif
Chen Gang704eff62015-08-21 05:37:33 +08008987#ifdef TARGET_NR_mknod
bellard31e31b82003-02-18 22:55:36 +00008988 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00008989 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008990 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008991 ret = get_errno(mknod(p, arg2, arg3));
8992 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008993 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008994#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01008995#if defined(TARGET_NR_mknodat)
ths75ac37a2007-09-24 09:23:05 +00008996 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00008997 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008998 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01008999 ret = get_errno(mknodat(arg1, p, arg3, arg4));
bellard579a97f2007-11-11 14:26:47 +00009000 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009001 return ret;
ths75ac37a2007-09-24 09:23:05 +00009002#endif
Chen Gang704eff62015-08-21 05:37:33 +08009003#ifdef TARGET_NR_chmod
bellard31e31b82003-02-18 22:55:36 +00009004 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00009005 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009006 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009007 ret = get_errno(chmod(p, arg2));
9008 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009009 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009010#endif
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009011#ifdef TARGET_NR_lseek
bellard31e31b82003-02-18 22:55:36 +00009012 case TARGET_NR_lseek:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009013 return get_errno(lseek(arg1, arg2, arg3));
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009014#endif
Richard Henderson92317332010-05-03 10:07:53 -07009015#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA)
9016 /* Alpha specific */
j_mayer7a3148a2007-04-05 07:13:51 +00009017 case TARGET_NR_getxpid:
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02009018 cpu_env->ir[IR_A4] = getppid();
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009019 return get_errno(getpid());
Richard Henderson92317332010-05-03 10:07:53 -07009020#endif
9021#ifdef TARGET_NR_getpid
9022 case TARGET_NR_getpid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009023 return get_errno(getpid());
Richard Henderson92317332010-05-03 10:07:53 -07009024#endif
bellard31e31b82003-02-18 22:55:36 +00009025 case TARGET_NR_mount:
Paul Burton356d7712014-06-22 11:25:37 +01009026 {
9027 /* need to look at the data field */
9028 void *p2, *p3;
9029
9030 if (arg1) {
9031 p = lock_user_string(arg1);
9032 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009033 return -TARGET_EFAULT;
Paul Burton356d7712014-06-22 11:25:37 +01009034 }
9035 } else {
9036 p = NULL;
9037 }
9038
9039 p2 = lock_user_string(arg2);
9040 if (!p2) {
9041 if (arg1) {
9042 unlock_user(p, arg1, 0);
9043 }
Richard Henderson2852aaf2018-08-18 12:01:06 -07009044 return -TARGET_EFAULT;
Paul Burton356d7712014-06-22 11:25:37 +01009045 }
9046
9047 if (arg3) {
9048 p3 = lock_user_string(arg3);
9049 if (!p3) {
9050 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00009051 unlock_user(p, arg1, 0);
Paul Burton356d7712014-06-22 11:25:37 +01009052 }
9053 unlock_user(p2, arg2, 0);
Richard Henderson2852aaf2018-08-18 12:01:06 -07009054 return -TARGET_EFAULT;
Paul Burton356d7712014-06-22 11:25:37 +01009055 }
9056 } else {
9057 p3 = NULL;
9058 }
9059
9060 /* FIXME - arg5 should be locked, but it isn't clear how to
9061 * do that since it's not guaranteed to be a NULL-terminated
9062 * string.
9063 */
9064 if (!arg5) {
9065 ret = mount(p, p2, p3, (unsigned long)arg4, NULL);
9066 } else {
Richard Henderson3e8f1622021-02-12 10:48:43 -08009067 ret = mount(p, p2, p3, (unsigned long)arg4, g2h(cpu, arg5));
Paul Burton356d7712014-06-22 11:25:37 +01009068 }
9069 ret = get_errno(ret);
9070
9071 if (arg1) {
9072 unlock_user(p, arg1, 0);
9073 }
9074 unlock_user(p2, arg2, 0);
9075 if (arg3) {
9076 unlock_user(p3, arg3, 0);
9077 }
9078 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009079 return ret;
Laurent Vivier6eb9dbf2020-05-02 21:46:42 +02009080#if defined(TARGET_NR_umount) || defined(TARGET_NR_oldumount)
9081#if defined(TARGET_NR_umount)
bellard31e31b82003-02-18 22:55:36 +00009082 case TARGET_NR_umount:
Laurent Vivier6eb9dbf2020-05-02 21:46:42 +02009083#endif
9084#if defined(TARGET_NR_oldumount)
9085 case TARGET_NR_oldumount:
9086#endif
bellard579a97f2007-11-11 14:26:47 +00009087 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009088 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009089 ret = get_errno(umount(p));
9090 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009091 return ret;
thse5febef2007-04-01 18:31:35 +00009092#endif
j_mayer7a3148a2007-04-05 07:13:51 +00009093#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009094 case TARGET_NR_stime:
9095 {
Laurent Vivier0f1f2d42019-11-12 15:25:56 +01009096 struct timespec ts;
9097 ts.tv_nsec = 0;
9098 if (get_user_sal(ts.tv_sec, arg1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009099 return -TARGET_EFAULT;
Laurent Vivier0f1f2d42019-11-12 15:25:56 +01009100 }
9101 return get_errno(clock_settime(CLOCK_REALTIME, &ts));
bellard31e31b82003-02-18 22:55:36 +00009102 }
j_mayer7a3148a2007-04-05 07:13:51 +00009103#endif
j_mayer7a3148a2007-04-05 07:13:51 +00009104#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009105 case TARGET_NR_alarm:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009106 return alarm(arg1);
j_mayer7a3148a2007-04-05 07:13:51 +00009107#endif
j_mayer7a3148a2007-04-05 07:13:51 +00009108#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009109 case TARGET_NR_pause:
Timothy E Baldwinf59ec602016-05-27 15:51:55 +01009110 if (!block_signals()) {
9111 sigsuspend(&((TaskState *)cpu->opaque)->signal_mask);
9112 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009113 return -TARGET_EINTR;
j_mayer7a3148a2007-04-05 07:13:51 +00009114#endif
thse5febef2007-04-01 18:31:35 +00009115#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00009116 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00009117 {
pbrook53a59602006-03-25 19:31:22 +00009118 struct utimbuf tbuf, *host_tbuf;
9119 struct target_utimbuf *target_tbuf;
9120 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00009121 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009122 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02009123 tbuf.actime = tswapal(target_tbuf->actime);
9124 tbuf.modtime = tswapal(target_tbuf->modtime);
pbrook53a59602006-03-25 19:31:22 +00009125 unlock_user_struct(target_tbuf, arg2, 0);
9126 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00009127 } else {
pbrook53a59602006-03-25 19:31:22 +00009128 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00009129 }
bellard579a97f2007-11-11 14:26:47 +00009130 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009131 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009132 ret = get_errno(utime(p, host_tbuf));
9133 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00009134 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009135 return ret;
thse5febef2007-04-01 18:31:35 +00009136#endif
Chen Gang704eff62015-08-21 05:37:33 +08009137#ifdef TARGET_NR_utimes
bellard978a66f2004-12-06 22:58:05 +00009138 case TARGET_NR_utimes:
9139 {
bellard978a66f2004-12-06 22:58:05 +00009140 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00009141 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00009142 if (copy_from_user_timeval(&tv[0], arg2)
9143 || copy_from_user_timeval(&tv[1],
9144 arg2 + sizeof(struct target_timeval)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009145 return -TARGET_EFAULT;
bellard978a66f2004-12-06 22:58:05 +00009146 tvp = tv;
9147 } else {
9148 tvp = NULL;
9149 }
bellard579a97f2007-11-11 14:26:47 +00009150 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009151 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009152 ret = get_errno(utimes(p, tvp));
9153 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00009154 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009155 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009156#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01009157#if defined(TARGET_NR_futimesat)
balrogac8a6552008-09-20 02:25:39 +00009158 case TARGET_NR_futimesat:
9159 {
9160 struct timeval *tvp, tv[2];
9161 if (arg3) {
9162 if (copy_from_user_timeval(&tv[0], arg3)
9163 || copy_from_user_timeval(&tv[1],
9164 arg3 + sizeof(struct target_timeval)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009165 return -TARGET_EFAULT;
balrogac8a6552008-09-20 02:25:39 +00009166 tvp = tv;
9167 } else {
9168 tvp = NULL;
9169 }
Richard Henderson2852aaf2018-08-18 12:01:06 -07009170 if (!(p = lock_user_string(arg2))) {
9171 return -TARGET_EFAULT;
9172 }
Peter Maydellc0d472b2013-06-12 16:20:21 +01009173 ret = get_errno(futimesat(arg1, path(p), tvp));
balrogac8a6552008-09-20 02:25:39 +00009174 unlock_user(p, arg2, 0);
9175 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009176 return ret;
balrogac8a6552008-09-20 02:25:39 +00009177#endif
Chen Gang704eff62015-08-21 05:37:33 +08009178#ifdef TARGET_NR_access
bellard31e31b82003-02-18 22:55:36 +00009179 case TARGET_NR_access:
Richard Henderson2852aaf2018-08-18 12:01:06 -07009180 if (!(p = lock_user_string(arg1))) {
9181 return -TARGET_EFAULT;
9182 }
Ulrich Hecht719f9082009-07-03 17:09:29 +02009183 ret = get_errno(access(path(p), arg2));
pbrook53a59602006-03-25 19:31:22 +00009184 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009185 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009186#endif
ths92a34c12007-09-24 09:27:49 +00009187#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
9188 case TARGET_NR_faccessat:
Richard Henderson2852aaf2018-08-18 12:01:06 -07009189 if (!(p = lock_user_string(arg2))) {
9190 return -TARGET_EFAULT;
9191 }
Peter Maydellc0d472b2013-06-12 16:20:21 +01009192 ret = get_errno(faccessat(arg1, p, arg3, 0));
bellard579a97f2007-11-11 14:26:47 +00009193 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009194 return ret;
ths92a34c12007-09-24 09:27:49 +00009195#endif
WANG Xuerui35a2c852022-10-09 14:08:13 +08009196#if defined(TARGET_NR_faccessat2)
9197 case TARGET_NR_faccessat2:
9198 if (!(p = lock_user_string(arg2))) {
9199 return -TARGET_EFAULT;
9200 }
9201 ret = get_errno(faccessat(arg1, p, arg3, arg4));
9202 unlock_user(p, arg2, 0);
9203 return ret;
9204#endif
j_mayer7a3148a2007-04-05 07:13:51 +00009205#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009206 case TARGET_NR_nice:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009207 return get_errno(nice(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +00009208#endif
bellard31e31b82003-02-18 22:55:36 +00009209 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00009210 sync();
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009211 return 0;
Aleksandar Markovic5a03cd02016-10-10 13:23:30 +02009212#if defined(TARGET_NR_syncfs) && defined(CONFIG_SYNCFS)
9213 case TARGET_NR_syncfs:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009214 return get_errno(syncfs(arg1));
Aleksandar Markovic5a03cd02016-10-10 13:23:30 +02009215#endif
bellard31e31b82003-02-18 22:55:36 +00009216 case TARGET_NR_kill:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009217 return get_errno(safe_kill(arg1, target_to_host_signal(arg2)));
Chen Gang704eff62015-08-21 05:37:33 +08009218#ifdef TARGET_NR_rename
bellard31e31b82003-02-18 22:55:36 +00009219 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00009220 {
9221 void *p2;
9222 p = lock_user_string(arg1);
9223 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00009224 if (!p || !p2)
9225 ret = -TARGET_EFAULT;
9226 else
9227 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00009228 unlock_user(p2, arg2, 0);
9229 unlock_user(p, arg1, 0);
9230 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009231 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009232#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01009233#if defined(TARGET_NR_renameat)
ths722183f2007-09-24 09:24:37 +00009234 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00009235 {
bellard579a97f2007-11-11 14:26:47 +00009236 void *p2;
ths722183f2007-09-24 09:24:37 +00009237 p = lock_user_string(arg2);
9238 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00009239 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00009240 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00009241 else
Peter Maydellc0d472b2013-06-12 16:20:21 +01009242 ret = get_errno(renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00009243 unlock_user(p2, arg4, 0);
9244 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00009245 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009246 return ret;
ths722183f2007-09-24 09:24:37 +00009247#endif
Andreas Schwab95d03072018-01-23 11:53:31 +01009248#if defined(TARGET_NR_renameat2)
9249 case TARGET_NR_renameat2:
9250 {
9251 void *p2;
9252 p = lock_user_string(arg2);
9253 p2 = lock_user_string(arg4);
9254 if (!p || !p2) {
9255 ret = -TARGET_EFAULT;
9256 } else {
9257 ret = get_errno(sys_renameat2(arg1, p, arg3, p2, arg5));
9258 }
9259 unlock_user(p2, arg4, 0);
9260 unlock_user(p, arg2, 0);
9261 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009262 return ret;
Andreas Schwab95d03072018-01-23 11:53:31 +01009263#endif
Chen Gang704eff62015-08-21 05:37:33 +08009264#ifdef TARGET_NR_mkdir
bellard31e31b82003-02-18 22:55:36 +00009265 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00009266 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009267 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009268 ret = get_errno(mkdir(p, arg2));
9269 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009270 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009271#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01009272#if defined(TARGET_NR_mkdirat)
ths4472ad02007-09-24 09:22:32 +00009273 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00009274 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009275 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01009276 ret = get_errno(mkdirat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00009277 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009278 return ret;
ths4472ad02007-09-24 09:22:32 +00009279#endif
Chen Gang704eff62015-08-21 05:37:33 +08009280#ifdef TARGET_NR_rmdir
bellard31e31b82003-02-18 22:55:36 +00009281 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00009282 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009283 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009284 ret = get_errno(rmdir(p));
9285 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009286 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009287#endif
bellard31e31b82003-02-18 22:55:36 +00009288 case TARGET_NR_dup:
9289 ret = get_errno(dup(arg1));
Laurent Viviere36800c2015-10-02 14:48:09 +02009290 if (ret >= 0) {
9291 fd_trans_dup(arg1, ret);
9292 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009293 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009294#ifdef TARGET_NR_pipe
bellard31e31b82003-02-18 22:55:36 +00009295 case TARGET_NR_pipe:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009296 return do_pipe(cpu_env, arg1, 0, 0);
Chen Gang704eff62015-08-21 05:37:33 +08009297#endif
Riku Voipio099d6b02009-05-05 12:10:04 +03009298#ifdef TARGET_NR_pipe2
9299 case TARGET_NR_pipe2:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009300 return do_pipe(cpu_env, arg1,
9301 target_to_host_bitmask(arg2, fcntl_flags_tbl), 1);
Riku Voipio099d6b02009-05-05 12:10:04 +03009302#endif
bellard31e31b82003-02-18 22:55:36 +00009303 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00009304 {
pbrook53a59602006-03-25 19:31:22 +00009305 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00009306 struct tms tms;
9307 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00009308 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00009309 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
9310 if (!tmsp)
Richard Henderson2852aaf2018-08-18 12:01:06 -07009311 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02009312 tmsp->tms_utime = tswapal(host_to_target_clock_t(tms.tms_utime));
9313 tmsp->tms_stime = tswapal(host_to_target_clock_t(tms.tms_stime));
9314 tmsp->tms_cutime = tswapal(host_to_target_clock_t(tms.tms_cutime));
9315 tmsp->tms_cstime = tswapal(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00009316 }
bellardc596ed12003-07-13 17:32:31 +00009317 if (!is_error(ret))
9318 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00009319 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009320 return ret;
bellard31e31b82003-02-18 22:55:36 +00009321 case TARGET_NR_acct:
aurel3238d840e2009-01-30 19:48:17 +00009322 if (arg1 == 0) {
9323 ret = get_errno(acct(NULL));
9324 } else {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009325 if (!(p = lock_user_string(arg1))) {
9326 return -TARGET_EFAULT;
9327 }
aurel3238d840e2009-01-30 19:48:17 +00009328 ret = get_errno(acct(path(p)));
9329 unlock_user(p, arg1, 0);
9330 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009331 return ret;
Richard Henderson8070e7b2013-07-24 09:50:00 -10009332#ifdef TARGET_NR_umount2
bellard31e31b82003-02-18 22:55:36 +00009333 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00009334 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009335 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009336 ret = get_errno(umount2(p, arg2));
9337 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009338 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00009339#endif
bellard31e31b82003-02-18 22:55:36 +00009340 case TARGET_NR_ioctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009341 return do_ioctl(arg1, arg2, arg3);
Michael Clark47ae93c2018-03-03 01:31:11 +13009342#ifdef TARGET_NR_fcntl
bellard31e31b82003-02-18 22:55:36 +00009343 case TARGET_NR_fcntl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009344 return do_fcntl(arg1, arg2, arg3);
Michael Clark47ae93c2018-03-03 01:31:11 +13009345#endif
bellard31e31b82003-02-18 22:55:36 +00009346 case TARGET_NR_setpgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009347 return get_errno(setpgid(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00009348 case TARGET_NR_umask:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009349 return get_errno(umask(arg1));
bellard31e31b82003-02-18 22:55:36 +00009350 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00009351 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009352 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009353 ret = get_errno(chroot(p));
9354 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009355 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009356#ifdef TARGET_NR_dup2
bellard31e31b82003-02-18 22:55:36 +00009357 case TARGET_NR_dup2:
9358 ret = get_errno(dup2(arg1, arg2));
Laurent Viviere36800c2015-10-02 14:48:09 +02009359 if (ret >= 0) {
9360 fd_trans_dup(arg1, arg2);
9361 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009362 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009363#endif
Ulrich Hechtd0927932009-09-17 20:22:14 +03009364#if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3)
9365 case TARGET_NR_dup3:
Peter Maydell10fa9932017-12-15 15:18:00 +00009366 {
9367 int host_flags;
9368
9369 if ((arg3 & ~TARGET_O_CLOEXEC) != 0) {
9370 return -EINVAL;
9371 }
9372 host_flags = target_to_host_bitmask(arg3, fcntl_flags_tbl);
9373 ret = get_errno(dup3(arg1, arg2, host_flags));
Laurent Viviere36800c2015-10-02 14:48:09 +02009374 if (ret >= 0) {
9375 fd_trans_dup(arg1, arg2);
9376 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009377 return ret;
Peter Maydell10fa9932017-12-15 15:18:00 +00009378 }
Ulrich Hechtd0927932009-09-17 20:22:14 +03009379#endif
j_mayer7a3148a2007-04-05 07:13:51 +00009380#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009381 case TARGET_NR_getppid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009382 return get_errno(getppid());
j_mayer7a3148a2007-04-05 07:13:51 +00009383#endif
Chen Gang704eff62015-08-21 05:37:33 +08009384#ifdef TARGET_NR_getpgrp
bellard31e31b82003-02-18 22:55:36 +00009385 case TARGET_NR_getpgrp:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009386 return get_errno(getpgrp());
Chen Gang704eff62015-08-21 05:37:33 +08009387#endif
bellard31e31b82003-02-18 22:55:36 +00009388 case TARGET_NR_setsid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009389 return get_errno(setsid());
thse5febef2007-04-01 18:31:35 +00009390#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00009391 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00009392 {
Richard Henderson02d0de12021-04-22 16:02:26 -07009393#if defined(TARGET_MIPS)
bellard106ec872006-06-27 21:08:10 +00009394 struct target_sigaction act, oact, *pact, *old_act;
9395
9396 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00009397 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009398 return -TARGET_EFAULT;
bellard106ec872006-06-27 21:08:10 +00009399 act._sa_handler = old_act->_sa_handler;
9400 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
9401 act.sa_flags = old_act->sa_flags;
9402 unlock_user_struct(old_act, arg2, 0);
9403 pact = &act;
9404 } else {
9405 pact = NULL;
9406 }
9407
Richard Henderson02fb28e2021-04-22 16:02:23 -07009408 ret = get_errno(do_sigaction(arg1, pact, &oact, 0));
bellard106ec872006-06-27 21:08:10 +00009409
9410 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00009411 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009412 return -TARGET_EFAULT;
bellard106ec872006-06-27 21:08:10 +00009413 old_act->_sa_handler = oact._sa_handler;
9414 old_act->sa_flags = oact.sa_flags;
9415 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
9416 old_act->sa_mask.sig[1] = 0;
9417 old_act->sa_mask.sig[2] = 0;
9418 old_act->sa_mask.sig[3] = 0;
9419 unlock_user_struct(old_act, arg3, 1);
9420 }
Richard Henderson6049f4f2009-12-27 18:30:03 -08009421#else
9422 struct target_old_sigaction *old_act;
9423 struct target_sigaction act, oact, *pact;
9424 if (arg2) {
9425 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009426 return -TARGET_EFAULT;
Richard Henderson6049f4f2009-12-27 18:30:03 -08009427 act._sa_handler = old_act->_sa_handler;
9428 target_siginitset(&act.sa_mask, old_act->sa_mask);
9429 act.sa_flags = old_act->sa_flags;
Richard Hendersonca192272021-04-22 16:02:24 -07009430#ifdef TARGET_ARCH_HAS_SA_RESTORER
Richard Henderson6049f4f2009-12-27 18:30:03 -08009431 act.sa_restorer = old_act->sa_restorer;
Richard Hendersonca192272021-04-22 16:02:24 -07009432#endif
Richard Henderson6049f4f2009-12-27 18:30:03 -08009433 unlock_user_struct(old_act, arg2, 0);
9434 pact = &act;
9435 } else {
9436 pact = NULL;
9437 }
Richard Henderson02fb28e2021-04-22 16:02:23 -07009438 ret = get_errno(do_sigaction(arg1, pact, &oact, 0));
Richard Henderson6049f4f2009-12-27 18:30:03 -08009439 if (!is_error(ret) && arg3) {
9440 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009441 return -TARGET_EFAULT;
Richard Henderson6049f4f2009-12-27 18:30:03 -08009442 old_act->_sa_handler = oact._sa_handler;
9443 old_act->sa_mask = oact.sa_mask.sig[0];
9444 old_act->sa_flags = oact.sa_flags;
Richard Hendersonca192272021-04-22 16:02:24 -07009445#ifdef TARGET_ARCH_HAS_SA_RESTORER
Richard Henderson6049f4f2009-12-27 18:30:03 -08009446 old_act->sa_restorer = oact.sa_restorer;
Richard Hendersonca192272021-04-22 16:02:24 -07009447#endif
Richard Henderson6049f4f2009-12-27 18:30:03 -08009448 unlock_user_struct(old_act, arg3, 1);
9449 }
ths388bb212007-05-13 13:58:00 +00009450#endif
bellard31e31b82003-02-18 22:55:36 +00009451 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009452 return ret;
thse5febef2007-04-01 18:31:35 +00009453#endif
bellard66fb9762003-03-23 01:06:05 +00009454 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00009455 {
Richard Henderson0f6f9902021-04-22 16:02:25 -07009456 /*
9457 * For Alpha and SPARC this is a 5 argument syscall, with
Peter Maydell78bfef72017-11-06 18:33:26 +00009458 * a 'restorer' parameter which must be copied into the
9459 * sa_restorer field of the sigaction struct.
9460 * For Alpha that 'restorer' is arg5; for SPARC it is arg4,
9461 * and arg5 is the sigsetsize.
Peter Maydell78bfef72017-11-06 18:33:26 +00009462 */
Richard Henderson0f6f9902021-04-22 16:02:25 -07009463#if defined(TARGET_ALPHA)
9464 target_ulong sigsetsize = arg4;
9465 target_ulong restorer = arg5;
9466#elif defined(TARGET_SPARC)
Peter Maydell78bfef72017-11-06 18:33:26 +00009467 target_ulong restorer = arg4;
9468 target_ulong sigsetsize = arg5;
9469#else
9470 target_ulong sigsetsize = arg4;
Richard Henderson02fb28e2021-04-22 16:02:23 -07009471 target_ulong restorer = 0;
Peter Maydell78bfef72017-11-06 18:33:26 +00009472#endif
Richard Hendersonfb804392021-04-22 16:02:27 -07009473 struct target_sigaction *act = NULL;
9474 struct target_sigaction *oact = NULL;
pbrook53a59602006-03-25 19:31:22 +00009475
Peter Maydell78bfef72017-11-06 18:33:26 +00009476 if (sigsetsize != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009477 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01009478 }
Richard Hendersonfb804392021-04-22 16:02:27 -07009479 if (arg2 && !lock_user_struct(VERIFY_READ, act, arg2, 1)) {
9480 return -TARGET_EFAULT;
Peter Maydell78bfef72017-11-06 18:33:26 +00009481 }
Richard Hendersonfb804392021-04-22 16:02:27 -07009482 if (arg3 && !lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
9483 ret = -TARGET_EFAULT;
9484 } else {
9485 ret = get_errno(do_sigaction(arg1, act, oact, restorer));
9486 if (oact) {
9487 unlock_user_struct(oact, arg3, 1);
bellard579a97f2007-11-11 14:26:47 +00009488 }
Richard Hendersonfb804392021-04-22 16:02:27 -07009489 }
9490 if (act) {
pbrook53a59602006-03-25 19:31:22 +00009491 unlock_user_struct(act, arg2, 0);
Richard Hendersonfb804392021-04-22 16:02:27 -07009492 }
pbrook53a59602006-03-25 19:31:22 +00009493 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009494 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00009495#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009496 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00009497 {
9498 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00009499 abi_ulong target_set;
Peter Maydell3d3efba2016-05-27 15:51:49 +01009500 ret = do_sigprocmask(0, NULL, &cur_set);
9501 if (!ret) {
9502 host_to_target_old_sigset(&target_set, &cur_set);
9503 ret = target_set;
9504 }
bellard66fb9762003-03-23 01:06:05 +00009505 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009506 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00009507#endif
9508#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009509 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00009510 {
Miloš Stojanovića8617d82017-05-15 16:59:43 +02009511 sigset_t set, oset;
blueswir1992f48a2007-10-14 16:27:31 +00009512 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00009513 target_to_host_old_sigset(&set, &target_set);
Peter Maydell3d3efba2016-05-27 15:51:49 +01009514 ret = do_sigprocmask(SIG_SETMASK, &set, &oset);
9515 if (!ret) {
9516 host_to_target_old_sigset(&target_set, &oset);
9517 ret = target_set;
9518 }
bellard66fb9762003-03-23 01:06:05 +00009519 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009520 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00009521#endif
thse5febef2007-04-01 18:31:35 +00009522#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00009523 case TARGET_NR_sigprocmask:
9524 {
Richard Hendersona5b3b132010-05-03 10:07:55 -07009525#if defined(TARGET_ALPHA)
9526 sigset_t set, oldset;
9527 abi_ulong mask;
9528 int how;
9529
9530 switch (arg1) {
9531 case TARGET_SIG_BLOCK:
9532 how = SIG_BLOCK;
9533 break;
9534 case TARGET_SIG_UNBLOCK:
9535 how = SIG_UNBLOCK;
9536 break;
9537 case TARGET_SIG_SETMASK:
9538 how = SIG_SETMASK;
9539 break;
9540 default:
Richard Henderson259841c2018-08-18 12:01:09 -07009541 return -TARGET_EINVAL;
Richard Hendersona5b3b132010-05-03 10:07:55 -07009542 }
9543 mask = arg2;
9544 target_to_host_old_sigset(&set, &mask);
9545
Peter Maydell3d3efba2016-05-27 15:51:49 +01009546 ret = do_sigprocmask(how, &set, &oldset);
Richard Hendersona5b3b132010-05-03 10:07:55 -07009547 if (!is_error(ret)) {
9548 host_to_target_old_sigset(&mask, &oldset);
9549 ret = mask;
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02009550 cpu_env->ir[IR_V0] = 0; /* force no error */
Richard Hendersona5b3b132010-05-03 10:07:55 -07009551 }
9552#else
bellard66fb9762003-03-23 01:06:05 +00009553 sigset_t set, oldset, *set_ptr;
Richard Hendersona5b3b132010-05-03 10:07:55 -07009554 int how;
ths3b46e622007-09-17 08:09:54 +00009555
pbrook53a59602006-03-25 19:31:22 +00009556 if (arg2) {
Patrick Ventureebce1712022-01-26 13:25:59 -08009557 p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1);
9558 if (!p) {
9559 return -TARGET_EFAULT;
9560 }
9561 target_to_host_old_sigset(&set, p);
9562 unlock_user(p, arg2, 0);
9563 set_ptr = &set;
Richard Hendersona5b3b132010-05-03 10:07:55 -07009564 switch (arg1) {
bellard66fb9762003-03-23 01:06:05 +00009565 case TARGET_SIG_BLOCK:
9566 how = SIG_BLOCK;
9567 break;
9568 case TARGET_SIG_UNBLOCK:
9569 how = SIG_UNBLOCK;
9570 break;
9571 case TARGET_SIG_SETMASK:
9572 how = SIG_SETMASK;
9573 break;
9574 default:
Richard Henderson259841c2018-08-18 12:01:09 -07009575 return -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00009576 }
bellard66fb9762003-03-23 01:06:05 +00009577 } else {
9578 how = 0;
9579 set_ptr = NULL;
9580 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01009581 ret = do_sigprocmask(how, set_ptr, &oldset);
pbrook53a59602006-03-25 19:31:22 +00009582 if (!is_error(ret) && arg3) {
Anthony Liguoric227f092009-10-01 16:12:16 -05009583 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009584 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009585 host_to_target_old_sigset(p, &oldset);
Anthony Liguoric227f092009-10-01 16:12:16 -05009586 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00009587 }
Richard Hendersona5b3b132010-05-03 10:07:55 -07009588#endif
bellard66fb9762003-03-23 01:06:05 +00009589 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009590 return ret;
thse5febef2007-04-01 18:31:35 +00009591#endif
bellard66fb9762003-03-23 01:06:05 +00009592 case TARGET_NR_rt_sigprocmask:
9593 {
9594 int how = arg1;
9595 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00009596
Peter Maydellc8157012016-06-30 14:23:24 +01009597 if (arg4 != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009598 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01009599 }
9600
pbrook53a59602006-03-25 19:31:22 +00009601 if (arg2) {
Shu-Chun Wengd3ced2a2022-01-26 13:25:58 -08009602 p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1);
9603 if (!p) {
9604 return -TARGET_EFAULT;
9605 }
9606 target_to_host_sigset(&set, p);
9607 unlock_user(p, arg2, 0);
9608 set_ptr = &set;
bellard66fb9762003-03-23 01:06:05 +00009609 switch(how) {
9610 case TARGET_SIG_BLOCK:
9611 how = SIG_BLOCK;
9612 break;
9613 case TARGET_SIG_UNBLOCK:
9614 how = SIG_UNBLOCK;
9615 break;
9616 case TARGET_SIG_SETMASK:
9617 how = SIG_SETMASK;
9618 break;
9619 default:
Richard Henderson259841c2018-08-18 12:01:09 -07009620 return -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00009621 }
bellard66fb9762003-03-23 01:06:05 +00009622 } else {
9623 how = 0;
9624 set_ptr = NULL;
9625 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01009626 ret = do_sigprocmask(how, set_ptr, &oldset);
pbrook53a59602006-03-25 19:31:22 +00009627 if (!is_error(ret) && arg3) {
Anthony Liguoric227f092009-10-01 16:12:16 -05009628 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009629 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009630 host_to_target_sigset(p, &oldset);
Anthony Liguoric227f092009-10-01 16:12:16 -05009631 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00009632 }
9633 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009634 return ret;
thse5febef2007-04-01 18:31:35 +00009635#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00009636 case TARGET_NR_sigpending:
9637 {
9638 sigset_t set;
9639 ret = get_errno(sigpending(&set));
9640 if (!is_error(ret)) {
Anthony Liguoric227f092009-10-01 16:12:16 -05009641 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009642 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009643 host_to_target_old_sigset(p, &set);
Anthony Liguoric227f092009-10-01 16:12:16 -05009644 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00009645 }
9646 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009647 return ret;
thse5febef2007-04-01 18:31:35 +00009648#endif
bellard66fb9762003-03-23 01:06:05 +00009649 case TARGET_NR_rt_sigpending:
9650 {
9651 sigset_t set;
Peter Maydellc8157012016-06-30 14:23:24 +01009652
9653 /* Yes, this check is >, not != like most. We follow the kernel's
9654 * logic and it does it like this because it implements
9655 * NR_sigpending through the same code path, and in that case
9656 * the old_sigset_t is smaller in size.
9657 */
9658 if (arg2 > sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009659 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01009660 }
9661
bellard66fb9762003-03-23 01:06:05 +00009662 ret = get_errno(sigpending(&set));
9663 if (!is_error(ret)) {
Anthony Liguoric227f092009-10-01 16:12:16 -05009664 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009665 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009666 host_to_target_sigset(p, &set);
Anthony Liguoric227f092009-10-01 16:12:16 -05009667 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00009668 }
9669 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009670 return ret;
thse5febef2007-04-01 18:31:35 +00009671#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00009672 case TARGET_NR_sigsuspend:
9673 {
Richard Henderson0a99f092022-03-15 01:43:05 -07009674 sigset_t *set;
9675
Richard Hendersonf43ce122010-05-03 10:07:54 -07009676#if defined(TARGET_ALPHA)
Richard Henderson0a99f092022-03-15 01:43:05 -07009677 TaskState *ts = cpu->opaque;
Richard Henderson7fb5ef32022-03-15 01:43:04 -07009678 /* target_to_host_old_sigset will bswap back */
9679 abi_ulong mask = tswapal(arg1);
Richard Henderson0a99f092022-03-15 01:43:05 -07009680 set = &ts->sigsuspend_mask;
9681 target_to_host_old_sigset(set, &mask);
Richard Hendersonf43ce122010-05-03 10:07:54 -07009682#else
Richard Henderson0a99f092022-03-15 01:43:05 -07009683 ret = process_sigsuspend_mask(&set, arg1, sizeof(target_sigset_t));
9684 if (ret != 0) {
9685 return ret;
Peter Maydell3d3efba2016-05-27 15:51:49 +01009686 }
Richard Henderson0a99f092022-03-15 01:43:05 -07009687#endif
9688 ret = get_errno(safe_rt_sigsuspend(set, SIGSET_T_SIZE));
9689 finish_sigsuspend_mask(ret);
bellard66fb9762003-03-23 01:06:05 +00009690 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009691 return ret;
thse5febef2007-04-01 18:31:35 +00009692#endif
bellard66fb9762003-03-23 01:06:05 +00009693 case TARGET_NR_rt_sigsuspend:
9694 {
Richard Henderson0a99f092022-03-15 01:43:05 -07009695 sigset_t *set;
Peter Maydellc8157012016-06-30 14:23:24 +01009696
Richard Henderson0a99f092022-03-15 01:43:05 -07009697 ret = process_sigsuspend_mask(&set, arg1, arg2);
9698 if (ret != 0) {
9699 return ret;
Peter Maydellc8157012016-06-30 14:23:24 +01009700 }
Richard Henderson0a99f092022-03-15 01:43:05 -07009701 ret = get_errno(safe_rt_sigsuspend(set, SIGSET_T_SIZE));
9702 finish_sigsuspend_mask(ret);
bellard66fb9762003-03-23 01:06:05 +00009703 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009704 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -07009705#ifdef TARGET_NR_rt_sigtimedwait
bellard66fb9762003-03-23 01:06:05 +00009706 case TARGET_NR_rt_sigtimedwait:
9707 {
bellard66fb9762003-03-23 01:06:05 +00009708 sigset_t set;
9709 struct timespec uts, *puts;
9710 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00009711
Peter Maydellc8157012016-06-30 14:23:24 +01009712 if (arg4 != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009713 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01009714 }
9715
Anthony Liguoric227f092009-10-01 16:12:16 -05009716 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009717 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009718 target_to_host_sigset(&set, p);
9719 unlock_user(p, arg1, 0);
9720 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00009721 puts = &uts;
Filip Bozuta4d213002020-07-24 20:16:51 +02009722 if (target_to_host_timespec(puts, arg3)) {
9723 return -TARGET_EFAULT;
9724 }
bellard66fb9762003-03-23 01:06:05 +00009725 } else {
9726 puts = NULL;
9727 }
Peter Maydellb3f82332016-06-06 19:58:08 +01009728 ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts,
9729 SIGSET_T_SIZE));
Petar Jovanovic974a1962014-03-03 15:07:41 +01009730 if (!is_error(ret)) {
9731 if (arg2) {
9732 p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t),
9733 0);
9734 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009735 return -TARGET_EFAULT;
Petar Jovanovic974a1962014-03-03 15:07:41 +01009736 }
9737 host_to_target_siginfo(p, &uinfo);
9738 unlock_user(p, arg2, sizeof(target_siginfo_t));
9739 }
9740 ret = host_to_target_signal(ret);
bellard66fb9762003-03-23 01:06:05 +00009741 }
9742 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009743 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -07009744#endif
Filip Bozutaddcbde12020-08-24 21:21:16 +02009745#ifdef TARGET_NR_rt_sigtimedwait_time64
9746 case TARGET_NR_rt_sigtimedwait_time64:
9747 {
9748 sigset_t set;
9749 struct timespec uts, *puts;
9750 siginfo_t uinfo;
9751
9752 if (arg4 != sizeof(target_sigset_t)) {
9753 return -TARGET_EINVAL;
9754 }
9755
9756 p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
9757 if (!p) {
9758 return -TARGET_EFAULT;
9759 }
9760 target_to_host_sigset(&set, p);
9761 unlock_user(p, arg1, 0);
9762 if (arg3) {
9763 puts = &uts;
9764 if (target_to_host_timespec64(puts, arg3)) {
9765 return -TARGET_EFAULT;
9766 }
9767 } else {
9768 puts = NULL;
9769 }
9770 ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts,
9771 SIGSET_T_SIZE));
9772 if (!is_error(ret)) {
9773 if (arg2) {
9774 p = lock_user(VERIFY_WRITE, arg2,
9775 sizeof(target_siginfo_t), 0);
9776 if (!p) {
9777 return -TARGET_EFAULT;
9778 }
9779 host_to_target_siginfo(p, &uinfo);
9780 unlock_user(p, arg2, sizeof(target_siginfo_t));
9781 }
9782 ret = host_to_target_signal(ret);
9783 }
9784 }
9785 return ret;
9786#endif
bellard66fb9762003-03-23 01:06:05 +00009787 case TARGET_NR_rt_sigqueueinfo:
9788 {
9789 siginfo_t uinfo;
Peter Maydell4debae62016-06-20 15:50:36 +01009790
9791 p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
9792 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009793 return -TARGET_EFAULT;
Peter Maydell4debae62016-06-20 15:50:36 +01009794 }
pbrook53a59602006-03-25 19:31:22 +00009795 target_to_host_siginfo(&uinfo, p);
Miloš Stojanovićd8b6d892017-05-15 16:59:44 +02009796 unlock_user(p, arg3, 0);
fanwenjie9b9145f2022-08-31 11:55:25 +08009797 ret = get_errno(sys_rt_sigqueueinfo(arg1, target_to_host_signal(arg2), &uinfo));
bellard66fb9762003-03-23 01:06:05 +00009798 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009799 return ret;
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +02009800 case TARGET_NR_rt_tgsigqueueinfo:
9801 {
9802 siginfo_t uinfo;
9803
9804 p = lock_user(VERIFY_READ, arg4, sizeof(target_siginfo_t), 1);
9805 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009806 return -TARGET_EFAULT;
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +02009807 }
9808 target_to_host_siginfo(&uinfo, p);
9809 unlock_user(p, arg4, 0);
fanwenjie9b9145f2022-08-31 11:55:25 +08009810 ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, target_to_host_signal(arg3), &uinfo));
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +02009811 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009812 return ret;
thse5febef2007-04-01 18:31:35 +00009813#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00009814 case TARGET_NR_sigreturn:
Peter Maydell3d3efba2016-05-27 15:51:49 +01009815 if (block_signals()) {
Richard Hendersonaf254a22021-11-22 19:47:33 +01009816 return -QEMU_ERESTARTSYS;
Peter Maydell3d3efba2016-05-27 15:51:49 +01009817 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009818 return do_sigreturn(cpu_env);
thse5febef2007-04-01 18:31:35 +00009819#endif
bellard66fb9762003-03-23 01:06:05 +00009820 case TARGET_NR_rt_sigreturn:
Peter Maydell3d3efba2016-05-27 15:51:49 +01009821 if (block_signals()) {
Richard Hendersonaf254a22021-11-22 19:47:33 +01009822 return -QEMU_ERESTARTSYS;
Peter Maydell3d3efba2016-05-27 15:51:49 +01009823 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009824 return do_rt_sigreturn(cpu_env);
bellard31e31b82003-02-18 22:55:36 +00009825 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00009826 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009827 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009828 ret = get_errno(sethostname(p, arg2));
9829 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009830 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009831#ifdef TARGET_NR_setrlimit
bellard31e31b82003-02-18 22:55:36 +00009832 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +00009833 {
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03009834 int resource = target_to_host_resource(arg1);
pbrook53a59602006-03-25 19:31:22 +00009835 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00009836 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +00009837 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009838 return -TARGET_EFAULT;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09009839 rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
9840 rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00009841 unlock_user_struct(target_rlim, arg2, 0);
Max Filippov5dfa88f2018-09-17 11:13:14 -07009842 /*
9843 * If we just passed through resource limit settings for memory then
9844 * they would also apply to QEMU's own allocations, and QEMU will
9845 * crash or hang or die if its allocations fail. Ideally we would
9846 * track the guest allocations in QEMU and apply the limits ourselves.
9847 * For now, just tell the guest the call succeeded but don't actually
9848 * limit anything.
9849 */
9850 if (resource != RLIMIT_AS &&
9851 resource != RLIMIT_DATA &&
9852 resource != RLIMIT_STACK) {
9853 return get_errno(setrlimit(resource, &rlim));
9854 } else {
9855 return 0;
9856 }
bellard9de5e442003-03-23 16:49:39 +00009857 }
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009858#endif
9859#ifdef TARGET_NR_getrlimit
bellard31e31b82003-02-18 22:55:36 +00009860 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00009861 {
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03009862 int resource = target_to_host_resource(arg1);
pbrook53a59602006-03-25 19:31:22 +00009863 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00009864 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00009865
bellard9de5e442003-03-23 16:49:39 +00009866 ret = get_errno(getrlimit(resource, &rlim));
9867 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00009868 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009869 return -TARGET_EFAULT;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09009870 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
9871 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00009872 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00009873 }
9874 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009875 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009876#endif
bellard31e31b82003-02-18 22:55:36 +00009877 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00009878 {
9879 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00009880 ret = get_errno(getrusage(arg1, &rusage));
9881 if (!is_error(ret)) {
Petar Jovanovica39fb272014-04-08 19:24:30 +02009882 ret = host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00009883 }
9884 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009885 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -07009886#if defined(TARGET_NR_gettimeofday)
bellard31e31b82003-02-18 22:55:36 +00009887 case TARGET_NR_gettimeofday:
9888 {
bellard31e31b82003-02-18 22:55:36 +00009889 struct timeval tv;
Richard Hendersona52f5f82020-02-12 19:22:23 -08009890 struct timezone tz;
9891
9892 ret = get_errno(gettimeofday(&tv, &tz));
bellard31e31b82003-02-18 22:55:36 +00009893 if (!is_error(ret)) {
Richard Hendersona52f5f82020-02-12 19:22:23 -08009894 if (arg1 && copy_to_user_timeval(arg1, &tv)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009895 return -TARGET_EFAULT;
Richard Hendersona52f5f82020-02-12 19:22:23 -08009896 }
9897 if (arg2 && copy_to_user_timezone(arg2, &tz)) {
9898 return -TARGET_EFAULT;
9899 }
bellard31e31b82003-02-18 22:55:36 +00009900 }
9901 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009902 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -07009903#endif
9904#if defined(TARGET_NR_settimeofday)
bellard31e31b82003-02-18 22:55:36 +00009905 case TARGET_NR_settimeofday:
9906 {
Paul Burtonb67d8032014-06-22 11:25:41 +01009907 struct timeval tv, *ptv = NULL;
Paul Burtonef4467e2014-06-22 11:25:40 +01009908 struct timezone tz, *ptz = NULL;
9909
Paul Burtonb67d8032014-06-22 11:25:41 +01009910 if (arg1) {
9911 if (copy_from_user_timeval(&tv, arg1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009912 return -TARGET_EFAULT;
Paul Burtonb67d8032014-06-22 11:25:41 +01009913 }
9914 ptv = &tv;
9915 }
Paul Burtonef4467e2014-06-22 11:25:40 +01009916
9917 if (arg2) {
9918 if (copy_from_user_timezone(&tz, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009919 return -TARGET_EFAULT;
Paul Burtonef4467e2014-06-22 11:25:40 +01009920 }
9921 ptz = &tz;
9922 }
9923
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009924 return get_errno(settimeofday(ptv, ptz));
bellard31e31b82003-02-18 22:55:36 +00009925 }
Alistair Francis859e8a82020-03-12 15:13:49 -07009926#endif
Laurent Vivier9468a5d2013-01-10 22:30:50 +01009927#if defined(TARGET_NR_select)
bellard31e31b82003-02-18 22:55:36 +00009928 case TARGET_NR_select:
Laurent Vivier5457dc92016-07-08 01:17:27 +02009929#if defined(TARGET_WANT_NI_OLD_SELECT)
9930 /* some architectures used to have old_select here
9931 * but now ENOSYS it.
9932 */
9933 ret = -TARGET_ENOSYS;
9934#elif defined(TARGET_WANT_OLD_SYS_SELECT)
9935 ret = do_old_select(arg1);
Laurent Vivier9468a5d2013-01-10 22:30:50 +01009936#else
Laurent Vivier5457dc92016-07-08 01:17:27 +02009937 ret = do_select(arg1, arg2, arg3, arg4, arg5);
Laurent Vivier9468a5d2013-01-10 22:30:50 +01009938#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009939 return ret;
bellard048f6b42005-11-26 18:47:20 +00009940#endif
Riku Voipio9e423822010-05-07 12:28:05 +00009941#ifdef TARGET_NR_pselect6
9942 case TARGET_NR_pselect6:
Filip Bozutae5ce9682020-08-25 00:30:49 +02009943 return do_pselect6(arg1, arg2, arg3, arg4, arg5, arg6, false);
9944#endif
9945#ifdef TARGET_NR_pselect6_time64
9946 case TARGET_NR_pselect6_time64:
9947 return do_pselect6(arg1, arg2, arg3, arg4, arg5, arg6, true);
Riku Voipio9e423822010-05-07 12:28:05 +00009948#endif
Chen Gang704eff62015-08-21 05:37:33 +08009949#ifdef TARGET_NR_symlink
bellard31e31b82003-02-18 22:55:36 +00009950 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00009951 {
9952 void *p2;
9953 p = lock_user_string(arg1);
9954 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00009955 if (!p || !p2)
9956 ret = -TARGET_EFAULT;
9957 else
9958 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00009959 unlock_user(p2, arg2, 0);
9960 unlock_user(p, arg1, 0);
9961 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009962 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009963#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01009964#if defined(TARGET_NR_symlinkat)
thsf0b62432007-09-24 09:25:40 +00009965 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00009966 {
bellard579a97f2007-11-11 14:26:47 +00009967 void *p2;
thsf0b62432007-09-24 09:25:40 +00009968 p = lock_user_string(arg1);
9969 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00009970 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00009971 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00009972 else
Peter Maydellc0d472b2013-06-12 16:20:21 +01009973 ret = get_errno(symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00009974 unlock_user(p2, arg3, 0);
9975 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00009976 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009977 return ret;
thsf0b62432007-09-24 09:25:40 +00009978#endif
Chen Gang704eff62015-08-21 05:37:33 +08009979#ifdef TARGET_NR_readlink
bellard31e31b82003-02-18 22:55:36 +00009980 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00009981 {
Andreas Schwab463d8e72013-07-02 14:04:12 +01009982 void *p2;
pbrook53a59602006-03-25 19:31:22 +00009983 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00009984 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
Andreas Schwab463d8e72013-07-02 14:04:12 +01009985 if (!p || !p2) {
bellard579a97f2007-11-11 14:26:47 +00009986 ret = -TARGET_EFAULT;
Mike Frysingerf17f4982014-08-08 09:40:25 +09009987 } else if (!arg3) {
9988 /* Short circuit this for the magic exe check. */
9989 ret = -TARGET_EINVAL;
Andreas Schwab463d8e72013-07-02 14:04:12 +01009990 } else if (is_proc_myself((const char *)p, "exe")) {
9991 char real[PATH_MAX], *temp;
9992 temp = realpath(exec_path, real);
Mike Frysingerf17f4982014-08-08 09:40:25 +09009993 /* Return value is # of bytes that we wrote to the buffer. */
9994 if (temp == NULL) {
9995 ret = get_errno(-1);
9996 } else {
9997 /* Don't worry about sign mismatch as earlier mapping
9998 * logic would have thrown a bad address error. */
9999 ret = MIN(strlen(real), arg3);
10000 /* We cannot NUL terminate the string. */
10001 memcpy(p2, real, ret);
10002 }
Andreas Schwab463d8e72013-07-02 14:04:12 +010010003 } else {
10004 ret = get_errno(readlink(path(p), p2, arg3));
aurel32d088d662009-01-30 20:09:01 +000010005 }
pbrook53a59602006-03-25 19:31:22 +000010006 unlock_user(p2, arg2, ret);
10007 unlock_user(p, arg1, 0);
10008 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010009 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080010010#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +010010011#if defined(TARGET_NR_readlinkat)
ths5e0ccb12007-09-24 09:26:10 +000010012 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +000010013 {
bellard579a97f2007-11-11 14:26:47 +000010014 void *p2;
ths5e0ccb12007-09-24 09:26:10 +000010015 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +000010016 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
Andreas Schwab463d8e72013-07-02 14:04:12 +010010017 if (!p || !p2) {
10018 ret = -TARGET_EFAULT;
Jameson Nash65d48302022-08-08 15:07:27 -040010019 } else if (!arg4) {
10020 /* Short circuit this for the magic exe check. */
10021 ret = -TARGET_EINVAL;
Andreas Schwab463d8e72013-07-02 14:04:12 +010010022 } else if (is_proc_myself((const char *)p, "exe")) {
10023 char real[PATH_MAX], *temp;
10024 temp = realpath(exec_path, real);
Jameson Nash65d48302022-08-08 15:07:27 -040010025 /* Return value is # of bytes that we wrote to the buffer. */
10026 if (temp == NULL) {
10027 ret = get_errno(-1);
10028 } else {
10029 /* Don't worry about sign mismatch as earlier mapping
10030 * logic would have thrown a bad address error. */
10031 ret = MIN(strlen(real), arg4);
10032 /* We cannot NUL terminate the string. */
10033 memcpy(p2, real, ret);
10034 }
Andreas Schwab463d8e72013-07-02 14:04:12 +010010035 } else {
Peter Maydellc0d472b2013-06-12 16:20:21 +010010036 ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
Andreas Schwab463d8e72013-07-02 14:04:12 +010010037 }
bellard579a97f2007-11-11 14:26:47 +000010038 unlock_user(p2, arg3, ret);
10039 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +000010040 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010041 return ret;
ths5e0ccb12007-09-24 09:26:10 +000010042#endif
thse5febef2007-04-01 18:31:35 +000010043#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +000010044 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +000010045 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010046 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010047 ret = get_errno(swapon(p, arg2));
10048 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010049 return ret;
thse5febef2007-04-01 18:31:35 +000010050#endif
bellard31e31b82003-02-18 22:55:36 +000010051 case TARGET_NR_reboot:
Laurent Vivierc07ecc62013-01-07 11:40:06 +000010052 if (arg3 == LINUX_REBOOT_CMD_RESTART2) {
10053 /* arg4 must be ignored in all other cases */
10054 p = lock_user_string(arg4);
10055 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010056 return -TARGET_EFAULT;
Laurent Vivierc07ecc62013-01-07 11:40:06 +000010057 }
10058 ret = get_errno(reboot(arg1, arg2, arg3, p));
10059 unlock_user(p, arg4, 0);
10060 } else {
10061 ret = get_errno(reboot(arg1, arg2, arg3, NULL));
10062 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010063 return ret;
thse5febef2007-04-01 18:31:35 +000010064#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +000010065 case TARGET_NR_mmap:
Alexander Graf09701192013-09-03 20:12:15 +010010066#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
10067 (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
Ulrich Hechta4c075f2009-07-24 16:57:31 +020010068 defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \
10069 || defined(TARGET_S390X)
bellard31e31b82003-02-18 22:55:36 +000010070 {
blueswir1992f48a2007-10-14 16:27:31 +000010071 abi_ulong *v;
10072 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +000010073 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010074 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +020010075 v1 = tswapal(v[0]);
10076 v2 = tswapal(v[1]);
10077 v3 = tswapal(v[2]);
10078 v4 = tswapal(v[3]);
10079 v5 = tswapal(v[4]);
10080 v6 = tswapal(v[5]);
pbrook53a59602006-03-25 19:31:22 +000010081 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +000010082 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +000010083 target_to_host_bitmask(v4, mmap_flags_tbl),
10084 v5, v6));
bellard31e31b82003-02-18 22:55:36 +000010085 }
bellard31e31b82003-02-18 22:55:36 +000010086#else
Richard Hendersonee1bf832021-02-12 10:48:44 -080010087 /* mmap pointers are always untagged */
ths5fafdf22007-09-16 21:08:06 +000010088 ret = get_errno(target_mmap(arg1, arg2, arg3,
10089 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +000010090 arg5,
10091 arg6));
bellard31e31b82003-02-18 22:55:36 +000010092#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010093 return ret;
thse5febef2007-04-01 18:31:35 +000010094#endif
bellarda315a142005-01-30 22:59:18 +000010095#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +000010096 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +000010097#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +000010098#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +000010099#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010100 ret = target_mmap(arg1, arg2, arg3,
10101 target_to_host_bitmask(arg4, mmap_flags_tbl),
10102 arg5, arg6 << MMAP_SHIFT);
10103 return get_errno(ret);
bellarda315a142005-01-30 22:59:18 +000010104#endif
bellard31e31b82003-02-18 22:55:36 +000010105 case TARGET_NR_munmap:
Richard Hendersonee1bf832021-02-12 10:48:44 -080010106 arg1 = cpu_untagged_addr(cpu, arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010107 return get_errno(target_munmap(arg1, arg2));
bellard9de5e442003-03-23 16:49:39 +000010108 case TARGET_NR_mprotect:
Richard Hendersonee1bf832021-02-12 10:48:44 -080010109 arg1 = cpu_untagged_addr(cpu, arg1);
Paul Brook97374d32010-06-16 13:03:51 +010010110 {
Andreas Färber0429a972013-08-26 18:14:44 +020010111 TaskState *ts = cpu->opaque;
Paul Brook97374d32010-06-16 13:03:51 +010010112 /* Special hack to detect libc making the stack executable. */
10113 if ((arg3 & PROT_GROWSDOWN)
10114 && arg1 >= ts->info->stack_limit
10115 && arg1 <= ts->info->start_stack) {
10116 arg3 &= ~PROT_GROWSDOWN;
10117 arg2 = arg2 + arg1 - ts->info->stack_limit;
10118 arg1 = ts->info->stack_limit;
10119 }
10120 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010121 return get_errno(target_mprotect(arg1, arg2, arg3));
thse5febef2007-04-01 18:31:35 +000010122#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +000010123 case TARGET_NR_mremap:
Richard Hendersonee1bf832021-02-12 10:48:44 -080010124 arg1 = cpu_untagged_addr(cpu, arg1);
10125 /* mremap new_addr (arg5) is always untagged */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010126 return get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
thse5febef2007-04-01 18:31:35 +000010127#endif
pbrook53a59602006-03-25 19:31:22 +000010128 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +000010129#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +000010130 case TARGET_NR_msync:
Richard Henderson3e8f1622021-02-12 10:48:43 -080010131 return get_errno(msync(g2h(cpu, arg1), arg2, arg3));
thse5febef2007-04-01 18:31:35 +000010132#endif
10133#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +000010134 case TARGET_NR_mlock:
Richard Henderson3e8f1622021-02-12 10:48:43 -080010135 return get_errno(mlock(g2h(cpu, arg1), arg2));
thse5febef2007-04-01 18:31:35 +000010136#endif
10137#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +000010138 case TARGET_NR_munlock:
Richard Henderson3e8f1622021-02-12 10:48:43 -080010139 return get_errno(munlock(g2h(cpu, arg1), arg2));
thse5febef2007-04-01 18:31:35 +000010140#endif
10141#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +000010142 case TARGET_NR_mlockall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010143 return get_errno(mlockall(target_to_host_mlockall_arg(arg1)));
thse5febef2007-04-01 18:31:35 +000010144#endif
10145#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +000010146 case TARGET_NR_munlockall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010147 return get_errno(munlockall());
thse5febef2007-04-01 18:31:35 +000010148#endif
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010149#ifdef TARGET_NR_truncate
bellard31e31b82003-02-18 22:55:36 +000010150 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +000010151 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010152 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010153 ret = get_errno(truncate(p, arg2));
10154 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010155 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010156#endif
10157#ifdef TARGET_NR_ftruncate
bellard31e31b82003-02-18 22:55:36 +000010158 case TARGET_NR_ftruncate:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010159 return get_errno(ftruncate(arg1, arg2));
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010160#endif
bellard31e31b82003-02-18 22:55:36 +000010161 case TARGET_NR_fchmod:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010162 return get_errno(fchmod(arg1, arg2));
Peter Maydellc0d472b2013-06-12 16:20:21 +010010163#if defined(TARGET_NR_fchmodat)
ths814d7972007-09-24 09:26:51 +000010164 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +000010165 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010166 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +010010167 ret = get_errno(fchmodat(arg1, p, arg3, 0));
bellard579a97f2007-11-11 14:26:47 +000010168 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010169 return ret;
ths814d7972007-09-24 09:26:51 +000010170#endif
bellard31e31b82003-02-18 22:55:36 +000010171 case TARGET_NR_getpriority:
Richard Henderson95c09822012-06-07 15:14:50 -070010172 /* Note that negative values are valid for getpriority, so we must
10173 differentiate based on errno settings. */
10174 errno = 0;
10175 ret = getpriority(arg1, arg2);
10176 if (ret == -1 && errno != 0) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010177 return -host_to_target_errno(errno);
Richard Henderson95c09822012-06-07 15:14:50 -070010178 }
10179#ifdef TARGET_ALPHA
10180 /* Return value is the unbiased priority. Signal no error. */
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020010181 cpu_env->ir[IR_V0] = 0;
Richard Henderson95c09822012-06-07 15:14:50 -070010182#else
10183 /* Return value is a biased priority to avoid negative numbers. */
10184 ret = 20 - ret;
10185#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010186 return ret;
bellard31e31b82003-02-18 22:55:36 +000010187 case TARGET_NR_setpriority:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010188 return get_errno(setpriority(arg1, arg2, arg3));
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010189#ifdef TARGET_NR_statfs
bellard31e31b82003-02-18 22:55:36 +000010190 case TARGET_NR_statfs:
Richard Henderson2852aaf2018-08-18 12:01:06 -070010191 if (!(p = lock_user_string(arg1))) {
10192 return -TARGET_EFAULT;
10193 }
pbrook53a59602006-03-25 19:31:22 +000010194 ret = get_errno(statfs(path(p), &stfs));
10195 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +000010196 convert_statfs:
10197 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +000010198 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +000010199
bellard579a97f2007-11-11 14:26:47 +000010200 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010201 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000010202 __put_user(stfs.f_type, &target_stfs->f_type);
10203 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
10204 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
10205 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
10206 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
10207 __put_user(stfs.f_files, &target_stfs->f_files);
10208 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
10209 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
10210 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
10211 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
Alexander Graf229d3372012-09-19 04:39:53 +020010212 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
Shea Levyd4247ec2018-03-01 06:15:00 -050010213#ifdef _STATFS_F_FLAGS
10214 __put_user(stfs.f_flags, &target_stfs->f_flags);
10215#else
10216 __put_user(0, &target_stfs->f_flags);
10217#endif
Alexander Graf229d3372012-09-19 04:39:53 +020010218 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
pbrook53a59602006-03-25 19:31:22 +000010219 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +000010220 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010221 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010222#endif
10223#ifdef TARGET_NR_fstatfs
bellard31e31b82003-02-18 22:55:36 +000010224 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +000010225 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +000010226 goto convert_statfs;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010227#endif
bellard56c8f682005-11-28 22:28:41 +000010228#ifdef TARGET_NR_statfs64
10229 case TARGET_NR_statfs64:
Richard Henderson2852aaf2018-08-18 12:01:06 -070010230 if (!(p = lock_user_string(arg1))) {
10231 return -TARGET_EFAULT;
10232 }
pbrook53a59602006-03-25 19:31:22 +000010233 ret = get_errno(statfs(path(p), &stfs));
10234 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +000010235 convert_statfs64:
10236 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +000010237 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +000010238
bellard579a97f2007-11-11 14:26:47 +000010239 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010240 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000010241 __put_user(stfs.f_type, &target_stfs->f_type);
10242 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
10243 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
10244 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
10245 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
10246 __put_user(stfs.f_files, &target_stfs->f_files);
10247 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
10248 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
10249 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
10250 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
Alexander Graf229d3372012-09-19 04:39:53 +020010251 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
Frajob94e2b42020-01-30 15:00:30 +020010252#ifdef _STATFS_F_FLAGS
10253 __put_user(stfs.f_flags, &target_stfs->f_flags);
10254#else
10255 __put_user(0, &target_stfs->f_flags);
10256#endif
Alexander Graf229d3372012-09-19 04:39:53 +020010257 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
bellard579a97f2007-11-11 14:26:47 +000010258 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +000010259 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010260 return ret;
bellard56c8f682005-11-28 22:28:41 +000010261 case TARGET_NR_fstatfs64:
10262 ret = get_errno(fstatfs(arg1, &stfs));
10263 goto convert_statfs64;
10264#endif
thse5febef2007-04-01 18:31:35 +000010265#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +000010266 case TARGET_NR_socketcall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010267 return do_socketcall(arg1, arg2);
thse5febef2007-04-01 18:31:35 +000010268#endif
bellard3532fa72006-06-24 15:06:03 +000010269#ifdef TARGET_NR_accept
10270 case TARGET_NR_accept:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010271 return do_accept4(arg1, arg2, arg3, 0);
Peter Maydella94b4982013-02-08 04:35:04 +000010272#endif
10273#ifdef TARGET_NR_accept4
10274 case TARGET_NR_accept4:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010275 return do_accept4(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +000010276#endif
10277#ifdef TARGET_NR_bind
10278 case TARGET_NR_bind:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010279 return do_bind(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +000010280#endif
10281#ifdef TARGET_NR_connect
10282 case TARGET_NR_connect:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010283 return do_connect(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +000010284#endif
10285#ifdef TARGET_NR_getpeername
10286 case TARGET_NR_getpeername:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010287 return do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +000010288#endif
10289#ifdef TARGET_NR_getsockname
10290 case TARGET_NR_getsockname:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010291 return do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +000010292#endif
10293#ifdef TARGET_NR_getsockopt
10294 case TARGET_NR_getsockopt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010295 return do_getsockopt(arg1, arg2, arg3, arg4, arg5);
bellard3532fa72006-06-24 15:06:03 +000010296#endif
10297#ifdef TARGET_NR_listen
10298 case TARGET_NR_listen:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010299 return get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +000010300#endif
10301#ifdef TARGET_NR_recv
10302 case TARGET_NR_recv:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010303 return do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +000010304#endif
10305#ifdef TARGET_NR_recvfrom
10306 case TARGET_NR_recvfrom:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010307 return do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +000010308#endif
10309#ifdef TARGET_NR_recvmsg
10310 case TARGET_NR_recvmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010311 return do_sendrecvmsg(arg1, arg2, arg3, 0);
bellard3532fa72006-06-24 15:06:03 +000010312#endif
10313#ifdef TARGET_NR_send
10314 case TARGET_NR_send:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010315 return do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +000010316#endif
10317#ifdef TARGET_NR_sendmsg
10318 case TARGET_NR_sendmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010319 return do_sendrecvmsg(arg1, arg2, arg3, 1);
bellard3532fa72006-06-24 15:06:03 +000010320#endif
Alexander Graff19e00d2014-03-02 19:36:42 +000010321#ifdef TARGET_NR_sendmmsg
10322 case TARGET_NR_sendmmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010323 return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1);
Alistair Francis859e8a82020-03-12 15:13:49 -070010324#endif
10325#ifdef TARGET_NR_recvmmsg
Alexander Graff19e00d2014-03-02 19:36:42 +000010326 case TARGET_NR_recvmmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010327 return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0);
Alexander Graff19e00d2014-03-02 19:36:42 +000010328#endif
bellard3532fa72006-06-24 15:06:03 +000010329#ifdef TARGET_NR_sendto
10330 case TARGET_NR_sendto:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010331 return do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +000010332#endif
10333#ifdef TARGET_NR_shutdown
10334 case TARGET_NR_shutdown:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010335 return get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +000010336#endif
Laurent Vivierf894efd2016-02-21 10:56:23 +010010337#if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
10338 case TARGET_NR_getrandom:
10339 p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
10340 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010341 return -TARGET_EFAULT;
Laurent Vivierf894efd2016-02-21 10:56:23 +010010342 }
10343 ret = get_errno(getrandom(p, arg2, arg3));
10344 unlock_user(p, arg1, ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010345 return ret;
Laurent Vivierf894efd2016-02-21 10:56:23 +010010346#endif
bellard3532fa72006-06-24 15:06:03 +000010347#ifdef TARGET_NR_socket
10348 case TARGET_NR_socket:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010349 return do_socket(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +000010350#endif
10351#ifdef TARGET_NR_socketpair
10352 case TARGET_NR_socketpair:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010353 return do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +000010354#endif
10355#ifdef TARGET_NR_setsockopt
10356 case TARGET_NR_setsockopt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010357 return do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
bellard3532fa72006-06-24 15:06:03 +000010358#endif
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010359#if defined(TARGET_NR_syslog)
bellard31e31b82003-02-18 22:55:36 +000010360 case TARGET_NR_syslog:
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010361 {
10362 int len = arg2;
ths7494b0f2007-02-11 18:26:53 +000010363
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010364 switch (arg1) {
10365 case TARGET_SYSLOG_ACTION_CLOSE: /* Close log */
10366 case TARGET_SYSLOG_ACTION_OPEN: /* Open log */
10367 case TARGET_SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
10368 case TARGET_SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging */
10369 case TARGET_SYSLOG_ACTION_CONSOLE_ON: /* Enable logging */
10370 case TARGET_SYSLOG_ACTION_CONSOLE_LEVEL: /* Set messages level */
10371 case TARGET_SYSLOG_ACTION_SIZE_UNREAD: /* Number of chars */
10372 case TARGET_SYSLOG_ACTION_SIZE_BUFFER: /* Size of the buffer */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010373 return get_errno(sys_syslog((int)arg1, NULL, (int)arg3));
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010374 case TARGET_SYSLOG_ACTION_READ: /* Read from log */
10375 case TARGET_SYSLOG_ACTION_READ_CLEAR: /* Read/clear msgs */
10376 case TARGET_SYSLOG_ACTION_READ_ALL: /* Read last messages */
10377 {
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010378 if (len < 0) {
Richard Henderson259841c2018-08-18 12:01:09 -070010379 return -TARGET_EINVAL;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010380 }
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010381 if (len == 0) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010382 return 0;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010383 }
10384 p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
10385 if (!p) {
Richard Henderson259841c2018-08-18 12:01:09 -070010386 return -TARGET_EFAULT;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010387 }
10388 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
10389 unlock_user(p, arg2, arg3);
10390 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010391 return ret;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010392 default:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010393 return -TARGET_EINVAL;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010394 }
10395 }
10396 break;
10397#endif
bellard31e31b82003-02-18 22:55:36 +000010398 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +000010399 {
bellard66fb9762003-03-23 01:06:05 +000010400 struct itimerval value, ovalue, *pvalue;
10401
pbrook53a59602006-03-25 19:31:22 +000010402 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +000010403 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +000010404 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
10405 || copy_from_user_timeval(&pvalue->it_value,
10406 arg2 + sizeof(struct target_timeval)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010407 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +000010408 } else {
10409 pvalue = NULL;
10410 }
10411 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +000010412 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +000010413 if (copy_to_user_timeval(arg3,
10414 &ovalue.it_interval)
10415 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
10416 &ovalue.it_value))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010417 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +000010418 }
10419 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010420 return ret;
bellard31e31b82003-02-18 22:55:36 +000010421 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +000010422 {
bellard66fb9762003-03-23 01:06:05 +000010423 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +000010424
bellard66fb9762003-03-23 01:06:05 +000010425 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +000010426 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +000010427 if (copy_to_user_timeval(arg2,
10428 &value.it_interval)
10429 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
10430 &value.it_value))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010431 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +000010432 }
10433 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010434 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080010435#ifdef TARGET_NR_stat
bellard31e31b82003-02-18 22:55:36 +000010436 case TARGET_NR_stat:
Richard Henderson2852aaf2018-08-18 12:01:06 -070010437 if (!(p = lock_user_string(arg1))) {
10438 return -TARGET_EFAULT;
10439 }
pbrook53a59602006-03-25 19:31:22 +000010440 ret = get_errno(stat(path(p), &st));
10441 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +000010442 goto do_stat;
Chen Gang704eff62015-08-21 05:37:33 +080010443#endif
10444#ifdef TARGET_NR_lstat
bellard31e31b82003-02-18 22:55:36 +000010445 case TARGET_NR_lstat:
Richard Henderson2852aaf2018-08-18 12:01:06 -070010446 if (!(p = lock_user_string(arg1))) {
10447 return -TARGET_EFAULT;
10448 }
pbrook53a59602006-03-25 19:31:22 +000010449 ret = get_errno(lstat(path(p), &st));
10450 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +000010451 goto do_stat;
Chen Gang704eff62015-08-21 05:37:33 +080010452#endif
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010453#ifdef TARGET_NR_fstat
bellard31e31b82003-02-18 22:55:36 +000010454 case TARGET_NR_fstat:
10455 {
10456 ret = get_errno(fstat(arg1, &st));
Chen Gang704eff62015-08-21 05:37:33 +080010457#if defined(TARGET_NR_stat) || defined(TARGET_NR_lstat)
bellard31e31b82003-02-18 22:55:36 +000010458 do_stat:
Chen Gang704eff62015-08-21 05:37:33 +080010459#endif
bellard31e31b82003-02-18 22:55:36 +000010460 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +000010461 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +000010462
bellard579a97f2007-11-11 14:26:47 +000010463 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010464 return -TARGET_EFAULT;
Ulrich Hecht12727912009-07-24 19:10:32 +020010465 memset(target_st, 0, sizeof(*target_st));
bellardd2fd1af2007-11-14 18:08:56 +000010466 __put_user(st.st_dev, &target_st->st_dev);
10467 __put_user(st.st_ino, &target_st->st_ino);
10468 __put_user(st.st_mode, &target_st->st_mode);
10469 __put_user(st.st_uid, &target_st->st_uid);
10470 __put_user(st.st_gid, &target_st->st_gid);
10471 __put_user(st.st_nlink, &target_st->st_nlink);
10472 __put_user(st.st_rdev, &target_st->st_rdev);
10473 __put_user(st.st_size, &target_st->st_size);
10474 __put_user(st.st_blksize, &target_st->st_blksize);
10475 __put_user(st.st_blocks, &target_st->st_blocks);
10476 __put_user(st.st_atime, &target_st->target_st_atime);
10477 __put_user(st.st_mtime, &target_st->target_st_mtime);
10478 __put_user(st.st_ctime, &target_st->target_st_ctime);
Michael Forneyfebf6fa2021-05-25 20:55:31 -070010479#if defined(HAVE_STRUCT_STAT_ST_ATIM) && defined(TARGET_STAT_HAVE_NSEC)
Chen-Yu Tsai5f992db2019-05-23 00:21:47 +080010480 __put_user(st.st_atim.tv_nsec,
10481 &target_st->target_st_atime_nsec);
10482 __put_user(st.st_mtim.tv_nsec,
10483 &target_st->target_st_mtime_nsec);
10484 __put_user(st.st_ctim.tv_nsec,
10485 &target_st->target_st_ctime_nsec);
10486#endif
pbrook53a59602006-03-25 19:31:22 +000010487 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +000010488 }
10489 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010490 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010491#endif
bellard31e31b82003-02-18 22:55:36 +000010492 case TARGET_NR_vhangup:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010493 return get_errno(vhangup());
bellard42ad6ae2005-01-03 22:48:11 +000010494#ifdef TARGET_NR_syscall
10495 case TARGET_NR_syscall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010496 return do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5,
10497 arg6, arg7, arg8, 0);
bellard42ad6ae2005-01-03 22:48:11 +000010498#endif
Alistair Francis859e8a82020-03-12 15:13:49 -070010499#if defined(TARGET_NR_wait4)
bellard31e31b82003-02-18 22:55:36 +000010500 case TARGET_NR_wait4:
10501 {
10502 int status;
blueswir1992f48a2007-10-14 16:27:31 +000010503 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +000010504 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +000010505 abi_ulong target_rusage = arg4;
Petar Jovanovica39fb272014-04-08 19:24:30 +020010506 abi_long rusage_err;
bellard31e31b82003-02-18 22:55:36 +000010507 if (target_rusage)
10508 rusage_ptr = &rusage;
10509 else
10510 rusage_ptr = NULL;
Timothy E Baldwin4af80a32016-05-12 18:47:49 +010010511 ret = get_errno(safe_wait4(arg1, &status, arg3, rusage_ptr));
bellard31e31b82003-02-18 22:55:36 +000010512 if (!is_error(ret)) {
Alexander Graf53795572011-11-24 00:44:43 +010010513 if (status_ptr && ret) {
pbrook1d9d8b52009-04-16 15:17:02 +000010514 status = host_to_target_waitstatus(status);
bellard2f619692007-11-16 10:46:05 +000010515 if (put_user_s32(status, status_ptr))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010516 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +000010517 }
Petar Jovanovica39fb272014-04-08 19:24:30 +020010518 if (target_rusage) {
10519 rusage_err = host_to_target_rusage(target_rusage, &rusage);
10520 if (rusage_err) {
10521 ret = rusage_err;
10522 }
10523 }
bellard31e31b82003-02-18 22:55:36 +000010524 }
10525 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010526 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070010527#endif
thse5febef2007-04-01 18:31:35 +000010528#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +000010529 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +000010530 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010531 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010532 ret = get_errno(swapoff(p));
10533 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010534 return ret;
thse5febef2007-04-01 18:31:35 +000010535#endif
bellard31e31b82003-02-18 22:55:36 +000010536 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +000010537 {
pbrook53a59602006-03-25 19:31:22 +000010538 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +000010539 struct sysinfo value;
10540 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +000010541 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +000010542 {
bellard579a97f2007-11-11 14:26:47 +000010543 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010544 return -TARGET_EFAULT;
bellarda5448a72004-06-19 16:59:03 +000010545 __put_user(value.uptime, &target_value->uptime);
10546 __put_user(value.loads[0], &target_value->loads[0]);
10547 __put_user(value.loads[1], &target_value->loads[1]);
10548 __put_user(value.loads[2], &target_value->loads[2]);
10549 __put_user(value.totalram, &target_value->totalram);
10550 __put_user(value.freeram, &target_value->freeram);
10551 __put_user(value.sharedram, &target_value->sharedram);
10552 __put_user(value.bufferram, &target_value->bufferram);
10553 __put_user(value.totalswap, &target_value->totalswap);
10554 __put_user(value.freeswap, &target_value->freeswap);
10555 __put_user(value.procs, &target_value->procs);
10556 __put_user(value.totalhigh, &target_value->totalhigh);
10557 __put_user(value.freehigh, &target_value->freehigh);
10558 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +000010559 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +000010560 }
10561 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010562 return ret;
thse5febef2007-04-01 18:31:35 +000010563#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +000010564 case TARGET_NR_ipc:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010565 return do_ipc(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
thse5febef2007-04-01 18:31:35 +000010566#endif
aurel32e5289082009-04-18 16:16:12 +000010567#ifdef TARGET_NR_semget
10568 case TARGET_NR_semget:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010569 return get_errno(semget(arg1, arg2, arg3));
aurel32e5289082009-04-18 16:16:12 +000010570#endif
10571#ifdef TARGET_NR_semop
10572 case TARGET_NR_semop:
Filip Bozutacac46eb2020-08-25 00:30:50 +020010573 return do_semtimedop(arg1, arg2, arg3, 0, false);
Matus Kyseld8c08b12020-06-26 14:46:11 +020010574#endif
10575#ifdef TARGET_NR_semtimedop
10576 case TARGET_NR_semtimedop:
Filip Bozutacac46eb2020-08-25 00:30:50 +020010577 return do_semtimedop(arg1, arg2, arg3, arg4, false);
10578#endif
10579#ifdef TARGET_NR_semtimedop_time64
10580 case TARGET_NR_semtimedop_time64:
10581 return do_semtimedop(arg1, arg2, arg3, arg4, true);
aurel32e5289082009-04-18 16:16:12 +000010582#endif
10583#ifdef TARGET_NR_semctl
10584 case TARGET_NR_semctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010585 return do_semctl(arg1, arg2, arg3, arg4);
aurel32e5289082009-04-18 16:16:12 +000010586#endif
aurel32eeb438c2008-10-13 21:08:55 +000010587#ifdef TARGET_NR_msgctl
10588 case TARGET_NR_msgctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010589 return do_msgctl(arg1, arg2, arg3);
aurel32eeb438c2008-10-13 21:08:55 +000010590#endif
10591#ifdef TARGET_NR_msgget
10592 case TARGET_NR_msgget:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010593 return get_errno(msgget(arg1, arg2));
aurel32eeb438c2008-10-13 21:08:55 +000010594#endif
10595#ifdef TARGET_NR_msgrcv
10596 case TARGET_NR_msgrcv:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010597 return do_msgrcv(arg1, arg2, arg3, arg4, arg5);
aurel32eeb438c2008-10-13 21:08:55 +000010598#endif
10599#ifdef TARGET_NR_msgsnd
10600 case TARGET_NR_msgsnd:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010601 return do_msgsnd(arg1, arg2, arg3, arg4);
aurel32eeb438c2008-10-13 21:08:55 +000010602#endif
Riku Voipio88a8c982009-04-03 10:42:00 +030010603#ifdef TARGET_NR_shmget
10604 case TARGET_NR_shmget:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010605 return get_errno(shmget(arg1, arg2, arg3));
Riku Voipio88a8c982009-04-03 10:42:00 +030010606#endif
10607#ifdef TARGET_NR_shmctl
10608 case TARGET_NR_shmctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010609 return do_shmctl(arg1, arg2, arg3);
Riku Voipio88a8c982009-04-03 10:42:00 +030010610#endif
10611#ifdef TARGET_NR_shmat
10612 case TARGET_NR_shmat:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010613 return do_shmat(cpu_env, arg1, arg2, arg3);
Riku Voipio88a8c982009-04-03 10:42:00 +030010614#endif
10615#ifdef TARGET_NR_shmdt
10616 case TARGET_NR_shmdt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010617 return do_shmdt(arg1);
Riku Voipio88a8c982009-04-03 10:42:00 +030010618#endif
bellard31e31b82003-02-18 22:55:36 +000010619 case TARGET_NR_fsync:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010620 return get_errno(fsync(arg1));
bellard31e31b82003-02-18 22:55:36 +000010621 case TARGET_NR_clone:
Peter Maydell4ce62432013-07-16 18:44:57 +010010622 /* Linux manages to have three different orderings for its
10623 * arguments to clone(); the BACKWARDS and BACKWARDS2 defines
10624 * match the kernel's CONFIG_CLONE_* settings.
10625 * Microblaze is further special in that it uses a sixth
10626 * implicit argument to clone for the TLS pointer.
10627 */
10628#if defined(TARGET_MICROBLAZE)
Edgar E. Iglesiasa5b3bdc2012-04-26 14:17:41 +020010629 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5));
Peter Maydell4ce62432013-07-16 18:44:57 +010010630#elif defined(TARGET_CLONE_BACKWARDS)
10631 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
10632#elif defined(TARGET_CLONE_BACKWARDS2)
Ulrich Hechta4c075f2009-07-24 16:57:31 +020010633 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
aurel320b6d3ae2008-09-15 07:43:43 +000010634#else
Peter Maydell4ce62432013-07-16 18:44:57 +010010635 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
aurel320b6d3ae2008-09-15 07:43:43 +000010636#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010637 return ret;
bellardec86b0f2003-04-11 00:15:04 +000010638#ifdef __NR_exit_group
10639 /* new thread calls */
10640 case TARGET_NR_exit_group:
Alex Bennée708b6a62018-06-22 17:09:10 +010010641 preexit_cleanup(cpu_env, arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010642 return get_errno(exit_group(arg1));
bellardec86b0f2003-04-11 00:15:04 +000010643#endif
bellard31e31b82003-02-18 22:55:36 +000010644 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +000010645 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010646 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010647 ret = get_errno(setdomainname(p, arg2));
10648 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010649 return ret;
bellard31e31b82003-02-18 22:55:36 +000010650 case TARGET_NR_uname:
10651 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +000010652 {
10653 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +000010654
bellard579a97f2007-11-11 14:26:47 +000010655 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010656 return -TARGET_EFAULT;
bellard29e619b2004-09-13 21:41:04 +000010657 ret = get_errno(sys_uname(buf));
10658 if (!is_error(ret)) {
Peter Maydell332c9782016-07-12 13:02:16 +010010659 /* Overwrite the native machine name with whatever is being
bellard29e619b2004-09-13 21:41:04 +000010660 emulated. */
Philippe Mathieu-Daudé871f95c2017-07-24 15:27:47 -030010661 g_strlcpy(buf->machine, cpu_to_uname_machine(cpu_env),
10662 sizeof(buf->machine));
pbrookc5937222006-05-14 11:30:38 +000010663 /* Allow the user to override the reported release. */
Peter Maydell332c9782016-07-12 13:02:16 +010010664 if (qemu_uname_release && *qemu_uname_release) {
10665 g_strlcpy(buf->release, qemu_uname_release,
10666 sizeof(buf->release));
10667 }
bellard29e619b2004-09-13 21:41:04 +000010668 }
pbrook53a59602006-03-25 19:31:22 +000010669 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +000010670 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010671 return ret;
bellard6dbad632003-03-16 18:05:05 +000010672#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +000010673 case TARGET_NR_modify_ldt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010674 return do_modify_ldt(cpu_env, arg1, arg2, arg3);
j_mayer84409dd2007-04-06 08:56:50 +000010675#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +000010676 case TARGET_NR_vm86:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010677 return do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +000010678#endif
j_mayer84409dd2007-04-06 08:56:50 +000010679#endif
Alistair Francis859e8a82020-03-12 15:13:49 -070010680#if defined(TARGET_NR_adjtimex)
bellard31e31b82003-02-18 22:55:36 +000010681 case TARGET_NR_adjtimex:
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +020010682 {
10683 struct timex host_buf;
10684
10685 if (target_to_host_timex(&host_buf, arg1) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010686 return -TARGET_EFAULT;
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +020010687 }
10688 ret = get_errno(adjtimex(&host_buf));
10689 if (!is_error(ret)) {
10690 if (host_to_target_timex(arg1, &host_buf) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010691 return -TARGET_EFAULT;
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +020010692 }
10693 }
10694 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010695 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070010696#endif
Aleksandar Markovic38860a02016-10-10 13:23:29 +020010697#if defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME)
10698 case TARGET_NR_clock_adjtime:
10699 {
10700 struct timex htx, *phtx = &htx;
10701
10702 if (target_to_host_timex(phtx, arg2) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010703 return -TARGET_EFAULT;
Aleksandar Markovic38860a02016-10-10 13:23:29 +020010704 }
10705 ret = get_errno(clock_adjtime(arg1, phtx));
10706 if (!is_error(ret) && phtx) {
10707 if (host_to_target_timex(arg2, phtx) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010708 return -TARGET_EFAULT;
Aleksandar Markovic38860a02016-10-10 13:23:29 +020010709 }
10710 }
10711 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010712 return ret;
Aleksandar Markovic38860a02016-10-10 13:23:29 +020010713#endif
Filip Bozuta6ac03b22020-08-24 21:21:15 +020010714#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
10715 case TARGET_NR_clock_adjtime64:
10716 {
10717 struct timex htx;
10718
10719 if (target_to_host_timex64(&htx, arg2) != 0) {
10720 return -TARGET_EFAULT;
10721 }
10722 ret = get_errno(clock_adjtime(arg1, &htx));
10723 if (!is_error(ret) && host_to_target_timex64(arg2, &htx)) {
10724 return -TARGET_EFAULT;
10725 }
10726 }
10727 return ret;
10728#endif
bellard31e31b82003-02-18 22:55:36 +000010729 case TARGET_NR_getpgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010730 return get_errno(getpgid(arg1));
bellard31e31b82003-02-18 22:55:36 +000010731 case TARGET_NR_fchdir:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010732 return get_errno(fchdir(arg1));
bellard31e31b82003-02-18 22:55:36 +000010733 case TARGET_NR_personality:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010734 return get_errno(personality(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +000010735#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +000010736 case TARGET_NR__llseek:
10737 {
10738 int64_t res;
Peter Maydell0c1592d2011-02-22 13:02:26 +000010739#if !defined(__NR_llseek)
Peter Maydell9fea2732016-08-11 18:59:39 +010010740 res = lseek(arg1, ((uint64_t)arg2 << 32) | (abi_ulong)arg3, arg5);
Peter Maydell0c1592d2011-02-22 13:02:26 +000010741 if (res == -1) {
10742 ret = get_errno(res);
10743 } else {
10744 ret = 0;
10745 }
10746#else
bellard31e31b82003-02-18 22:55:36 +000010747 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard4f2ac232004-04-26 19:44:02 +000010748#endif
Peter Maydell0c1592d2011-02-22 13:02:26 +000010749 if ((ret == 0) && put_user_s64(res, arg4)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010750 return -TARGET_EFAULT;
Peter Maydell0c1592d2011-02-22 13:02:26 +000010751 }
bellard31e31b82003-02-18 22:55:36 +000010752 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010753 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +000010754#endif
Chen Gang704eff62015-08-21 05:37:33 +080010755#ifdef TARGET_NR_getdents
bellard31e31b82003-02-18 22:55:36 +000010756 case TARGET_NR_getdents:
Richard Hendersonfd08ddb2021-11-14 11:35:36 +010010757 return do_getdents(arg1, arg2, arg3);
Chen Gang704eff62015-08-21 05:37:33 +080010758#endif /* TARGET_NR_getdents */
ths3ae43202007-09-16 21:39:48 +000010759#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +000010760 case TARGET_NR_getdents64:
Richard Hendersonfd08ddb2021-11-14 11:35:36 +010010761 return do_getdents64(arg1, arg2, arg3);
bellarda541f292004-04-12 20:39:29 +000010762#endif /* TARGET_NR_getdents64 */
Laurent Vivier9468a5d2013-01-10 22:30:50 +010010763#if defined(TARGET_NR__newselect)
bellard31e31b82003-02-18 22:55:36 +000010764 case TARGET_NR__newselect:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010765 return do_select(arg1, arg2, arg3, arg4, arg5);
thse5febef2007-04-01 18:31:35 +000010766#endif
Filip Bozutae5ce9682020-08-25 00:30:49 +020010767#ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +000010768 case TARGET_NR_poll:
Filip Bozutae5ce9682020-08-25 00:30:49 +020010769 return do_ppoll(arg1, arg2, arg3, arg4, arg5, false, false);
10770#endif
10771#ifdef TARGET_NR_ppoll
Mike Frysingerd8035d42011-02-07 01:05:51 -050010772 case TARGET_NR_ppoll:
Filip Bozutae5ce9682020-08-25 00:30:49 +020010773 return do_ppoll(arg1, arg2, arg3, arg4, arg5, true, false);
10774#endif
10775#ifdef TARGET_NR_ppoll_time64
10776 case TARGET_NR_ppoll_time64:
10777 return do_ppoll(arg1, arg2, arg3, arg4, arg5, true, true);
thse5febef2007-04-01 18:31:35 +000010778#endif
bellard31e31b82003-02-18 22:55:36 +000010779 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +000010780 /* NOTE: the flock constant seems to be the same for every
10781 Linux platform */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010782 return get_errno(safe_flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +000010783 case TARGET_NR_readv:
10784 {
Richard Hendersonf287b2c2012-09-15 13:20:25 -070010785 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
10786 if (vec != NULL) {
Peter Maydell918c03e2016-06-06 19:58:02 +010010787 ret = get_errno(safe_readv(arg1, vec, arg3));
Richard Hendersonf287b2c2012-09-15 13:20:25 -070010788 unlock_iovec(vec, arg2, arg3, 1);
10789 } else {
10790 ret = -host_to_target_errno(errno);
10791 }
bellard31e31b82003-02-18 22:55:36 +000010792 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010793 return ret;
bellard31e31b82003-02-18 22:55:36 +000010794 case TARGET_NR_writev:
10795 {
Richard Hendersonf287b2c2012-09-15 13:20:25 -070010796 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
10797 if (vec != NULL) {
Peter Maydell918c03e2016-06-06 19:58:02 +010010798 ret = get_errno(safe_writev(arg1, vec, arg3));
Richard Hendersonf287b2c2012-09-15 13:20:25 -070010799 unlock_iovec(vec, arg2, arg3, 0);
10800 } else {
10801 ret = -host_to_target_errno(errno);
10802 }
bellard31e31b82003-02-18 22:55:36 +000010803 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010804 return ret;
Dejan Jovicevic0f263862016-10-11 11:52:46 +020010805#if defined(TARGET_NR_preadv)
10806 case TARGET_NR_preadv:
10807 {
10808 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
10809 if (vec != NULL) {
Max Filippov9ac22512018-04-04 17:30:41 -070010810 unsigned long low, high;
10811
10812 target_to_host_low_high(arg4, arg5, &low, &high);
10813 ret = get_errno(safe_preadv(arg1, vec, arg3, low, high));
Dejan Jovicevic0f263862016-10-11 11:52:46 +020010814 unlock_iovec(vec, arg2, arg3, 1);
10815 } else {
10816 ret = -host_to_target_errno(errno);
10817 }
10818 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010819 return ret;
Dejan Jovicevic0f263862016-10-11 11:52:46 +020010820#endif
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +020010821#if defined(TARGET_NR_pwritev)
10822 case TARGET_NR_pwritev:
10823 {
10824 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
10825 if (vec != NULL) {
Max Filippov9ac22512018-04-04 17:30:41 -070010826 unsigned long low, high;
10827
10828 target_to_host_low_high(arg4, arg5, &low, &high);
10829 ret = get_errno(safe_pwritev(arg1, vec, arg3, low, high));
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +020010830 unlock_iovec(vec, arg2, arg3, 0);
10831 } else {
10832 ret = -host_to_target_errno(errno);
10833 }
10834 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010835 return ret;
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +020010836#endif
bellard31e31b82003-02-18 22:55:36 +000010837 case TARGET_NR_getsid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010838 return get_errno(getsid(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +000010839#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +000010840 case TARGET_NR_fdatasync:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010841 return get_errno(fdatasync(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +000010842#endif
Mike Frysinger737de1d2011-02-07 01:05:55 -050010843 case TARGET_NR_sched_getaffinity:
10844 {
10845 unsigned int mask_size;
10846 unsigned long *mask;
10847
10848 /*
10849 * sched_getaffinity needs multiples of ulong, so need to take
10850 * care of mismatches between target ulong and host ulong sizes.
10851 */
10852 if (arg2 & (sizeof(abi_ulong) - 1)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010853 return -TARGET_EINVAL;
Mike Frysinger737de1d2011-02-07 01:05:55 -050010854 }
10855 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
10856
10857 mask = alloca(mask_size);
Samuel Thibault2e0a8712018-01-09 21:16:43 +010010858 memset(mask, 0, mask_size);
Mike Frysinger737de1d2011-02-07 01:05:55 -050010859 ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
10860
10861 if (!is_error(ret)) {
Peter Maydellbe3bd282014-05-15 14:40:23 +010010862 if (ret > arg2) {
10863 /* More data returned than the caller's buffer will fit.
10864 * This only happens if sizeof(abi_long) < sizeof(long)
10865 * and the caller passed us a buffer holding an odd number
10866 * of abi_longs. If the host kernel is actually using the
10867 * extra 4 bytes then fail EINVAL; otherwise we can just
10868 * ignore them and only copy the interesting part.
10869 */
10870 int numcpus = sysconf(_SC_NPROCESSORS_CONF);
10871 if (numcpus > arg2 * 8) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010872 return -TARGET_EINVAL;
Peter Maydellbe3bd282014-05-15 14:40:23 +010010873 }
10874 ret = arg2;
10875 }
10876
Samuel Thibault5fdefcf2018-02-11 18:47:04 +010010877 if (host_to_target_cpu_mask(mask, mask_size, arg3, ret)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010878 return -TARGET_EFAULT;
Samuel Thibault5fdefcf2018-02-11 18:47:04 +010010879 }
Mike Frysinger737de1d2011-02-07 01:05:55 -050010880 }
10881 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010882 return ret;
Mike Frysinger737de1d2011-02-07 01:05:55 -050010883 case TARGET_NR_sched_setaffinity:
10884 {
10885 unsigned int mask_size;
10886 unsigned long *mask;
10887
10888 /*
10889 * sched_setaffinity needs multiples of ulong, so need to take
10890 * care of mismatches between target ulong and host ulong sizes.
10891 */
10892 if (arg2 & (sizeof(abi_ulong) - 1)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010893 return -TARGET_EINVAL;
Mike Frysinger737de1d2011-02-07 01:05:55 -050010894 }
10895 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
Mike Frysinger737de1d2011-02-07 01:05:55 -050010896 mask = alloca(mask_size);
Samuel Thibault2e0a8712018-01-09 21:16:43 +010010897
10898 ret = target_to_host_cpu_mask(mask, mask_size, arg3, arg2);
10899 if (ret) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010900 return ret;
Mike Frysinger737de1d2011-02-07 01:05:55 -050010901 }
Mike Frysinger737de1d2011-02-07 01:05:55 -050010902
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010903 return get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
Mike Frysinger737de1d2011-02-07 01:05:55 -050010904 }
Samuel Thibaultb827c3e2018-01-12 09:14:35 +010010905 case TARGET_NR_getcpu:
10906 {
10907 unsigned cpu, node;
10908 ret = get_errno(sys_getcpu(arg1 ? &cpu : NULL,
10909 arg2 ? &node : NULL,
10910 NULL));
10911 if (is_error(ret)) {
Richard Henderson259841c2018-08-18 12:01:09 -070010912 return ret;
Samuel Thibaultb827c3e2018-01-12 09:14:35 +010010913 }
10914 if (arg1 && put_user_u32(cpu, arg1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010915 return -TARGET_EFAULT;
Samuel Thibaultb827c3e2018-01-12 09:14:35 +010010916 }
10917 if (arg2 && put_user_u32(node, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010918 return -TARGET_EFAULT;
Samuel Thibaultb827c3e2018-01-12 09:14:35 +010010919 }
10920 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010921 return ret;
bellard31e31b82003-02-18 22:55:36 +000010922 case TARGET_NR_sched_setparam:
bellard5cd43932003-03-29 16:54:36 +000010923 {
Tonis Tiigi407a1192022-01-04 20:18:19 -080010924 struct target_sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +000010925 struct sched_param schp;
pbrook53a59602006-03-25 19:31:22 +000010926
Tom Mustaa1d5c5b2014-08-12 13:53:38 -050010927 if (arg2 == 0) {
10928 return -TARGET_EINVAL;
10929 }
Tonis Tiigi407a1192022-01-04 20:18:19 -080010930 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010931 return -TARGET_EFAULT;
Tonis Tiigi407a1192022-01-04 20:18:19 -080010932 }
bellard5cd43932003-03-29 16:54:36 +000010933 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +000010934 unlock_user_struct(target_schp, arg2, 0);
Tonis Tiigi407a1192022-01-04 20:18:19 -080010935 return get_errno(sys_sched_setparam(arg1, &schp));
bellard5cd43932003-03-29 16:54:36 +000010936 }
bellard31e31b82003-02-18 22:55:36 +000010937 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +000010938 {
Tonis Tiigi407a1192022-01-04 20:18:19 -080010939 struct target_sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +000010940 struct sched_param schp;
Tom Mustaa1d5c5b2014-08-12 13:53:38 -050010941
10942 if (arg2 == 0) {
10943 return -TARGET_EINVAL;
10944 }
Tonis Tiigi407a1192022-01-04 20:18:19 -080010945 ret = get_errno(sys_sched_getparam(arg1, &schp));
bellard5cd43932003-03-29 16:54:36 +000010946 if (!is_error(ret)) {
Tonis Tiigi407a1192022-01-04 20:18:19 -080010947 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010948 return -TARGET_EFAULT;
Tonis Tiigi407a1192022-01-04 20:18:19 -080010949 }
bellard5cd43932003-03-29 16:54:36 +000010950 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +000010951 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +000010952 }
10953 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010954 return ret;
bellard31e31b82003-02-18 22:55:36 +000010955 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +000010956 {
Tonis Tiigi407a1192022-01-04 20:18:19 -080010957 struct target_sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +000010958 struct sched_param schp;
Tom Mustaa1d5c5b2014-08-12 13:53:38 -050010959 if (arg3 == 0) {
10960 return -TARGET_EINVAL;
10961 }
Tonis Tiigi407a1192022-01-04 20:18:19 -080010962 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010963 return -TARGET_EFAULT;
Tonis Tiigi407a1192022-01-04 20:18:19 -080010964 }
bellard5cd43932003-03-29 16:54:36 +000010965 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +000010966 unlock_user_struct(target_schp, arg3, 0);
Tonis Tiigi407a1192022-01-04 20:18:19 -080010967 return get_errno(sys_sched_setscheduler(arg1, arg2, &schp));
bellard5cd43932003-03-29 16:54:36 +000010968 }
bellard31e31b82003-02-18 22:55:36 +000010969 case TARGET_NR_sched_getscheduler:
Tonis Tiigi407a1192022-01-04 20:18:19 -080010970 return get_errno(sys_sched_getscheduler(arg1));
Tonis Tiigi45ad7612022-01-04 20:18:18 -080010971 case TARGET_NR_sched_getattr:
10972 {
10973 struct target_sched_attr *target_scha;
10974 struct sched_attr scha;
10975 if (arg2 == 0) {
10976 return -TARGET_EINVAL;
10977 }
10978 if (arg3 > sizeof(scha)) {
10979 arg3 = sizeof(scha);
10980 }
10981 ret = get_errno(sys_sched_getattr(arg1, &scha, arg3, arg4));
10982 if (!is_error(ret)) {
10983 target_scha = lock_user(VERIFY_WRITE, arg2, arg3, 0);
10984 if (!target_scha) {
10985 return -TARGET_EFAULT;
10986 }
10987 target_scha->size = tswap32(scha.size);
10988 target_scha->sched_policy = tswap32(scha.sched_policy);
10989 target_scha->sched_flags = tswap64(scha.sched_flags);
10990 target_scha->sched_nice = tswap32(scha.sched_nice);
10991 target_scha->sched_priority = tswap32(scha.sched_priority);
10992 target_scha->sched_runtime = tswap64(scha.sched_runtime);
10993 target_scha->sched_deadline = tswap64(scha.sched_deadline);
10994 target_scha->sched_period = tswap64(scha.sched_period);
10995 if (scha.size > offsetof(struct sched_attr, sched_util_min)) {
10996 target_scha->sched_util_min = tswap32(scha.sched_util_min);
10997 target_scha->sched_util_max = tswap32(scha.sched_util_max);
10998 }
10999 unlock_user(target_scha, arg2, arg3);
11000 }
11001 return ret;
11002 }
11003 case TARGET_NR_sched_setattr:
11004 {
11005 struct target_sched_attr *target_scha;
11006 struct sched_attr scha;
11007 uint32_t size;
11008 int zeroed;
11009 if (arg2 == 0) {
11010 return -TARGET_EINVAL;
11011 }
11012 if (get_user_u32(size, arg2)) {
11013 return -TARGET_EFAULT;
11014 }
11015 if (!size) {
11016 size = offsetof(struct target_sched_attr, sched_util_min);
11017 }
11018 if (size < offsetof(struct target_sched_attr, sched_util_min)) {
11019 if (put_user_u32(sizeof(struct target_sched_attr), arg2)) {
11020 return -TARGET_EFAULT;
11021 }
11022 return -TARGET_E2BIG;
11023 }
11024
11025 zeroed = check_zeroed_user(arg2, sizeof(struct target_sched_attr), size);
11026 if (zeroed < 0) {
11027 return zeroed;
11028 } else if (zeroed == 0) {
11029 if (put_user_u32(sizeof(struct target_sched_attr), arg2)) {
11030 return -TARGET_EFAULT;
11031 }
11032 return -TARGET_E2BIG;
11033 }
11034 if (size > sizeof(struct target_sched_attr)) {
11035 size = sizeof(struct target_sched_attr);
11036 }
11037
11038 target_scha = lock_user(VERIFY_READ, arg2, size, 1);
11039 if (!target_scha) {
11040 return -TARGET_EFAULT;
11041 }
11042 scha.size = size;
11043 scha.sched_policy = tswap32(target_scha->sched_policy);
11044 scha.sched_flags = tswap64(target_scha->sched_flags);
11045 scha.sched_nice = tswap32(target_scha->sched_nice);
11046 scha.sched_priority = tswap32(target_scha->sched_priority);
11047 scha.sched_runtime = tswap64(target_scha->sched_runtime);
11048 scha.sched_deadline = tswap64(target_scha->sched_deadline);
11049 scha.sched_period = tswap64(target_scha->sched_period);
11050 if (size > offsetof(struct target_sched_attr, sched_util_min)) {
11051 scha.sched_util_min = tswap32(target_scha->sched_util_min);
11052 scha.sched_util_max = tswap32(target_scha->sched_util_max);
11053 }
11054 unlock_user(target_scha, arg2, 0);
11055 return get_errno(sys_sched_setattr(arg1, &scha, arg3));
11056 }
bellard31e31b82003-02-18 22:55:36 +000011057 case TARGET_NR_sched_yield:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011058 return get_errno(sched_yield());
bellard31e31b82003-02-18 22:55:36 +000011059 case TARGET_NR_sched_get_priority_max:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011060 return get_errno(sched_get_priority_max(arg1));
bellard31e31b82003-02-18 22:55:36 +000011061 case TARGET_NR_sched_get_priority_min:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011062 return get_errno(sched_get_priority_min(arg1));
Alistair Francis859e8a82020-03-12 15:13:49 -070011063#ifdef TARGET_NR_sched_rr_get_interval
bellard31e31b82003-02-18 22:55:36 +000011064 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +000011065 {
bellard5cd43932003-03-29 16:54:36 +000011066 struct timespec ts;
11067 ret = get_errno(sched_rr_get_interval(arg1, &ts));
11068 if (!is_error(ret)) {
Tom Mustad4290c42014-08-12 13:53:39 -050011069 ret = host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +000011070 }
11071 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011072 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070011073#endif
Filip Bozutaddcbde12020-08-24 21:21:16 +020011074#ifdef TARGET_NR_sched_rr_get_interval_time64
11075 case TARGET_NR_sched_rr_get_interval_time64:
11076 {
11077 struct timespec ts;
11078 ret = get_errno(sched_rr_get_interval(arg1, &ts));
11079 if (!is_error(ret)) {
11080 ret = host_to_target_timespec64(arg2, &ts);
11081 }
11082 }
11083 return ret;
11084#endif
Alistair Francis859e8a82020-03-12 15:13:49 -070011085#if defined(TARGET_NR_nanosleep)
bellard31e31b82003-02-18 22:55:36 +000011086 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +000011087 {
bellard1b6b0292003-03-22 17:31:38 +000011088 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +000011089 target_to_host_timespec(&req, arg1);
Peter Maydell9e518222016-06-06 19:58:09 +010011090 ret = get_errno(safe_nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +000011091 if (is_error(ret) && arg2) {
11092 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +000011093 }
11094 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011095 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070011096#endif
bellard31e31b82003-02-18 22:55:36 +000011097 case TARGET_NR_prctl:
Richard Henderson87e9bf22021-12-27 07:01:22 -080011098 return do_prctl(cpu_env, arg1, arg2, arg3, arg4, arg5);
ths39b9aae2007-02-11 18:36:44 +000011099 break;
bellardd2fd1af2007-11-14 18:08:56 +000011100#ifdef TARGET_NR_arch_prctl
11101 case TARGET_NR_arch_prctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011102 return do_arch_prctl(cpu_env, arg1, arg2);
bellardd2fd1af2007-11-14 18:08:56 +000011103#endif
aurel32f2c7ba12008-03-28 22:32:06 +000011104#ifdef TARGET_NR_pread64
11105 case TARGET_NR_pread64:
James Clarke8bf8e9d2017-09-15 20:33:13 +010011106 if (regpairs_aligned(cpu_env, num)) {
Alexander Grafae017a52012-09-29 15:32:39 +000011107 arg4 = arg5;
11108 arg5 = arg6;
11109 }
Peter Maydell2bd3f892019-01-08 18:49:00 +000011110 if (arg2 == 0 && arg3 == 0) {
11111 /* Special-case NULL buffer and zero length, which should succeed */
11112 p = 0;
11113 } else {
11114 p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
11115 if (!p) {
11116 return -TARGET_EFAULT;
11117 }
11118 }
aurel32f2c7ba12008-03-28 22:32:06 +000011119 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
11120 unlock_user(p, arg2, ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011121 return ret;
aurel32f2c7ba12008-03-28 22:32:06 +000011122 case TARGET_NR_pwrite64:
James Clarke8bf8e9d2017-09-15 20:33:13 +010011123 if (regpairs_aligned(cpu_env, num)) {
Alexander Grafae017a52012-09-29 15:32:39 +000011124 arg4 = arg5;
11125 arg5 = arg6;
11126 }
Peter Maydell2bd3f892019-01-08 18:49:00 +000011127 if (arg2 == 0 && arg3 == 0) {
11128 /* Special-case NULL buffer and zero length, which should succeed */
11129 p = 0;
11130 } else {
11131 p = lock_user(VERIFY_READ, arg2, arg3, 1);
11132 if (!p) {
11133 return -TARGET_EFAULT;
11134 }
11135 }
aurel32f2c7ba12008-03-28 22:32:06 +000011136 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
11137 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011138 return ret;
aurel32f2c7ba12008-03-28 22:32:06 +000011139#endif
bellard31e31b82003-02-18 22:55:36 +000011140 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +000011141 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011142 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011143 ret = get_errno(sys_getcwd1(p, arg2));
11144 unlock_user(p, arg1, ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011145 return ret;
bellard31e31b82003-02-18 22:55:36 +000011146 case TARGET_NR_capget:
11147 case TARGET_NR_capset:
Peter Maydelle0eb2102014-03-17 12:15:35 +000011148 {
11149 struct target_user_cap_header *target_header;
11150 struct target_user_cap_data *target_data = NULL;
11151 struct __user_cap_header_struct header;
11152 struct __user_cap_data_struct data[2];
11153 struct __user_cap_data_struct *dataptr = NULL;
11154 int i, target_datalen;
11155 int data_items = 1;
11156
11157 if (!lock_user_struct(VERIFY_WRITE, target_header, arg1, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011158 return -TARGET_EFAULT;
Peter Maydelle0eb2102014-03-17 12:15:35 +000011159 }
11160 header.version = tswap32(target_header->version);
11161 header.pid = tswap32(target_header->pid);
11162
Peter Maydellec864872014-03-19 16:07:30 +000011163 if (header.version != _LINUX_CAPABILITY_VERSION) {
Peter Maydelle0eb2102014-03-17 12:15:35 +000011164 /* Version 2 and up takes pointer to two user_data structs */
11165 data_items = 2;
11166 }
11167
11168 target_datalen = sizeof(*target_data) * data_items;
11169
11170 if (arg2) {
11171 if (num == TARGET_NR_capget) {
11172 target_data = lock_user(VERIFY_WRITE, arg2, target_datalen, 0);
11173 } else {
11174 target_data = lock_user(VERIFY_READ, arg2, target_datalen, 1);
11175 }
11176 if (!target_data) {
11177 unlock_user_struct(target_header, arg1, 0);
Richard Henderson2852aaf2018-08-18 12:01:06 -070011178 return -TARGET_EFAULT;
Peter Maydelle0eb2102014-03-17 12:15:35 +000011179 }
11180
11181 if (num == TARGET_NR_capset) {
11182 for (i = 0; i < data_items; i++) {
11183 data[i].effective = tswap32(target_data[i].effective);
11184 data[i].permitted = tswap32(target_data[i].permitted);
11185 data[i].inheritable = tswap32(target_data[i].inheritable);
11186 }
11187 }
11188
11189 dataptr = data;
11190 }
11191
11192 if (num == TARGET_NR_capget) {
11193 ret = get_errno(capget(&header, dataptr));
11194 } else {
11195 ret = get_errno(capset(&header, dataptr));
11196 }
11197
11198 /* The kernel always updates version for both capget and capset */
11199 target_header->version = tswap32(header.version);
11200 unlock_user_struct(target_header, arg1, 1);
11201
11202 if (arg2) {
11203 if (num == TARGET_NR_capget) {
11204 for (i = 0; i < data_items; i++) {
11205 target_data[i].effective = tswap32(data[i].effective);
11206 target_data[i].permitted = tswap32(data[i].permitted);
11207 target_data[i].inheritable = tswap32(data[i].inheritable);
11208 }
11209 unlock_user(target_data, arg2, target_datalen);
11210 } else {
11211 unlock_user(target_data, arg2, 0);
11212 }
11213 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011214 return ret;
Peter Maydelle0eb2102014-03-17 12:15:35 +000011215 }
bellard31e31b82003-02-18 22:55:36 +000011216 case TARGET_NR_sigaltstack:
Richard Henderson6b208752021-04-25 19:53:12 -070011217 return do_sigaltstack(arg1, arg2, cpu_env);
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011218
11219#ifdef CONFIG_SENDFILE
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020011220#ifdef TARGET_NR_sendfile
bellard31e31b82003-02-18 22:55:36 +000011221 case TARGET_NR_sendfile:
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011222 {
11223 off_t *offp = NULL;
11224 off_t off;
11225 if (arg3) {
11226 ret = get_user_sal(off, arg3);
11227 if (is_error(ret)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011228 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011229 }
11230 offp = &off;
11231 }
11232 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
11233 if (!is_error(ret) && arg3) {
11234 abi_long ret2 = put_user_sal(off, arg3);
11235 if (is_error(ret2)) {
11236 ret = ret2;
11237 }
11238 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011239 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011240 }
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020011241#endif
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011242#ifdef TARGET_NR_sendfile64
11243 case TARGET_NR_sendfile64:
11244 {
11245 off_t *offp = NULL;
11246 off_t off;
11247 if (arg3) {
11248 ret = get_user_s64(off, arg3);
11249 if (is_error(ret)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011250 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011251 }
11252 offp = &off;
11253 }
11254 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
11255 if (!is_error(ret) && arg3) {
11256 abi_long ret2 = put_user_s64(off, arg3);
11257 if (is_error(ret2)) {
11258 ret = ret2;
11259 }
11260 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011261 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011262 }
11263#endif
bellardebc05482003-09-30 21:08:41 +000011264#endif
bellard048f6b42005-11-26 18:47:20 +000011265#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +000011266 case TARGET_NR_vfork:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011267 return get_errno(do_fork(cpu_env,
11268 CLONE_VFORK | CLONE_VM | TARGET_SIGCHLD,
11269 0, 0, 0, 0));
bellard048f6b42005-11-26 18:47:20 +000011270#endif
bellardebc05482003-09-30 21:08:41 +000011271#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +000011272 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +000011273 {
11274 struct rlimit rlim;
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +030011275 int resource = target_to_host_resource(arg1);
11276 ret = get_errno(getrlimit(resource, &rlim));
bellard728584b2003-04-29 20:43:36 +000011277 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +000011278 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +000011279 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011280 return -TARGET_EFAULT;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +090011281 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
11282 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +000011283 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +000011284 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011285 return ret;
bellard728584b2003-04-29 20:43:36 +000011286 }
bellardebc05482003-09-30 21:08:41 +000011287#endif
bellarda315a142005-01-30 22:59:18 +000011288#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +000011289 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +000011290 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011291 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011292 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
11293 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011294 return ret;
bellarda315a142005-01-30 22:59:18 +000011295#endif
11296#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +000011297 case TARGET_NR_ftruncate64:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011298 return target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellarda315a142005-01-30 22:59:18 +000011299#endif
11300#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +000011301 case TARGET_NR_stat64:
Richard Henderson2852aaf2018-08-18 12:01:06 -070011302 if (!(p = lock_user_string(arg1))) {
11303 return -TARGET_EFAULT;
11304 }
pbrook53a59602006-03-25 19:31:22 +000011305 ret = get_errno(stat(path(p), &st));
11306 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +000011307 if (!is_error(ret))
11308 ret = host_to_target_stat64(cpu_env, arg2, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011309 return ret;
bellarda315a142005-01-30 22:59:18 +000011310#endif
11311#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +000011312 case TARGET_NR_lstat64:
Richard Henderson2852aaf2018-08-18 12:01:06 -070011313 if (!(p = lock_user_string(arg1))) {
11314 return -TARGET_EFAULT;
11315 }
pbrook53a59602006-03-25 19:31:22 +000011316 ret = get_errno(lstat(path(p), &st));
11317 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +000011318 if (!is_error(ret))
11319 ret = host_to_target_stat64(cpu_env, arg2, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011320 return ret;
bellarda315a142005-01-30 22:59:18 +000011321#endif
11322#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +000011323 case TARGET_NR_fstat64:
balrog6a24a772008-09-20 02:23:36 +000011324 ret = get_errno(fstat(arg1, &st));
11325 if (!is_error(ret))
11326 ret = host_to_target_stat64(cpu_env, arg2, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011327 return ret;
bellardec86b0f2003-04-11 00:15:04 +000011328#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +010011329#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat))
aurel329d33b762009-04-08 23:07:05 +000011330#ifdef TARGET_NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +000011331 case TARGET_NR_fstatat64:
aurel329d33b762009-04-08 23:07:05 +000011332#endif
11333#ifdef TARGET_NR_newfstatat
11334 case TARGET_NR_newfstatat:
11335#endif
Richard Henderson2852aaf2018-08-18 12:01:06 -070011336 if (!(p = lock_user_string(arg2))) {
11337 return -TARGET_EFAULT;
11338 }
Peter Maydellc0d472b2013-06-12 16:20:21 +010011339 ret = get_errno(fstatat(arg1, path(p), &st, arg4));
Richard Henderson2852aaf2018-08-18 12:01:06 -070011340 unlock_user(p, arg2, 0);
balrog6a24a772008-09-20 02:23:36 +000011341 if (!is_error(ret))
11342 ret = host_to_target_stat64(cpu_env, arg3, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011343 return ret;
bellarda315a142005-01-30 22:59:18 +000011344#endif
Aleksandar Rikaloefa92182019-06-28 12:43:34 +020011345#if defined(TARGET_NR_statx)
11346 case TARGET_NR_statx:
11347 {
11348 struct target_statx *target_stx;
11349 int dirfd = arg1;
11350 int flags = arg3;
11351
11352 p = lock_user_string(arg2);
11353 if (p == NULL) {
11354 return -TARGET_EFAULT;
11355 }
11356#if defined(__NR_statx)
11357 {
11358 /*
11359 * It is assumed that struct statx is architecture independent.
11360 */
11361 struct target_statx host_stx;
11362 int mask = arg4;
11363
11364 ret = get_errno(sys_statx(dirfd, p, flags, mask, &host_stx));
11365 if (!is_error(ret)) {
11366 if (host_to_target_statx(&host_stx, arg5) != 0) {
11367 unlock_user(p, arg2, 0);
11368 return -TARGET_EFAULT;
11369 }
11370 }
11371
11372 if (ret != -TARGET_ENOSYS) {
11373 unlock_user(p, arg2, 0);
11374 return ret;
11375 }
11376 }
11377#endif
11378 ret = get_errno(fstatat(dirfd, path(p), &st, flags));
11379 unlock_user(p, arg2, 0);
11380
11381 if (!is_error(ret)) {
11382 if (!lock_user_struct(VERIFY_WRITE, target_stx, arg5, 0)) {
11383 return -TARGET_EFAULT;
11384 }
11385 memset(target_stx, 0, sizeof(*target_stx));
11386 __put_user(major(st.st_dev), &target_stx->stx_dev_major);
11387 __put_user(minor(st.st_dev), &target_stx->stx_dev_minor);
11388 __put_user(st.st_ino, &target_stx->stx_ino);
11389 __put_user(st.st_mode, &target_stx->stx_mode);
11390 __put_user(st.st_uid, &target_stx->stx_uid);
11391 __put_user(st.st_gid, &target_stx->stx_gid);
11392 __put_user(st.st_nlink, &target_stx->stx_nlink);
11393 __put_user(major(st.st_rdev), &target_stx->stx_rdev_major);
11394 __put_user(minor(st.st_rdev), &target_stx->stx_rdev_minor);
11395 __put_user(st.st_size, &target_stx->stx_size);
11396 __put_user(st.st_blksize, &target_stx->stx_blksize);
11397 __put_user(st.st_blocks, &target_stx->stx_blocks);
11398 __put_user(st.st_atime, &target_stx->stx_atime.tv_sec);
11399 __put_user(st.st_mtime, &target_stx->stx_mtime.tv_sec);
11400 __put_user(st.st_ctime, &target_stx->stx_ctime.tv_sec);
11401 unlock_user_struct(target_stx, arg5, 1);
11402 }
11403 }
11404 return ret;
11405#endif
Chen Gang704eff62015-08-21 05:37:33 +080011406#ifdef TARGET_NR_lchown
bellard67867302003-11-23 17:05:30 +000011407 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +000011408 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011409 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011410 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
11411 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011412 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080011413#endif
Riku Voipio0c866a72011-04-18 15:23:06 +030011414#ifdef TARGET_NR_getuid
bellard67867302003-11-23 17:05:30 +000011415 case TARGET_NR_getuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011416 return get_errno(high2lowuid(getuid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030011417#endif
11418#ifdef TARGET_NR_getgid
bellard67867302003-11-23 17:05:30 +000011419 case TARGET_NR_getgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011420 return get_errno(high2lowgid(getgid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030011421#endif
11422#ifdef TARGET_NR_geteuid
bellard67867302003-11-23 17:05:30 +000011423 case TARGET_NR_geteuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011424 return get_errno(high2lowuid(geteuid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030011425#endif
11426#ifdef TARGET_NR_getegid
bellard67867302003-11-23 17:05:30 +000011427 case TARGET_NR_getegid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011428 return get_errno(high2lowgid(getegid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030011429#endif
bellard67867302003-11-23 17:05:30 +000011430 case TARGET_NR_setreuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011431 return get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
bellard67867302003-11-23 17:05:30 +000011432 case TARGET_NR_setregid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011433 return get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
bellard67867302003-11-23 17:05:30 +000011434 case TARGET_NR_getgroups:
11435 {
11436 int gidsetsize = arg1;
Riku Voipio0c866a72011-04-18 15:23:06 +030011437 target_id *target_grouplist;
bellard67867302003-11-23 17:05:30 +000011438 gid_t *grouplist;
11439 int i;
11440
11441 grouplist = alloca(gidsetsize * sizeof(gid_t));
11442 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +000011443 if (gidsetsize == 0)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011444 return ret;
bellard67867302003-11-23 17:05:30 +000011445 if (!is_error(ret)) {
Andreas Schwab03903ff2013-04-09 05:41:33 +000011446 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * sizeof(target_id), 0);
bellard579a97f2007-11-11 14:26:47 +000011447 if (!target_grouplist)
Richard Henderson2852aaf2018-08-18 12:01:06 -070011448 return -TARGET_EFAULT;
balroga2155fc2008-09-20 02:12:08 +000011449 for(i = 0;i < ret; i++)
Riku Voipio0c866a72011-04-18 15:23:06 +030011450 target_grouplist[i] = tswapid(high2lowgid(grouplist[i]));
Andreas Schwab03903ff2013-04-09 05:41:33 +000011451 unlock_user(target_grouplist, arg2, gidsetsize * sizeof(target_id));
bellard67867302003-11-23 17:05:30 +000011452 }
11453 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011454 return ret;
bellard67867302003-11-23 17:05:30 +000011455 case TARGET_NR_setgroups:
11456 {
11457 int gidsetsize = arg1;
Riku Voipio0c866a72011-04-18 15:23:06 +030011458 target_id *target_grouplist;
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050011459 gid_t *grouplist = NULL;
bellard67867302003-11-23 17:05:30 +000011460 int i;
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050011461 if (gidsetsize) {
11462 grouplist = alloca(gidsetsize * sizeof(gid_t));
Andreas Schwab03903ff2013-04-09 05:41:33 +000011463 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * sizeof(target_id), 1);
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050011464 if (!target_grouplist) {
Richard Henderson259841c2018-08-18 12:01:09 -070011465 return -TARGET_EFAULT;
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050011466 }
11467 for (i = 0; i < gidsetsize; i++) {
11468 grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
11469 }
11470 unlock_user(target_grouplist, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +000011471 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011472 return get_errno(setgroups(gidsetsize, grouplist));
bellard67867302003-11-23 17:05:30 +000011473 }
bellard67867302003-11-23 17:05:30 +000011474 case TARGET_NR_fchown:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011475 return get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
Peter Maydellc0d472b2013-06-12 16:20:21 +010011476#if defined(TARGET_NR_fchownat)
thsccfa72b2007-09-24 09:23:34 +000011477 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +000011478 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011479 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +010011480 ret = get_errno(fchownat(arg1, p, low2highuid(arg3),
11481 low2highgid(arg4), arg5));
bellard579a97f2007-11-11 14:26:47 +000011482 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011483 return ret;
thsccfa72b2007-09-24 09:23:34 +000011484#endif
bellard67867302003-11-23 17:05:30 +000011485#ifdef TARGET_NR_setresuid
11486 case TARGET_NR_setresuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011487 return get_errno(sys_setresuid(low2highuid(arg1),
11488 low2highuid(arg2),
11489 low2highuid(arg3)));
bellard67867302003-11-23 17:05:30 +000011490#endif
11491#ifdef TARGET_NR_getresuid
11492 case TARGET_NR_getresuid:
11493 {
pbrook53a59602006-03-25 19:31:22 +000011494 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +000011495 ret = get_errno(getresuid(&ruid, &euid, &suid));
11496 if (!is_error(ret)) {
Peter Maydell76ca3102014-03-02 19:36:41 +000011497 if (put_user_id(high2lowuid(ruid), arg1)
11498 || put_user_id(high2lowuid(euid), arg2)
11499 || put_user_id(high2lowuid(suid), arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011500 return -TARGET_EFAULT;
bellard67867302003-11-23 17:05:30 +000011501 }
11502 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011503 return ret;
bellard67867302003-11-23 17:05:30 +000011504#endif
11505#ifdef TARGET_NR_getresgid
11506 case TARGET_NR_setresgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011507 return get_errno(sys_setresgid(low2highgid(arg1),
11508 low2highgid(arg2),
11509 low2highgid(arg3)));
bellard67867302003-11-23 17:05:30 +000011510#endif
11511#ifdef TARGET_NR_getresgid
11512 case TARGET_NR_getresgid:
11513 {
pbrook53a59602006-03-25 19:31:22 +000011514 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +000011515 ret = get_errno(getresgid(&rgid, &egid, &sgid));
11516 if (!is_error(ret)) {
Peter Maydell76ca3102014-03-02 19:36:41 +000011517 if (put_user_id(high2lowgid(rgid), arg1)
11518 || put_user_id(high2lowgid(egid), arg2)
11519 || put_user_id(high2lowgid(sgid), arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011520 return -TARGET_EFAULT;
bellard67867302003-11-23 17:05:30 +000011521 }
11522 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011523 return ret;
bellard67867302003-11-23 17:05:30 +000011524#endif
Chen Gang704eff62015-08-21 05:37:33 +080011525#ifdef TARGET_NR_chown
bellard67867302003-11-23 17:05:30 +000011526 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +000011527 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011528 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011529 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
11530 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011531 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080011532#endif
bellard67867302003-11-23 17:05:30 +000011533 case TARGET_NR_setuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011534 return get_errno(sys_setuid(low2highuid(arg1)));
bellard67867302003-11-23 17:05:30 +000011535 case TARGET_NR_setgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011536 return get_errno(sys_setgid(low2highgid(arg1)));
bellard67867302003-11-23 17:05:30 +000011537 case TARGET_NR_setfsuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011538 return get_errno(setfsuid(arg1));
bellard67867302003-11-23 17:05:30 +000011539 case TARGET_NR_setfsgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011540 return get_errno(setfsgid(arg1));
bellard67867302003-11-23 17:05:30 +000011541
bellarda315a142005-01-30 22:59:18 +000011542#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +000011543 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +000011544 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011545 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011546 ret = get_errno(lchown(p, arg2, arg3));
11547 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011548 return ret;
bellarda315a142005-01-30 22:59:18 +000011549#endif
11550#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +000011551 case TARGET_NR_getuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011552 return get_errno(getuid());
bellarda315a142005-01-30 22:59:18 +000011553#endif
aurel3264b4d282008-11-14 17:20:15 +000011554
11555#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
11556 /* Alpha specific */
11557 case TARGET_NR_getxuid:
Richard Hendersonba0e2762009-12-09 15:56:29 -080011558 {
11559 uid_t euid;
11560 euid=geteuid();
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020011561 cpu_env->ir[IR_A4]=euid;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011562 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011563 return get_errno(getuid());
aurel3264b4d282008-11-14 17:20:15 +000011564#endif
11565#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
11566 /* Alpha specific */
11567 case TARGET_NR_getxgid:
Richard Hendersonba0e2762009-12-09 15:56:29 -080011568 {
11569 uid_t egid;
11570 egid=getegid();
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020011571 cpu_env->ir[IR_A4]=egid;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011572 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011573 return get_errno(getgid());
aurel3264b4d282008-11-14 17:20:15 +000011574#endif
Richard Hendersonba0e2762009-12-09 15:56:29 -080011575#if defined(TARGET_NR_osf_getsysinfo) && defined(TARGET_ALPHA)
11576 /* Alpha specific */
11577 case TARGET_NR_osf_getsysinfo:
11578 ret = -TARGET_EOPNOTSUPP;
11579 switch (arg1) {
11580 case TARGET_GSI_IEEE_FP_CONTROL:
11581 {
Richard Henderson21ba8562019-04-26 15:20:51 -070011582 uint64_t fpcr = cpu_alpha_load_fpcr(cpu_env);
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020011583 uint64_t swcr = cpu_env->swcr;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011584
Richard Henderson21ba8562019-04-26 15:20:51 -070011585 swcr &= ~SWCR_STATUS_MASK;
11586 swcr |= (fpcr >> 35) & SWCR_STATUS_MASK;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011587
11588 if (put_user_u64 (swcr, arg2))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011589 return -TARGET_EFAULT;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011590 ret = 0;
11591 }
11592 break;
11593
11594 /* case GSI_IEEE_STATE_AT_SIGNAL:
11595 -- Not implemented in linux kernel.
11596 case GSI_UACPROC:
11597 -- Retrieves current unaligned access state; not much used.
11598 case GSI_PROC_TYPE:
11599 -- Retrieves implver information; surely not used.
11600 case GSI_GET_HWRPB:
11601 -- Grabs a copy of the HWRPB; surely not used.
11602 */
11603 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011604 return ret;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011605#endif
11606#if defined(TARGET_NR_osf_setsysinfo) && defined(TARGET_ALPHA)
11607 /* Alpha specific */
11608 case TARGET_NR_osf_setsysinfo:
11609 ret = -TARGET_EOPNOTSUPP;
11610 switch (arg1) {
11611 case TARGET_SSI_IEEE_FP_CONTROL:
Richard Hendersonba0e2762009-12-09 15:56:29 -080011612 {
Richard Henderson21ba8562019-04-26 15:20:51 -070011613 uint64_t swcr, fpcr;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011614
Richard Henderson6e06d512012-06-01 09:08:21 -070011615 if (get_user_u64 (swcr, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011616 return -TARGET_EFAULT;
Richard Henderson6e06d512012-06-01 09:08:21 -070011617 }
Richard Hendersonba0e2762009-12-09 15:56:29 -080011618
Richard Henderson21ba8562019-04-26 15:20:51 -070011619 /*
11620 * The kernel calls swcr_update_status to update the
11621 * status bits from the fpcr at every point that it
11622 * could be queried. Therefore, we store the status
11623 * bits only in FPCR.
11624 */
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020011625 cpu_env->swcr = swcr & (SWCR_TRAP_ENABLE_MASK | SWCR_MAP_MASK);
Richard Hendersonba0e2762009-12-09 15:56:29 -080011626
Richard Henderson21ba8562019-04-26 15:20:51 -070011627 fpcr = cpu_alpha_load_fpcr(cpu_env);
11628 fpcr &= ((uint64_t)FPCR_DYN_MASK << 32);
11629 fpcr |= alpha_ieee_swcr_to_fpcr(swcr);
Richard Henderson6e06d512012-06-01 09:08:21 -070011630 cpu_alpha_store_fpcr(cpu_env, fpcr);
11631 ret = 0;
11632 }
11633 break;
11634
11635 case TARGET_SSI_IEEE_RAISE_EXCEPTION:
11636 {
Richard Henderson21ba8562019-04-26 15:20:51 -070011637 uint64_t exc, fpcr, fex;
Richard Henderson6e06d512012-06-01 09:08:21 -070011638
11639 if (get_user_u64(exc, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011640 return -TARGET_EFAULT;
Richard Henderson6e06d512012-06-01 09:08:21 -070011641 }
Richard Henderson21ba8562019-04-26 15:20:51 -070011642 exc &= SWCR_STATUS_MASK;
11643 fpcr = cpu_alpha_load_fpcr(cpu_env);
Richard Hendersonba0e2762009-12-09 15:56:29 -080011644
Richard Henderson6e06d512012-06-01 09:08:21 -070011645 /* Old exceptions are not signaled. */
Richard Henderson21ba8562019-04-26 15:20:51 -070011646 fex = alpha_ieee_fpcr_to_swcr(fpcr);
11647 fex = exc & ~fex;
11648 fex >>= SWCR_STATUS_TO_EXCSUM_SHIFT;
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020011649 fex &= (cpu_env)->swcr;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011650
Richard Henderson21ba8562019-04-26 15:20:51 -070011651 /* Update the hardware fpcr. */
11652 fpcr |= alpha_ieee_swcr_to_fpcr(exc);
11653 cpu_alpha_store_fpcr(cpu_env, fpcr);
11654
11655 if (fex) {
11656 int si_code = TARGET_FPE_FLTUNK;
Richard Henderson6e06d512012-06-01 09:08:21 -070011657 target_siginfo_t info;
Richard Henderson21ba8562019-04-26 15:20:51 -070011658
11659 if (fex & SWCR_TRAP_ENABLE_DNO) {
11660 si_code = TARGET_FPE_FLTUND;
11661 }
11662 if (fex & SWCR_TRAP_ENABLE_INE) {
11663 si_code = TARGET_FPE_FLTRES;
11664 }
11665 if (fex & SWCR_TRAP_ENABLE_UNF) {
11666 si_code = TARGET_FPE_FLTUND;
11667 }
11668 if (fex & SWCR_TRAP_ENABLE_OVF) {
11669 si_code = TARGET_FPE_FLTOVF;
11670 }
11671 if (fex & SWCR_TRAP_ENABLE_DZE) {
11672 si_code = TARGET_FPE_FLTDIV;
11673 }
11674 if (fex & SWCR_TRAP_ENABLE_INV) {
11675 si_code = TARGET_FPE_FLTINV;
11676 }
11677
Richard Henderson6e06d512012-06-01 09:08:21 -070011678 info.si_signo = SIGFPE;
11679 info.si_errno = 0;
11680 info.si_code = si_code;
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020011681 info._sifields._sigfault._addr = (cpu_env)->pc;
11682 queue_signal(cpu_env, info.si_signo,
Peter Maydell9d2803f2016-07-28 16:44:46 +010011683 QEMU_SI_FAULT, &info);
Richard Hendersonba0e2762009-12-09 15:56:29 -080011684 }
Richard Henderson21ba8562019-04-26 15:20:51 -070011685 ret = 0;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011686 }
11687 break;
11688
11689 /* case SSI_NVPAIRS:
11690 -- Used with SSIN_UACPROC to enable unaligned accesses.
11691 case SSI_IEEE_STATE_AT_SIGNAL:
11692 case SSI_IEEE_IGNORE_STATE_AT_SIGNAL:
11693 -- Not implemented in linux kernel
11694 */
11695 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011696 return ret;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011697#endif
11698#ifdef TARGET_NR_osf_sigprocmask
11699 /* Alpha specific. */
11700 case TARGET_NR_osf_sigprocmask:
11701 {
11702 abi_ulong mask;
Juan Quintelabc088ba2011-06-16 17:37:10 +010011703 int how;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011704 sigset_t set, oldset;
11705
11706 switch(arg1) {
11707 case TARGET_SIG_BLOCK:
11708 how = SIG_BLOCK;
11709 break;
11710 case TARGET_SIG_UNBLOCK:
11711 how = SIG_UNBLOCK;
11712 break;
11713 case TARGET_SIG_SETMASK:
11714 how = SIG_SETMASK;
11715 break;
11716 default:
Richard Henderson259841c2018-08-18 12:01:09 -070011717 return -TARGET_EINVAL;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011718 }
11719 mask = arg2;
11720 target_to_host_old_sigset(&set, &mask);
Peter Maydell3d3efba2016-05-27 15:51:49 +010011721 ret = do_sigprocmask(how, &set, &oldset);
11722 if (!ret) {
11723 host_to_target_old_sigset(&mask, &oldset);
11724 ret = mask;
11725 }
Richard Hendersonba0e2762009-12-09 15:56:29 -080011726 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011727 return ret;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011728#endif
aurel3264b4d282008-11-14 17:20:15 +000011729
bellarda315a142005-01-30 22:59:18 +000011730#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +000011731 case TARGET_NR_getgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011732 return get_errno(getgid());
bellarda315a142005-01-30 22:59:18 +000011733#endif
11734#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +000011735 case TARGET_NR_geteuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011736 return get_errno(geteuid());
bellarda315a142005-01-30 22:59:18 +000011737#endif
11738#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +000011739 case TARGET_NR_getegid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011740 return get_errno(getegid());
bellarda315a142005-01-30 22:59:18 +000011741#endif
11742#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +000011743 case TARGET_NR_setreuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011744 return get_errno(setreuid(arg1, arg2));
bellarda315a142005-01-30 22:59:18 +000011745#endif
11746#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +000011747 case TARGET_NR_setregid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011748 return get_errno(setregid(arg1, arg2));
bellarda315a142005-01-30 22:59:18 +000011749#endif
11750#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +000011751 case TARGET_NR_getgroups32:
bellard99c475a2005-01-31 20:45:13 +000011752 {
11753 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +000011754 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +000011755 gid_t *grouplist;
11756 int i;
11757
11758 grouplist = alloca(gidsetsize * sizeof(gid_t));
11759 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +000011760 if (gidsetsize == 0)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011761 return ret;
bellard99c475a2005-01-31 20:45:13 +000011762 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +000011763 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
11764 if (!target_grouplist) {
Richard Henderson259841c2018-08-18 12:01:09 -070011765 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000011766 }
balroga2155fc2008-09-20 02:12:08 +000011767 for(i = 0;i < ret; i++)
pbrook53a59602006-03-25 19:31:22 +000011768 target_grouplist[i] = tswap32(grouplist[i]);
11769 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +000011770 }
11771 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011772 return ret;
bellarda315a142005-01-30 22:59:18 +000011773#endif
11774#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +000011775 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +000011776 {
11777 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +000011778 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +000011779 gid_t *grouplist;
11780 int i;
ths3b46e622007-09-17 08:09:54 +000011781
bellard99c475a2005-01-31 20:45:13 +000011782 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +000011783 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
11784 if (!target_grouplist) {
Richard Henderson259841c2018-08-18 12:01:09 -070011785 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000011786 }
bellard99c475a2005-01-31 20:45:13 +000011787 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +000011788 grouplist[i] = tswap32(target_grouplist[i]);
11789 unlock_user(target_grouplist, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011790 return get_errno(setgroups(gidsetsize, grouplist));
bellard99c475a2005-01-31 20:45:13 +000011791 }
bellarda315a142005-01-30 22:59:18 +000011792#endif
11793#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +000011794 case TARGET_NR_fchown32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011795 return get_errno(fchown(arg1, arg2, arg3));
bellarda315a142005-01-30 22:59:18 +000011796#endif
11797#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +000011798 case TARGET_NR_setresuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011799 return get_errno(sys_setresuid(arg1, arg2, arg3));
bellarda315a142005-01-30 22:59:18 +000011800#endif
11801#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +000011802 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +000011803 {
pbrook53a59602006-03-25 19:31:22 +000011804 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +000011805 ret = get_errno(getresuid(&ruid, &euid, &suid));
11806 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +000011807 if (put_user_u32(ruid, arg1)
11808 || put_user_u32(euid, arg2)
11809 || put_user_u32(suid, arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011810 return -TARGET_EFAULT;
bellardb03c60f2003-03-23 17:19:56 +000011811 }
11812 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011813 return ret;
bellarda315a142005-01-30 22:59:18 +000011814#endif
11815#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +000011816 case TARGET_NR_setresgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011817 return get_errno(sys_setresgid(arg1, arg2, arg3));
bellarda315a142005-01-30 22:59:18 +000011818#endif
11819#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +000011820 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +000011821 {
pbrook53a59602006-03-25 19:31:22 +000011822 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +000011823 ret = get_errno(getresgid(&rgid, &egid, &sgid));
11824 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +000011825 if (put_user_u32(rgid, arg1)
11826 || put_user_u32(egid, arg2)
11827 || put_user_u32(sgid, arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011828 return -TARGET_EFAULT;
bellardb03c60f2003-03-23 17:19:56 +000011829 }
11830 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011831 return ret;
bellarda315a142005-01-30 22:59:18 +000011832#endif
11833#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +000011834 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +000011835 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011836 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011837 ret = get_errno(chown(p, arg2, arg3));
11838 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011839 return ret;
bellarda315a142005-01-30 22:59:18 +000011840#endif
11841#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +000011842 case TARGET_NR_setuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011843 return get_errno(sys_setuid(arg1));
bellarda315a142005-01-30 22:59:18 +000011844#endif
11845#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +000011846 case TARGET_NR_setgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011847 return get_errno(sys_setgid(arg1));
bellarda315a142005-01-30 22:59:18 +000011848#endif
11849#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +000011850 case TARGET_NR_setfsuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011851 return get_errno(setfsuid(arg1));
bellarda315a142005-01-30 22:59:18 +000011852#endif
11853#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +000011854 case TARGET_NR_setfsgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011855 return get_errno(setfsgid(arg1));
bellarda315a142005-01-30 22:59:18 +000011856#endif
bellardffa65c32004-01-04 23:57:22 +000011857#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +000011858 case TARGET_NR_mincore:
aurel3204bb9ac2008-10-01 21:46:41 +000011859 {
Richard Henderson259841c2018-08-18 12:01:09 -070011860 void *a = lock_user(VERIFY_READ, arg1, arg2, 0);
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000011861 if (!a) {
Richard Henderson259841c2018-08-18 12:01:09 -070011862 return -TARGET_ENOMEM;
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000011863 }
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000011864 p = lock_user_string(arg3);
11865 if (!p) {
Richard Henderson259841c2018-08-18 12:01:09 -070011866 ret = -TARGET_EFAULT;
11867 } else {
11868 ret = get_errno(mincore(a, arg2, p));
11869 unlock_user(p, arg3, ret);
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000011870 }
aurel3204bb9ac2008-10-01 21:46:41 +000011871 unlock_user(a, arg1, 0);
11872 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011873 return ret;
bellardffa65c32004-01-04 23:57:22 +000011874#endif
aurel32408321b2008-10-01 21:46:32 +000011875#ifdef TARGET_NR_arm_fadvise64_64
11876 case TARGET_NR_arm_fadvise64_64:
Peter Maydelle0156a92016-05-31 15:45:09 +010011877 /* arm_fadvise64_64 looks like fadvise64_64 but
11878 * with different argument order: fd, advice, offset, len
11879 * rather than the usual fd, offset, len, advice.
11880 * Note that offset and len are both 64-bit so appear as
11881 * pairs of 32-bit registers.
11882 */
11883 ret = posix_fadvise(arg1, target_offset64(arg3, arg4),
11884 target_offset64(arg5, arg6), arg2);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011885 return -host_to_target_errno(ret);
aurel32408321b2008-10-01 21:46:32 +000011886#endif
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011887
WANG Xueruieeed2292022-10-06 16:55:00 +080011888#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011889
11890#ifdef TARGET_NR_fadvise64_64
11891 case TARGET_NR_fadvise64_64:
Max Filippov64a563d2018-04-01 15:02:34 -070011892#if defined(TARGET_PPC) || defined(TARGET_XTENSA)
Laurent Vivier43046b52017-03-02 01:11:45 +010011893 /* 6 args: fd, advice, offset (high, low), len (high, low) */
11894 ret = arg2;
11895 arg2 = arg3;
11896 arg3 = arg4;
11897 arg4 = arg5;
11898 arg5 = arg6;
11899 arg6 = ret;
11900#else
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011901 /* 6 args: fd, offset (high, low), len (high, low), advice */
James Clarke8bf8e9d2017-09-15 20:33:13 +010011902 if (regpairs_aligned(cpu_env, num)) {
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011903 /* offset is in (3,4), len in (5,6) and advice in 7 */
11904 arg2 = arg3;
11905 arg3 = arg4;
11906 arg4 = arg5;
11907 arg5 = arg6;
11908 arg6 = arg7;
11909 }
Laurent Vivier43046b52017-03-02 01:11:45 +010011910#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011911 ret = posix_fadvise(arg1, target_offset64(arg2, arg3),
11912 target_offset64(arg4, arg5), arg6);
11913 return -host_to_target_errno(ret);
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011914#endif
11915
11916#ifdef TARGET_NR_fadvise64
11917 case TARGET_NR_fadvise64:
11918 /* 5 args: fd, offset (high, low), len, advice */
James Clarke8bf8e9d2017-09-15 20:33:13 +010011919 if (regpairs_aligned(cpu_env, num)) {
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011920 /* offset is in (3,4), len in 5 and advice in 6 */
11921 arg2 = arg3;
11922 arg3 = arg4;
11923 arg4 = arg5;
11924 arg5 = arg6;
11925 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011926 ret = posix_fadvise(arg1, target_offset64(arg2, arg3), arg4, arg5);
11927 return -host_to_target_errno(ret);
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011928#endif
11929
11930#else /* not a 32-bit ABI */
Peter Maydelle0156a92016-05-31 15:45:09 +010011931#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_fadvise64)
aurel32408321b2008-10-01 21:46:32 +000011932#ifdef TARGET_NR_fadvise64_64
11933 case TARGET_NR_fadvise64_64:
11934#endif
Ulrich Hechte72d2cc2009-07-24 19:10:31 +020011935#ifdef TARGET_NR_fadvise64
11936 case TARGET_NR_fadvise64:
11937#endif
11938#ifdef TARGET_S390X
11939 switch (arg4) {
11940 case 4: arg4 = POSIX_FADV_NOREUSE + 1; break; /* make sure it's an invalid value */
11941 case 5: arg4 = POSIX_FADV_NOREUSE + 2; break; /* ditto */
11942 case 6: arg4 = POSIX_FADV_DONTNEED; break;
11943 case 7: arg4 = POSIX_FADV_NOREUSE; break;
11944 default: break;
11945 }
11946#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011947 return -host_to_target_errno(posix_fadvise(arg1, arg2, arg3, arg4));
aurel32408321b2008-10-01 21:46:32 +000011948#endif
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011949#endif /* end of 64-bit ABI fadvise handling */
11950
bellardffa65c32004-01-04 23:57:22 +000011951#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +000011952 case TARGET_NR_madvise:
Ilya Leoshkevich892a4f62022-06-21 16:42:05 +020011953 return target_madvise(arg1, arg2, arg3);
bellardffa65c32004-01-04 23:57:22 +000011954#endif
Alex Bennéebbf5f2a2020-04-03 20:11:40 +010011955#ifdef TARGET_NR_fcntl64
bellard31e31b82003-02-18 22:55:36 +000011956 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +000011957 {
Alex Bennéebbf5f2a2020-04-03 20:11:40 +010011958 int cmd;
11959 struct flock64 fl;
Peter Maydell213d3e92016-06-13 11:22:05 +010011960 from_flock64_fn *copyfrom = copy_from_user_flock64;
11961 to_flock64_fn *copyto = copy_to_user_flock64;
11962
pbrookce4defa2006-02-09 16:49:55 +000011963#ifdef TARGET_ARM
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020011964 if (!cpu_env->eabi) {
Laurent Vivier7f254c52018-05-02 23:57:30 +020011965 copyfrom = copy_from_user_oabi_flock64;
11966 copyto = copy_to_user_oabi_flock64;
Peter Maydell213d3e92016-06-13 11:22:05 +010011967 }
pbrookce4defa2006-02-09 16:49:55 +000011968#endif
bellard77e46722003-04-29 20:39:06 +000011969
Alex Bennéebbf5f2a2020-04-03 20:11:40 +010011970 cmd = target_to_host_fcntl_cmd(arg2);
Peter Maydell31b63192011-12-05 23:11:50 +000011971 if (cmd == -TARGET_EINVAL) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011972 return cmd;
Peter Maydell31b63192011-12-05 23:11:50 +000011973 }
thsb1e341e2007-03-20 21:50:52 +000011974
bellard60cd49d2003-03-16 22:53:56 +000011975 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +000011976 case TARGET_F_GETLK64:
Peter Maydell213d3e92016-06-13 11:22:05 +010011977 ret = copyfrom(&fl, arg3);
11978 if (ret) {
11979 break;
ths58134272007-03-31 18:59:32 +000011980 }
Laurent Vivieraf8ab2b2018-07-13 14:58:05 +020011981 ret = get_errno(safe_fcntl(arg1, cmd, &fl));
Peter Maydell213d3e92016-06-13 11:22:05 +010011982 if (ret == 0) {
11983 ret = copyto(arg3, &fl);
11984 }
bellard77e46722003-04-29 20:39:06 +000011985 break;
11986
thsb1e341e2007-03-20 21:50:52 +000011987 case TARGET_F_SETLK64:
11988 case TARGET_F_SETLKW64:
Peter Maydell213d3e92016-06-13 11:22:05 +010011989 ret = copyfrom(&fl, arg3);
11990 if (ret) {
11991 break;
pbrookce4defa2006-02-09 16:49:55 +000011992 }
Peter Maydell435da5e2016-06-13 11:22:05 +010011993 ret = get_errno(safe_fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +000011994 break;
bellard60cd49d2003-03-16 22:53:56 +000011995 default:
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +020011996 ret = do_fcntl(arg1, arg2, arg3);
bellard60cd49d2003-03-16 22:53:56 +000011997 break;
11998 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011999 return ret;
bellard77e46722003-04-29 20:39:06 +000012000 }
bellard60cd49d2003-03-16 22:53:56 +000012001#endif
ths7d600c82006-12-08 01:32:58 +000012002#ifdef TARGET_NR_cacheflush
12003 case TARGET_NR_cacheflush:
12004 /* self-modifying code is handled automatically, so nothing needed */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012005 return 0;
ths7d600c82006-12-08 01:32:58 +000012006#endif
bellardc573ff62004-01-04 15:51:36 +000012007#ifdef TARGET_NR_getpagesize
12008 case TARGET_NR_getpagesize:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012009 return TARGET_PAGE_SIZE;
bellardc573ff62004-01-04 15:51:36 +000012010#endif
bellard31e31b82003-02-18 22:55:36 +000012011 case TARGET_NR_gettid:
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +000012012 return get_errno(sys_gettid());
thse5febef2007-04-01 18:31:35 +000012013#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +000012014 case TARGET_NR_readahead:
WANG Xueruieeed2292022-10-06 16:55:00 +080012015#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
James Clarke8bf8e9d2017-09-15 20:33:13 +010012016 if (regpairs_aligned(cpu_env, num)) {
aurel322054ac92008-10-13 21:08:07 +000012017 arg2 = arg3;
12018 arg3 = arg4;
12019 arg4 = arg5;
12020 }
Lena Djokic77c68502016-11-24 17:08:56 +010012021 ret = get_errno(readahead(arg1, target_offset64(arg2, arg3) , arg4));
aurel322054ac92008-10-13 21:08:07 +000012022#else
12023 ret = get_errno(readahead(arg1, arg2, arg3));
12024#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012025 return ret;
thse5febef2007-04-01 18:31:35 +000012026#endif
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012027#ifdef CONFIG_ATTR
bellardebc05482003-09-30 21:08:41 +000012028#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +000012029 case TARGET_NR_listxattr:
12030 case TARGET_NR_llistxattr:
Peter Maydellfb5590f2011-12-14 15:37:19 +000012031 {
12032 void *p, *b = 0;
12033 if (arg2) {
12034 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
12035 if (!b) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012036 return -TARGET_EFAULT;
Peter Maydellfb5590f2011-12-14 15:37:19 +000012037 }
12038 }
12039 p = lock_user_string(arg1);
12040 if (p) {
12041 if (num == TARGET_NR_listxattr) {
12042 ret = get_errno(listxattr(p, b, arg3));
12043 } else {
12044 ret = get_errno(llistxattr(p, b, arg3));
12045 }
12046 } else {
12047 ret = -TARGET_EFAULT;
12048 }
12049 unlock_user(p, arg1, 0);
12050 unlock_user(b, arg2, arg3);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012051 return ret;
Peter Maydellfb5590f2011-12-14 15:37:19 +000012052 }
12053 case TARGET_NR_flistxattr:
12054 {
12055 void *b = 0;
12056 if (arg2) {
12057 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
12058 if (!b) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012059 return -TARGET_EFAULT;
Peter Maydellfb5590f2011-12-14 15:37:19 +000012060 }
12061 }
12062 ret = get_errno(flistxattr(arg1, b, arg3));
12063 unlock_user(b, arg2, arg3);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012064 return ret;
Peter Maydellfb5590f2011-12-14 15:37:19 +000012065 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012066 case TARGET_NR_setxattr:
Peter Maydell30297b52011-12-14 15:37:18 +000012067 case TARGET_NR_lsetxattr:
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012068 {
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012069 void *p, *n, *v = 0;
12070 if (arg3) {
12071 v = lock_user(VERIFY_READ, arg3, arg4, 1);
12072 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012073 return -TARGET_EFAULT;
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012074 }
12075 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012076 p = lock_user_string(arg1);
12077 n = lock_user_string(arg2);
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012078 if (p && n) {
Peter Maydell30297b52011-12-14 15:37:18 +000012079 if (num == TARGET_NR_setxattr) {
12080 ret = get_errno(setxattr(p, n, v, arg4, arg5));
12081 } else {
12082 ret = get_errno(lsetxattr(p, n, v, arg4, arg5));
12083 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012084 } else {
12085 ret = -TARGET_EFAULT;
12086 }
12087 unlock_user(p, arg1, 0);
12088 unlock_user(n, arg2, 0);
12089 unlock_user(v, arg3, 0);
12090 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012091 return ret;
Peter Maydell30297b52011-12-14 15:37:18 +000012092 case TARGET_NR_fsetxattr:
12093 {
12094 void *n, *v = 0;
12095 if (arg3) {
12096 v = lock_user(VERIFY_READ, arg3, arg4, 1);
12097 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012098 return -TARGET_EFAULT;
Peter Maydell30297b52011-12-14 15:37:18 +000012099 }
12100 }
12101 n = lock_user_string(arg2);
12102 if (n) {
12103 ret = get_errno(fsetxattr(arg1, n, v, arg4, arg5));
12104 } else {
12105 ret = -TARGET_EFAULT;
12106 }
12107 unlock_user(n, arg2, 0);
12108 unlock_user(v, arg3, 0);
12109 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012110 return ret;
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012111 case TARGET_NR_getxattr:
Peter Maydell30297b52011-12-14 15:37:18 +000012112 case TARGET_NR_lgetxattr:
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012113 {
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012114 void *p, *n, *v = 0;
12115 if (arg3) {
12116 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
12117 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012118 return -TARGET_EFAULT;
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012119 }
12120 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012121 p = lock_user_string(arg1);
12122 n = lock_user_string(arg2);
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012123 if (p && n) {
Peter Maydell30297b52011-12-14 15:37:18 +000012124 if (num == TARGET_NR_getxattr) {
12125 ret = get_errno(getxattr(p, n, v, arg4));
12126 } else {
12127 ret = get_errno(lgetxattr(p, n, v, arg4));
12128 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012129 } else {
12130 ret = -TARGET_EFAULT;
12131 }
12132 unlock_user(p, arg1, 0);
12133 unlock_user(n, arg2, 0);
12134 unlock_user(v, arg3, arg4);
12135 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012136 return ret;
Peter Maydell30297b52011-12-14 15:37:18 +000012137 case TARGET_NR_fgetxattr:
12138 {
12139 void *n, *v = 0;
12140 if (arg3) {
12141 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
12142 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012143 return -TARGET_EFAULT;
Peter Maydell30297b52011-12-14 15:37:18 +000012144 }
12145 }
12146 n = lock_user_string(arg2);
12147 if (n) {
12148 ret = get_errno(fgetxattr(arg1, n, v, arg4));
12149 } else {
12150 ret = -TARGET_EFAULT;
12151 }
12152 unlock_user(n, arg2, 0);
12153 unlock_user(v, arg3, arg4);
12154 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012155 return ret;
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012156 case TARGET_NR_removexattr:
Peter Maydell30297b52011-12-14 15:37:18 +000012157 case TARGET_NR_lremovexattr:
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012158 {
12159 void *p, *n;
12160 p = lock_user_string(arg1);
12161 n = lock_user_string(arg2);
12162 if (p && n) {
Peter Maydell30297b52011-12-14 15:37:18 +000012163 if (num == TARGET_NR_removexattr) {
12164 ret = get_errno(removexattr(p, n));
12165 } else {
12166 ret = get_errno(lremovexattr(p, n));
12167 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012168 } else {
12169 ret = -TARGET_EFAULT;
12170 }
12171 unlock_user(p, arg1, 0);
12172 unlock_user(n, arg2, 0);
12173 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012174 return ret;
Peter Maydell30297b52011-12-14 15:37:18 +000012175 case TARGET_NR_fremovexattr:
12176 {
12177 void *n;
12178 n = lock_user_string(arg2);
12179 if (n) {
12180 ret = get_errno(fremovexattr(arg1, n));
12181 } else {
12182 ret = -TARGET_EFAULT;
12183 }
12184 unlock_user(n, arg2, 0);
12185 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012186 return ret;
bellardebc05482003-09-30 21:08:41 +000012187#endif
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012188#endif /* CONFIG_ATTR */
bellardebc05482003-09-30 21:08:41 +000012189#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +000012190 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +000012191#if defined(TARGET_MIPS)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020012192 cpu_env->active_tc.CP0_UserLocal = arg1;
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012193 return 0;
edgar_iglef967792009-01-07 14:19:38 +000012194#elif defined(TARGET_CRIS)
12195 if (arg1 & 0xff)
12196 ret = -TARGET_EINVAL;
12197 else {
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020012198 cpu_env->pregs[PR_PID] = arg1;
edgar_iglef967792009-01-07 14:19:38 +000012199 ret = 0;
12200 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012201 return ret;
bellard8d18e892007-11-14 15:18:40 +000012202#elif defined(TARGET_I386) && defined(TARGET_ABI32)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012203 return do_set_thread_area(cpu_env, arg1);
Peter Maydell1ccd9372013-07-16 18:44:55 +010012204#elif defined(TARGET_M68K)
12205 {
Andreas Färber0429a972013-08-26 18:14:44 +020012206 TaskState *ts = cpu->opaque;
Peter Maydell1ccd9372013-07-16 18:44:55 +010012207 ts->tp_value = arg1;
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012208 return 0;
Peter Maydell1ccd9372013-07-16 18:44:55 +010012209 }
ths6f5b89a2007-03-02 20:48:00 +000012210#else
Richard Henderson10f45d92018-08-18 12:01:07 -070012211 return -TARGET_ENOSYS;
ths6f5b89a2007-03-02 20:48:00 +000012212#endif
12213#endif
12214#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +000012215 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +000012216#if defined(TARGET_I386) && defined(TARGET_ABI32)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012217 return do_get_thread_area(cpu_env, arg1);
Peter Maydell1ccd9372013-07-16 18:44:55 +010012218#elif defined(TARGET_M68K)
12219 {
Andreas Färber0429a972013-08-26 18:14:44 +020012220 TaskState *ts = cpu->opaque;
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012221 return ts->tp_value;
Peter Maydell1ccd9372013-07-16 18:44:55 +010012222 }
bellard8d18e892007-11-14 15:18:40 +000012223#else
Richard Henderson10f45d92018-08-18 12:01:07 -070012224 return -TARGET_ENOSYS;
bellardebc05482003-09-30 21:08:41 +000012225#endif
bellard8d18e892007-11-14 15:18:40 +000012226#endif
bellard48dc41e2006-06-21 18:15:50 +000012227#ifdef TARGET_NR_getdomainname
12228 case TARGET_NR_getdomainname:
Richard Henderson10f45d92018-08-18 12:01:07 -070012229 return -TARGET_ENOSYS;
bellard48dc41e2006-06-21 18:15:50 +000012230#endif
ths6f5b89a2007-03-02 20:48:00 +000012231
Max Filippov12e33402018-04-01 13:13:49 -070012232#ifdef TARGET_NR_clock_settime
12233 case TARGET_NR_clock_settime:
12234 {
12235 struct timespec ts;
12236
12237 ret = target_to_host_timespec(&ts, arg2);
12238 if (!is_error(ret)) {
12239 ret = get_errno(clock_settime(arg1, &ts));
12240 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012241 return ret;
Max Filippov12e33402018-04-01 13:13:49 -070012242 }
12243#endif
Alistair Francisc6c8d102020-03-12 15:13:53 -070012244#ifdef TARGET_NR_clock_settime64
12245 case TARGET_NR_clock_settime64:
12246 {
12247 struct timespec ts;
12248
12249 ret = target_to_host_timespec64(&ts, arg2);
12250 if (!is_error(ret)) {
12251 ret = get_errno(clock_settime(arg1, &ts));
12252 }
12253 return ret;
12254 }
12255#endif
thsb5906f92007-03-19 13:32:45 +000012256#ifdef TARGET_NR_clock_gettime
12257 case TARGET_NR_clock_gettime:
12258 {
12259 struct timespec ts;
12260 ret = get_errno(clock_gettime(arg1, &ts));
12261 if (!is_error(ret)) {
Max Filippovb9f99082018-04-01 13:14:04 -070012262 ret = host_to_target_timespec(arg2, &ts);
thsb5906f92007-03-19 13:32:45 +000012263 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012264 return ret;
thsb5906f92007-03-19 13:32:45 +000012265 }
12266#endif
Alistair Francisc6c8d102020-03-12 15:13:53 -070012267#ifdef TARGET_NR_clock_gettime64
12268 case TARGET_NR_clock_gettime64:
12269 {
12270 struct timespec ts;
12271 ret = get_errno(clock_gettime(arg1, &ts));
12272 if (!is_error(ret)) {
12273 ret = host_to_target_timespec64(arg2, &ts);
12274 }
12275 return ret;
12276 }
12277#endif
thsb5906f92007-03-19 13:32:45 +000012278#ifdef TARGET_NR_clock_getres
12279 case TARGET_NR_clock_getres:
12280 {
12281 struct timespec ts;
12282 ret = get_errno(clock_getres(arg1, &ts));
12283 if (!is_error(ret)) {
12284 host_to_target_timespec(arg2, &ts);
12285 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012286 return ret;
thsb5906f92007-03-19 13:32:45 +000012287 }
12288#endif
Filip Bozuta828cb3a2020-07-22 17:34:21 +020012289#ifdef TARGET_NR_clock_getres_time64
12290 case TARGET_NR_clock_getres_time64:
12291 {
12292 struct timespec ts;
12293 ret = get_errno(clock_getres(arg1, &ts));
12294 if (!is_error(ret)) {
12295 host_to_target_timespec64(arg2, &ts);
12296 }
12297 return ret;
12298 }
12299#endif
pbrook63d76512008-05-29 13:43:29 +000012300#ifdef TARGET_NR_clock_nanosleep
12301 case TARGET_NR_clock_nanosleep:
12302 {
12303 struct timespec ts;
Filip Bozutab09d6402020-07-27 22:13:26 +020012304 if (target_to_host_timespec(&ts, arg3)) {
12305 return -TARGET_EFAULT;
12306 }
Peter Maydell9e518222016-06-06 19:58:09 +010012307 ret = get_errno(safe_clock_nanosleep(arg1, arg2,
12308 &ts, arg4 ? &ts : NULL));
Laurent Vivier8ec68a02020-07-24 07:45:05 +010012309 /*
12310 * if the call is interrupted by a signal handler, it fails
12311 * with error -TARGET_EINTR and if arg4 is not NULL and arg2 is not
12312 * TIMER_ABSTIME, it returns the remaining unslept time in arg4.
12313 */
Filip Bozutab09d6402020-07-27 22:13:26 +020012314 if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME &&
12315 host_to_target_timespec(arg4, &ts)) {
12316 return -TARGET_EFAULT;
Laurent Vivier8ec68a02020-07-24 07:45:05 +010012317 }
Tom Musta8fbe8fd2014-08-12 13:53:41 -050012318
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012319 return ret;
pbrook63d76512008-05-29 13:43:29 +000012320 }
12321#endif
Filip Bozuta6ac03b22020-08-24 21:21:15 +020012322#ifdef TARGET_NR_clock_nanosleep_time64
12323 case TARGET_NR_clock_nanosleep_time64:
12324 {
12325 struct timespec ts;
12326
12327 if (target_to_host_timespec64(&ts, arg3)) {
12328 return -TARGET_EFAULT;
12329 }
12330
12331 ret = get_errno(safe_clock_nanosleep(arg1, arg2,
12332 &ts, arg4 ? &ts : NULL));
12333
12334 if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME &&
12335 host_to_target_timespec64(arg4, &ts)) {
12336 return -TARGET_EFAULT;
12337 }
12338 return ret;
12339 }
12340#endif
thsb5906f92007-03-19 13:32:45 +000012341
Helge Deller9a7f6822022-05-28 12:52:10 +020012342#if defined(TARGET_NR_set_tid_address)
ths6f5b89a2007-03-02 20:48:00 +000012343 case TARGET_NR_set_tid_address:
Helge Deller9a7f6822022-05-28 12:52:10 +020012344 {
12345 TaskState *ts = cpu->opaque;
12346 ts->child_tidptr = arg1;
12347 /* do not call host set_tid_address() syscall, instead return tid() */
12348 return get_errno(sys_gettid());
12349 }
ths6f5b89a2007-03-02 20:48:00 +000012350#endif
12351
ths4cae1d12007-07-12 11:06:53 +000012352 case TARGET_NR_tkill:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012353 return get_errno(safe_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +000012354
ths71455572007-06-21 21:45:30 +000012355 case TARGET_NR_tgkill:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012356 return get_errno(safe_tgkill((int)arg1, (int)arg2,
12357 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +000012358
ths4f2b1fe2007-06-21 21:57:12 +000012359#ifdef TARGET_NR_set_robust_list
12360 case TARGET_NR_set_robust_list:
Peter Maydelle9a970a2013-02-08 04:34:54 +000012361 case TARGET_NR_get_robust_list:
12362 /* The ABI for supporting robust futexes has userspace pass
12363 * the kernel a pointer to a linked list which is updated by
12364 * userspace after the syscall; the list is walked by the kernel
12365 * when the thread exits. Since the linked list in QEMU guest
12366 * memory isn't a valid linked list for the host and we have
12367 * no way to reliably intercept the thread-death event, we can't
12368 * support these. Silently return ENOSYS so that guest userspace
12369 * falls back to a non-robust futex implementation (which should
12370 * be OK except in the corner case of the guest crashing while
12371 * holding a mutex that is shared with another process via
12372 * shared memory).
12373 */
Richard Henderson10f45d92018-08-18 12:01:07 -070012374 return -TARGET_ENOSYS;
ths4f2b1fe2007-06-21 21:57:12 +000012375#endif
12376
Peter Maydell1acae9f2013-07-02 14:04:12 +010012377#if defined(TARGET_NR_utimensat)
ths9007f0e2007-09-25 17:50:37 +000012378 case TARGET_NR_utimensat:
12379 {
Riku Voipioebc996f2009-04-21 15:01:51 +030012380 struct timespec *tsp, ts[2];
12381 if (!arg3) {
12382 tsp = NULL;
12383 } else {
Filip Bozutab3a3af72020-08-11 13:31:01 +020012384 if (target_to_host_timespec(ts, arg3)) {
12385 return -TARGET_EFAULT;
12386 }
12387 if (target_to_host_timespec(ts + 1, arg3 +
12388 sizeof(struct target_timespec))) {
12389 return -TARGET_EFAULT;
12390 }
Riku Voipioebc996f2009-04-21 15:01:51 +030012391 tsp = ts;
12392 }
ths9007f0e2007-09-25 17:50:37 +000012393 if (!arg2)
Riku Voipioebc996f2009-04-21 15:01:51 +030012394 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
ths9007f0e2007-09-25 17:50:37 +000012395 else {
bellard579a97f2007-11-11 14:26:47 +000012396 if (!(p = lock_user_string(arg2))) {
Richard Henderson259841c2018-08-18 12:01:09 -070012397 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000012398 }
Riku Voipioebc996f2009-04-21 15:01:51 +030012399 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
bellard579a97f2007-11-11 14:26:47 +000012400 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +000012401 }
12402 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012403 return ret;
ths9007f0e2007-09-25 17:50:37 +000012404#endif
Filip Bozutacac46eb2020-08-25 00:30:50 +020012405#ifdef TARGET_NR_utimensat_time64
12406 case TARGET_NR_utimensat_time64:
12407 {
12408 struct timespec *tsp, ts[2];
12409 if (!arg3) {
12410 tsp = NULL;
12411 } else {
12412 if (target_to_host_timespec64(ts, arg3)) {
12413 return -TARGET_EFAULT;
12414 }
12415 if (target_to_host_timespec64(ts + 1, arg3 +
12416 sizeof(struct target__kernel_timespec))) {
12417 return -TARGET_EFAULT;
12418 }
12419 tsp = ts;
12420 }
12421 if (!arg2)
12422 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
12423 else {
12424 p = lock_user_string(arg2);
12425 if (!p) {
12426 return -TARGET_EFAULT;
12427 }
12428 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
12429 unlock_user(p, arg2, 0);
12430 }
12431 }
12432 return ret;
12433#endif
Alistair Francis859e8a82020-03-12 15:13:49 -070012434#ifdef TARGET_NR_futex
pbrookbd0c5662008-05-29 14:34:11 +000012435 case TARGET_NR_futex:
Richard Henderson0fbc0f82022-08-28 19:09:59 -070012436 return do_futex(cpu, false, arg1, arg2, arg3, arg4, arg5, arg6);
Alistair Francis859e8a82020-03-12 15:13:49 -070012437#endif
Alistair Francis14690292020-03-18 15:47:01 -070012438#ifdef TARGET_NR_futex_time64
12439 case TARGET_NR_futex_time64:
Richard Henderson0fbc0f82022-08-28 19:09:59 -070012440 return do_futex(cpu, true, arg1, arg2, arg3, arg4, arg5, arg6);
Alistair Francis14690292020-03-18 15:47:01 -070012441#endif
Paul Brook33f53ac2022-01-26 20:26:36 +000012442#ifdef CONFIG_INOTIFY
12443#if defined(TARGET_NR_inotify_init)
aurel3239b59762008-10-01 21:46:50 +000012444 case TARGET_NR_inotify_init:
Paul Brook33f53ac2022-01-26 20:26:36 +000012445 ret = get_errno(inotify_init());
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030012446 if (ret >= 0) {
12447 fd_trans_register(ret, &target_inotify_trans);
12448 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012449 return ret;
aurel3239b59762008-10-01 21:46:50 +000012450#endif
Paul Brook33f53ac2022-01-26 20:26:36 +000012451#if defined(TARGET_NR_inotify_init1) && defined(CONFIG_INOTIFY1)
Riku Voipioc05c7a72010-03-26 15:25:11 +000012452 case TARGET_NR_inotify_init1:
Paul Brook33f53ac2022-01-26 20:26:36 +000012453 ret = get_errno(inotify_init1(target_to_host_bitmask(arg1,
Lena Djokicfea243e2016-11-24 17:08:53 +010012454 fcntl_flags_tbl)));
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030012455 if (ret >= 0) {
12456 fd_trans_register(ret, &target_inotify_trans);
12457 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012458 return ret;
Riku Voipioc05c7a72010-03-26 15:25:11 +000012459#endif
Paul Brook33f53ac2022-01-26 20:26:36 +000012460#if defined(TARGET_NR_inotify_add_watch)
aurel3239b59762008-10-01 21:46:50 +000012461 case TARGET_NR_inotify_add_watch:
12462 p = lock_user_string(arg2);
Paul Brook33f53ac2022-01-26 20:26:36 +000012463 ret = get_errno(inotify_add_watch(arg1, path(p), arg3));
aurel3239b59762008-10-01 21:46:50 +000012464 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012465 return ret;
aurel3239b59762008-10-01 21:46:50 +000012466#endif
Paul Brook33f53ac2022-01-26 20:26:36 +000012467#if defined(TARGET_NR_inotify_rm_watch)
aurel3239b59762008-10-01 21:46:50 +000012468 case TARGET_NR_inotify_rm_watch:
Paul Brook33f53ac2022-01-26 20:26:36 +000012469 return get_errno(inotify_rm_watch(arg1, arg2));
12470#endif
aurel3239b59762008-10-01 21:46:50 +000012471#endif
ths9007f0e2007-09-25 17:50:37 +000012472
Nathan Froyd8ec9cf82009-07-22 09:14:36 -070012473#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
aurel3224e10032009-04-15 16:11:43 +000012474 case TARGET_NR_mq_open:
12475 {
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020012476 struct mq_attr posix_mq_attr;
Lena Djokic26400772016-11-24 17:08:58 +010012477 struct mq_attr *pposix_mq_attr;
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020012478 int host_flags;
aurel3224e10032009-04-15 16:11:43 +000012479
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020012480 host_flags = target_to_host_bitmask(arg2, fcntl_flags_tbl);
Lena Djokic26400772016-11-24 17:08:58 +010012481 pposix_mq_attr = NULL;
12482 if (arg4) {
12483 if (copy_from_user_mq_attr(&posix_mq_attr, arg4) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012484 return -TARGET_EFAULT;
Lena Djokic26400772016-11-24 17:08:58 +010012485 }
12486 pposix_mq_attr = &posix_mq_attr;
Tom Mustab6ce1f62014-08-12 13:53:36 -050012487 }
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020012488 p = lock_user_string(arg1 - 1);
12489 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012490 return -TARGET_EFAULT;
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020012491 }
Lena Djokic26400772016-11-24 17:08:58 +010012492 ret = get_errno(mq_open(p, host_flags, arg3, pposix_mq_attr));
aurel3224e10032009-04-15 16:11:43 +000012493 unlock_user (p, arg1, 0);
12494 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012495 return ret;
aurel3224e10032009-04-15 16:11:43 +000012496
12497 case TARGET_NR_mq_unlink:
12498 p = lock_user_string(arg1 - 1);
Peter Maydell32112152016-07-12 13:02:13 +010012499 if (!p) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012500 return -TARGET_EFAULT;
Peter Maydell32112152016-07-12 13:02:13 +010012501 }
aurel3224e10032009-04-15 16:11:43 +000012502 ret = get_errno(mq_unlink(p));
12503 unlock_user (p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012504 return ret;
aurel3224e10032009-04-15 16:11:43 +000012505
Alistair Francis859e8a82020-03-12 15:13:49 -070012506#ifdef TARGET_NR_mq_timedsend
aurel3224e10032009-04-15 16:11:43 +000012507 case TARGET_NR_mq_timedsend:
12508 {
12509 struct timespec ts;
12510
12511 p = lock_user (VERIFY_READ, arg2, arg3, 1);
12512 if (arg5 != 0) {
Filip Bozutadcbcf5c2020-08-24 21:37:51 +020012513 if (target_to_host_timespec(&ts, arg5)) {
12514 return -TARGET_EFAULT;
12515 }
Peter Maydelld40ecd62016-06-06 19:58:06 +010012516 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts));
Filip Bozutadcbcf5c2020-08-24 21:37:51 +020012517 if (!is_error(ret) && host_to_target_timespec(arg5, &ts)) {
12518 return -TARGET_EFAULT;
12519 }
Peter Maydelld40ecd62016-06-06 19:58:06 +010012520 } else {
12521 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL));
aurel3224e10032009-04-15 16:11:43 +000012522 }
aurel3224e10032009-04-15 16:11:43 +000012523 unlock_user (p, arg2, arg3);
12524 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012525 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070012526#endif
Filip Bozutad107e372020-08-24 21:37:52 +020012527#ifdef TARGET_NR_mq_timedsend_time64
12528 case TARGET_NR_mq_timedsend_time64:
12529 {
12530 struct timespec ts;
12531
12532 p = lock_user(VERIFY_READ, arg2, arg3, 1);
12533 if (arg5 != 0) {
12534 if (target_to_host_timespec64(&ts, arg5)) {
12535 return -TARGET_EFAULT;
12536 }
12537 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts));
12538 if (!is_error(ret) && host_to_target_timespec64(arg5, &ts)) {
12539 return -TARGET_EFAULT;
12540 }
12541 } else {
12542 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL));
12543 }
12544 unlock_user(p, arg2, arg3);
12545 }
12546 return ret;
12547#endif
aurel3224e10032009-04-15 16:11:43 +000012548
Alistair Francis859e8a82020-03-12 15:13:49 -070012549#ifdef TARGET_NR_mq_timedreceive
aurel3224e10032009-04-15 16:11:43 +000012550 case TARGET_NR_mq_timedreceive:
12551 {
12552 struct timespec ts;
12553 unsigned int prio;
12554
12555 p = lock_user (VERIFY_READ, arg2, arg3, 1);
12556 if (arg5 != 0) {
Filip Bozutadcbcf5c2020-08-24 21:37:51 +020012557 if (target_to_host_timespec(&ts, arg5)) {
12558 return -TARGET_EFAULT;
12559 }
Peter Maydelld40ecd62016-06-06 19:58:06 +010012560 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12561 &prio, &ts));
Filip Bozutadcbcf5c2020-08-24 21:37:51 +020012562 if (!is_error(ret) && host_to_target_timespec(arg5, &ts)) {
12563 return -TARGET_EFAULT;
12564 }
Peter Maydelld40ecd62016-06-06 19:58:06 +010012565 } else {
12566 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12567 &prio, NULL));
aurel3224e10032009-04-15 16:11:43 +000012568 }
aurel3224e10032009-04-15 16:11:43 +000012569 unlock_user (p, arg2, arg3);
12570 if (arg4 != 0)
12571 put_user_u32(prio, arg4);
12572 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012573 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070012574#endif
Filip Bozutad107e372020-08-24 21:37:52 +020012575#ifdef TARGET_NR_mq_timedreceive_time64
12576 case TARGET_NR_mq_timedreceive_time64:
12577 {
12578 struct timespec ts;
12579 unsigned int prio;
12580
12581 p = lock_user(VERIFY_READ, arg2, arg3, 1);
12582 if (arg5 != 0) {
12583 if (target_to_host_timespec64(&ts, arg5)) {
12584 return -TARGET_EFAULT;
12585 }
12586 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12587 &prio, &ts));
12588 if (!is_error(ret) && host_to_target_timespec64(arg5, &ts)) {
12589 return -TARGET_EFAULT;
12590 }
12591 } else {
12592 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12593 &prio, NULL));
12594 }
12595 unlock_user(p, arg2, arg3);
12596 if (arg4 != 0) {
12597 put_user_u32(prio, arg4);
12598 }
12599 }
12600 return ret;
12601#endif
aurel3224e10032009-04-15 16:11:43 +000012602
12603 /* Not implemented for now... */
12604/* case TARGET_NR_mq_notify: */
12605/* break; */
12606
12607 case TARGET_NR_mq_getsetattr:
12608 {
12609 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
12610 ret = 0;
aurel3224e10032009-04-15 16:11:43 +000012611 if (arg2 != 0) {
12612 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
Max Filippova23ea402018-03-31 08:20:15 -070012613 ret = get_errno(mq_setattr(arg1, &posix_mq_attr_in,
12614 &posix_mq_attr_out));
12615 } else if (arg3 != 0) {
12616 ret = get_errno(mq_getattr(arg1, &posix_mq_attr_out));
aurel3224e10032009-04-15 16:11:43 +000012617 }
Max Filippova23ea402018-03-31 08:20:15 -070012618 if (ret == 0 && arg3 != 0) {
12619 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
12620 }
aurel3224e10032009-04-15 16:11:43 +000012621 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012622 return ret;
aurel3224e10032009-04-15 16:11:43 +000012623#endif
12624
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012625#ifdef CONFIG_SPLICE
12626#ifdef TARGET_NR_tee
12627 case TARGET_NR_tee:
12628 {
12629 ret = get_errno(tee(arg1,arg2,arg3,arg4));
12630 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012631 return ret;
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012632#endif
12633#ifdef TARGET_NR_splice
12634 case TARGET_NR_splice:
12635 {
12636 loff_t loff_in, loff_out;
12637 loff_t *ploff_in = NULL, *ploff_out = NULL;
Andreas Schwab17644b32015-03-10 17:11:35 +010012638 if (arg2) {
12639 if (get_user_u64(loff_in, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012640 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010012641 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012642 ploff_in = &loff_in;
12643 }
Andreas Schwab17644b32015-03-10 17:11:35 +010012644 if (arg4) {
12645 if (get_user_u64(loff_out, arg4)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012646 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010012647 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012648 ploff_out = &loff_out;
12649 }
12650 ret = get_errno(splice(arg1, ploff_in, arg3, ploff_out, arg5, arg6));
Andreas Schwab17644b32015-03-10 17:11:35 +010012651 if (arg2) {
12652 if (put_user_u64(loff_in, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012653 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010012654 }
12655 }
12656 if (arg4) {
12657 if (put_user_u64(loff_out, arg4)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012658 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010012659 }
12660 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012661 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012662 return ret;
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012663#endif
12664#ifdef TARGET_NR_vmsplice
12665 case TARGET_NR_vmsplice:
12666 {
Richard Hendersonf287b2c2012-09-15 13:20:25 -070012667 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
12668 if (vec != NULL) {
12669 ret = get_errno(vmsplice(arg1, vec, arg3, arg4));
12670 unlock_iovec(vec, arg2, arg3, 0);
12671 } else {
12672 ret = -host_to_target_errno(errno);
12673 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012674 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012675 return ret;
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012676#endif
12677#endif /* CONFIG_SPLICE */
Riku Voipioc2882b92009-08-12 15:08:24 +030012678#ifdef CONFIG_EVENTFD
12679#if defined(TARGET_NR_eventfd)
12680 case TARGET_NR_eventfd:
12681 ret = get_errno(eventfd(arg1, 0));
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030012682 if (ret >= 0) {
12683 fd_trans_register(ret, &target_eventfd_trans);
12684 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012685 return ret;
Riku Voipioc2882b92009-08-12 15:08:24 +030012686#endif
12687#if defined(TARGET_NR_eventfd2)
12688 case TARGET_NR_eventfd2:
Petar Jovanovic5947c692013-04-08 20:26:10 +020012689 {
Helge Deller78721302021-02-10 07:12:14 +010012690 int host_flags = arg2 & (~(TARGET_O_NONBLOCK_MASK | TARGET_O_CLOEXEC));
Petar Jovanovic5947c692013-04-08 20:26:10 +020012691 if (arg2 & TARGET_O_NONBLOCK) {
12692 host_flags |= O_NONBLOCK;
12693 }
12694 if (arg2 & TARGET_O_CLOEXEC) {
12695 host_flags |= O_CLOEXEC;
12696 }
12697 ret = get_errno(eventfd(arg1, host_flags));
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030012698 if (ret >= 0) {
12699 fd_trans_register(ret, &target_eventfd_trans);
12700 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012701 return ret;
Petar Jovanovic5947c692013-04-08 20:26:10 +020012702 }
Riku Voipioc2882b92009-08-12 15:08:24 +030012703#endif
12704#endif /* CONFIG_EVENTFD */
Ulrich Hechtd0927932009-09-17 20:22:14 +030012705#if defined(CONFIG_FALLOCATE) && defined(TARGET_NR_fallocate)
12706 case TARGET_NR_fallocate:
WANG Xueruieeed2292022-10-06 16:55:00 +080012707#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
Alexander Graf20249ae2012-02-06 21:37:07 +010012708 ret = get_errno(fallocate(arg1, arg2, target_offset64(arg3, arg4),
12709 target_offset64(arg5, arg6)));
12710#else
Ulrich Hechtd0927932009-09-17 20:22:14 +030012711 ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
Alexander Graf20249ae2012-02-06 21:37:07 +010012712#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012713 return ret;
Ulrich Hechtd0927932009-09-17 20:22:14 +030012714#endif
Peter Maydellc727f472011-01-06 11:05:10 +000012715#if defined(CONFIG_SYNC_FILE_RANGE)
12716#if defined(TARGET_NR_sync_file_range)
12717 case TARGET_NR_sync_file_range:
WANG Xueruieeed2292022-10-06 16:55:00 +080012718#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
Riku Voipiobfcedc52011-06-20 16:24:39 +030012719#if defined(TARGET_MIPS)
12720 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
12721 target_offset64(arg5, arg6), arg7));
12722#else
Peter Maydellc727f472011-01-06 11:05:10 +000012723 ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3),
12724 target_offset64(arg4, arg5), arg6));
Riku Voipiobfcedc52011-06-20 16:24:39 +030012725#endif /* !TARGET_MIPS */
Peter Maydellc727f472011-01-06 11:05:10 +000012726#else
12727 ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4));
12728#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012729 return ret;
Peter Maydellc727f472011-01-06 11:05:10 +000012730#endif
Laurent Vivier5bcb4982020-03-10 11:33:50 +010012731#if defined(TARGET_NR_sync_file_range2) || \
12732 defined(TARGET_NR_arm_sync_file_range)
Peter Maydellc727f472011-01-06 11:05:10 +000012733#if defined(TARGET_NR_sync_file_range2)
12734 case TARGET_NR_sync_file_range2:
Laurent Vivier5bcb4982020-03-10 11:33:50 +010012735#endif
12736#if defined(TARGET_NR_arm_sync_file_range)
12737 case TARGET_NR_arm_sync_file_range:
12738#endif
Peter Maydellc727f472011-01-06 11:05:10 +000012739 /* This is like sync_file_range but the arguments are reordered */
WANG Xueruieeed2292022-10-06 16:55:00 +080012740#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
Peter Maydellc727f472011-01-06 11:05:10 +000012741 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
12742 target_offset64(arg5, arg6), arg2));
12743#else
12744 ret = get_errno(sync_file_range(arg1, arg3, arg4, arg2));
12745#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012746 return ret;
Peter Maydellc727f472011-01-06 11:05:10 +000012747#endif
12748#endif
Laurent Viviere36800c2015-10-02 14:48:09 +020012749#if defined(TARGET_NR_signalfd4)
12750 case TARGET_NR_signalfd4:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012751 return do_signalfd4(arg1, arg2, arg4);
Laurent Viviere36800c2015-10-02 14:48:09 +020012752#endif
12753#if defined(TARGET_NR_signalfd)
12754 case TARGET_NR_signalfd:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012755 return do_signalfd4(arg1, arg2, 0);
Laurent Viviere36800c2015-10-02 14:48:09 +020012756#endif
Peter Maydell3b6edd12011-02-15 18:35:05 +000012757#if defined(CONFIG_EPOLL)
12758#if defined(TARGET_NR_epoll_create)
12759 case TARGET_NR_epoll_create:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012760 return get_errno(epoll_create(arg1));
Peter Maydell3b6edd12011-02-15 18:35:05 +000012761#endif
12762#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1)
12763 case TARGET_NR_epoll_create1:
Sergei Trofimovich386d3862020-04-15 23:05:08 +010012764 return get_errno(epoll_create1(target_to_host_bitmask(arg1, fcntl_flags_tbl)));
Peter Maydell3b6edd12011-02-15 18:35:05 +000012765#endif
12766#if defined(TARGET_NR_epoll_ctl)
12767 case TARGET_NR_epoll_ctl:
12768 {
12769 struct epoll_event ep;
12770 struct epoll_event *epp = 0;
12771 if (arg4) {
LemonBoyc7811022020-04-17 17:34:54 +020012772 if (arg2 != EPOLL_CTL_DEL) {
12773 struct target_epoll_event *target_ep;
12774 if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) {
12775 return -TARGET_EFAULT;
12776 }
12777 ep.events = tswap32(target_ep->events);
12778 /*
12779 * The epoll_data_t union is just opaque data to the kernel,
12780 * so we transfer all 64 bits across and need not worry what
12781 * actual data type it is.
12782 */
12783 ep.data.u64 = tswap64(target_ep->data.u64);
12784 unlock_user_struct(target_ep, arg4, 0);
Peter Maydell3b6edd12011-02-15 18:35:05 +000012785 }
LemonBoyc7811022020-04-17 17:34:54 +020012786 /*
12787 * before kernel 2.6.9, EPOLL_CTL_DEL operation required a
12788 * non-null pointer, even though this argument is ignored.
12789 *
Peter Maydell3b6edd12011-02-15 18:35:05 +000012790 */
Peter Maydell3b6edd12011-02-15 18:35:05 +000012791 epp = &ep;
12792 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012793 return get_errno(epoll_ctl(arg1, arg2, arg3, epp));
Peter Maydell3b6edd12011-02-15 18:35:05 +000012794 }
12795#endif
12796
Peter Maydell227f0212016-06-06 19:58:11 +010012797#if defined(TARGET_NR_epoll_wait) || defined(TARGET_NR_epoll_pwait)
Peter Maydell3b6edd12011-02-15 18:35:05 +000012798#if defined(TARGET_NR_epoll_wait)
12799 case TARGET_NR_epoll_wait:
12800#endif
Peter Maydell227f0212016-06-06 19:58:11 +010012801#if defined(TARGET_NR_epoll_pwait)
Peter Maydell3b6edd12011-02-15 18:35:05 +000012802 case TARGET_NR_epoll_pwait:
12803#endif
12804 {
12805 struct target_epoll_event *target_ep;
12806 struct epoll_event *ep;
12807 int epfd = arg1;
12808 int maxevents = arg3;
12809 int timeout = arg4;
12810
Peter Maydell2ba7fae32016-07-18 15:35:59 +010012811 if (maxevents <= 0 || maxevents > TARGET_EP_MAX_EVENTS) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012812 return -TARGET_EINVAL;
Peter Maydell2ba7fae32016-07-18 15:35:59 +010012813 }
12814
Peter Maydell3b6edd12011-02-15 18:35:05 +000012815 target_ep = lock_user(VERIFY_WRITE, arg2,
12816 maxevents * sizeof(struct target_epoll_event), 1);
12817 if (!target_ep) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012818 return -TARGET_EFAULT;
Peter Maydell3b6edd12011-02-15 18:35:05 +000012819 }
12820
Peter Maydell04c95f42016-07-18 15:36:00 +010012821 ep = g_try_new(struct epoll_event, maxevents);
12822 if (!ep) {
12823 unlock_user(target_ep, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012824 return -TARGET_ENOMEM;
Peter Maydell04c95f42016-07-18 15:36:00 +010012825 }
Peter Maydell3b6edd12011-02-15 18:35:05 +000012826
12827 switch (num) {
Peter Maydell227f0212016-06-06 19:58:11 +010012828#if defined(TARGET_NR_epoll_pwait)
Peter Maydell3b6edd12011-02-15 18:35:05 +000012829 case TARGET_NR_epoll_pwait:
12830 {
Richard Hendersoncd0e31a2022-03-15 01:43:07 -070012831 sigset_t *set = NULL;
Peter Maydell3b6edd12011-02-15 18:35:05 +000012832
12833 if (arg5) {
Richard Hendersoncd0e31a2022-03-15 01:43:07 -070012834 ret = process_sigsuspend_mask(&set, arg5, arg6);
12835 if (ret != 0) {
Peter Maydellc8157012016-06-30 14:23:24 +010012836 break;
12837 }
Peter Maydell3b6edd12011-02-15 18:35:05 +000012838 }
12839
Peter Maydell227f0212016-06-06 19:58:11 +010012840 ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
12841 set, SIGSET_T_SIZE));
Richard Hendersoncd0e31a2022-03-15 01:43:07 -070012842
12843 if (set) {
12844 finish_sigsuspend_mask(ret);
12845 }
Peter Maydell3b6edd12011-02-15 18:35:05 +000012846 break;
12847 }
12848#endif
12849#if defined(TARGET_NR_epoll_wait)
12850 case TARGET_NR_epoll_wait:
Peter Maydell227f0212016-06-06 19:58:11 +010012851 ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
12852 NULL, 0));
Peter Maydell3b6edd12011-02-15 18:35:05 +000012853 break;
12854#endif
12855 default:
12856 ret = -TARGET_ENOSYS;
12857 }
12858 if (!is_error(ret)) {
12859 int i;
12860 for (i = 0; i < ret; i++) {
12861 target_ep[i].events = tswap32(ep[i].events);
12862 target_ep[i].data.u64 = tswap64(ep[i].data.u64);
12863 }
Peter Maydell04c95f42016-07-18 15:36:00 +010012864 unlock_user(target_ep, arg2,
12865 ret * sizeof(struct target_epoll_event));
12866 } else {
12867 unlock_user(target_ep, arg2, 0);
Peter Maydell3b6edd12011-02-15 18:35:05 +000012868 }
Peter Maydell04c95f42016-07-18 15:36:00 +010012869 g_free(ep);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012870 return ret;
Peter Maydell3b6edd12011-02-15 18:35:05 +000012871 }
12872#endif
12873#endif
Peter Maydell163a05a2011-06-27 17:44:52 +010012874#ifdef TARGET_NR_prlimit64
12875 case TARGET_NR_prlimit64:
12876 {
12877 /* args: pid, resource number, ptr to new rlimit, ptr to old rlimit */
12878 struct target_rlimit64 *target_rnew, *target_rold;
12879 struct host_rlimit64 rnew, rold, *rnewp = 0;
Felix Janda95018012014-12-02 22:11:17 +010012880 int resource = target_to_host_resource(arg2);
Tobias Koch055d92f2020-03-05 21:24:00 +010012881
12882 if (arg3 && (resource != RLIMIT_AS &&
12883 resource != RLIMIT_DATA &&
12884 resource != RLIMIT_STACK)) {
Peter Maydell163a05a2011-06-27 17:44:52 +010012885 if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012886 return -TARGET_EFAULT;
Peter Maydell163a05a2011-06-27 17:44:52 +010012887 }
12888 rnew.rlim_cur = tswap64(target_rnew->rlim_cur);
12889 rnew.rlim_max = tswap64(target_rnew->rlim_max);
12890 unlock_user_struct(target_rnew, arg3, 0);
12891 rnewp = &rnew;
12892 }
12893
Felix Janda95018012014-12-02 22:11:17 +010012894 ret = get_errno(sys_prlimit64(arg1, resource, rnewp, arg4 ? &rold : 0));
Peter Maydell163a05a2011-06-27 17:44:52 +010012895 if (!is_error(ret) && arg4) {
12896 if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012897 return -TARGET_EFAULT;
Peter Maydell163a05a2011-06-27 17:44:52 +010012898 }
12899 target_rold->rlim_cur = tswap64(rold.rlim_cur);
12900 target_rold->rlim_max = tswap64(rold.rlim_max);
12901 unlock_user_struct(target_rold, arg4, 1);
12902 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012903 return ret;
Peter Maydell163a05a2011-06-27 17:44:52 +010012904 }
12905#endif
Richard Henderson3d21d292012-09-15 13:20:46 -070012906#ifdef TARGET_NR_gethostname
12907 case TARGET_NR_gethostname:
12908 {
12909 char *name = lock_user(VERIFY_WRITE, arg1, arg2, 0);
12910 if (name) {
12911 ret = get_errno(gethostname(name, arg2));
12912 unlock_user(name, arg1, arg2);
12913 } else {
12914 ret = -TARGET_EFAULT;
12915 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012916 return ret;
Richard Henderson3d21d292012-09-15 13:20:46 -070012917 }
12918#endif
Riku Voipio89aaf1a2013-07-24 09:44:26 +030012919#ifdef TARGET_NR_atomic_cmpxchg_32
12920 case TARGET_NR_atomic_cmpxchg_32:
12921 {
12922 /* should use start_exclusive from main.c */
12923 abi_ulong mem_value;
12924 if (get_user_u32(mem_value, arg6)) {
12925 target_siginfo_t info;
12926 info.si_signo = SIGSEGV;
12927 info.si_errno = 0;
12928 info.si_code = TARGET_SEGV_MAPERR;
12929 info._sifields._sigfault._addr = arg6;
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020012930 queue_signal(cpu_env, info.si_signo, QEMU_SI_FAULT, &info);
Riku Voipio89aaf1a2013-07-24 09:44:26 +030012931 ret = 0xdeadbeef;
12932
12933 }
12934 if (mem_value == arg2)
12935 put_user_u32(arg1, arg6);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012936 return mem_value;
Riku Voipio89aaf1a2013-07-24 09:44:26 +030012937 }
12938#endif
12939#ifdef TARGET_NR_atomic_barrier
12940 case TARGET_NR_atomic_barrier:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012941 /* Like the kernel implementation and the
12942 qemu arm barrier, no-op this? */
12943 return 0;
Riku Voipio89aaf1a2013-07-24 09:44:26 +030012944#endif
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012945
12946#ifdef TARGET_NR_timer_create
12947 case TARGET_NR_timer_create:
12948 {
12949 /* args: clockid_t clockid, struct sigevent *sevp, timer_t *timerid */
12950
12951 struct sigevent host_sevp = { {0}, }, *phost_sevp = NULL;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012952
12953 int clkid = arg1;
12954 int timer_index = next_free_host_timer();
12955
12956 if (timer_index < 0) {
12957 ret = -TARGET_EAGAIN;
12958 } else {
12959 timer_t *phtimer = g_posix_timers + timer_index;
12960
12961 if (arg2) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012962 phost_sevp = &host_sevp;
Peter Maydellc0659762014-08-09 15:42:32 +010012963 ret = target_to_host_sigevent(phost_sevp, arg2);
12964 if (ret != 0) {
Peter Maydell9e598992022-07-25 12:00:35 +010012965 free_host_timer_slot(timer_index);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012966 return ret;
Peter Maydellc0659762014-08-09 15:42:32 +010012967 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012968 }
12969
12970 ret = get_errno(timer_create(clkid, phost_sevp, phtimer));
12971 if (ret) {
Peter Maydell9e598992022-07-25 12:00:35 +010012972 free_host_timer_slot(timer_index);
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012973 } else {
Alexander Grafaecc8862014-11-10 21:33:03 +010012974 if (put_user(TIMER_MAGIC | timer_index, arg3, target_timer_t)) {
Peter Maydell9e598992022-07-25 12:00:35 +010012975 timer_delete(*phtimer);
12976 free_host_timer_slot(timer_index);
Richard Henderson2852aaf2018-08-18 12:01:06 -070012977 return -TARGET_EFAULT;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012978 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012979 }
12980 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012981 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012982 }
12983#endif
12984
12985#ifdef TARGET_NR_timer_settime
12986 case TARGET_NR_timer_settime:
12987 {
12988 /* args: timer_t timerid, int flags, const struct itimerspec *new_value,
12989 * struct itimerspec * old_value */
Alexander Grafaecc8862014-11-10 21:33:03 +010012990 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020012991
Alexander Grafaecc8862014-11-10 21:33:03 +010012992 if (timerid < 0) {
12993 ret = timerid;
12994 } else if (arg3 == 0) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012995 ret = -TARGET_EINVAL;
12996 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020012997 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012998 struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
12999
Marc-André Lureau40c80b52017-01-19 10:15:32 -050013000 if (target_to_host_itimerspec(&hspec_new, arg3)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013001 return -TARGET_EFAULT;
Marc-André Lureau40c80b52017-01-19 10:15:32 -050013002 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013003 ret = get_errno(
13004 timer_settime(htimer, arg2, &hspec_new, &hspec_old));
Marc-André Lureau40c80b52017-01-19 10:15:32 -050013005 if (arg4 && host_to_target_itimerspec(arg4, &hspec_old)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013006 return -TARGET_EFAULT;
Marc-André Lureau40c80b52017-01-19 10:15:32 -050013007 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013008 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013009 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013010 }
13011#endif
13012
Filip Bozuta828cb3a2020-07-22 17:34:21 +020013013#ifdef TARGET_NR_timer_settime64
13014 case TARGET_NR_timer_settime64:
13015 {
13016 target_timer_t timerid = get_timer_id(arg1);
13017
13018 if (timerid < 0) {
13019 ret = timerid;
13020 } else if (arg3 == 0) {
13021 ret = -TARGET_EINVAL;
13022 } else {
13023 timer_t htimer = g_posix_timers[timerid];
13024 struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
13025
13026 if (target_to_host_itimerspec64(&hspec_new, arg3)) {
13027 return -TARGET_EFAULT;
13028 }
13029 ret = get_errno(
13030 timer_settime(htimer, arg2, &hspec_new, &hspec_old));
13031 if (arg4 && host_to_target_itimerspec64(arg4, &hspec_old)) {
13032 return -TARGET_EFAULT;
13033 }
13034 }
13035 return ret;
13036 }
13037#endif
13038
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013039#ifdef TARGET_NR_timer_gettime
13040 case TARGET_NR_timer_gettime:
13041 {
13042 /* args: timer_t timerid, struct itimerspec *curr_value */
Alexander Grafaecc8862014-11-10 21:33:03 +010013043 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020013044
Alexander Grafaecc8862014-11-10 21:33:03 +010013045 if (timerid < 0) {
13046 ret = timerid;
13047 } else if (!arg2) {
13048 ret = -TARGET_EFAULT;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013049 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020013050 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013051 struct itimerspec hspec;
13052 ret = get_errno(timer_gettime(htimer, &hspec));
13053
13054 if (host_to_target_itimerspec(arg2, &hspec)) {
13055 ret = -TARGET_EFAULT;
13056 }
13057 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013058 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013059 }
13060#endif
13061
Filip Bozuta828cb3a2020-07-22 17:34:21 +020013062#ifdef TARGET_NR_timer_gettime64
13063 case TARGET_NR_timer_gettime64:
13064 {
13065 /* args: timer_t timerid, struct itimerspec64 *curr_value */
13066 target_timer_t timerid = get_timer_id(arg1);
13067
13068 if (timerid < 0) {
13069 ret = timerid;
13070 } else if (!arg2) {
13071 ret = -TARGET_EFAULT;
13072 } else {
13073 timer_t htimer = g_posix_timers[timerid];
13074 struct itimerspec hspec;
13075 ret = get_errno(timer_gettime(htimer, &hspec));
13076
13077 if (host_to_target_itimerspec64(arg2, &hspec)) {
13078 ret = -TARGET_EFAULT;
13079 }
13080 }
13081 return ret;
13082 }
13083#endif
13084
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013085#ifdef TARGET_NR_timer_getoverrun
13086 case TARGET_NR_timer_getoverrun:
13087 {
13088 /* args: timer_t timerid */
Alexander Grafaecc8862014-11-10 21:33:03 +010013089 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020013090
Alexander Grafaecc8862014-11-10 21:33:03 +010013091 if (timerid < 0) {
13092 ret = timerid;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013093 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020013094 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013095 ret = get_errno(timer_getoverrun(htimer));
13096 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013097 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013098 }
13099#endif
13100
13101#ifdef TARGET_NR_timer_delete
13102 case TARGET_NR_timer_delete:
13103 {
13104 /* args: timer_t timerid */
Alexander Grafaecc8862014-11-10 21:33:03 +010013105 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020013106
Alexander Grafaecc8862014-11-10 21:33:03 +010013107 if (timerid < 0) {
13108 ret = timerid;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013109 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020013110 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013111 ret = get_errno(timer_delete(htimer));
Peter Maydell9e598992022-07-25 12:00:35 +010013112 free_host_timer_slot(timerid);
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013113 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013114 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013115 }
13116#endif
13117
Riku Voipio51834342014-06-22 11:25:42 +010013118#if defined(TARGET_NR_timerfd_create) && defined(CONFIG_TIMERFD)
13119 case TARGET_NR_timerfd_create:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013120 return get_errno(timerfd_create(arg1,
13121 target_to_host_bitmask(arg2, fcntl_flags_tbl)));
Riku Voipio51834342014-06-22 11:25:42 +010013122#endif
13123
13124#if defined(TARGET_NR_timerfd_gettime) && defined(CONFIG_TIMERFD)
13125 case TARGET_NR_timerfd_gettime:
13126 {
13127 struct itimerspec its_curr;
13128
13129 ret = get_errno(timerfd_gettime(arg1, &its_curr));
13130
13131 if (arg2 && host_to_target_itimerspec(arg2, &its_curr)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013132 return -TARGET_EFAULT;
Riku Voipio51834342014-06-22 11:25:42 +010013133 }
13134 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013135 return ret;
Riku Voipio51834342014-06-22 11:25:42 +010013136#endif
13137
Filip Bozuta828cb3a2020-07-22 17:34:21 +020013138#if defined(TARGET_NR_timerfd_gettime64) && defined(CONFIG_TIMERFD)
13139 case TARGET_NR_timerfd_gettime64:
13140 {
13141 struct itimerspec its_curr;
13142
13143 ret = get_errno(timerfd_gettime(arg1, &its_curr));
13144
13145 if (arg2 && host_to_target_itimerspec64(arg2, &its_curr)) {
13146 return -TARGET_EFAULT;
13147 }
13148 }
13149 return ret;
13150#endif
13151
Riku Voipio51834342014-06-22 11:25:42 +010013152#if defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD)
13153 case TARGET_NR_timerfd_settime:
13154 {
13155 struct itimerspec its_new, its_old, *p_new;
13156
13157 if (arg3) {
13158 if (target_to_host_itimerspec(&its_new, arg3)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013159 return -TARGET_EFAULT;
Riku Voipio51834342014-06-22 11:25:42 +010013160 }
13161 p_new = &its_new;
13162 } else {
13163 p_new = NULL;
13164 }
13165
13166 ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
13167
13168 if (arg4 && host_to_target_itimerspec(arg4, &its_old)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013169 return -TARGET_EFAULT;
Riku Voipio51834342014-06-22 11:25:42 +010013170 }
13171 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013172 return ret;
Riku Voipio51834342014-06-22 11:25:42 +010013173#endif
13174
Filip Bozuta828cb3a2020-07-22 17:34:21 +020013175#if defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)
13176 case TARGET_NR_timerfd_settime64:
13177 {
13178 struct itimerspec its_new, its_old, *p_new;
13179
13180 if (arg3) {
13181 if (target_to_host_itimerspec64(&its_new, arg3)) {
13182 return -TARGET_EFAULT;
13183 }
13184 p_new = &its_new;
13185 } else {
13186 p_new = NULL;
13187 }
13188
13189 ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
13190
13191 if (arg4 && host_to_target_itimerspec64(arg4, &its_old)) {
13192 return -TARGET_EFAULT;
13193 }
13194 }
13195 return ret;
13196#endif
13197
Paul Burtonab31cda2014-06-22 11:25:43 +010013198#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
13199 case TARGET_NR_ioprio_get:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013200 return get_errno(ioprio_get(arg1, arg2));
Paul Burtonab31cda2014-06-22 11:25:43 +010013201#endif
13202
13203#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
13204 case TARGET_NR_ioprio_set:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013205 return get_errno(ioprio_set(arg1, arg2, arg3));
Paul Burtonab31cda2014-06-22 11:25:43 +010013206#endif
13207
Riku Voipio9af5c902014-08-12 15:58:57 +030013208#if defined(TARGET_NR_setns) && defined(CONFIG_SETNS)
13209 case TARGET_NR_setns:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013210 return get_errno(setns(arg1, arg2));
Riku Voipio9af5c902014-08-12 15:58:57 +030013211#endif
13212#if defined(TARGET_NR_unshare) && defined(CONFIG_SETNS)
13213 case TARGET_NR_unshare:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013214 return get_errno(unshare(arg1));
Riku Voipio9af5c902014-08-12 15:58:57 +030013215#endif
Laurent Vivier2f147882016-09-25 22:20:20 +020013216#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
13217 case TARGET_NR_kcmp:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013218 return get_errno(kcmp(arg1, arg2, arg3, arg4, arg5));
Laurent Vivier2f147882016-09-25 22:20:20 +020013219#endif
Richard Hendersonfa97e382018-07-18 13:06:48 -070013220#ifdef TARGET_NR_swapcontext
13221 case TARGET_NR_swapcontext:
13222 /* PowerPC specific. */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013223 return do_swapcontext(cpu_env, arg1, arg2, arg3);
Richard Hendersonfa97e382018-07-18 13:06:48 -070013224#endif
Shu-Chun Weng9bdfa4d2019-08-19 11:09:47 -070013225#ifdef TARGET_NR_memfd_create
13226 case TARGET_NR_memfd_create:
13227 p = lock_user_string(arg1);
13228 if (!p) {
13229 return -TARGET_EFAULT;
13230 }
13231 ret = get_errno(memfd_create(p, arg2));
13232 fd_trans_unregister(ret);
13233 unlock_user(p, arg1, 0);
13234 return ret;
13235#endif
Andreas Schwab85004762019-05-13 11:02:53 +020013236#if defined TARGET_NR_membarrier && defined __NR_membarrier
13237 case TARGET_NR_membarrier:
13238 return get_errno(membarrier(arg1, arg2));
13239#endif
Riku Voipio9af5c902014-08-12 15:58:57 +030013240
Andreas Schwab84946452020-11-12 12:45:16 +010013241#if defined(TARGET_NR_copy_file_range) && defined(__NR_copy_file_range)
13242 case TARGET_NR_copy_file_range:
13243 {
13244 loff_t inoff, outoff;
13245 loff_t *pinoff = NULL, *poutoff = NULL;
13246
13247 if (arg2) {
13248 if (get_user_u64(inoff, arg2)) {
13249 return -TARGET_EFAULT;
13250 }
13251 pinoff = &inoff;
13252 }
13253 if (arg4) {
13254 if (get_user_u64(outoff, arg4)) {
13255 return -TARGET_EFAULT;
13256 }
13257 poutoff = &outoff;
13258 }
Giuseppe Musacchio0fa259d2021-05-03 19:41:59 +020013259 /* Do not sign-extend the count parameter. */
Andreas Schwab84946452020-11-12 12:45:16 +010013260 ret = get_errno(safe_copy_file_range(arg1, pinoff, arg3, poutoff,
Giuseppe Musacchio0fa259d2021-05-03 19:41:59 +020013261 (abi_ulong)arg5, arg6));
Andreas Schwab84946452020-11-12 12:45:16 +010013262 if (!is_error(ret) && ret > 0) {
13263 if (arg2) {
13264 if (put_user_u64(inoff, arg2)) {
13265 return -TARGET_EFAULT;
13266 }
13267 }
13268 if (arg4) {
13269 if (put_user_u64(outoff, arg4)) {
13270 return -TARGET_EFAULT;
13271 }
13272 }
13273 }
13274 }
13275 return ret;
13276#endif
13277
YAMAMOTO Takashie10fbe82021-05-31 14:50:12 +090013278#if defined(TARGET_NR_pivot_root)
13279 case TARGET_NR_pivot_root:
13280 {
13281 void *p2;
13282 p = lock_user_string(arg1); /* new_root */
13283 p2 = lock_user_string(arg2); /* put_old */
13284 if (!p || !p2) {
13285 ret = -TARGET_EFAULT;
13286 } else {
13287 ret = get_errno(pivot_root(p, p2));
13288 }
13289 unlock_user(p2, arg2, 0);
13290 unlock_user(p, arg1, 0);
13291 }
13292 return ret;
13293#endif
13294
bellard31e31b82003-02-18 22:55:36 +000013295 default:
Philippe Mathieu-Daudé122f9c82018-07-06 12:51:25 -030013296 qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013297 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +000013298 }
bellard31e31b82003-02-18 22:55:36 +000013299 return ret;
13300}
Richard Hendersondc1ce182018-08-18 12:01:04 -070013301
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +020013302abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1,
Richard Hendersondc1ce182018-08-18 12:01:04 -070013303 abi_long arg2, abi_long arg3, abi_long arg4,
13304 abi_long arg5, abi_long arg6, abi_long arg7,
13305 abi_long arg8)
13306{
Richard Henderson29a0af62019-03-22 16:07:18 -070013307 CPUState *cpu = env_cpu(cpu_env);
Richard Hendersondc1ce182018-08-18 12:01:04 -070013308 abi_long ret;
13309
13310#ifdef DEBUG_ERESTARTSYS
13311 /* Debug-only code for exercising the syscall-restart code paths
13312 * in the per-architecture cpu main loops: restart every syscall
13313 * the guest makes once before letting it through.
13314 */
13315 {
13316 static bool flag;
13317 flag = !flag;
13318 if (flag) {
Richard Hendersonaf254a22021-11-22 19:47:33 +010013319 return -QEMU_ERESTARTSYS;
Richard Hendersondc1ce182018-08-18 12:01:04 -070013320 }
13321 }
13322#endif
13323
Emilio G. Cotac36f7a62018-10-21 13:27:44 -040013324 record_syscall_start(cpu, num, arg1,
13325 arg2, arg3, arg4, arg5, arg6, arg7, arg8);
Richard Hendersondc1ce182018-08-18 12:01:04 -070013326
Josh Kunz4b25a502020-02-03 18:54:14 -080013327 if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
Filip Bozutae400e112020-08-11 18:45:49 +020013328 print_syscall(cpu_env, num, arg1, arg2, arg3, arg4, arg5, arg6);
Josh Kunz4b25a502020-02-03 18:54:14 -080013329 }
13330
13331 ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4,
13332 arg5, arg6, arg7, arg8);
13333
13334 if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
Filip Bozutae400e112020-08-11 18:45:49 +020013335 print_syscall_ret(cpu_env, num, ret, arg1, arg2,
13336 arg3, arg4, arg5, arg6);
Richard Hendersondc1ce182018-08-18 12:01:04 -070013337 }
13338
Emilio G. Cotac36f7a62018-10-21 13:27:44 -040013339 record_syscall_return(cpu, num, ret);
Richard Hendersondc1ce182018-08-18 12:01:04 -070013340 return ret;
13341}