blob: 669add74c11ae19bacdfdd3c6715700b72ae2292 [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"
bellard31e31b82003-02-18 22:55:36 +0000143
Peter Maydell5ea2fc82016-08-02 18:41:27 +0100144#ifndef CLONE_IO
145#define CLONE_IO 0x80000000 /* Clone io context */
146#endif
147
148/* We can't directly call the host clone syscall, because this will
149 * badly confuse libc (breaking mutexes, for example). So we must
150 * divide clone flags into:
151 * * flag combinations that look like pthread_create()
152 * * flag combinations that look like fork()
153 * * flags we can implement within QEMU itself
154 * * flags we can't support and will return an error for
155 */
156/* For thread creation, all these flags must be present; for
157 * fork, none must be present.
158 */
159#define CLONE_THREAD_FLAGS \
160 (CLONE_VM | CLONE_FS | CLONE_FILES | \
161 CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM)
162
163/* These flags are ignored:
164 * CLONE_DETACHED is now ignored by the kernel;
165 * CLONE_IO is just an optimisation hint to the I/O scheduler
166 */
167#define CLONE_IGNORED_FLAGS \
168 (CLONE_DETACHED | CLONE_IO)
169
170/* Flags for fork which we can implement within QEMU itself */
171#define CLONE_OPTIONAL_FORK_FLAGS \
172 (CLONE_SETTLS | CLONE_PARENT_SETTID | \
173 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID)
174
175/* Flags for thread creation which we can implement within QEMU itself */
176#define CLONE_OPTIONAL_THREAD_FLAGS \
177 (CLONE_SETTLS | CLONE_PARENT_SETTID | \
178 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | CLONE_PARENT)
179
180#define CLONE_INVALID_FORK_FLAGS \
181 (~(CSIGNAL | CLONE_OPTIONAL_FORK_FLAGS | CLONE_IGNORED_FLAGS))
182
183#define CLONE_INVALID_THREAD_FLAGS \
184 (~(CSIGNAL | CLONE_THREAD_FLAGS | CLONE_OPTIONAL_THREAD_FLAGS | \
185 CLONE_IGNORED_FLAGS))
186
187/* CLONE_VFORK is special cased early in do_fork(). The other flag bits
188 * have almost all been allocated. We cannot support any of
189 * CLONE_NEWNS, CLONE_NEWCGROUP, CLONE_NEWUTS, CLONE_NEWIPC,
190 * CLONE_NEWUSER, CLONE_NEWPID, CLONE_NEWNET, CLONE_PTRACE, CLONE_UNTRACED.
191 * The checks against the invalid thread masks above will catch these.
192 * (The one remaining unallocated bit is 0x1000 which used to be CLONE_PID.)
193 */
pbrook30813ce2008-06-02 15:45:44 +0000194
Timothy E Baldwin71a8f7f2016-05-12 18:47:45 +0100195/* Define DEBUG_ERESTARTSYS to force every syscall to be restarted
196 * once. This exercises the codepaths for restart.
197 */
198//#define DEBUG_ERESTARTSYS
bellard31e31b82003-02-18 22:55:36 +0000199
bellard1a9353d2003-03-16 20:28:50 +0000200//#include <linux/msdos_fs.h>
Richard Henderson540a7362021-11-14 11:35:37 +0100201#define VFAT_IOCTL_READDIR_BOTH \
202 _IOC(_IOC_READ, 'r', 1, (sizeof(struct linux_dirent) + 256) * 2)
203#define VFAT_IOCTL_READDIR_SHORT \
204 _IOC(_IOC_READ, 'r', 2, (sizeof(struct linux_dirent) + 256) * 2)
bellard1a9353d2003-03-16 20:28:50 +0000205
bellard70a194b2003-08-11 22:20:16 +0000206#undef _syscall0
207#undef _syscall1
208#undef _syscall2
209#undef _syscall3
210#undef _syscall4
211#undef _syscall5
bellard83fcb512006-06-14 13:37:16 +0000212#undef _syscall6
bellard70a194b2003-08-11 22:20:16 +0000213
bellard83fcb512006-06-14 13:37:16 +0000214#define _syscall0(type,name) \
blueswir18fcd3692008-08-17 20:26:25 +0000215static type name (void) \
bellard83fcb512006-06-14 13:37:16 +0000216{ \
217 return syscall(__NR_##name); \
bellard70a194b2003-08-11 22:20:16 +0000218}
219
bellard83fcb512006-06-14 13:37:16 +0000220#define _syscall1(type,name,type1,arg1) \
blueswir18fcd3692008-08-17 20:26:25 +0000221static type name (type1 arg1) \
bellard83fcb512006-06-14 13:37:16 +0000222{ \
223 return syscall(__NR_##name, arg1); \
bellard70a194b2003-08-11 22:20:16 +0000224}
225
bellard83fcb512006-06-14 13:37:16 +0000226#define _syscall2(type,name,type1,arg1,type2,arg2) \
blueswir18fcd3692008-08-17 20:26:25 +0000227static type name (type1 arg1,type2 arg2) \
bellard83fcb512006-06-14 13:37:16 +0000228{ \
229 return syscall(__NR_##name, arg1, arg2); \
bellard70a194b2003-08-11 22:20:16 +0000230}
231
bellard83fcb512006-06-14 13:37:16 +0000232#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
blueswir18fcd3692008-08-17 20:26:25 +0000233static type name (type1 arg1,type2 arg2,type3 arg3) \
bellard83fcb512006-06-14 13:37:16 +0000234{ \
235 return syscall(__NR_##name, arg1, arg2, arg3); \
bellard70a194b2003-08-11 22:20:16 +0000236}
237
bellard83fcb512006-06-14 13:37:16 +0000238#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
blueswir18fcd3692008-08-17 20:26:25 +0000239static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
bellard83fcb512006-06-14 13:37:16 +0000240{ \
241 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
bellard70a194b2003-08-11 22:20:16 +0000242}
243
bellard83fcb512006-06-14 13:37:16 +0000244#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
245 type5,arg5) \
blueswir18fcd3692008-08-17 20:26:25 +0000246static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
bellard83fcb512006-06-14 13:37:16 +0000247{ \
248 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
bellard70a194b2003-08-11 22:20:16 +0000249}
bellard83fcb512006-06-14 13:37:16 +0000250
251
252#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
253 type5,arg5,type6,arg6) \
blueswir18fcd3692008-08-17 20:26:25 +0000254static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
255 type6 arg6) \
bellard83fcb512006-06-14 13:37:16 +0000256{ \
257 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
258}
259
bellard70a194b2003-08-11 22:20:16 +0000260
bellard31e31b82003-02-18 22:55:36 +0000261#define __NR_sys_uname __NR_uname
bellard72f03902003-02-18 23:33:18 +0000262#define __NR_sys_getcwd1 __NR_getcwd
bellard72f03902003-02-18 23:33:18 +0000263#define __NR_sys_getdents __NR_getdents
bellarddab2ed92003-03-22 15:23:14 +0000264#define __NR_sys_getdents64 __NR_getdents64
thsc6cda172007-10-09 03:42:34 +0000265#define __NR_sys_getpriority __NR_getpriority
bellard66fb9762003-03-23 01:06:05 +0000266#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +0200267#define __NR_sys_rt_tgsigqueueinfo __NR_rt_tgsigqueueinfo
ths7494b0f2007-02-11 18:26:53 +0000268#define __NR_sys_syslog __NR_syslog
Alistair Francis14690292020-03-18 15:47:01 -0700269#if defined(__NR_futex)
270# define __NR_sys_futex __NR_futex
271#endif
272#if defined(__NR_futex_time64)
273# define __NR_sys_futex_time64 __NR_futex_time64
274#endif
Aleksandar Rikaloefa92182019-06-28 12:43:34 +0200275#define __NR_sys_statx __NR_statx
bellard31e31b82003-02-18 22:55:36 +0000276
Peter Maydellb1cef6d2018-01-25 16:19:49 +0000277#if defined(__alpha__) || defined(__x86_64__) || defined(__s390x__)
bellard9af9eaa2003-04-07 21:34:41 +0000278#define __NR__llseek __NR_lseek
279#endif
280
James Hogana29e5ba2014-03-25 21:51:08 +0000281/* Newer kernel ports have llseek() instead of _llseek() */
282#if defined(TARGET_NR_llseek) && !defined(TARGET_NR__llseek)
283#define TARGET_NR__llseek TARGET_NR_llseek
284#endif
285
Helge Deller78721302021-02-10 07:12:14 +0100286/* some platforms need to mask more bits than just TARGET_O_NONBLOCK */
287#ifndef TARGET_O_NONBLOCK_MASK
288#define TARGET_O_NONBLOCK_MASK TARGET_O_NONBLOCK
289#endif
290
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +0000291#define __NR_sys_gettid __NR_gettid
292_syscall0(int, sys_gettid)
Peter Maydell2b3f64c2018-04-19 13:57:40 +0100293
294/* For the 64-bit guest on 32-bit host case we must emulate
295 * getdents using getdents64, because otherwise the host
296 * might hand us back more dirent records than we can fit
297 * into the guest buffer after structure format conversion.
298 * Otherwise we emulate getdents with getdents if the host has it.
299 */
300#if defined(__NR_getdents) && HOST_LONG_BITS >= TARGET_ABI_BITS
301#define EMULATE_GETDENTS_WITH_GETDENTS
302#endif
303
304#if defined(TARGET_NR_getdents) && defined(EMULATE_GETDENTS_WITH_GETDENTS)
aurel323b3f24a2009-04-15 16:12:13 +0000305_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
Peter Maydell3307e232013-06-12 16:20:21 +0100306#endif
Peter Maydell2b3f64c2018-04-19 13:57:40 +0100307#if (defined(TARGET_NR_getdents) && \
308 !defined(EMULATE_GETDENTS_WITH_GETDENTS)) || \
Peter Maydell3307e232013-06-12 16:20:21 +0100309 (defined(TARGET_NR_getdents64) && defined(__NR_getdents64))
aurel323b3f24a2009-04-15 16:12:13 +0000310_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
311#endif
Richard Hendersond35b2612010-06-04 12:14:10 -0700312#if defined(TARGET_NR__llseek) && defined(__NR_llseek)
aurel323b3f24a2009-04-15 16:12:13 +0000313_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
314 loff_t *, res, uint, wh);
315#endif
Miloš Stojanovićc1a402a2017-05-15 16:59:45 +0200316_syscall3(int, sys_rt_sigqueueinfo, pid_t, pid, int, sig, siginfo_t *, uinfo)
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +0200317_syscall4(int, sys_rt_tgsigqueueinfo, pid_t, pid, pid_t, tid, int, sig,
318 siginfo_t *, uinfo)
aurel323b3f24a2009-04-15 16:12:13 +0000319_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
aurel323b3f24a2009-04-15 16:12:13 +0000320#ifdef __NR_exit_group
321_syscall1(int,exit_group,int,error_code)
322#endif
Alistair Francis14690292020-03-18 15:47:01 -0700323#if defined(__NR_futex)
aurel323b3f24a2009-04-15 16:12:13 +0000324_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
325 const struct timespec *,timeout,int *,uaddr2,int,val3)
326#endif
Alistair Francis14690292020-03-18 15:47:01 -0700327#if defined(__NR_futex_time64)
328_syscall6(int,sys_futex_time64,int *,uaddr,int,op,int,val,
329 const struct timespec *,timeout,int *,uaddr2,int,val3)
330#endif
Mike Frysinger737de1d2011-02-07 01:05:55 -0500331#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
332_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
333 unsigned long *, user_mask_ptr);
334#define __NR_sys_sched_setaffinity __NR_sched_setaffinity
335_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
336 unsigned long *, user_mask_ptr);
Tonis Tiigi45ad7612022-01-04 20:18:18 -0800337/* sched_attr is not defined in glibc */
338struct sched_attr {
339 uint32_t size;
340 uint32_t sched_policy;
341 uint64_t sched_flags;
342 int32_t sched_nice;
343 uint32_t sched_priority;
344 uint64_t sched_runtime;
345 uint64_t sched_deadline;
346 uint64_t sched_period;
347 uint32_t sched_util_min;
348 uint32_t sched_util_max;
349};
350#define __NR_sys_sched_getattr __NR_sched_getattr
351_syscall4(int, sys_sched_getattr, pid_t, pid, struct sched_attr *, attr,
352 unsigned int, size, unsigned int, flags);
353#define __NR_sys_sched_setattr __NR_sched_setattr
354_syscall3(int, sys_sched_setattr, pid_t, pid, struct sched_attr *, attr,
355 unsigned int, flags);
Tonis Tiigi407a1192022-01-04 20:18:19 -0800356#define __NR_sys_sched_getscheduler __NR_sched_getscheduler
357_syscall1(int, sys_sched_getscheduler, pid_t, pid);
358#define __NR_sys_sched_setscheduler __NR_sched_setscheduler
359_syscall3(int, sys_sched_setscheduler, pid_t, pid, int, policy,
360 const struct sched_param *, param);
361#define __NR_sys_sched_getparam __NR_sched_getparam
362_syscall2(int, sys_sched_getparam, pid_t, pid,
363 struct sched_param *, param);
364#define __NR_sys_sched_setparam __NR_sched_setparam
365_syscall2(int, sys_sched_setparam, pid_t, pid,
366 const struct sched_param *, param);
Samuel Thibaultb827c3e2018-01-12 09:14:35 +0100367#define __NR_sys_getcpu __NR_getcpu
368_syscall3(int, sys_getcpu, unsigned *, cpu, unsigned *, node, void *, tcache);
Alexander Graf0f6b4d22011-09-27 14:39:42 +0200369_syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd,
370 void *, arg);
Peter Maydelle0eb2102014-03-17 12:15:35 +0000371_syscall2(int, capget, struct __user_cap_header_struct *, header,
372 struct __user_cap_data_struct *, data);
373_syscall2(int, capset, struct __user_cap_header_struct *, header,
374 struct __user_cap_data_struct *, data);
Paul Burtonab31cda2014-06-22 11:25:43 +0100375#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
376_syscall2(int, ioprio_get, int, which, int, who)
377#endif
378#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
379_syscall3(int, ioprio_set, int, which, int, who, int, ioprio)
380#endif
Laurent Vivierf894efd2016-02-21 10:56:23 +0100381#if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
382_syscall3(int, getrandom, void *, buf, size_t, buflen, unsigned int, flags)
383#endif
aurel323b3f24a2009-04-15 16:12:13 +0000384
Laurent Vivier2f147882016-09-25 22:20:20 +0200385#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
386_syscall5(int, kcmp, pid_t, pid1, pid_t, pid2, int, type,
387 unsigned long, idx1, unsigned long, idx2)
388#endif
389
Aleksandar Rikaloefa92182019-06-28 12:43:34 +0200390/*
391 * It is assumed that struct statx is architecture independent.
392 */
393#if defined(TARGET_NR_statx) && defined(__NR_statx)
394_syscall5(int, sys_statx, int, dirfd, const char *, pathname, int, flags,
395 unsigned int, mask, struct target_statx *, statxbuf)
396#endif
Andreas Schwab85004762019-05-13 11:02:53 +0200397#if defined(TARGET_NR_membarrier) && defined(__NR_membarrier)
398_syscall2(int, membarrier, int, cmd, int, flags)
399#endif
Aleksandar Rikaloefa92182019-06-28 12:43:34 +0200400
Philippe Mathieu-Daudé180d4ef2021-05-17 07:52:43 +0200401static const bitmask_transtbl fcntl_flags_tbl[] = {
aurel323b3f24a2009-04-15 16:12:13 +0000402 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
403 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
404 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
405 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
406 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
407 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
408 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
409 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
Richard Hendersonafc87632012-07-25 14:30:34 -0700410 { TARGET_O_SYNC, TARGET_O_DSYNC, O_SYNC, O_DSYNC, },
aurel323b3f24a2009-04-15 16:12:13 +0000411 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
412 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
413 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
414 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
aurel323b3f24a2009-04-15 16:12:13 +0000415#if defined(O_DIRECT)
416 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
417#endif
Richard Hendersonafc87632012-07-25 14:30:34 -0700418#if defined(O_NOATIME)
419 { TARGET_O_NOATIME, TARGET_O_NOATIME, O_NOATIME, O_NOATIME },
420#endif
421#if defined(O_CLOEXEC)
422 { TARGET_O_CLOEXEC, TARGET_O_CLOEXEC, O_CLOEXEC, O_CLOEXEC },
423#endif
424#if defined(O_PATH)
425 { TARGET_O_PATH, TARGET_O_PATH, O_PATH, O_PATH },
426#endif
Riku Voipio5f9cee42017-08-08 16:01:19 +0300427#if defined(O_TMPFILE)
428 { TARGET_O_TMPFILE, TARGET_O_TMPFILE, O_TMPFILE, O_TMPFILE },
429#endif
Richard Hendersonafc87632012-07-25 14:30:34 -0700430 /* Don't terminate the list prematurely on 64-bit host+guest. */
431#if TARGET_O_LARGEFILE != 0 || O_LARGEFILE != 0
432 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
433#endif
aurel323b3f24a2009-04-15 16:12:13 +0000434 { 0, 0, 0, 0 }
435};
436
Andreas Schwab0f6bb192020-07-23 12:27:13 +0200437_syscall2(int, sys_getcwd1, char *, buf, size_t, size)
aurel323b3f24a2009-04-15 16:12:13 +0000438
Filip Bozutacac46eb2020-08-25 00:30:50 +0200439#if defined(TARGET_NR_utimensat) || defined(TARGET_NR_utimensat_time64)
Peter Maydell700fa582016-07-18 11:47:55 +0100440#if defined(__NR_utimensat)
Peter Maydell1acae9f2013-07-02 14:04:12 +0100441#define __NR_sys_utimensat __NR_utimensat
ths9007f0e2007-09-25 17:50:37 +0000442_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
443 const struct timespec *,tsp,int,flags)
Peter Maydell1acae9f2013-07-02 14:04:12 +0100444#else
445static int sys_utimensat(int dirfd, const char *pathname,
446 const struct timespec times[2], int flags)
447{
448 errno = ENOSYS;
449 return -1;
450}
ths9007f0e2007-09-25 17:50:37 +0000451#endif
Peter Maydell1acae9f2013-07-02 14:04:12 +0100452#endif /* TARGET_NR_utimensat */
aurel323b3f24a2009-04-15 16:12:13 +0000453
Andreas Schwab95d03072018-01-23 11:53:31 +0100454#ifdef TARGET_NR_renameat2
455#if defined(__NR_renameat2)
456#define __NR_sys_renameat2 __NR_renameat2
457_syscall5(int, sys_renameat2, int, oldfd, const char *, old, int, newfd,
458 const char *, new, unsigned int, flags)
459#else
460static int sys_renameat2(int oldfd, const char *old,
461 int newfd, const char *new, int flags)
462{
463 if (flags == 0) {
464 return renameat(oldfd, old, newfd, new);
465 }
466 errno = ENOSYS;
467 return -1;
468}
469#endif
470#endif /* TARGET_NR_renameat2 */
471
aurel323b3f24a2009-04-15 16:12:13 +0000472#ifdef CONFIG_INOTIFY
aurel328690e422009-04-17 13:50:32 +0000473#include <sys/inotify.h>
aurel323b3f24a2009-04-15 16:12:13 +0000474#else
475/* Userspace can usually survive runtime without inotify */
476#undef TARGET_NR_inotify_init
Riku Voipioc05c7a72010-03-26 15:25:11 +0000477#undef TARGET_NR_inotify_init1
aurel323b3f24a2009-04-15 16:12:13 +0000478#undef TARGET_NR_inotify_add_watch
479#undef TARGET_NR_inotify_rm_watch
480#endif /* CONFIG_INOTIFY */
481
Peter Maydell163a05a2011-06-27 17:44:52 +0100482#if defined(TARGET_NR_prlimit64)
483#ifndef __NR_prlimit64
484# define __NR_prlimit64 -1
485#endif
486#define __NR_sys_prlimit64 __NR_prlimit64
487/* The glibc rlimit structure may not be that used by the underlying syscall */
488struct host_rlimit64 {
489 uint64_t rlim_cur;
490 uint64_t rlim_max;
491};
492_syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
493 const struct host_rlimit64 *, new_limit,
494 struct host_rlimit64 *, old_limit)
495#endif
496
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +1100497
498#if defined(TARGET_NR_timer_create)
zhaolichang6f9ff552020-09-17 15:50:25 +0800499/* Maximum of 32 active POSIX timers allowed at any one time. */
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +1100500static timer_t g_posix_timers[32] = { 0, } ;
501
502static inline int next_free_host_timer(void)
503{
504 int k ;
505 /* FIXME: Does finding the next free slot require a lock? */
506 for (k = 0; k < ARRAY_SIZE(g_posix_timers); k++) {
507 if (g_posix_timers[k] == 0) {
508 g_posix_timers[k] = (timer_t) 1;
509 return k;
510 }
511 }
512 return -1;
513}
514#endif
515
Philippe Mathieu-Daudé3ffe3262021-07-08 19:05:49 +0200516static inline int host_to_target_errno(int host_errno)
ths637947f2007-06-01 12:09:19 +0000517{
Philippe Mathieu-Daudé3ffe3262021-07-08 19:05:49 +0200518 switch (host_errno) {
519#define E(X) case X: return TARGET_##X;
520#include "errnos.c.inc"
521#undef E
522 default:
523 return host_errno;
Timothy E Baldwin24661192016-05-12 18:47:25 +0100524 }
ths637947f2007-06-01 12:09:19 +0000525}
526
Philippe Mathieu-Daudé3ffe3262021-07-08 19:05:49 +0200527static inline int target_to_host_errno(int target_errno)
thsb92c47c2007-11-01 00:07:38 +0000528{
Philippe Mathieu-Daudé3ffe3262021-07-08 19:05:49 +0200529 switch (target_errno) {
530#define E(X) case TARGET_##X: return X;
531#include "errnos.c.inc"
532#undef E
533 default:
534 return target_errno;
Timothy E Baldwin24661192016-05-12 18:47:25 +0100535 }
thsb92c47c2007-11-01 00:07:38 +0000536}
537
Ilya Leoshkevich892a4f62022-06-21 16:42:05 +0200538abi_long get_errno(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000539{
540 if (ret == -1)
ths637947f2007-06-01 12:09:19 +0000541 return -host_to_target_errno(errno);
bellard31e31b82003-02-18 22:55:36 +0000542 else
543 return ret;
544}
545
Peter Maydell7dcdaea2016-06-06 19:58:18 +0100546const char *target_strerror(int err)
thsb92c47c2007-11-01 00:07:38 +0000547{
Richard Hendersonaf254a22021-11-22 19:47:33 +0100548 if (err == QEMU_ERESTARTSYS) {
Peter Maydellda2a34f2016-06-06 19:58:19 +0100549 return "To be restarted";
550 }
Richard Henderson57a0c932021-11-17 05:14:52 -0800551 if (err == QEMU_ESIGRETURN) {
Peter Maydellda2a34f2016-06-06 19:58:19 +0100552 return "Successful exit from sigreturn";
553 }
554
thsb92c47c2007-11-01 00:07:38 +0000555 return strerror(target_to_host_errno(err));
556}
557
Tonis Tiigi45ad7612022-01-04 20:18:18 -0800558static int check_zeroed_user(abi_long addr, size_t ksize, size_t usize)
559{
560 int i;
561 uint8_t b;
562 if (usize <= ksize) {
563 return 1;
564 }
565 for (i = ksize; i < usize; i++) {
566 if (get_user_u8(b, addr + i)) {
567 return -TARGET_EFAULT;
568 }
569 if (b != 0) {
570 return 0;
571 }
572 }
573 return 1;
574}
575
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100576#define safe_syscall0(type, name) \
577static type safe_##name(void) \
578{ \
579 return safe_syscall(__NR_##name); \
580}
581
582#define safe_syscall1(type, name, type1, arg1) \
583static type safe_##name(type1 arg1) \
584{ \
585 return safe_syscall(__NR_##name, arg1); \
586}
587
588#define safe_syscall2(type, name, type1, arg1, type2, arg2) \
589static type safe_##name(type1 arg1, type2 arg2) \
590{ \
591 return safe_syscall(__NR_##name, arg1, arg2); \
592}
593
594#define safe_syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
595static type safe_##name(type1 arg1, type2 arg2, type3 arg3) \
596{ \
597 return safe_syscall(__NR_##name, arg1, arg2, arg3); \
598}
599
600#define safe_syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
601 type4, arg4) \
602static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
603{ \
604 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4); \
605}
606
607#define safe_syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \
608 type4, arg4, type5, arg5) \
609static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
610 type5 arg5) \
611{ \
612 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
613}
614
615#define safe_syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \
616 type4, arg4, type5, arg5, type6, arg6) \
617static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
618 type5 arg5, type6 arg6) \
619{ \
620 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
621}
622
Timothy E Baldwin50afd022016-05-12 18:47:47 +0100623safe_syscall3(ssize_t, read, int, fd, void *, buff, size_t, count)
624safe_syscall3(ssize_t, write, int, fd, const void *, buff, size_t, count)
Timothy E Baldwinc10a0732016-05-12 18:47:48 +0100625safe_syscall4(int, openat, int, dirfd, const char *, pathname, \
626 int, flags, mode_t, mode)
Alistair Francis859e8a82020-03-12 15:13:49 -0700627#if defined(TARGET_NR_wait4) || defined(TARGET_NR_waitpid)
Timothy E Baldwin4af80a32016-05-12 18:47:49 +0100628safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \
629 struct rusage *, rusage)
Alistair Francis859e8a82020-03-12 15:13:49 -0700630#endif
Timothy E Baldwin4af80a32016-05-12 18:47:49 +0100631safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \
632 int, options, struct rusage *, rusage)
Timothy E Baldwinffdcbe22016-05-12 18:47:50 +0100633safe_syscall3(int, execve, const char *, filename, char **, argv, char **, envp)
Alistair Francis859e8a82020-03-12 15:13:49 -0700634#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \
Filip Bozutae5ce9682020-08-25 00:30:49 +0200635 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
Peter Maydell6df9d382016-05-12 18:47:51 +0100636safe_syscall6(int, pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, \
637 fd_set *, exceptfds, struct timespec *, timeout, void *, sig)
Alistair Francis859e8a82020-03-12 15:13:49 -0700638#endif
Filip Bozutae5ce9682020-08-25 00:30:49 +0200639#if defined(TARGET_NR_ppoll) || defined(TARGET_NR_ppoll_time64)
Peter Maydella6130232016-06-06 19:58:10 +0100640safe_syscall5(int, ppoll, struct pollfd *, ufds, unsigned int, nfds,
641 struct timespec *, tsp, const sigset_t *, sigmask,
642 size_t, sigsetsize)
Alistair Francis859e8a82020-03-12 15:13:49 -0700643#endif
Peter Maydell227f0212016-06-06 19:58:11 +0100644safe_syscall6(int, epoll_pwait, int, epfd, struct epoll_event *, events,
645 int, maxevents, int, timeout, const sigset_t *, sigmask,
646 size_t, sigsetsize)
Alistair Francis14690292020-03-18 15:47:01 -0700647#if defined(__NR_futex)
Peter Maydelld509eeb2016-05-12 18:47:52 +0100648safe_syscall6(int,futex,int *,uaddr,int,op,int,val, \
649 const struct timespec *,timeout,int *,uaddr2,int,val3)
Alistair Francis859e8a82020-03-12 15:13:49 -0700650#endif
Alistair Francis14690292020-03-18 15:47:01 -0700651#if defined(__NR_futex_time64)
652safe_syscall6(int,futex_time64,int *,uaddr,int,op,int,val, \
653 const struct timespec *,timeout,int *,uaddr2,int,val3)
654#endif
Peter Maydell2fe4fba2016-05-27 15:51:48 +0100655safe_syscall2(int, rt_sigsuspend, sigset_t *, newset, size_t, sigsetsize)
Peter Maydellbef653d2016-05-27 15:51:57 +0100656safe_syscall2(int, kill, pid_t, pid, int, sig)
657safe_syscall2(int, tkill, int, tid, int, sig)
658safe_syscall3(int, tgkill, int, tgid, int, pid, int, sig)
Peter Maydell918c03e2016-06-06 19:58:02 +0100659safe_syscall3(ssize_t, readv, int, fd, const struct iovec *, iov, int, iovcnt)
660safe_syscall3(ssize_t, writev, int, fd, const struct iovec *, iov, int, iovcnt)
Dejan Jovicevic0f263862016-10-11 11:52:46 +0200661safe_syscall5(ssize_t, preadv, int, fd, const struct iovec *, iov, int, iovcnt,
662 unsigned long, pos_l, unsigned long, pos_h)
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +0200663safe_syscall5(ssize_t, pwritev, int, fd, const struct iovec *, iov, int, iovcnt,
664 unsigned long, pos_l, unsigned long, pos_h)
Peter Maydell2a3c7612016-06-06 19:58:03 +0100665safe_syscall3(int, connect, int, fd, const struct sockaddr *, addr,
666 socklen_t, addrlen)
Peter Maydell66687532016-06-06 19:58:04 +0100667safe_syscall6(ssize_t, sendto, int, fd, const void *, buf, size_t, len,
668 int, flags, const struct sockaddr *, addr, socklen_t, addrlen)
669safe_syscall6(ssize_t, recvfrom, int, fd, void *, buf, size_t, len,
670 int, flags, struct sockaddr *, addr, socklen_t *, addrlen)
671safe_syscall3(ssize_t, sendmsg, int, fd, const struct msghdr *, msg, int, flags)
672safe_syscall3(ssize_t, recvmsg, int, fd, struct msghdr *, msg, int, flags)
Peter Maydell2a845982016-06-06 19:58:07 +0100673safe_syscall2(int, flock, int, fd, int, operation)
Filip Bozutaddcbde12020-08-24 21:21:16 +0200674#if defined(TARGET_NR_rt_sigtimedwait) || defined(TARGET_NR_rt_sigtimedwait_time64)
Peter Maydellb3f82332016-06-06 19:58:08 +0100675safe_syscall4(int, rt_sigtimedwait, const sigset_t *, these, siginfo_t *, uinfo,
676 const struct timespec *, uts, size_t, sigsetsize)
Alistair Francis859e8a82020-03-12 15:13:49 -0700677#endif
Peter Maydellff6dc132016-06-06 19:58:13 +0100678safe_syscall4(int, accept4, int, fd, struct sockaddr *, addr, socklen_t *, len,
679 int, flags)
Alistair Francis859e8a82020-03-12 15:13:49 -0700680#if defined(TARGET_NR_nanosleep)
Peter Maydell9e518222016-06-06 19:58:09 +0100681safe_syscall2(int, nanosleep, const struct timespec *, req,
682 struct timespec *, rem)
Alistair Francis859e8a82020-03-12 15:13:49 -0700683#endif
Filip Bozuta6ac03b22020-08-24 21:21:15 +0200684#if defined(TARGET_NR_clock_nanosleep) || \
685 defined(TARGET_NR_clock_nanosleep_time64)
Peter Maydell9e518222016-06-06 19:58:09 +0100686safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags,
687 const struct timespec *, req, struct timespec *, rem)
688#endif
Laurent Vivier524fa342019-05-29 10:48:04 +0200689#ifdef __NR_ipc
Matus Kyseld8c08b12020-06-26 14:46:11 +0200690#ifdef __s390x__
691safe_syscall5(int, ipc, int, call, long, first, long, second, long, third,
692 void *, ptr)
693#else
Peter Maydell89f9fe42016-06-06 19:58:05 +0100694safe_syscall6(int, ipc, int, call, long, first, long, second, long, third,
695 void *, ptr, long, fifth)
Laurent Vivier86e63692019-05-23 19:54:13 +0200696#endif
Matus Kyseld8c08b12020-06-26 14:46:11 +0200697#endif
Laurent Vivier86e63692019-05-23 19:54:13 +0200698#ifdef __NR_msgsnd
699safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz,
700 int, flags)
Laurent Vivier86e63692019-05-23 19:54:13 +0200701#endif
702#ifdef __NR_msgrcv
703safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz,
704 long, msgtype, int, flags)
Laurent Vivier86e63692019-05-23 19:54:13 +0200705#endif
706#ifdef __NR_semtimedop
707safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops,
708 unsigned, nsops, const struct timespec *, timeout)
Peter Maydell89f9fe42016-06-06 19:58:05 +0100709#endif
Filip Bozutad107e372020-08-24 21:37:52 +0200710#if defined(TARGET_NR_mq_timedsend) || \
711 defined(TARGET_NR_mq_timedsend_time64)
Peter Maydelld40ecd62016-06-06 19:58:06 +0100712safe_syscall5(int, mq_timedsend, int, mqdes, const char *, msg_ptr,
713 size_t, len, unsigned, prio, const struct timespec *, timeout)
Alistair Francis859e8a82020-03-12 15:13:49 -0700714#endif
Filip Bozutad107e372020-08-24 21:37:52 +0200715#if defined(TARGET_NR_mq_timedreceive) || \
716 defined(TARGET_NR_mq_timedreceive_time64)
Peter Maydelld40ecd62016-06-06 19:58:06 +0100717safe_syscall5(int, mq_timedreceive, int, mqdes, char *, msg_ptr,
718 size_t, len, unsigned *, prio, const struct timespec *, timeout)
719#endif
Andreas Schwab84946452020-11-12 12:45:16 +0100720#if defined(TARGET_NR_copy_file_range) && defined(__NR_copy_file_range)
721safe_syscall6(ssize_t, copy_file_range, int, infd, loff_t *, pinoff,
722 int, outfd, loff_t *, poutoff, size_t, length,
723 unsigned int, flags)
724#endif
725
Peter Maydell49ca6f32016-06-06 19:58:14 +0100726/* We do ioctl like this rather than via safe_syscall3 to preserve the
727 * "third argument might be integer or pointer or not present" behaviour of
728 * the libc function.
729 */
730#define safe_ioctl(...) safe_syscall(__NR_ioctl, __VA_ARGS__)
Peter Maydell435da5e2016-06-13 11:22:05 +0100731/* Similarly for fcntl. Note that callers must always:
732 * pass the F_GETLK64 etc constants rather than the unsuffixed F_GETLK
733 * use the flock64 struct rather than unsuffixed flock
734 * This will then work and use a 64-bit offset for both 32-bit and 64-bit hosts.
735 */
736#ifdef __NR_fcntl64
737#define safe_fcntl(...) safe_syscall(__NR_fcntl64, __VA_ARGS__)
738#else
739#define safe_fcntl(...) safe_syscall(__NR_fcntl, __VA_ARGS__)
740#endif
Timothy E Baldwin50afd022016-05-12 18:47:47 +0100741
Paul Burton8289d112014-06-22 11:25:33 +0100742static inline int host_to_target_sock_type(int host_type)
743{
744 int target_type;
745
746 switch (host_type & 0xf /* SOCK_TYPE_MASK */) {
747 case SOCK_DGRAM:
748 target_type = TARGET_SOCK_DGRAM;
749 break;
750 case SOCK_STREAM:
751 target_type = TARGET_SOCK_STREAM;
752 break;
753 default:
754 target_type = host_type & 0xf /* SOCK_TYPE_MASK */;
755 break;
756 }
757
758#if defined(SOCK_CLOEXEC)
759 if (host_type & SOCK_CLOEXEC) {
760 target_type |= TARGET_SOCK_CLOEXEC;
761 }
762#endif
763
764#if defined(SOCK_NONBLOCK)
765 if (host_type & SOCK_NONBLOCK) {
766 target_type |= TARGET_SOCK_NONBLOCK;
767 }
768#endif
769
770 return target_type;
771}
772
blueswir1992f48a2007-10-14 16:27:31 +0000773static abi_ulong target_brk;
774static abi_ulong target_original_brk;
vincent4d1de872011-06-14 21:56:33 +0000775static abi_ulong brk_page;
bellard31e31b82003-02-18 22:55:36 +0000776
blueswir1992f48a2007-10-14 16:27:31 +0000777void target_set_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000778{
blueswir14c1de732007-07-07 20:45:44 +0000779 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
vincent4d1de872011-06-14 21:56:33 +0000780 brk_page = HOST_PAGE_ALIGN(target_brk);
bellard31e31b82003-02-18 22:55:36 +0000781}
782
vincent4d1de872011-06-14 21:56:33 +0000783//#define DEBUGF_BRK(message, args...) do { fprintf(stderr, (message), ## args); } while (0)
784#define DEBUGF_BRK(message, args...)
785
ths0da46a62007-10-20 20:23:07 +0000786/* do_brk() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000787abi_long do_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000788{
blueswir1992f48a2007-10-14 16:27:31 +0000789 abi_long mapped_addr;
Peter Maydellef4330c2016-07-22 13:41:52 +0100790 abi_ulong new_alloc_size;
bellard31e31b82003-02-18 22:55:36 +0000791
Richard Hendersonee1bf832021-02-12 10:48:44 -0800792 /* brk pointers are always untagged */
793
Paul Brook3a0c6c42012-02-09 19:04:27 +0000794 DEBUGF_BRK("do_brk(" TARGET_ABI_FMT_lx ") -> ", new_brk);
ths3b46e622007-09-17 08:09:54 +0000795
vincent4d1de872011-06-14 21:56:33 +0000796 if (!new_brk) {
Paul Brook3a0c6c42012-02-09 19:04:27 +0000797 DEBUGF_BRK(TARGET_ABI_FMT_lx " (!new_brk)\n", target_brk);
vincent4d1de872011-06-14 21:56:33 +0000798 return target_brk;
799 }
800 if (new_brk < target_original_brk) {
Paul Brook3a0c6c42012-02-09 19:04:27 +0000801 DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk < target_original_brk)\n",
802 target_brk);
vincent4d1de872011-06-14 21:56:33 +0000803 return target_brk;
804 }
bellard31e31b82003-02-18 22:55:36 +0000805
vincent4d1de872011-06-14 21:56:33 +0000806 /* If the new brk is less than the highest page reserved to the
807 * target heap allocation, set it and we're almost done... */
808 if (new_brk <= brk_page) {
809 /* Heap contents are initialized to zero, as for anonymous
810 * mapped pages. */
811 if (new_brk > target_brk) {
Richard Henderson3e8f1622021-02-12 10:48:43 -0800812 memset(g2h_untagged(target_brk), 0, new_brk - target_brk);
vincent4d1de872011-06-14 21:56:33 +0000813 }
bellard31e31b82003-02-18 22:55:36 +0000814 target_brk = new_brk;
Paul Brook3a0c6c42012-02-09 19:04:27 +0000815 DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk <= brk_page)\n", target_brk);
Paolo Bonzini72e21db2018-12-13 23:37:36 +0100816 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000817 }
818
Peter Maydell00faf082011-04-18 16:34:24 +0100819 /* We need to allocate more memory after the brk... Note that
820 * we don't use MAP_FIXED because that will map over the top of
821 * any existing mapping (like the one with the host libc or qemu
822 * itself); instead we treat "mapped but at wrong address" as
823 * a failure and unmap again.
824 */
vincent4d1de872011-06-14 21:56:33 +0000825 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page);
ths5fafdf22007-09-16 21:08:06 +0000826 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
bellard54936002003-05-13 00:25:15 +0000827 PROT_READ|PROT_WRITE,
Peter Maydell00faf082011-04-18 16:34:24 +0100828 MAP_ANON|MAP_PRIVATE, 0, 0));
829
830 if (mapped_addr == brk_page) {
Cédric VINCENT70afc342011-08-26 10:56:50 +0200831 /* Heap contents are initialized to zero, as for anonymous
832 * mapped pages. Technically the new pages are already
833 * initialized to zero since they *are* anonymous mapped
834 * pages, however we have to take care with the contents that
835 * come from the remaining part of the previous page: it may
836 * contains garbage data due to a previous heap usage (grown
837 * then shrunken). */
Richard Henderson3e8f1622021-02-12 10:48:43 -0800838 memset(g2h_untagged(target_brk), 0, brk_page - target_brk);
Cédric VINCENT70afc342011-08-26 10:56:50 +0200839
Peter Maydell00faf082011-04-18 16:34:24 +0100840 target_brk = new_brk;
vincent4d1de872011-06-14 21:56:33 +0000841 brk_page = HOST_PAGE_ALIGN(target_brk);
Paul Brook3a0c6c42012-02-09 19:04:27 +0000842 DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr == brk_page)\n",
843 target_brk);
Peter Maydell00faf082011-04-18 16:34:24 +0100844 return target_brk;
845 } else if (mapped_addr != -1) {
846 /* Mapped but at wrong address, meaning there wasn't actually
847 * enough space for this brk.
848 */
849 target_munmap(mapped_addr, new_alloc_size);
850 mapped_addr = -1;
Paul Brook3a0c6c42012-02-09 19:04:27 +0000851 DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr != -1)\n", target_brk);
vincent4d1de872011-06-14 21:56:33 +0000852 }
853 else {
Paul Brook3a0c6c42012-02-09 19:04:27 +0000854 DEBUGF_BRK(TARGET_ABI_FMT_lx " (otherwise)\n", target_brk);
Peter Maydell00faf082011-04-18 16:34:24 +0100855 }
balrog7ab240a2008-04-26 12:17:34 +0000856
Richard Henderson7dd46c02010-05-03 10:07:49 -0700857#if defined(TARGET_ALPHA)
858 /* We (partially) emulate OSF/1 on Alpha, which requires we
859 return a proper errno, not an unchanged brk value. */
Peter Maydell00faf082011-04-18 16:34:24 +0100860 return -TARGET_ENOMEM;
Richard Henderson7dd46c02010-05-03 10:07:49 -0700861#endif
Peter Maydell00faf082011-04-18 16:34:24 +0100862 /* For everything else, return the previous break. */
balrog7ab240a2008-04-26 12:17:34 +0000863 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000864}
865
Alistair Francis859e8a82020-03-12 15:13:49 -0700866#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \
Filip Bozutae5ce9682020-08-25 00:30:49 +0200867 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
ths26edcf42007-12-09 02:25:24 +0000868static inline abi_long copy_from_user_fdset(fd_set *fds,
869 abi_ulong target_fds_addr,
870 int n)
bellard31e31b82003-02-18 22:55:36 +0000871{
ths26edcf42007-12-09 02:25:24 +0000872 int i, nw, j, k;
873 abi_ulong b, *target_fds;
874
Laurent Vivierb1b2db22016-05-31 18:36:02 +0200875 nw = DIV_ROUND_UP(n, TARGET_ABI_BITS);
ths26edcf42007-12-09 02:25:24 +0000876 if (!(target_fds = lock_user(VERIFY_READ,
877 target_fds_addr,
878 sizeof(abi_ulong) * nw,
879 1)))
880 return -TARGET_EFAULT;
881
882 FD_ZERO(fds);
883 k = 0;
884 for (i = 0; i < nw; i++) {
885 /* grab the abi_ulong */
886 __get_user(b, &target_fds[i]);
887 for (j = 0; j < TARGET_ABI_BITS; j++) {
888 /* check the bit inside the abi_ulong */
889 if ((b >> j) & 1)
890 FD_SET(k, fds);
891 k++;
bellard31e31b82003-02-18 22:55:36 +0000892 }
bellard31e31b82003-02-18 22:55:36 +0000893 }
ths26edcf42007-12-09 02:25:24 +0000894
895 unlock_user(target_fds, target_fds_addr, 0);
896
897 return 0;
bellard31e31b82003-02-18 22:55:36 +0000898}
899
Mike Frysinger055e0902011-06-03 17:01:49 -0400900static inline abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr,
901 abi_ulong target_fds_addr,
902 int n)
903{
904 if (target_fds_addr) {
905 if (copy_from_user_fdset(fds, target_fds_addr, n))
906 return -TARGET_EFAULT;
907 *fds_ptr = fds;
908 } else {
909 *fds_ptr = NULL;
910 }
911 return 0;
912}
913
ths26edcf42007-12-09 02:25:24 +0000914static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
915 const fd_set *fds,
916 int n)
bellard31e31b82003-02-18 22:55:36 +0000917{
bellard31e31b82003-02-18 22:55:36 +0000918 int i, nw, j, k;
blueswir1992f48a2007-10-14 16:27:31 +0000919 abi_long v;
ths26edcf42007-12-09 02:25:24 +0000920 abi_ulong *target_fds;
bellard31e31b82003-02-18 22:55:36 +0000921
Laurent Vivierb1b2db22016-05-31 18:36:02 +0200922 nw = DIV_ROUND_UP(n, TARGET_ABI_BITS);
ths26edcf42007-12-09 02:25:24 +0000923 if (!(target_fds = lock_user(VERIFY_WRITE,
924 target_fds_addr,
925 sizeof(abi_ulong) * nw,
926 0)))
927 return -TARGET_EFAULT;
928
929 k = 0;
930 for (i = 0; i < nw; i++) {
931 v = 0;
932 for (j = 0; j < TARGET_ABI_BITS; j++) {
Andreas Schwab9ab709b2013-04-09 01:02:34 +0000933 v |= ((abi_ulong)(FD_ISSET(k, fds) != 0) << j);
ths26edcf42007-12-09 02:25:24 +0000934 k++;
bellard31e31b82003-02-18 22:55:36 +0000935 }
ths26edcf42007-12-09 02:25:24 +0000936 __put_user(v, &target_fds[i]);
bellard31e31b82003-02-18 22:55:36 +0000937 }
ths26edcf42007-12-09 02:25:24 +0000938
939 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
940
941 return 0;
bellard31e31b82003-02-18 22:55:36 +0000942}
Alistair Francis859e8a82020-03-12 15:13:49 -0700943#endif
bellard31e31b82003-02-18 22:55:36 +0000944
bellardc596ed12003-07-13 17:32:31 +0000945#if defined(__alpha__)
946#define HOST_HZ 1024
947#else
948#define HOST_HZ 100
949#endif
950
blueswir1992f48a2007-10-14 16:27:31 +0000951static inline abi_long host_to_target_clock_t(long ticks)
bellardc596ed12003-07-13 17:32:31 +0000952{
953#if HOST_HZ == TARGET_HZ
954 return ticks;
955#else
956 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
957#endif
958}
959
bellard579a97f2007-11-11 14:26:47 +0000960static inline abi_long host_to_target_rusage(abi_ulong target_addr,
961 const struct rusage *rusage)
bellardb4091862003-05-16 15:39:34 +0000962{
pbrook53a59602006-03-25 19:31:22 +0000963 struct target_rusage *target_rusage;
964
bellard579a97f2007-11-11 14:26:47 +0000965 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
966 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200967 target_rusage->ru_utime.tv_sec = tswapal(rusage->ru_utime.tv_sec);
968 target_rusage->ru_utime.tv_usec = tswapal(rusage->ru_utime.tv_usec);
969 target_rusage->ru_stime.tv_sec = tswapal(rusage->ru_stime.tv_sec);
970 target_rusage->ru_stime.tv_usec = tswapal(rusage->ru_stime.tv_usec);
971 target_rusage->ru_maxrss = tswapal(rusage->ru_maxrss);
972 target_rusage->ru_ixrss = tswapal(rusage->ru_ixrss);
973 target_rusage->ru_idrss = tswapal(rusage->ru_idrss);
974 target_rusage->ru_isrss = tswapal(rusage->ru_isrss);
975 target_rusage->ru_minflt = tswapal(rusage->ru_minflt);
976 target_rusage->ru_majflt = tswapal(rusage->ru_majflt);
977 target_rusage->ru_nswap = tswapal(rusage->ru_nswap);
978 target_rusage->ru_inblock = tswapal(rusage->ru_inblock);
979 target_rusage->ru_oublock = tswapal(rusage->ru_oublock);
980 target_rusage->ru_msgsnd = tswapal(rusage->ru_msgsnd);
981 target_rusage->ru_msgrcv = tswapal(rusage->ru_msgrcv);
982 target_rusage->ru_nsignals = tswapal(rusage->ru_nsignals);
983 target_rusage->ru_nvcsw = tswapal(rusage->ru_nvcsw);
984 target_rusage->ru_nivcsw = tswapal(rusage->ru_nivcsw);
pbrook53a59602006-03-25 19:31:22 +0000985 unlock_user_struct(target_rusage, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000986
987 return 0;
bellardb4091862003-05-16 15:39:34 +0000988}
989
Alistair Francis859e8a82020-03-12 15:13:49 -0700990#ifdef TARGET_NR_setrlimit
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200991static inline rlim_t target_to_host_rlim(abi_ulong target_rlim)
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +0900992{
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200993 abi_ulong target_rlim_swap;
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +0300994 rlim_t result;
995
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200996 target_rlim_swap = tswapal(target_rlim);
997 if (target_rlim_swap == TARGET_RLIM_INFINITY)
998 return RLIM_INFINITY;
999
1000 result = target_rlim_swap;
1001 if (target_rlim_swap != (rlim_t)result)
1002 return RLIM_INFINITY;
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001003
1004 return result;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001005}
Alistair Francis859e8a82020-03-12 15:13:49 -07001006#endif
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001007
Alistair Francis859e8a82020-03-12 15:13:49 -07001008#if defined(TARGET_NR_getrlimit) || defined(TARGET_NR_ugetrlimit)
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001009static inline abi_ulong host_to_target_rlim(rlim_t rlim)
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001010{
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001011 abi_ulong target_rlim_swap;
1012 abi_ulong result;
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001013
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001014 if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim)
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001015 target_rlim_swap = TARGET_RLIM_INFINITY;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001016 else
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001017 target_rlim_swap = rlim;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001018 result = tswapal(target_rlim_swap);
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001019
1020 return result;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001021}
Alistair Francis859e8a82020-03-12 15:13:49 -07001022#endif
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001023
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03001024static inline int target_to_host_resource(int code)
1025{
1026 switch (code) {
1027 case TARGET_RLIMIT_AS:
1028 return RLIMIT_AS;
1029 case TARGET_RLIMIT_CORE:
1030 return RLIMIT_CORE;
1031 case TARGET_RLIMIT_CPU:
1032 return RLIMIT_CPU;
1033 case TARGET_RLIMIT_DATA:
1034 return RLIMIT_DATA;
1035 case TARGET_RLIMIT_FSIZE:
1036 return RLIMIT_FSIZE;
1037 case TARGET_RLIMIT_LOCKS:
1038 return RLIMIT_LOCKS;
1039 case TARGET_RLIMIT_MEMLOCK:
1040 return RLIMIT_MEMLOCK;
1041 case TARGET_RLIMIT_MSGQUEUE:
1042 return RLIMIT_MSGQUEUE;
1043 case TARGET_RLIMIT_NICE:
1044 return RLIMIT_NICE;
1045 case TARGET_RLIMIT_NOFILE:
1046 return RLIMIT_NOFILE;
1047 case TARGET_RLIMIT_NPROC:
1048 return RLIMIT_NPROC;
1049 case TARGET_RLIMIT_RSS:
1050 return RLIMIT_RSS;
1051 case TARGET_RLIMIT_RTPRIO:
1052 return RLIMIT_RTPRIO;
Fabrice Fontainec3a28d72022-05-23 12:52:39 +02001053#ifdef RLIMIT_RTTIME
Serge Belyshev244fd082022-01-29 22:48:23 +03001054 case TARGET_RLIMIT_RTTIME:
1055 return RLIMIT_RTTIME;
Fabrice Fontainec3a28d72022-05-23 12:52:39 +02001056#endif
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03001057 case TARGET_RLIMIT_SIGPENDING:
1058 return RLIMIT_SIGPENDING;
1059 case TARGET_RLIMIT_STACK:
1060 return RLIMIT_STACK;
1061 default:
1062 return code;
1063 }
1064}
1065
ths788f5ec2007-12-09 02:37:05 +00001066static inline abi_long copy_from_user_timeval(struct timeval *tv,
1067 abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +00001068{
pbrook53a59602006-03-25 19:31:22 +00001069 struct target_timeval *target_tv;
1070
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001071 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) {
bellard579a97f2007-11-11 14:26:47 +00001072 return -TARGET_EFAULT;
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001073 }
ths788f5ec2007-12-09 02:37:05 +00001074
1075 __get_user(tv->tv_sec, &target_tv->tv_sec);
1076 __get_user(tv->tv_usec, &target_tv->tv_usec);
1077
1078 unlock_user_struct(target_tv, target_tv_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001079
1080 return 0;
bellard31e31b82003-02-18 22:55:36 +00001081}
1082
ths788f5ec2007-12-09 02:37:05 +00001083static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
1084 const struct timeval *tv)
bellard31e31b82003-02-18 22:55:36 +00001085{
pbrook53a59602006-03-25 19:31:22 +00001086 struct target_timeval *target_tv;
1087
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001088 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
bellard579a97f2007-11-11 14:26:47 +00001089 return -TARGET_EFAULT;
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001090 }
ths788f5ec2007-12-09 02:37:05 +00001091
1092 __put_user(tv->tv_sec, &target_tv->tv_sec);
1093 __put_user(tv->tv_usec, &target_tv->tv_usec);
1094
1095 unlock_user_struct(target_tv, target_tv_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001096
1097 return 0;
bellard31e31b82003-02-18 22:55:36 +00001098}
1099
Filip Bozuta6ac03b22020-08-24 21:21:15 +02001100#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
1101static inline abi_long copy_from_user_timeval64(struct timeval *tv,
1102 abi_ulong target_tv_addr)
1103{
1104 struct target__kernel_sock_timeval *target_tv;
1105
1106 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) {
1107 return -TARGET_EFAULT;
1108 }
1109
1110 __get_user(tv->tv_sec, &target_tv->tv_sec);
1111 __get_user(tv->tv_usec, &target_tv->tv_usec);
1112
1113 unlock_user_struct(target_tv, target_tv_addr, 0);
1114
1115 return 0;
1116}
1117#endif
1118
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001119static inline abi_long copy_to_user_timeval64(abi_ulong target_tv_addr,
Filip Bozuta6ac03b22020-08-24 21:21:15 +02001120 const struct timeval *tv)
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001121{
1122 struct target__kernel_sock_timeval *target_tv;
1123
1124 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
1125 return -TARGET_EFAULT;
1126 }
1127
1128 __put_user(tv->tv_sec, &target_tv->tv_sec);
1129 __put_user(tv->tv_usec, &target_tv->tv_usec);
1130
1131 unlock_user_struct(target_tv, target_tv_addr, 1);
1132
1133 return 0;
1134}
1135
Alistair Francis859e8a82020-03-12 15:13:49 -07001136#if defined(TARGET_NR_futex) || \
1137 defined(TARGET_NR_rt_sigtimedwait) || \
1138 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6) || \
1139 defined(TARGET_NR_nanosleep) || defined(TARGET_NR_clock_settime) || \
1140 defined(TARGET_NR_utimensat) || defined(TARGET_NR_mq_timedsend) || \
Matus Kyseld8c08b12020-06-26 14:46:11 +02001141 defined(TARGET_NR_mq_timedreceive) || defined(TARGET_NR_ipc) || \
Filip Bozuta2c86c902020-07-22 17:34:20 +02001142 defined(TARGET_NR_semop) || defined(TARGET_NR_semtimedop) || \
1143 defined(TARGET_NR_timer_settime) || \
1144 (defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD))
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001145static inline abi_long target_to_host_timespec(struct timespec *host_ts,
1146 abi_ulong target_addr)
1147{
1148 struct target_timespec *target_ts;
1149
1150 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) {
1151 return -TARGET_EFAULT;
1152 }
1153 __get_user(host_ts->tv_sec, &target_ts->tv_sec);
1154 __get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1155 unlock_user_struct(target_ts, target_addr, 0);
1156 return 0;
1157}
Alistair Francis859e8a82020-03-12 15:13:49 -07001158#endif
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001159
Filip Bozuta828cb3a2020-07-22 17:34:21 +02001160#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) || \
1161 defined(TARGET_NR_timer_settime64) || \
Filip Bozutad107e372020-08-24 21:37:52 +02001162 defined(TARGET_NR_mq_timedsend_time64) || \
1163 defined(TARGET_NR_mq_timedreceive_time64) || \
Filip Bozuta6ac03b22020-08-24 21:21:15 +02001164 (defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)) || \
Filip Bozutaddcbde12020-08-24 21:21:16 +02001165 defined(TARGET_NR_clock_nanosleep_time64) || \
Filip Bozutacac46eb2020-08-25 00:30:50 +02001166 defined(TARGET_NR_rt_sigtimedwait_time64) || \
1167 defined(TARGET_NR_utimensat) || \
1168 defined(TARGET_NR_utimensat_time64) || \
Filip Bozutae5ce9682020-08-25 00:30:49 +02001169 defined(TARGET_NR_semtimedop_time64) || \
1170 defined(TARGET_NR_pselect6_time64) || defined(TARGET_NR_ppoll_time64)
Alistair Francisc6c8d102020-03-12 15:13:53 -07001171static inline abi_long target_to_host_timespec64(struct timespec *host_ts,
1172 abi_ulong target_addr)
1173{
1174 struct target__kernel_timespec *target_ts;
1175
1176 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) {
1177 return -TARGET_EFAULT;
1178 }
1179 __get_user(host_ts->tv_sec, &target_ts->tv_sec);
1180 __get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
Laurent Vivier00576752020-08-27 09:04:49 +02001181 /* in 32bit mode, this drops the padding */
1182 host_ts->tv_nsec = (long)(abi_long)host_ts->tv_nsec;
Alistair Francisc6c8d102020-03-12 15:13:53 -07001183 unlock_user_struct(target_ts, target_addr, 0);
1184 return 0;
1185}
1186#endif
1187
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001188static inline abi_long host_to_target_timespec(abi_ulong target_addr,
1189 struct timespec *host_ts)
1190{
1191 struct target_timespec *target_ts;
1192
1193 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) {
1194 return -TARGET_EFAULT;
1195 }
1196 __put_user(host_ts->tv_sec, &target_ts->tv_sec);
1197 __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1198 unlock_user_struct(target_ts, target_addr, 1);
1199 return 0;
1200}
1201
1202static inline abi_long host_to_target_timespec64(abi_ulong target_addr,
1203 struct timespec *host_ts)
1204{
1205 struct target__kernel_timespec *target_ts;
1206
1207 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) {
1208 return -TARGET_EFAULT;
1209 }
1210 __put_user(host_ts->tv_sec, &target_ts->tv_sec);
1211 __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1212 unlock_user_struct(target_ts, target_addr, 1);
1213 return 0;
1214}
1215
Richard Hendersona52f5f82020-02-12 19:22:23 -08001216#if defined(TARGET_NR_gettimeofday)
1217static inline abi_long copy_to_user_timezone(abi_ulong target_tz_addr,
1218 struct timezone *tz)
1219{
1220 struct target_timezone *target_tz;
1221
1222 if (!lock_user_struct(VERIFY_WRITE, target_tz, target_tz_addr, 1)) {
1223 return -TARGET_EFAULT;
1224 }
1225
1226 __put_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
1227 __put_user(tz->tz_dsttime, &target_tz->tz_dsttime);
1228
1229 unlock_user_struct(target_tz, target_tz_addr, 1);
1230
1231 return 0;
1232}
1233#endif
1234
Alistair Francis859e8a82020-03-12 15:13:49 -07001235#if defined(TARGET_NR_settimeofday)
Paul Burtonef4467e2014-06-22 11:25:40 +01001236static inline abi_long copy_from_user_timezone(struct timezone *tz,
1237 abi_ulong target_tz_addr)
1238{
1239 struct target_timezone *target_tz;
1240
1241 if (!lock_user_struct(VERIFY_READ, target_tz, target_tz_addr, 1)) {
1242 return -TARGET_EFAULT;
1243 }
1244
1245 __get_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
1246 __get_user(tz->tz_dsttime, &target_tz->tz_dsttime);
1247
1248 unlock_user_struct(target_tz, target_tz_addr, 0);
1249
1250 return 0;
1251}
Alistair Francis859e8a82020-03-12 15:13:49 -07001252#endif
Paul Burtonef4467e2014-06-22 11:25:40 +01001253
Nathan Froyd8ec9cf82009-07-22 09:14:36 -07001254#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
1255#include <mqueue.h>
1256
aurel3224e10032009-04-15 16:11:43 +00001257static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr,
1258 abi_ulong target_mq_attr_addr)
1259{
1260 struct target_mq_attr *target_mq_attr;
1261
1262 if (!lock_user_struct(VERIFY_READ, target_mq_attr,
1263 target_mq_attr_addr, 1))
1264 return -TARGET_EFAULT;
1265
1266 __get_user(attr->mq_flags, &target_mq_attr->mq_flags);
1267 __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
1268 __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
1269 __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
1270
1271 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0);
1272
1273 return 0;
1274}
1275
1276static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
1277 const struct mq_attr *attr)
1278{
1279 struct target_mq_attr *target_mq_attr;
1280
1281 if (!lock_user_struct(VERIFY_WRITE, target_mq_attr,
1282 target_mq_attr_addr, 0))
1283 return -TARGET_EFAULT;
1284
1285 __put_user(attr->mq_flags, &target_mq_attr->mq_flags);
1286 __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
1287 __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
1288 __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
1289
1290 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1);
1291
1292 return 0;
1293}
Nathan Froyd8ec9cf82009-07-22 09:14:36 -07001294#endif
bellard31e31b82003-02-18 22:55:36 +00001295
Mike Frysinger055e0902011-06-03 17:01:49 -04001296#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect)
ths0da46a62007-10-20 20:23:07 +00001297/* do_select() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001298static abi_long do_select(int n,
ths26edcf42007-12-09 02:25:24 +00001299 abi_ulong rfd_addr, abi_ulong wfd_addr,
1300 abi_ulong efd_addr, abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +00001301{
1302 fd_set rfds, wfds, efds;
1303 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
Peter Maydell6df9d382016-05-12 18:47:51 +01001304 struct timeval tv;
1305 struct timespec ts, *ts_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00001306 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00001307
Mike Frysinger055e0902011-06-03 17:01:49 -04001308 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
1309 if (ret) {
1310 return ret;
pbrook53a59602006-03-25 19:31:22 +00001311 }
Mike Frysinger055e0902011-06-03 17:01:49 -04001312 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
1313 if (ret) {
1314 return ret;
pbrook53a59602006-03-25 19:31:22 +00001315 }
Mike Frysinger055e0902011-06-03 17:01:49 -04001316 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
1317 if (ret) {
1318 return ret;
pbrook53a59602006-03-25 19:31:22 +00001319 }
ths3b46e622007-09-17 08:09:54 +00001320
ths26edcf42007-12-09 02:25:24 +00001321 if (target_tv_addr) {
ths788f5ec2007-12-09 02:37:05 +00001322 if (copy_from_user_timeval(&tv, target_tv_addr))
1323 return -TARGET_EFAULT;
Peter Maydell6df9d382016-05-12 18:47:51 +01001324 ts.tv_sec = tv.tv_sec;
1325 ts.tv_nsec = tv.tv_usec * 1000;
1326 ts_ptr = &ts;
bellard31e31b82003-02-18 22:55:36 +00001327 } else {
Peter Maydell6df9d382016-05-12 18:47:51 +01001328 ts_ptr = NULL;
bellard31e31b82003-02-18 22:55:36 +00001329 }
ths26edcf42007-12-09 02:25:24 +00001330
Peter Maydell6df9d382016-05-12 18:47:51 +01001331 ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
1332 ts_ptr, NULL));
pbrook53a59602006-03-25 19:31:22 +00001333
ths26edcf42007-12-09 02:25:24 +00001334 if (!is_error(ret)) {
1335 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
1336 return -TARGET_EFAULT;
1337 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
1338 return -TARGET_EFAULT;
1339 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
1340 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00001341
Peter Maydell6df9d382016-05-12 18:47:51 +01001342 if (target_tv_addr) {
1343 tv.tv_sec = ts.tv_sec;
1344 tv.tv_usec = ts.tv_nsec / 1000;
1345 if (copy_to_user_timeval(target_tv_addr, &tv)) {
1346 return -TARGET_EFAULT;
1347 }
1348 }
bellard31e31b82003-02-18 22:55:36 +00001349 }
bellard579a97f2007-11-11 14:26:47 +00001350
bellard31e31b82003-02-18 22:55:36 +00001351 return ret;
1352}
Laurent Vivier5457dc92016-07-08 01:17:27 +02001353
1354#if defined(TARGET_WANT_OLD_SYS_SELECT)
1355static abi_long do_old_select(abi_ulong arg1)
1356{
1357 struct target_sel_arg_struct *sel;
1358 abi_ulong inp, outp, exp, tvp;
1359 long nsel;
1360
1361 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1)) {
1362 return -TARGET_EFAULT;
1363 }
1364
1365 nsel = tswapal(sel->n);
1366 inp = tswapal(sel->inp);
1367 outp = tswapal(sel->outp);
1368 exp = tswapal(sel->exp);
1369 tvp = tswapal(sel->tvp);
1370
1371 unlock_user_struct(sel, arg1, 0);
1372
1373 return do_select(nsel, inp, outp, exp, tvp);
1374}
1375#endif
Mike Frysinger055e0902011-06-03 17:01:49 -04001376#endif
bellard31e31b82003-02-18 22:55:36 +00001377
Filip Bozutae5ce9682020-08-25 00:30:49 +02001378#if defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
1379static abi_long do_pselect6(abi_long arg1, abi_long arg2, abi_long arg3,
1380 abi_long arg4, abi_long arg5, abi_long arg6,
1381 bool time64)
1382{
1383 abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr;
1384 fd_set rfds, wfds, efds;
1385 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
1386 struct timespec ts, *ts_ptr;
1387 abi_long ret;
1388
1389 /*
1390 * The 6th arg is actually two args smashed together,
1391 * so we cannot use the C library.
1392 */
Filip Bozutae5ce9682020-08-25 00:30:49 +02001393 struct {
1394 sigset_t *set;
1395 size_t size;
1396 } sig, *sig_ptr;
1397
1398 abi_ulong arg_sigset, arg_sigsize, *arg7;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001399
1400 n = arg1;
1401 rfd_addr = arg2;
1402 wfd_addr = arg3;
1403 efd_addr = arg4;
1404 ts_addr = arg5;
1405
1406 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
1407 if (ret) {
1408 return ret;
1409 }
1410 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
1411 if (ret) {
1412 return ret;
1413 }
1414 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
1415 if (ret) {
1416 return ret;
1417 }
1418
1419 /*
1420 * This takes a timespec, and not a timeval, so we cannot
1421 * use the do_select() helper ...
1422 */
1423 if (ts_addr) {
1424 if (time64) {
1425 if (target_to_host_timespec64(&ts, ts_addr)) {
1426 return -TARGET_EFAULT;
1427 }
1428 } else {
1429 if (target_to_host_timespec(&ts, ts_addr)) {
1430 return -TARGET_EFAULT;
1431 }
1432 }
1433 ts_ptr = &ts;
1434 } else {
1435 ts_ptr = NULL;
1436 }
1437
1438 /* Extract the two packed args for the sigset */
Richard Hendersoncb226032022-03-15 01:43:06 -07001439 sig_ptr = NULL;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001440 if (arg6) {
Filip Bozutae5ce9682020-08-25 00:30:49 +02001441 arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1);
1442 if (!arg7) {
1443 return -TARGET_EFAULT;
1444 }
1445 arg_sigset = tswapal(arg7[0]);
1446 arg_sigsize = tswapal(arg7[1]);
1447 unlock_user(arg7, arg6, 0);
1448
1449 if (arg_sigset) {
Richard Hendersoncb226032022-03-15 01:43:06 -07001450 ret = process_sigsuspend_mask(&sig.set, arg_sigset, arg_sigsize);
1451 if (ret != 0) {
1452 return ret;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001453 }
Richard Hendersoncb226032022-03-15 01:43:06 -07001454 sig_ptr = &sig;
1455 sig.size = SIGSET_T_SIZE;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001456 }
Filip Bozutae5ce9682020-08-25 00:30:49 +02001457 }
1458
1459 ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
1460 ts_ptr, sig_ptr));
1461
Richard Hendersoncb226032022-03-15 01:43:06 -07001462 if (sig_ptr) {
1463 finish_sigsuspend_mask(ret);
1464 }
1465
Filip Bozutae5ce9682020-08-25 00:30:49 +02001466 if (!is_error(ret)) {
1467 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n)) {
1468 return -TARGET_EFAULT;
1469 }
1470 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n)) {
1471 return -TARGET_EFAULT;
1472 }
1473 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n)) {
1474 return -TARGET_EFAULT;
1475 }
1476 if (time64) {
1477 if (ts_addr && host_to_target_timespec64(ts_addr, &ts)) {
1478 return -TARGET_EFAULT;
1479 }
1480 } else {
1481 if (ts_addr && host_to_target_timespec(ts_addr, &ts)) {
1482 return -TARGET_EFAULT;
1483 }
1484 }
1485 }
1486 return ret;
1487}
1488#endif
1489
1490#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll) || \
1491 defined(TARGET_NR_ppoll_time64)
1492static abi_long do_ppoll(abi_long arg1, abi_long arg2, abi_long arg3,
1493 abi_long arg4, abi_long arg5, bool ppoll, bool time64)
1494{
1495 struct target_pollfd *target_pfd;
1496 unsigned int nfds = arg2;
1497 struct pollfd *pfd;
1498 unsigned int i;
1499 abi_long ret;
1500
1501 pfd = NULL;
1502 target_pfd = NULL;
1503 if (nfds) {
1504 if (nfds > (INT_MAX / sizeof(struct target_pollfd))) {
1505 return -TARGET_EINVAL;
1506 }
1507 target_pfd = lock_user(VERIFY_WRITE, arg1,
1508 sizeof(struct target_pollfd) * nfds, 1);
1509 if (!target_pfd) {
1510 return -TARGET_EFAULT;
1511 }
1512
1513 pfd = alloca(sizeof(struct pollfd) * nfds);
1514 for (i = 0; i < nfds; i++) {
1515 pfd[i].fd = tswap32(target_pfd[i].fd);
1516 pfd[i].events = tswap16(target_pfd[i].events);
1517 }
1518 }
1519 if (ppoll) {
1520 struct timespec _timeout_ts, *timeout_ts = &_timeout_ts;
Richard Hendersondb36aa72022-03-15 01:43:08 -07001521 sigset_t *set = NULL;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001522
1523 if (arg3) {
1524 if (time64) {
1525 if (target_to_host_timespec64(timeout_ts, arg3)) {
1526 unlock_user(target_pfd, arg1, 0);
1527 return -TARGET_EFAULT;
1528 }
1529 } else {
1530 if (target_to_host_timespec(timeout_ts, arg3)) {
1531 unlock_user(target_pfd, arg1, 0);
1532 return -TARGET_EFAULT;
1533 }
1534 }
1535 } else {
1536 timeout_ts = NULL;
1537 }
1538
1539 if (arg4) {
Richard Hendersondb36aa72022-03-15 01:43:08 -07001540 ret = process_sigsuspend_mask(&set, arg4, arg5);
1541 if (ret != 0) {
Filip Bozutae5ce9682020-08-25 00:30:49 +02001542 unlock_user(target_pfd, arg1, 0);
Richard Hendersondb36aa72022-03-15 01:43:08 -07001543 return ret;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001544 }
Filip Bozutae5ce9682020-08-25 00:30:49 +02001545 }
1546
1547 ret = get_errno(safe_ppoll(pfd, nfds, timeout_ts,
1548 set, SIGSET_T_SIZE));
1549
Richard Hendersondb36aa72022-03-15 01:43:08 -07001550 if (set) {
1551 finish_sigsuspend_mask(ret);
1552 }
Filip Bozutae5ce9682020-08-25 00:30:49 +02001553 if (!is_error(ret) && arg3) {
1554 if (time64) {
1555 if (host_to_target_timespec64(arg3, timeout_ts)) {
1556 return -TARGET_EFAULT;
1557 }
1558 } else {
1559 if (host_to_target_timespec(arg3, timeout_ts)) {
1560 return -TARGET_EFAULT;
1561 }
1562 }
1563 }
Filip Bozutae5ce9682020-08-25 00:30:49 +02001564 } else {
1565 struct timespec ts, *pts;
1566
1567 if (arg3 >= 0) {
1568 /* Convert ms to secs, ns */
1569 ts.tv_sec = arg3 / 1000;
1570 ts.tv_nsec = (arg3 % 1000) * 1000000LL;
1571 pts = &ts;
1572 } else {
1573 /* -ve poll() timeout means "infinite" */
1574 pts = NULL;
1575 }
1576 ret = get_errno(safe_ppoll(pfd, nfds, pts, NULL, 0));
1577 }
1578
1579 if (!is_error(ret)) {
1580 for (i = 0; i < nfds; i++) {
1581 target_pfd[i].revents = tswap16(pfd[i].revents);
1582 }
1583 }
1584 unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds);
1585 return ret;
1586}
1587#endif
1588
Riku Voipio099d6b02009-05-05 12:10:04 +03001589static abi_long do_pipe2(int host_pipe[], int flags)
1590{
1591#ifdef CONFIG_PIPE2
1592 return pipe2(host_pipe, flags);
1593#else
1594 return -ENOSYS;
1595#endif
1596}
1597
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02001598static abi_long do_pipe(CPUArchState *cpu_env, abi_ulong pipedes,
Richard Hendersonfb41a662010-05-03 10:07:52 -07001599 int flags, int is_pipe2)
Riku Voipio099d6b02009-05-05 12:10:04 +03001600{
1601 int host_pipe[2];
1602 abi_long ret;
1603 ret = flags ? do_pipe2(host_pipe, flags) : pipe(host_pipe);
1604
1605 if (is_error(ret))
1606 return get_errno(ret);
Richard Hendersonfb41a662010-05-03 10:07:52 -07001607
1608 /* Several targets have special calling conventions for the original
1609 pipe syscall, but didn't replicate this into the pipe2 syscall. */
1610 if (!is_pipe2) {
1611#if defined(TARGET_ALPHA)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02001612 cpu_env->ir[IR_A4] = host_pipe[1];
Richard Hendersonfb41a662010-05-03 10:07:52 -07001613 return host_pipe[0];
1614#elif defined(TARGET_MIPS)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02001615 cpu_env->active_tc.gpr[3] = host_pipe[1];
Richard Hendersonfb41a662010-05-03 10:07:52 -07001616 return host_pipe[0];
1617#elif defined(TARGET_SH4)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02001618 cpu_env->gregs[1] = host_pipe[1];
Richard Hendersonfb41a662010-05-03 10:07:52 -07001619 return host_pipe[0];
Peter Maydell82f05b62013-07-06 17:39:48 +01001620#elif defined(TARGET_SPARC)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02001621 cpu_env->regwptr[1] = host_pipe[1];
Peter Maydell82f05b62013-07-06 17:39:48 +01001622 return host_pipe[0];
takasi-y@ops.dti.ne.jp597c0212010-02-18 00:35:03 +09001623#endif
Richard Hendersonfb41a662010-05-03 10:07:52 -07001624 }
1625
Riku Voipio099d6b02009-05-05 12:10:04 +03001626 if (put_user_s32(host_pipe[0], pipedes)
1627 || put_user_s32(host_pipe[1], pipedes + sizeof(host_pipe[0])))
1628 return -TARGET_EFAULT;
Riku Voipio099d6b02009-05-05 12:10:04 +03001629 return get_errno(ret);
1630}
1631
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001632static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
1633 abi_ulong target_addr,
1634 socklen_t len)
1635{
1636 struct target_ip_mreqn *target_smreqn;
1637
1638 target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
1639 if (!target_smreqn)
1640 return -TARGET_EFAULT;
1641 mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
1642 mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
1643 if (len == sizeof(struct target_ip_mreqn))
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001644 mreqn->imr_ifindex = tswapal(target_smreqn->imr_ifindex);
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001645 unlock_user(target_smreqn, target_addr, 0);
1646
1647 return 0;
1648}
1649
Laurent Vivier7b36f782015-10-28 21:40:44 +01001650static inline abi_long target_to_host_sockaddr(int fd, struct sockaddr *addr,
bellard579a97f2007-11-11 14:26:47 +00001651 abi_ulong target_addr,
1652 socklen_t len)
bellard7854b052003-03-29 17:22:23 +00001653{
aurel32607175e2009-04-15 16:11:59 +00001654 const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
1655 sa_family_t sa_family;
pbrook53a59602006-03-25 19:31:22 +00001656 struct target_sockaddr *target_saddr;
1657
Laurent Vivier7b36f782015-10-28 21:40:44 +01001658 if (fd_trans_target_to_host_addr(fd)) {
1659 return fd_trans_target_to_host_addr(fd)(addr, target_addr, len);
1660 }
1661
bellard579a97f2007-11-11 14:26:47 +00001662 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
1663 if (!target_saddr)
1664 return -TARGET_EFAULT;
aurel32607175e2009-04-15 16:11:59 +00001665
1666 sa_family = tswap16(target_saddr->sa_family);
1667
1668 /* Oops. The caller might send a incomplete sun_path; sun_path
1669 * must be terminated by \0 (see the manual page), but
1670 * unfortunately it is quite common to specify sockaddr_un
1671 * length as "strlen(x->sun_path)" while it should be
1672 * "strlen(...) + 1". We'll fix that here if needed.
1673 * Linux kernel has a similar feature.
1674 */
1675
1676 if (sa_family == AF_UNIX) {
1677 if (len < unix_maxlen && len > 0) {
1678 char *cp = (char*)target_saddr;
1679
1680 if ( cp[len-1] && !cp[len] )
1681 len++;
1682 }
1683 if (len > unix_maxlen)
1684 len = unix_maxlen;
1685 }
1686
pbrook53a59602006-03-25 19:31:22 +00001687 memcpy(addr, target_saddr, len);
aurel32607175e2009-04-15 16:11:59 +00001688 addr->sa_family = sa_family;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02001689 if (sa_family == AF_NETLINK) {
1690 struct sockaddr_nl *nladdr;
1691
1692 nladdr = (struct sockaddr_nl *)addr;
1693 nladdr->nl_pid = tswap32(nladdr->nl_pid);
1694 nladdr->nl_groups = tswap32(nladdr->nl_groups);
1695 } else if (sa_family == AF_PACKET) {
Joakim Tjernlund33a29b52014-07-12 15:47:07 +02001696 struct target_sockaddr_ll *lladdr;
1697
1698 lladdr = (struct target_sockaddr_ll *)addr;
1699 lladdr->sll_ifindex = tswap32(lladdr->sll_ifindex);
1700 lladdr->sll_hatype = tswap16(lladdr->sll_hatype);
1701 }
pbrook53a59602006-03-25 19:31:22 +00001702 unlock_user(target_saddr, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001703
1704 return 0;
bellard7854b052003-03-29 17:22:23 +00001705}
1706
bellard579a97f2007-11-11 14:26:47 +00001707static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
1708 struct sockaddr *addr,
1709 socklen_t len)
bellard7854b052003-03-29 17:22:23 +00001710{
pbrook53a59602006-03-25 19:31:22 +00001711 struct target_sockaddr *target_saddr;
1712
Peter Maydella1e22192016-07-07 15:44:43 +01001713 if (len == 0) {
1714 return 0;
1715 }
Philippe Mathieu-Daudé68607102017-07-26 23:42:18 -03001716 assert(addr);
Peter Maydella1e22192016-07-07 15:44:43 +01001717
bellard579a97f2007-11-11 14:26:47 +00001718 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
1719 if (!target_saddr)
1720 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001721 memcpy(target_saddr, addr, len);
Peter Maydella1e22192016-07-07 15:44:43 +01001722 if (len >= offsetof(struct target_sockaddr, sa_family) +
1723 sizeof(target_saddr->sa_family)) {
1724 target_saddr->sa_family = tswap16(addr->sa_family);
1725 }
Philippe Mathieu-Daudéa47401b2019-10-21 13:48:52 +02001726 if (addr->sa_family == AF_NETLINK &&
1727 len >= sizeof(struct target_sockaddr_nl)) {
1728 struct target_sockaddr_nl *target_nl =
1729 (struct target_sockaddr_nl *)target_saddr;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02001730 target_nl->nl_pid = tswap32(target_nl->nl_pid);
1731 target_nl->nl_groups = tswap32(target_nl->nl_groups);
Laurent Viviera82ea932016-06-27 00:18:22 +02001732 } else if (addr->sa_family == AF_PACKET) {
1733 struct sockaddr_ll *target_ll = (struct sockaddr_ll *)target_saddr;
1734 target_ll->sll_ifindex = tswap32(target_ll->sll_ifindex);
1735 target_ll->sll_hatype = tswap16(target_ll->sll_hatype);
Helge Delleree1ac3a2017-02-18 23:31:30 +01001736 } else if (addr->sa_family == AF_INET6 &&
1737 len >= sizeof(struct target_sockaddr_in6)) {
1738 struct target_sockaddr_in6 *target_in6 =
1739 (struct target_sockaddr_in6 *)target_saddr;
1740 target_in6->sin6_scope_id = tswap16(target_in6->sin6_scope_id);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02001741 }
pbrook53a59602006-03-25 19:31:22 +00001742 unlock_user(target_saddr, target_addr, len);
bellard579a97f2007-11-11 14:26:47 +00001743
1744 return 0;
bellard7854b052003-03-29 17:22:23 +00001745}
1746
bellard5a4a8982007-11-11 17:39:18 +00001747static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
1748 struct target_msghdr *target_msgh)
bellard7854b052003-03-29 17:22:23 +00001749{
1750 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001751 abi_long msg_controllen;
1752 abi_ulong target_cmsg_addr;
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001753 struct target_cmsghdr *target_cmsg, *target_cmsg_start;
bellard7854b052003-03-29 17:22:23 +00001754 socklen_t space = 0;
bellard5a4a8982007-11-11 17:39:18 +00001755
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001756 msg_controllen = tswapal(target_msgh->msg_controllen);
bellard5a4a8982007-11-11 17:39:18 +00001757 if (msg_controllen < sizeof (struct target_cmsghdr))
1758 goto the_end;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001759 target_cmsg_addr = tswapal(target_msgh->msg_control);
bellard5a4a8982007-11-11 17:39:18 +00001760 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001761 target_cmsg_start = target_cmsg;
bellard5a4a8982007-11-11 17:39:18 +00001762 if (!target_cmsg)
1763 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001764
1765 while (cmsg && target_cmsg) {
1766 void *data = CMSG_DATA(cmsg);
1767 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1768
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001769 int len = tswapal(target_cmsg->cmsg_len)
Peter Maydellad762b92017-12-15 13:52:56 +00001770 - sizeof(struct target_cmsghdr);
bellard7854b052003-03-29 17:22:23 +00001771
1772 space += CMSG_SPACE(len);
1773 if (space > msgh->msg_controllen) {
1774 space -= CMSG_SPACE(len);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001775 /* This is a QEMU bug, since we allocated the payload
1776 * area ourselves (unlike overflow in host-to-target
1777 * conversion, which is just the guest giving us a buffer
1778 * that's too small). It can't happen for the payload types
1779 * we currently support; if it becomes an issue in future
1780 * we would need to improve our allocation strategy to
1781 * something more intelligent than "twice the size of the
1782 * target buffer we're reading from".
1783 */
Josh Kunz39be5352020-02-03 18:54:13 -08001784 qemu_log_mask(LOG_UNIMP,
1785 ("Unsupported ancillary data %d/%d: "
1786 "unhandled msg size\n"),
1787 tswap32(target_cmsg->cmsg_level),
1788 tswap32(target_cmsg->cmsg_type));
bellard7854b052003-03-29 17:22:23 +00001789 break;
1790 }
1791
Petar Jovanovicdbf4f792013-09-13 19:27:29 +02001792 if (tswap32(target_cmsg->cmsg_level) == TARGET_SOL_SOCKET) {
1793 cmsg->cmsg_level = SOL_SOCKET;
1794 } else {
1795 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
1796 }
bellard7854b052003-03-29 17:22:23 +00001797 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
1798 cmsg->cmsg_len = CMSG_LEN(len);
1799
Alex Suykov30b8b682014-12-23 07:52:58 +02001800 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +00001801 int *fd = (int *)data;
1802 int *target_fd = (int *)target_data;
1803 int i, numfds = len / sizeof(int);
1804
Peter Maydell876e23c2015-05-26 19:46:32 +01001805 for (i = 0; i < numfds; i++) {
1806 __get_user(fd[i], target_fd + i);
1807 }
Alex Suykov30b8b682014-12-23 07:52:58 +02001808 } else if (cmsg->cmsg_level == SOL_SOCKET
1809 && cmsg->cmsg_type == SCM_CREDENTIALS) {
1810 struct ucred *cred = (struct ucred *)data;
1811 struct target_ucred *target_cred =
1812 (struct target_ucred *)target_data;
1813
Peter Maydell876e23c2015-05-26 19:46:32 +01001814 __get_user(cred->pid, &target_cred->pid);
1815 __get_user(cred->uid, &target_cred->uid);
1816 __get_user(cred->gid, &target_cred->gid);
Alex Suykov30b8b682014-12-23 07:52:58 +02001817 } else {
Josh Kunz39be5352020-02-03 18:54:13 -08001818 qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n",
1819 cmsg->cmsg_level, cmsg->cmsg_type);
Alex Suykov30b8b682014-12-23 07:52:58 +02001820 memcpy(data, target_data, len);
bellard7854b052003-03-29 17:22:23 +00001821 }
1822
1823 cmsg = CMSG_NXTHDR(msgh, cmsg);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001824 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg,
1825 target_cmsg_start);
bellard7854b052003-03-29 17:22:23 +00001826 }
bellard5a4a8982007-11-11 17:39:18 +00001827 unlock_user(target_cmsg, target_cmsg_addr, 0);
1828 the_end:
bellard7854b052003-03-29 17:22:23 +00001829 msgh->msg_controllen = space;
bellard5a4a8982007-11-11 17:39:18 +00001830 return 0;
bellard7854b052003-03-29 17:22:23 +00001831}
1832
bellard5a4a8982007-11-11 17:39:18 +00001833static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
1834 struct msghdr *msgh)
bellard7854b052003-03-29 17:22:23 +00001835{
1836 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001837 abi_long msg_controllen;
1838 abi_ulong target_cmsg_addr;
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001839 struct target_cmsghdr *target_cmsg, *target_cmsg_start;
bellard7854b052003-03-29 17:22:23 +00001840 socklen_t space = 0;
1841
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001842 msg_controllen = tswapal(target_msgh->msg_controllen);
bellard5a4a8982007-11-11 17:39:18 +00001843 if (msg_controllen < sizeof (struct target_cmsghdr))
1844 goto the_end;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001845 target_cmsg_addr = tswapal(target_msgh->msg_control);
bellard5a4a8982007-11-11 17:39:18 +00001846 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001847 target_cmsg_start = target_cmsg;
bellard5a4a8982007-11-11 17:39:18 +00001848 if (!target_cmsg)
1849 return -TARGET_EFAULT;
1850
bellard7854b052003-03-29 17:22:23 +00001851 while (cmsg && target_cmsg) {
1852 void *data = CMSG_DATA(cmsg);
1853 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1854
Peter Maydellad762b92017-12-15 13:52:56 +00001855 int len = cmsg->cmsg_len - sizeof(struct cmsghdr);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001856 int tgt_len, tgt_space;
bellard7854b052003-03-29 17:22:23 +00001857
Peter Maydellc2aeb252015-05-26 19:46:31 +01001858 /* We never copy a half-header but may copy half-data;
1859 * this is Linux's behaviour in put_cmsg(). Note that
1860 * truncation here is a guest problem (which we report
1861 * to the guest via the CTRUNC bit), unlike truncation
1862 * in target_to_host_cmsg, which is a QEMU bug.
1863 */
Peter Maydell71749702017-12-15 13:52:55 +00001864 if (msg_controllen < sizeof(struct target_cmsghdr)) {
Peter Maydellc2aeb252015-05-26 19:46:31 +01001865 target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
bellard7854b052003-03-29 17:22:23 +00001866 break;
1867 }
1868
Petar Jovanovicdbf4f792013-09-13 19:27:29 +02001869 if (cmsg->cmsg_level == SOL_SOCKET) {
1870 target_cmsg->cmsg_level = tswap32(TARGET_SOL_SOCKET);
1871 } else {
1872 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
1873 }
bellard7854b052003-03-29 17:22:23 +00001874 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
bellard7854b052003-03-29 17:22:23 +00001875
Peter Maydellc2aeb252015-05-26 19:46:31 +01001876 /* Payload types which need a different size of payload on
1877 * the target must adjust tgt_len here.
1878 */
Peter Maydell309786c2018-05-18 19:47:15 +01001879 tgt_len = len;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001880 switch (cmsg->cmsg_level) {
1881 case SOL_SOCKET:
1882 switch (cmsg->cmsg_type) {
1883 case SO_TIMESTAMP:
1884 tgt_len = sizeof(struct target_timeval);
1885 break;
1886 default:
1887 break;
1888 }
Peter Maydell309786c2018-05-18 19:47:15 +01001889 break;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001890 default:
1891 break;
1892 }
1893
Peter Maydell71749702017-12-15 13:52:55 +00001894 if (msg_controllen < TARGET_CMSG_LEN(tgt_len)) {
Peter Maydellc2aeb252015-05-26 19:46:31 +01001895 target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
Peter Maydell71749702017-12-15 13:52:55 +00001896 tgt_len = msg_controllen - sizeof(struct target_cmsghdr);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001897 }
1898
1899 /* We must now copy-and-convert len bytes of payload
1900 * into tgt_len bytes of destination space. Bear in mind
1901 * that in both source and destination we may be dealing
1902 * with a truncated value!
1903 */
Huw Davies52b65492014-04-17 14:02:47 +01001904 switch (cmsg->cmsg_level) {
1905 case SOL_SOCKET:
1906 switch (cmsg->cmsg_type) {
1907 case SCM_RIGHTS:
1908 {
1909 int *fd = (int *)data;
1910 int *target_fd = (int *)target_data;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001911 int i, numfds = tgt_len / sizeof(int);
bellard7854b052003-03-29 17:22:23 +00001912
Peter Maydell876e23c2015-05-26 19:46:32 +01001913 for (i = 0; i < numfds; i++) {
1914 __put_user(fd[i], target_fd + i);
1915 }
Huw Davies52b65492014-04-17 14:02:47 +01001916 break;
1917 }
1918 case SO_TIMESTAMP:
1919 {
1920 struct timeval *tv = (struct timeval *)data;
1921 struct target_timeval *target_tv =
1922 (struct target_timeval *)target_data;
Jing Huangaebf5bc2012-07-24 14:01:42 +00001923
Peter Maydellc2aeb252015-05-26 19:46:31 +01001924 if (len != sizeof(struct timeval) ||
1925 tgt_len != sizeof(struct target_timeval)) {
Huw Davies52b65492014-04-17 14:02:47 +01001926 goto unimplemented;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001927 }
Huw Davies52b65492014-04-17 14:02:47 +01001928
1929 /* copy struct timeval to target */
Peter Maydell876e23c2015-05-26 19:46:32 +01001930 __put_user(tv->tv_sec, &target_tv->tv_sec);
1931 __put_user(tv->tv_usec, &target_tv->tv_usec);
Huw Davies52b65492014-04-17 14:02:47 +01001932 break;
1933 }
Huw Davies4bc29752014-04-17 14:02:48 +01001934 case SCM_CREDENTIALS:
1935 {
1936 struct ucred *cred = (struct ucred *)data;
1937 struct target_ucred *target_cred =
1938 (struct target_ucred *)target_data;
1939
1940 __put_user(cred->pid, &target_cred->pid);
1941 __put_user(cred->uid, &target_cred->uid);
1942 __put_user(cred->gid, &target_cred->gid);
1943 break;
1944 }
Huw Davies52b65492014-04-17 14:02:47 +01001945 default:
1946 goto unimplemented;
1947 }
1948 break;
1949
Helge Delleree1ac3a2017-02-18 23:31:30 +01001950 case SOL_IP:
1951 switch (cmsg->cmsg_type) {
1952 case IP_TTL:
1953 {
1954 uint32_t *v = (uint32_t *)data;
1955 uint32_t *t_int = (uint32_t *)target_data;
1956
Peter Maydell71749702017-12-15 13:52:55 +00001957 if (len != sizeof(uint32_t) ||
1958 tgt_len != sizeof(uint32_t)) {
1959 goto unimplemented;
1960 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01001961 __put_user(*v, t_int);
1962 break;
1963 }
1964 case IP_RECVERR:
1965 {
1966 struct errhdr_t {
1967 struct sock_extended_err ee;
1968 struct sockaddr_in offender;
1969 };
1970 struct errhdr_t *errh = (struct errhdr_t *)data;
1971 struct errhdr_t *target_errh =
1972 (struct errhdr_t *)target_data;
1973
Peter Maydell71749702017-12-15 13:52:55 +00001974 if (len != sizeof(struct errhdr_t) ||
1975 tgt_len != sizeof(struct errhdr_t)) {
1976 goto unimplemented;
1977 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01001978 __put_user(errh->ee.ee_errno, &target_errh->ee.ee_errno);
1979 __put_user(errh->ee.ee_origin, &target_errh->ee.ee_origin);
1980 __put_user(errh->ee.ee_type, &target_errh->ee.ee_type);
1981 __put_user(errh->ee.ee_code, &target_errh->ee.ee_code);
1982 __put_user(errh->ee.ee_pad, &target_errh->ee.ee_pad);
1983 __put_user(errh->ee.ee_info, &target_errh->ee.ee_info);
1984 __put_user(errh->ee.ee_data, &target_errh->ee.ee_data);
1985 host_to_target_sockaddr((unsigned long) &target_errh->offender,
1986 (void *) &errh->offender, sizeof(errh->offender));
1987 break;
1988 }
1989 default:
1990 goto unimplemented;
1991 }
1992 break;
1993
1994 case SOL_IPV6:
1995 switch (cmsg->cmsg_type) {
1996 case IPV6_HOPLIMIT:
1997 {
1998 uint32_t *v = (uint32_t *)data;
1999 uint32_t *t_int = (uint32_t *)target_data;
2000
Peter Maydell71749702017-12-15 13:52:55 +00002001 if (len != sizeof(uint32_t) ||
2002 tgt_len != sizeof(uint32_t)) {
2003 goto unimplemented;
2004 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01002005 __put_user(*v, t_int);
2006 break;
2007 }
2008 case IPV6_RECVERR:
2009 {
2010 struct errhdr6_t {
2011 struct sock_extended_err ee;
2012 struct sockaddr_in6 offender;
2013 };
2014 struct errhdr6_t *errh = (struct errhdr6_t *)data;
2015 struct errhdr6_t *target_errh =
2016 (struct errhdr6_t *)target_data;
2017
Peter Maydell71749702017-12-15 13:52:55 +00002018 if (len != sizeof(struct errhdr6_t) ||
2019 tgt_len != sizeof(struct errhdr6_t)) {
2020 goto unimplemented;
2021 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01002022 __put_user(errh->ee.ee_errno, &target_errh->ee.ee_errno);
2023 __put_user(errh->ee.ee_origin, &target_errh->ee.ee_origin);
2024 __put_user(errh->ee.ee_type, &target_errh->ee.ee_type);
2025 __put_user(errh->ee.ee_code, &target_errh->ee.ee_code);
2026 __put_user(errh->ee.ee_pad, &target_errh->ee.ee_pad);
2027 __put_user(errh->ee.ee_info, &target_errh->ee.ee_info);
2028 __put_user(errh->ee.ee_data, &target_errh->ee.ee_data);
2029 host_to_target_sockaddr((unsigned long) &target_errh->offender,
2030 (void *) &errh->offender, sizeof(errh->offender));
2031 break;
2032 }
2033 default:
2034 goto unimplemented;
2035 }
2036 break;
2037
Huw Davies52b65492014-04-17 14:02:47 +01002038 default:
2039 unimplemented:
Josh Kunz39be5352020-02-03 18:54:13 -08002040 qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n",
2041 cmsg->cmsg_level, cmsg->cmsg_type);
Peter Maydellc2aeb252015-05-26 19:46:31 +01002042 memcpy(target_data, data, MIN(len, tgt_len));
2043 if (tgt_len > len) {
2044 memset(target_data + len, 0, tgt_len - len);
2045 }
bellard7854b052003-03-29 17:22:23 +00002046 }
2047
Peter Maydell71749702017-12-15 13:52:55 +00002048 target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(tgt_len));
2049 tgt_space = TARGET_CMSG_SPACE(tgt_len);
Peter Maydellc2aeb252015-05-26 19:46:31 +01002050 if (msg_controllen < tgt_space) {
2051 tgt_space = msg_controllen;
2052 }
2053 msg_controllen -= tgt_space;
2054 space += tgt_space;
bellard7854b052003-03-29 17:22:23 +00002055 cmsg = CMSG_NXTHDR(msgh, cmsg);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02002056 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg,
2057 target_cmsg_start);
bellard7854b052003-03-29 17:22:23 +00002058 }
bellard5a4a8982007-11-11 17:39:18 +00002059 unlock_user(target_cmsg, target_cmsg_addr, space);
2060 the_end:
Matthias Brauncbb21ee2011-08-12 19:57:41 +02002061 target_msgh->msg_controllen = tswapal(space);
bellard5a4a8982007-11-11 17:39:18 +00002062 return 0;
bellard7854b052003-03-29 17:22:23 +00002063}
2064
ths0da46a62007-10-20 20:23:07 +00002065/* do_setsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002066static abi_long do_setsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00002067 abi_ulong optval_addr, socklen_t optlen)
bellard7854b052003-03-29 17:22:23 +00002068{
blueswir1992f48a2007-10-14 16:27:31 +00002069 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +00002070 int val;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02002071 struct ip_mreqn *ip_mreq;
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02002072 struct ip_mreq_source *ip_mreq_source;
ths3b46e622007-09-17 08:09:54 +00002073
bellard8853f862004-02-22 14:57:26 +00002074 switch(level) {
2075 case SOL_TCP:
Shu-Chun Wengfe51b0a2020-12-18 11:32:11 -08002076 case SOL_UDP:
2077 /* TCP and UDP options all take an 'int' value. */
bellard7854b052003-03-29 17:22:23 +00002078 if (optlen < sizeof(uint32_t))
ths0da46a62007-10-20 20:23:07 +00002079 return -TARGET_EINVAL;
ths3b46e622007-09-17 08:09:54 +00002080
bellard2f619692007-11-16 10:46:05 +00002081 if (get_user_u32(val, optval_addr))
2082 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00002083 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
2084 break;
2085 case SOL_IP:
2086 switch(optname) {
bellard2efbe912005-07-23 15:10:20 +00002087 case IP_TOS:
2088 case IP_TTL:
bellard8853f862004-02-22 14:57:26 +00002089 case IP_HDRINCL:
bellard2efbe912005-07-23 15:10:20 +00002090 case IP_ROUTER_ALERT:
2091 case IP_RECVOPTS:
2092 case IP_RETOPTS:
2093 case IP_PKTINFO:
2094 case IP_MTU_DISCOVER:
2095 case IP_RECVERR:
Helge Delleree1ac3a2017-02-18 23:31:30 +01002096 case IP_RECVTTL:
bellard2efbe912005-07-23 15:10:20 +00002097 case IP_RECVTOS:
2098#ifdef IP_FREEBIND
2099 case IP_FREEBIND:
2100#endif
2101 case IP_MULTICAST_TTL:
2102 case IP_MULTICAST_LOOP:
bellard8853f862004-02-22 14:57:26 +00002103 val = 0;
2104 if (optlen >= sizeof(uint32_t)) {
bellard2f619692007-11-16 10:46:05 +00002105 if (get_user_u32(val, optval_addr))
2106 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00002107 } else if (optlen >= 1) {
bellard2f619692007-11-16 10:46:05 +00002108 if (get_user_u8(val, optval_addr))
2109 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00002110 }
2111 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
2112 break;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02002113 case IP_ADD_MEMBERSHIP:
2114 case IP_DROP_MEMBERSHIP:
2115 if (optlen < sizeof (struct target_ip_mreq) ||
2116 optlen > sizeof (struct target_ip_mreqn))
2117 return -TARGET_EINVAL;
2118
2119 ip_mreq = (struct ip_mreqn *) alloca(optlen);
2120 target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
2121 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen));
2122 break;
2123
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02002124 case IP_BLOCK_SOURCE:
2125 case IP_UNBLOCK_SOURCE:
2126 case IP_ADD_SOURCE_MEMBERSHIP:
2127 case IP_DROP_SOURCE_MEMBERSHIP:
2128 if (optlen != sizeof (struct target_ip_mreq_source))
2129 return -TARGET_EINVAL;
2130
2131 ip_mreq_source = lock_user(VERIFY_READ, optval_addr, optlen, 1);
Peter Maydell74e43b02021-08-09 16:54:24 +01002132 if (!ip_mreq_source) {
2133 return -TARGET_EFAULT;
2134 }
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02002135 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen));
2136 unlock_user (ip_mreq_source, optval_addr, 0);
2137 break;
2138
bellard8853f862004-02-22 14:57:26 +00002139 default:
2140 goto unimplemented;
2141 }
2142 break;
Laurent Vivier0d78b3b2013-08-30 01:46:43 +02002143 case SOL_IPV6:
2144 switch (optname) {
2145 case IPV6_MTU_DISCOVER:
2146 case IPV6_MTU:
2147 case IPV6_V6ONLY:
2148 case IPV6_RECVPKTINFO:
Helge Delleree1ac3a2017-02-18 23:31:30 +01002149 case IPV6_UNICAST_HOPS:
Laurent Vivier21749c42018-06-27 23:21:52 +02002150 case IPV6_MULTICAST_HOPS:
2151 case IPV6_MULTICAST_LOOP:
Helge Delleree1ac3a2017-02-18 23:31:30 +01002152 case IPV6_RECVERR:
2153 case IPV6_RECVHOPLIMIT:
2154 case IPV6_2292HOPLIMIT:
2155 case IPV6_CHECKSUM:
Helge Dellerb9cce6d2019-03-10 12:12:16 +01002156 case IPV6_ADDRFORM:
2157 case IPV6_2292PKTINFO:
2158 case IPV6_RECVTCLASS:
2159 case IPV6_RECVRTHDR:
2160 case IPV6_2292RTHDR:
2161 case IPV6_RECVHOPOPTS:
2162 case IPV6_2292HOPOPTS:
2163 case IPV6_RECVDSTOPTS:
2164 case IPV6_2292DSTOPTS:
2165 case IPV6_TCLASS:
Shu-Chun Weng22db1212020-12-18 11:32:12 -08002166 case IPV6_ADDR_PREFERENCES:
Helge Dellerb9cce6d2019-03-10 12:12:16 +01002167#ifdef IPV6_RECVPATHMTU
2168 case IPV6_RECVPATHMTU:
2169#endif
2170#ifdef IPV6_TRANSPARENT
2171 case IPV6_TRANSPARENT:
2172#endif
2173#ifdef IPV6_FREEBIND
2174 case IPV6_FREEBIND:
2175#endif
2176#ifdef IPV6_RECVORIGDSTADDR
2177 case IPV6_RECVORIGDSTADDR:
2178#endif
Laurent Vivier0d78b3b2013-08-30 01:46:43 +02002179 val = 0;
2180 if (optlen < sizeof(uint32_t)) {
2181 return -TARGET_EINVAL;
2182 }
2183 if (get_user_u32(val, optval_addr)) {
2184 return -TARGET_EFAULT;
2185 }
2186 ret = get_errno(setsockopt(sockfd, level, optname,
2187 &val, sizeof(val)));
2188 break;
Helge Delleree1ac3a2017-02-18 23:31:30 +01002189 case IPV6_PKTINFO:
2190 {
2191 struct in6_pktinfo pki;
2192
2193 if (optlen < sizeof(pki)) {
2194 return -TARGET_EINVAL;
2195 }
2196
2197 if (copy_from_user(&pki, optval_addr, sizeof(pki))) {
2198 return -TARGET_EFAULT;
2199 }
2200
2201 pki.ipi6_ifindex = tswap32(pki.ipi6_ifindex);
2202
2203 ret = get_errno(setsockopt(sockfd, level, optname,
2204 &pki, sizeof(pki)));
2205 break;
2206 }
Neng Chen22bf4ee2019-06-19 16:17:10 +02002207 case IPV6_ADD_MEMBERSHIP:
2208 case IPV6_DROP_MEMBERSHIP:
2209 {
2210 struct ipv6_mreq ipv6mreq;
2211
2212 if (optlen < sizeof(ipv6mreq)) {
2213 return -TARGET_EINVAL;
2214 }
2215
2216 if (copy_from_user(&ipv6mreq, optval_addr, sizeof(ipv6mreq))) {
2217 return -TARGET_EFAULT;
2218 }
2219
2220 ipv6mreq.ipv6mr_interface = tswap32(ipv6mreq.ipv6mr_interface);
2221
2222 ret = get_errno(setsockopt(sockfd, level, optname,
2223 &ipv6mreq, sizeof(ipv6mreq)));
2224 break;
2225 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01002226 default:
2227 goto unimplemented;
2228 }
2229 break;
2230 case SOL_ICMPV6:
2231 switch (optname) {
2232 case ICMPV6_FILTER:
2233 {
2234 struct icmp6_filter icmp6f;
2235
2236 if (optlen > sizeof(icmp6f)) {
2237 optlen = sizeof(icmp6f);
2238 }
2239
2240 if (copy_from_user(&icmp6f, optval_addr, optlen)) {
2241 return -TARGET_EFAULT;
2242 }
2243
2244 for (val = 0; val < 8; val++) {
2245 icmp6f.data[val] = tswap32(icmp6f.data[val]);
2246 }
2247
2248 ret = get_errno(setsockopt(sockfd, level, optname,
2249 &icmp6f, optlen));
2250 break;
2251 }
Laurent Vivier0d78b3b2013-08-30 01:46:43 +02002252 default:
2253 goto unimplemented;
2254 }
2255 break;
Jing Huang920394d2012-07-24 13:59:23 +00002256 case SOL_RAW:
2257 switch (optname) {
2258 case ICMP_FILTER:
Helge Delleree1ac3a2017-02-18 23:31:30 +01002259 case IPV6_CHECKSUM:
2260 /* those take an u32 value */
Jing Huang920394d2012-07-24 13:59:23 +00002261 if (optlen < sizeof(uint32_t)) {
2262 return -TARGET_EINVAL;
2263 }
2264
2265 if (get_user_u32(val, optval_addr)) {
2266 return -TARGET_EFAULT;
2267 }
2268 ret = get_errno(setsockopt(sockfd, level, optname,
2269 &val, sizeof(val)));
2270 break;
2271
2272 default:
2273 goto unimplemented;
2274 }
2275 break;
Yunqiang Suf31dddd2019-06-19 16:17:11 +02002276#if defined(SOL_ALG) && defined(ALG_SET_KEY) && defined(ALG_SET_AEAD_AUTHSIZE)
2277 case SOL_ALG:
2278 switch (optname) {
2279 case ALG_SET_KEY:
2280 {
2281 char *alg_key = g_malloc(optlen);
2282
2283 if (!alg_key) {
2284 return -TARGET_ENOMEM;
2285 }
2286 if (copy_from_user(alg_key, optval_addr, optlen)) {
2287 g_free(alg_key);
2288 return -TARGET_EFAULT;
2289 }
2290 ret = get_errno(setsockopt(sockfd, level, optname,
2291 alg_key, optlen));
2292 g_free(alg_key);
2293 break;
2294 }
2295 case ALG_SET_AEAD_AUTHSIZE:
2296 {
2297 ret = get_errno(setsockopt(sockfd, level, optname,
2298 NULL, optlen));
2299 break;
2300 }
2301 default:
2302 goto unimplemented;
2303 }
2304 break;
2305#endif
bellard3532fa72006-06-24 15:06:03 +00002306 case TARGET_SOL_SOCKET:
bellard8853f862004-02-22 14:57:26 +00002307 switch (optname) {
Laurent Vivier1b09aeb2013-01-01 08:24:11 +00002308 case TARGET_SO_RCVTIMEO:
2309 {
2310 struct timeval tv;
2311
2312 optname = SO_RCVTIMEO;
2313
2314set_timeout:
2315 if (optlen != sizeof(struct target_timeval)) {
2316 return -TARGET_EINVAL;
2317 }
2318
2319 if (copy_from_user_timeval(&tv, optval_addr)) {
2320 return -TARGET_EFAULT;
2321 }
2322
2323 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
2324 &tv, sizeof(tv)));
2325 return ret;
2326 }
2327 case TARGET_SO_SNDTIMEO:
2328 optname = SO_SNDTIMEO;
2329 goto set_timeout;
Laurent Vivierf57d4192013-08-30 01:46:41 +02002330 case TARGET_SO_ATTACH_FILTER:
2331 {
2332 struct target_sock_fprog *tfprog;
2333 struct target_sock_filter *tfilter;
2334 struct sock_fprog fprog;
2335 struct sock_filter *filter;
2336 int i;
2337
2338 if (optlen != sizeof(*tfprog)) {
2339 return -TARGET_EINVAL;
2340 }
2341 if (!lock_user_struct(VERIFY_READ, tfprog, optval_addr, 0)) {
2342 return -TARGET_EFAULT;
2343 }
2344 if (!lock_user_struct(VERIFY_READ, tfilter,
2345 tswapal(tfprog->filter), 0)) {
2346 unlock_user_struct(tfprog, optval_addr, 1);
2347 return -TARGET_EFAULT;
2348 }
2349
2350 fprog.len = tswap16(tfprog->len);
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05302351 filter = g_try_new(struct sock_filter, fprog.len);
Laurent Vivierf57d4192013-08-30 01:46:41 +02002352 if (filter == NULL) {
2353 unlock_user_struct(tfilter, tfprog->filter, 1);
2354 unlock_user_struct(tfprog, optval_addr, 1);
2355 return -TARGET_ENOMEM;
2356 }
2357 for (i = 0; i < fprog.len; i++) {
2358 filter[i].code = tswap16(tfilter[i].code);
2359 filter[i].jt = tfilter[i].jt;
2360 filter[i].jf = tfilter[i].jf;
2361 filter[i].k = tswap32(tfilter[i].k);
2362 }
2363 fprog.filter = filter;
2364
2365 ret = get_errno(setsockopt(sockfd, SOL_SOCKET,
2366 SO_ATTACH_FILTER, &fprog, sizeof(fprog)));
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05302367 g_free(filter);
Laurent Vivierf57d4192013-08-30 01:46:41 +02002368
2369 unlock_user_struct(tfilter, tfprog->filter, 1);
2370 unlock_user_struct(tfprog, optval_addr, 1);
2371 return ret;
2372 }
Joakim Tjernlund451aaf62014-07-12 15:47:06 +02002373 case TARGET_SO_BINDTODEVICE:
2374 {
2375 char *dev_ifname, *addr_ifname;
2376
2377 if (optlen > IFNAMSIZ - 1) {
2378 optlen = IFNAMSIZ - 1;
2379 }
2380 dev_ifname = lock_user(VERIFY_READ, optval_addr, optlen, 1);
2381 if (!dev_ifname) {
2382 return -TARGET_EFAULT;
2383 }
2384 optname = SO_BINDTODEVICE;
2385 addr_ifname = alloca(IFNAMSIZ);
2386 memcpy(addr_ifname, dev_ifname, optlen);
2387 addr_ifname[optlen] = 0;
Chen Gangfad6c582016-01-11 13:58:50 +08002388 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
2389 addr_ifname, optlen));
Joakim Tjernlund451aaf62014-07-12 15:47:06 +02002390 unlock_user (dev_ifname, optval_addr, 0);
2391 return ret;
2392 }
Carlo Marcelo Arenas Belón83eb6e52018-08-24 01:56:01 -07002393 case TARGET_SO_LINGER:
2394 {
2395 struct linger lg;
2396 struct target_linger *tlg;
2397
2398 if (optlen != sizeof(struct target_linger)) {
2399 return -TARGET_EINVAL;
2400 }
2401 if (!lock_user_struct(VERIFY_READ, tlg, optval_addr, 1)) {
2402 return -TARGET_EFAULT;
2403 }
2404 __get_user(lg.l_onoff, &tlg->l_onoff);
2405 __get_user(lg.l_linger, &tlg->l_linger);
2406 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, SO_LINGER,
2407 &lg, sizeof(lg)));
2408 unlock_user_struct(tlg, optval_addr, 0);
2409 return ret;
2410 }
bellard8853f862004-02-22 14:57:26 +00002411 /* Options with 'int' argument. */
bellard3532fa72006-06-24 15:06:03 +00002412 case TARGET_SO_DEBUG:
2413 optname = SO_DEBUG;
2414 break;
2415 case TARGET_SO_REUSEADDR:
2416 optname = SO_REUSEADDR;
2417 break;
Yunqiang Su113a9dd2018-10-30 13:55:08 +01002418#ifdef SO_REUSEPORT
2419 case TARGET_SO_REUSEPORT:
2420 optname = SO_REUSEPORT;
2421 break;
2422#endif
bellard3532fa72006-06-24 15:06:03 +00002423 case TARGET_SO_TYPE:
2424 optname = SO_TYPE;
2425 break;
2426 case TARGET_SO_ERROR:
2427 optname = SO_ERROR;
2428 break;
2429 case TARGET_SO_DONTROUTE:
2430 optname = SO_DONTROUTE;
2431 break;
2432 case TARGET_SO_BROADCAST:
2433 optname = SO_BROADCAST;
2434 break;
2435 case TARGET_SO_SNDBUF:
2436 optname = SO_SNDBUF;
2437 break;
Paul Burtond79b6cc2014-06-22 11:25:35 +01002438 case TARGET_SO_SNDBUFFORCE:
2439 optname = SO_SNDBUFFORCE;
2440 break;
bellard3532fa72006-06-24 15:06:03 +00002441 case TARGET_SO_RCVBUF:
2442 optname = SO_RCVBUF;
2443 break;
Paul Burtond79b6cc2014-06-22 11:25:35 +01002444 case TARGET_SO_RCVBUFFORCE:
2445 optname = SO_RCVBUFFORCE;
2446 break;
bellard3532fa72006-06-24 15:06:03 +00002447 case TARGET_SO_KEEPALIVE:
2448 optname = SO_KEEPALIVE;
2449 break;
2450 case TARGET_SO_OOBINLINE:
2451 optname = SO_OOBINLINE;
2452 break;
2453 case TARGET_SO_NO_CHECK:
2454 optname = SO_NO_CHECK;
2455 break;
2456 case TARGET_SO_PRIORITY:
2457 optname = SO_PRIORITY;
2458 break;
bellard5e83e8e2005-03-01 22:32:06 +00002459#ifdef SO_BSDCOMPAT
bellard3532fa72006-06-24 15:06:03 +00002460 case TARGET_SO_BSDCOMPAT:
2461 optname = SO_BSDCOMPAT;
2462 break;
bellard5e83e8e2005-03-01 22:32:06 +00002463#endif
bellard3532fa72006-06-24 15:06:03 +00002464 case TARGET_SO_PASSCRED:
2465 optname = SO_PASSCRED;
2466 break;
Paul Burton82d0fe62014-06-22 11:25:36 +01002467 case TARGET_SO_PASSSEC:
2468 optname = SO_PASSSEC;
2469 break;
bellard3532fa72006-06-24 15:06:03 +00002470 case TARGET_SO_TIMESTAMP:
2471 optname = SO_TIMESTAMP;
2472 break;
2473 case TARGET_SO_RCVLOWAT:
2474 optname = SO_RCVLOWAT;
2475 break;
bellard8853f862004-02-22 14:57:26 +00002476 default:
2477 goto unimplemented;
2478 }
bellard3532fa72006-06-24 15:06:03 +00002479 if (optlen < sizeof(uint32_t))
bellard2f619692007-11-16 10:46:05 +00002480 return -TARGET_EINVAL;
bellard3532fa72006-06-24 15:06:03 +00002481
bellard2f619692007-11-16 10:46:05 +00002482 if (get_user_u32(val, optval_addr))
2483 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00002484 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
bellard8853f862004-02-22 14:57:26 +00002485 break;
Josh Kunza2d86682019-10-29 15:43:10 -07002486#ifdef SOL_NETLINK
2487 case SOL_NETLINK:
2488 switch (optname) {
2489 case NETLINK_PKTINFO:
2490 case NETLINK_ADD_MEMBERSHIP:
2491 case NETLINK_DROP_MEMBERSHIP:
2492 case NETLINK_BROADCAST_ERROR:
2493 case NETLINK_NO_ENOBUFS:
2494#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2495 case NETLINK_LISTEN_ALL_NSID:
2496 case NETLINK_CAP_ACK:
2497#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2498#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
2499 case NETLINK_EXT_ACK:
2500#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2501#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
2502 case NETLINK_GET_STRICT_CHK:
2503#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2504 break;
2505 default:
2506 goto unimplemented;
2507 }
2508 val = 0;
2509 if (optlen < sizeof(uint32_t)) {
2510 return -TARGET_EINVAL;
2511 }
2512 if (get_user_u32(val, optval_addr)) {
2513 return -TARGET_EFAULT;
2514 }
2515 ret = get_errno(setsockopt(sockfd, SOL_NETLINK, optname, &val,
2516 sizeof(val)));
2517 break;
2518#endif /* SOL_NETLINK */
bellard7854b052003-03-29 17:22:23 +00002519 default:
bellard8853f862004-02-22 14:57:26 +00002520 unimplemented:
Josh Kunz39be5352020-02-03 18:54:13 -08002521 qemu_log_mask(LOG_UNIMP, "Unsupported setsockopt level=%d optname=%d\n",
2522 level, optname);
ths6fa13c12007-12-18 02:41:04 +00002523 ret = -TARGET_ENOPROTOOPT;
bellard7854b052003-03-29 17:22:23 +00002524 }
bellard8853f862004-02-22 14:57:26 +00002525 return ret;
bellard7854b052003-03-29 17:22:23 +00002526}
2527
ths0da46a62007-10-20 20:23:07 +00002528/* do_getsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002529static abi_long do_getsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00002530 abi_ulong optval_addr, abi_ulong optlen)
bellard7854b052003-03-29 17:22:23 +00002531{
blueswir1992f48a2007-10-14 16:27:31 +00002532 abi_long ret;
blueswir1b55266b2008-09-20 08:07:15 +00002533 int len, val;
2534 socklen_t lv;
bellard8853f862004-02-22 14:57:26 +00002535
2536 switch(level) {
bellard3532fa72006-06-24 15:06:03 +00002537 case TARGET_SOL_SOCKET:
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002538 level = SOL_SOCKET;
2539 switch (optname) {
2540 /* These don't just return a single integer */
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002541 case TARGET_SO_PEERNAME:
2542 goto unimplemented;
Andreas Schwab405dc4c2019-05-13 11:06:26 +02002543 case TARGET_SO_RCVTIMEO: {
2544 struct timeval tv;
2545 socklen_t tvlen;
2546
2547 optname = SO_RCVTIMEO;
2548
2549get_timeout:
2550 if (get_user_u32(len, optlen)) {
2551 return -TARGET_EFAULT;
2552 }
2553 if (len < 0) {
2554 return -TARGET_EINVAL;
2555 }
2556
2557 tvlen = sizeof(tv);
2558 ret = get_errno(getsockopt(sockfd, level, optname,
2559 &tv, &tvlen));
2560 if (ret < 0) {
2561 return ret;
2562 }
2563 if (len > sizeof(struct target_timeval)) {
2564 len = sizeof(struct target_timeval);
2565 }
2566 if (copy_to_user_timeval(optval_addr, &tv)) {
2567 return -TARGET_EFAULT;
2568 }
2569 if (put_user_u32(len, optlen)) {
2570 return -TARGET_EFAULT;
2571 }
2572 break;
2573 }
2574 case TARGET_SO_SNDTIMEO:
2575 optname = SO_SNDTIMEO;
2576 goto get_timeout;
Akos PASZTORY583359a2011-11-14 15:09:49 +02002577 case TARGET_SO_PEERCRED: {
2578 struct ucred cr;
2579 socklen_t crlen;
2580 struct target_ucred *tcr;
2581
2582 if (get_user_u32(len, optlen)) {
2583 return -TARGET_EFAULT;
2584 }
2585 if (len < 0) {
2586 return -TARGET_EINVAL;
2587 }
2588
2589 crlen = sizeof(cr);
2590 ret = get_errno(getsockopt(sockfd, level, SO_PEERCRED,
2591 &cr, &crlen));
2592 if (ret < 0) {
2593 return ret;
2594 }
2595 if (len > crlen) {
2596 len = crlen;
2597 }
2598 if (!lock_user_struct(VERIFY_WRITE, tcr, optval_addr, 0)) {
2599 return -TARGET_EFAULT;
2600 }
2601 __put_user(cr.pid, &tcr->pid);
2602 __put_user(cr.uid, &tcr->uid);
2603 __put_user(cr.gid, &tcr->gid);
2604 unlock_user_struct(tcr, optval_addr, 1);
2605 if (put_user_u32(len, optlen)) {
2606 return -TARGET_EFAULT;
2607 }
2608 break;
2609 }
Laurent Vivier6d485a52020-02-04 22:19:01 +01002610 case TARGET_SO_PEERSEC: {
2611 char *name;
2612
2613 if (get_user_u32(len, optlen)) {
2614 return -TARGET_EFAULT;
2615 }
2616 if (len < 0) {
2617 return -TARGET_EINVAL;
2618 }
2619 name = lock_user(VERIFY_WRITE, optval_addr, len, 0);
2620 if (!name) {
2621 return -TARGET_EFAULT;
2622 }
2623 lv = len;
2624 ret = get_errno(getsockopt(sockfd, level, SO_PEERSEC,
2625 name, &lv));
2626 if (put_user_u32(lv, optlen)) {
2627 ret = -TARGET_EFAULT;
2628 }
2629 unlock_user(name, optval_addr, lv);
2630 break;
2631 }
Carlo Marcelo Arenas Belón83eb6e52018-08-24 01:56:01 -07002632 case TARGET_SO_LINGER:
2633 {
2634 struct linger lg;
2635 socklen_t lglen;
2636 struct target_linger *tlg;
2637
2638 if (get_user_u32(len, optlen)) {
2639 return -TARGET_EFAULT;
2640 }
2641 if (len < 0) {
2642 return -TARGET_EINVAL;
2643 }
2644
2645 lglen = sizeof(lg);
2646 ret = get_errno(getsockopt(sockfd, level, SO_LINGER,
2647 &lg, &lglen));
2648 if (ret < 0) {
2649 return ret;
2650 }
2651 if (len > lglen) {
2652 len = lglen;
2653 }
2654 if (!lock_user_struct(VERIFY_WRITE, tlg, optval_addr, 0)) {
2655 return -TARGET_EFAULT;
2656 }
2657 __put_user(lg.l_onoff, &tlg->l_onoff);
2658 __put_user(lg.l_linger, &tlg->l_linger);
2659 unlock_user_struct(tlg, optval_addr, 1);
2660 if (put_user_u32(len, optlen)) {
2661 return -TARGET_EFAULT;
2662 }
2663 break;
2664 }
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002665 /* Options with 'int' argument. */
2666 case TARGET_SO_DEBUG:
2667 optname = SO_DEBUG;
2668 goto int_case;
2669 case TARGET_SO_REUSEADDR:
2670 optname = SO_REUSEADDR;
2671 goto int_case;
Yunqiang Su113a9dd2018-10-30 13:55:08 +01002672#ifdef SO_REUSEPORT
2673 case TARGET_SO_REUSEPORT:
2674 optname = SO_REUSEPORT;
2675 goto int_case;
2676#endif
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002677 case TARGET_SO_TYPE:
2678 optname = SO_TYPE;
2679 goto int_case;
2680 case TARGET_SO_ERROR:
2681 optname = SO_ERROR;
2682 goto int_case;
2683 case TARGET_SO_DONTROUTE:
2684 optname = SO_DONTROUTE;
2685 goto int_case;
2686 case TARGET_SO_BROADCAST:
2687 optname = SO_BROADCAST;
2688 goto int_case;
2689 case TARGET_SO_SNDBUF:
2690 optname = SO_SNDBUF;
2691 goto int_case;
2692 case TARGET_SO_RCVBUF:
2693 optname = SO_RCVBUF;
2694 goto int_case;
2695 case TARGET_SO_KEEPALIVE:
2696 optname = SO_KEEPALIVE;
2697 goto int_case;
2698 case TARGET_SO_OOBINLINE:
2699 optname = SO_OOBINLINE;
2700 goto int_case;
2701 case TARGET_SO_NO_CHECK:
2702 optname = SO_NO_CHECK;
2703 goto int_case;
2704 case TARGET_SO_PRIORITY:
2705 optname = SO_PRIORITY;
2706 goto int_case;
2707#ifdef SO_BSDCOMPAT
2708 case TARGET_SO_BSDCOMPAT:
2709 optname = SO_BSDCOMPAT;
2710 goto int_case;
2711#endif
2712 case TARGET_SO_PASSCRED:
2713 optname = SO_PASSCRED;
2714 goto int_case;
2715 case TARGET_SO_TIMESTAMP:
2716 optname = SO_TIMESTAMP;
2717 goto int_case;
2718 case TARGET_SO_RCVLOWAT:
2719 optname = SO_RCVLOWAT;
2720 goto int_case;
Paul Burtonaec1ca42014-06-22 11:25:34 +01002721 case TARGET_SO_ACCEPTCONN:
2722 optname = SO_ACCEPTCONN;
2723 goto int_case;
Jason A. Donenfeldec63e062021-02-04 16:39:25 +01002724 case TARGET_SO_PROTOCOL:
2725 optname = SO_PROTOCOL;
2726 goto int_case;
2727 case TARGET_SO_DOMAIN:
2728 optname = SO_DOMAIN;
2729 goto int_case;
bellard8853f862004-02-22 14:57:26 +00002730 default:
bellard2efbe912005-07-23 15:10:20 +00002731 goto int_case;
2732 }
2733 break;
2734 case SOL_TCP:
Shu-Chun Wengfe51b0a2020-12-18 11:32:11 -08002735 case SOL_UDP:
2736 /* TCP and UDP options all take an 'int' value. */
bellard2efbe912005-07-23 15:10:20 +00002737 int_case:
bellard2f619692007-11-16 10:46:05 +00002738 if (get_user_u32(len, optlen))
2739 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002740 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00002741 return -TARGET_EINVAL;
Mike Frysinger73160d92011-02-07 01:05:49 -05002742 lv = sizeof(lv);
bellard2efbe912005-07-23 15:10:20 +00002743 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2744 if (ret < 0)
2745 return ret;
Paul Burton8289d112014-06-22 11:25:33 +01002746 if (optname == SO_TYPE) {
2747 val = host_to_target_sock_type(val);
2748 }
bellard2efbe912005-07-23 15:10:20 +00002749 if (len > lv)
2750 len = lv;
bellard2f619692007-11-16 10:46:05 +00002751 if (len == 4) {
2752 if (put_user_u32(val, optval_addr))
2753 return -TARGET_EFAULT;
2754 } else {
2755 if (put_user_u8(val, optval_addr))
2756 return -TARGET_EFAULT;
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002757 }
bellard2f619692007-11-16 10:46:05 +00002758 if (put_user_u32(len, optlen))
2759 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002760 break;
2761 case SOL_IP:
2762 switch(optname) {
2763 case IP_TOS:
2764 case IP_TTL:
2765 case IP_HDRINCL:
2766 case IP_ROUTER_ALERT:
2767 case IP_RECVOPTS:
2768 case IP_RETOPTS:
2769 case IP_PKTINFO:
2770 case IP_MTU_DISCOVER:
2771 case IP_RECVERR:
2772 case IP_RECVTOS:
2773#ifdef IP_FREEBIND
2774 case IP_FREEBIND:
2775#endif
2776 case IP_MULTICAST_TTL:
2777 case IP_MULTICAST_LOOP:
bellard2f619692007-11-16 10:46:05 +00002778 if (get_user_u32(len, optlen))
2779 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00002780 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00002781 return -TARGET_EINVAL;
Mike Frysinger73160d92011-02-07 01:05:49 -05002782 lv = sizeof(lv);
bellard8853f862004-02-22 14:57:26 +00002783 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2784 if (ret < 0)
2785 return ret;
bellard2efbe912005-07-23 15:10:20 +00002786 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
bellard2efbe912005-07-23 15:10:20 +00002787 len = 1;
bellard2f619692007-11-16 10:46:05 +00002788 if (put_user_u32(len, optlen)
2789 || put_user_u8(val, optval_addr))
2790 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002791 } else {
bellard2efbe912005-07-23 15:10:20 +00002792 if (len > sizeof(int))
2793 len = sizeof(int);
bellard2f619692007-11-16 10:46:05 +00002794 if (put_user_u32(len, optlen)
2795 || put_user_u32(val, optval_addr))
2796 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002797 }
bellard8853f862004-02-22 14:57:26 +00002798 break;
bellard2efbe912005-07-23 15:10:20 +00002799 default:
thsc02f4992007-12-18 02:39:59 +00002800 ret = -TARGET_ENOPROTOOPT;
2801 break;
bellard8853f862004-02-22 14:57:26 +00002802 }
2803 break;
Tom Deseynbd8ed482018-12-13 14:06:11 +01002804 case SOL_IPV6:
2805 switch (optname) {
2806 case IPV6_MTU_DISCOVER:
2807 case IPV6_MTU:
2808 case IPV6_V6ONLY:
2809 case IPV6_RECVPKTINFO:
2810 case IPV6_UNICAST_HOPS:
2811 case IPV6_MULTICAST_HOPS:
2812 case IPV6_MULTICAST_LOOP:
2813 case IPV6_RECVERR:
2814 case IPV6_RECVHOPLIMIT:
2815 case IPV6_2292HOPLIMIT:
2816 case IPV6_CHECKSUM:
Helge Dellerb9cce6d2019-03-10 12:12:16 +01002817 case IPV6_ADDRFORM:
2818 case IPV6_2292PKTINFO:
2819 case IPV6_RECVTCLASS:
2820 case IPV6_RECVRTHDR:
2821 case IPV6_2292RTHDR:
2822 case IPV6_RECVHOPOPTS:
2823 case IPV6_2292HOPOPTS:
2824 case IPV6_RECVDSTOPTS:
2825 case IPV6_2292DSTOPTS:
2826 case IPV6_TCLASS:
Shu-Chun Weng22db1212020-12-18 11:32:12 -08002827 case IPV6_ADDR_PREFERENCES:
Helge Dellerb9cce6d2019-03-10 12:12:16 +01002828#ifdef IPV6_RECVPATHMTU
2829 case IPV6_RECVPATHMTU:
2830#endif
2831#ifdef IPV6_TRANSPARENT
2832 case IPV6_TRANSPARENT:
2833#endif
2834#ifdef IPV6_FREEBIND
2835 case IPV6_FREEBIND:
2836#endif
2837#ifdef IPV6_RECVORIGDSTADDR
2838 case IPV6_RECVORIGDSTADDR:
2839#endif
Tom Deseynbd8ed482018-12-13 14:06:11 +01002840 if (get_user_u32(len, optlen))
2841 return -TARGET_EFAULT;
2842 if (len < 0)
2843 return -TARGET_EINVAL;
2844 lv = sizeof(lv);
2845 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2846 if (ret < 0)
2847 return ret;
2848 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
2849 len = 1;
2850 if (put_user_u32(len, optlen)
2851 || put_user_u8(val, optval_addr))
2852 return -TARGET_EFAULT;
2853 } else {
2854 if (len > sizeof(int))
2855 len = sizeof(int);
2856 if (put_user_u32(len, optlen)
2857 || put_user_u32(val, optval_addr))
2858 return -TARGET_EFAULT;
2859 }
2860 break;
2861 default:
2862 ret = -TARGET_ENOPROTOOPT;
2863 break;
2864 }
2865 break;
Josh Kunza2d86682019-10-29 15:43:10 -07002866#ifdef SOL_NETLINK
2867 case SOL_NETLINK:
2868 switch (optname) {
2869 case NETLINK_PKTINFO:
2870 case NETLINK_BROADCAST_ERROR:
2871 case NETLINK_NO_ENOBUFS:
2872#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2873 case NETLINK_LISTEN_ALL_NSID:
2874 case NETLINK_CAP_ACK:
2875#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2876#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
2877 case NETLINK_EXT_ACK:
2878#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2879#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
2880 case NETLINK_GET_STRICT_CHK:
2881#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2882 if (get_user_u32(len, optlen)) {
2883 return -TARGET_EFAULT;
2884 }
2885 if (len != sizeof(val)) {
2886 return -TARGET_EINVAL;
2887 }
2888 lv = len;
2889 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2890 if (ret < 0) {
2891 return ret;
2892 }
2893 if (put_user_u32(lv, optlen)
2894 || put_user_u32(val, optval_addr)) {
2895 return -TARGET_EFAULT;
2896 }
2897 break;
2898#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2899 case NETLINK_LIST_MEMBERSHIPS:
2900 {
2901 uint32_t *results;
2902 int i;
2903 if (get_user_u32(len, optlen)) {
2904 return -TARGET_EFAULT;
2905 }
2906 if (len < 0) {
2907 return -TARGET_EINVAL;
2908 }
2909 results = lock_user(VERIFY_WRITE, optval_addr, len, 1);
Frédéric Fortier13e340c2021-03-28 14:01:35 -04002910 if (!results && len > 0) {
Josh Kunza2d86682019-10-29 15:43:10 -07002911 return -TARGET_EFAULT;
2912 }
2913 lv = len;
2914 ret = get_errno(getsockopt(sockfd, level, optname, results, &lv));
2915 if (ret < 0) {
2916 unlock_user(results, optval_addr, 0);
2917 return ret;
2918 }
2919 /* swap host endianess to target endianess. */
2920 for (i = 0; i < (len / sizeof(uint32_t)); i++) {
2921 results[i] = tswap32(results[i]);
2922 }
2923 if (put_user_u32(lv, optlen)) {
2924 return -TARGET_EFAULT;
2925 }
2926 unlock_user(results, optval_addr, 0);
2927 break;
2928 }
2929#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2930 default:
2931 goto unimplemented;
2932 }
Laurent Vivierc0cb8802019-11-12 11:50:55 +01002933 break;
Josh Kunza2d86682019-10-29 15:43:10 -07002934#endif /* SOL_NETLINK */
bellard8853f862004-02-22 14:57:26 +00002935 default:
2936 unimplemented:
Josh Kunz39be5352020-02-03 18:54:13 -08002937 qemu_log_mask(LOG_UNIMP,
2938 "getsockopt level=%d optname=%d not yet supported\n",
2939 level, optname);
thsc02f4992007-12-18 02:39:59 +00002940 ret = -TARGET_EOPNOTSUPP;
bellard8853f862004-02-22 14:57:26 +00002941 break;
2942 }
2943 return ret;
bellard7854b052003-03-29 17:22:23 +00002944}
2945
Max Filippov9ac22512018-04-04 17:30:41 -07002946/* Convert target low/high pair representing file offset into the host
2947 * low/high pair. This function doesn't handle offsets bigger than 64 bits
2948 * as the kernel doesn't handle them either.
2949 */
2950static void target_to_host_low_high(abi_ulong tlow,
2951 abi_ulong thigh,
2952 unsigned long *hlow,
2953 unsigned long *hhigh)
2954{
2955 uint64_t off = tlow |
2956 ((unsigned long long)thigh << TARGET_LONG_BITS / 2) <<
2957 TARGET_LONG_BITS / 2;
2958
2959 *hlow = off;
2960 *hhigh = (off >> HOST_LONG_BITS / 2) >> HOST_LONG_BITS / 2;
2961}
2962
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002963static struct iovec *lock_iovec(int type, abi_ulong target_addr,
Peter Maydelldab32b32016-07-15 14:57:26 +01002964 abi_ulong count, int copy)
pbrook53a59602006-03-25 19:31:22 +00002965{
2966 struct target_iovec *target_vec;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002967 struct iovec *vec;
2968 abi_ulong total_len, max_len;
balrogd732dcb2008-10-28 10:21:03 +00002969 int i;
Peter Maydell501bb4b2014-02-17 18:55:33 +00002970 int err = 0;
Tom Musta29560a62014-08-12 13:53:43 -05002971 bool bad_address = false;
pbrook53a59602006-03-25 19:31:22 +00002972
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002973 if (count == 0) {
2974 errno = 0;
2975 return NULL;
pbrook53a59602006-03-25 19:31:22 +00002976 }
Peter Maydelldab32b32016-07-15 14:57:26 +01002977 if (count > IOV_MAX) {
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002978 errno = EINVAL;
2979 return NULL;
2980 }
2981
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05302982 vec = g_try_new0(struct iovec, count);
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002983 if (vec == NULL) {
2984 errno = ENOMEM;
2985 return NULL;
2986 }
2987
2988 target_vec = lock_user(VERIFY_READ, target_addr,
2989 count * sizeof(struct target_iovec), 1);
2990 if (target_vec == NULL) {
Peter Maydell501bb4b2014-02-17 18:55:33 +00002991 err = EFAULT;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002992 goto fail2;
2993 }
2994
2995 /* ??? If host page size > target page size, this will result in a
2996 value larger than what we can actually support. */
2997 max_len = 0x7fffffff & TARGET_PAGE_MASK;
2998 total_len = 0;
2999
3000 for (i = 0; i < count; i++) {
3001 abi_ulong base = tswapal(target_vec[i].iov_base);
3002 abi_long len = tswapal(target_vec[i].iov_len);
3003
3004 if (len < 0) {
Peter Maydell501bb4b2014-02-17 18:55:33 +00003005 err = EINVAL;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003006 goto fail;
3007 } else if (len == 0) {
3008 /* Zero length pointer is ignored. */
3009 vec[i].iov_base = 0;
3010 } else {
3011 vec[i].iov_base = lock_user(type, base, len, copy);
Tom Musta29560a62014-08-12 13:53:43 -05003012 /* If the first buffer pointer is bad, this is a fault. But
3013 * subsequent bad buffers will result in a partial write; this
3014 * is realized by filling the vector with null pointers and
3015 * zero lengths. */
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003016 if (!vec[i].iov_base) {
Tom Musta29560a62014-08-12 13:53:43 -05003017 if (i == 0) {
3018 err = EFAULT;
3019 goto fail;
3020 } else {
3021 bad_address = true;
3022 }
3023 }
3024 if (bad_address) {
3025 len = 0;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003026 }
3027 if (len > max_len - total_len) {
3028 len = max_len - total_len;
3029 }
3030 }
3031 vec[i].iov_len = len;
3032 total_len += len;
3033 }
3034
3035 unlock_user(target_vec, target_addr, 0);
3036 return vec;
3037
3038 fail:
Chen Gang S7eff5182015-01-23 18:01:09 +08003039 while (--i >= 0) {
3040 if (tswapal(target_vec[i].iov_len) > 0) {
3041 unlock_user(vec[i].iov_base, tswapal(target_vec[i].iov_base), 0);
3042 }
3043 }
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003044 unlock_user(target_vec, target_addr, 0);
Peter Maydell501bb4b2014-02-17 18:55:33 +00003045 fail2:
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303046 g_free(vec);
Peter Maydell501bb4b2014-02-17 18:55:33 +00003047 errno = err;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003048 return NULL;
pbrook53a59602006-03-25 19:31:22 +00003049}
3050
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003051static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
Peter Maydelldab32b32016-07-15 14:57:26 +01003052 abi_ulong count, int copy)
pbrook53a59602006-03-25 19:31:22 +00003053{
3054 struct target_iovec *target_vec;
pbrook53a59602006-03-25 19:31:22 +00003055 int i;
3056
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003057 target_vec = lock_user(VERIFY_READ, target_addr,
3058 count * sizeof(struct target_iovec), 1);
3059 if (target_vec) {
3060 for (i = 0; i < count; i++) {
3061 abi_ulong base = tswapal(target_vec[i].iov_base);
Chen Gang S71ec7ce2015-01-23 18:07:50 +08003062 abi_long len = tswapal(target_vec[i].iov_len);
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003063 if (len < 0) {
3064 break;
3065 }
balrogd732dcb2008-10-28 10:21:03 +00003066 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
3067 }
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003068 unlock_user(target_vec, target_addr, 0);
pbrook53a59602006-03-25 19:31:22 +00003069 }
bellard579a97f2007-11-11 14:26:47 +00003070
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303071 g_free(vec);
pbrook53a59602006-03-25 19:31:22 +00003072}
3073
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003074static inline int target_to_host_sock_type(int *type)
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003075{
3076 int host_type = 0;
3077 int target_type = *type;
3078
3079 switch (target_type & TARGET_SOCK_TYPE_MASK) {
3080 case TARGET_SOCK_DGRAM:
3081 host_type = SOCK_DGRAM;
3082 break;
3083 case TARGET_SOCK_STREAM:
3084 host_type = SOCK_STREAM;
3085 break;
3086 default:
3087 host_type = target_type & TARGET_SOCK_TYPE_MASK;
3088 break;
3089 }
3090 if (target_type & TARGET_SOCK_CLOEXEC) {
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003091#if defined(SOCK_CLOEXEC)
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003092 host_type |= SOCK_CLOEXEC;
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003093#else
3094 return -TARGET_EINVAL;
3095#endif
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003096 }
3097 if (target_type & TARGET_SOCK_NONBLOCK) {
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003098#if defined(SOCK_NONBLOCK)
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003099 host_type |= SOCK_NONBLOCK;
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003100#elif !defined(O_NONBLOCK)
3101 return -TARGET_EINVAL;
3102#endif
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003103 }
3104 *type = host_type;
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003105 return 0;
3106}
3107
3108/* Try to emulate socket type flags after socket creation. */
3109static int sock_flags_fixup(int fd, int target_type)
3110{
3111#if !defined(SOCK_NONBLOCK) && defined(O_NONBLOCK)
3112 if (target_type & TARGET_SOCK_NONBLOCK) {
3113 int flags = fcntl(fd, F_GETFL);
3114 if (fcntl(fd, F_SETFL, O_NONBLOCK | flags) == -1) {
3115 close(fd);
3116 return -TARGET_EINVAL;
3117 }
3118 }
3119#endif
3120 return fd;
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003121}
3122
ths0da46a62007-10-20 20:23:07 +00003123/* do_socket() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003124static abi_long do_socket(int domain, int type, int protocol)
bellard3532fa72006-06-24 15:06:03 +00003125{
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003126 int target_type = type;
3127 int ret;
3128
3129 ret = target_to_host_sock_type(&type);
3130 if (ret) {
3131 return ret;
3132 }
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003133
Laurent Vivier575b22b2016-06-02 22:14:15 +02003134 if (domain == PF_NETLINK && !(
3135#ifdef CONFIG_RTNETLINK
3136 protocol == NETLINK_ROUTE ||
3137#endif
3138 protocol == NETLINK_KOBJECT_UEVENT ||
3139 protocol == NETLINK_AUDIT)) {
Josh Kunz71e24432020-07-06 17:10:36 -07003140 return -TARGET_EPROTONOSUPPORT;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003141 }
Laurent Vivierff626f22015-10-28 21:40:42 +01003142
3143 if (domain == AF_PACKET ||
3144 (domain == AF_INET && type == SOCK_PACKET)) {
3145 protocol = tswap16(protocol);
3146 }
3147
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003148 ret = get_errno(socket(domain, type, protocol));
3149 if (ret >= 0) {
3150 ret = sock_flags_fixup(ret, target_type);
Laurent Vivier0cf22722015-10-28 21:40:45 +01003151 if (type == SOCK_PACKET) {
3152 /* Manage an obsolete case :
3153 * if socket type is SOCK_PACKET, bind by name
3154 */
3155 fd_trans_register(ret, &target_packet_trans);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003156 } else if (domain == PF_NETLINK) {
3157 switch (protocol) {
Laurent Vivier575b22b2016-06-02 22:14:15 +02003158#ifdef CONFIG_RTNETLINK
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003159 case NETLINK_ROUTE:
3160 fd_trans_register(ret, &target_netlink_route_trans);
3161 break;
Laurent Vivier575b22b2016-06-02 22:14:15 +02003162#endif
Laurent Vivierb2656202016-05-22 18:56:20 +02003163 case NETLINK_KOBJECT_UEVENT:
3164 /* nothing to do: messages are strings */
3165 break;
Laurent Vivier5ce9bb52016-05-22 18:56:21 +02003166 case NETLINK_AUDIT:
3167 fd_trans_register(ret, &target_netlink_audit_trans);
3168 break;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003169 default:
3170 g_assert_not_reached();
3171 }
Laurent Vivier0cf22722015-10-28 21:40:45 +01003172 }
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003173 }
3174 return ret;
bellard3532fa72006-06-24 15:06:03 +00003175}
3176
ths0da46a62007-10-20 20:23:07 +00003177/* do_bind() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003178static abi_long do_bind(int sockfd, abi_ulong target_addr,
3179 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00003180{
aurel328f7aeaf2009-01-30 19:47:57 +00003181 void *addr;
Arnaud Patard917507b2009-06-19 10:44:45 +03003182 abi_long ret;
aurel328f7aeaf2009-01-30 19:47:57 +00003183
Blue Swirl38724252010-09-18 05:53:14 +00003184 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003185 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003186 }
aurel328f7aeaf2009-01-30 19:47:57 +00003187
aurel32607175e2009-04-15 16:11:59 +00003188 addr = alloca(addrlen+1);
ths3b46e622007-09-17 08:09:54 +00003189
Laurent Vivier7b36f782015-10-28 21:40:44 +01003190 ret = target_to_host_sockaddr(sockfd, addr, target_addr, addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03003191 if (ret)
3192 return ret;
3193
bellard3532fa72006-06-24 15:06:03 +00003194 return get_errno(bind(sockfd, addr, addrlen));
3195}
3196
ths0da46a62007-10-20 20:23:07 +00003197/* do_connect() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003198static abi_long do_connect(int sockfd, abi_ulong target_addr,
3199 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00003200{
aurel328f7aeaf2009-01-30 19:47:57 +00003201 void *addr;
Arnaud Patard917507b2009-06-19 10:44:45 +03003202 abi_long ret;
aurel328f7aeaf2009-01-30 19:47:57 +00003203
Blue Swirl38724252010-09-18 05:53:14 +00003204 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003205 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003206 }
aurel328f7aeaf2009-01-30 19:47:57 +00003207
Joakim Tjernlund2dd08df2014-07-11 17:18:03 +02003208 addr = alloca(addrlen+1);
ths3b46e622007-09-17 08:09:54 +00003209
Laurent Vivier7b36f782015-10-28 21:40:44 +01003210 ret = target_to_host_sockaddr(sockfd, addr, target_addr, addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03003211 if (ret)
3212 return ret;
3213
Peter Maydell2a3c7612016-06-06 19:58:03 +01003214 return get_errno(safe_connect(sockfd, addr, addrlen));
bellard3532fa72006-06-24 15:06:03 +00003215}
3216
Alexander Graff19e00d2014-03-02 19:36:42 +00003217/* do_sendrecvmsg_locked() Must return target values and target errnos. */
3218static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
3219 int flags, int send)
bellard3532fa72006-06-24 15:06:03 +00003220{
balrog6de645c2008-10-28 10:26:29 +00003221 abi_long ret, len;
bellard3532fa72006-06-24 15:06:03 +00003222 struct msghdr msg;
Peter Maydelldab32b32016-07-15 14:57:26 +01003223 abi_ulong count;
bellard3532fa72006-06-24 15:06:03 +00003224 struct iovec *vec;
blueswir1992f48a2007-10-14 16:27:31 +00003225 abi_ulong target_vec;
bellard3532fa72006-06-24 15:06:03 +00003226
bellard3532fa72006-06-24 15:06:03 +00003227 if (msgp->msg_name) {
3228 msg.msg_namelen = tswap32(msgp->msg_namelen);
Joakim Tjernlund2dd08df2014-07-11 17:18:03 +02003229 msg.msg_name = alloca(msg.msg_namelen+1);
Laurent Vivier7b36f782015-10-28 21:40:44 +01003230 ret = target_to_host_sockaddr(fd, msg.msg_name,
3231 tswapal(msgp->msg_name),
3232 msg.msg_namelen);
Peter Maydell26a6fc92016-07-15 14:57:28 +01003233 if (ret == -TARGET_EFAULT) {
3234 /* For connected sockets msg_name and msg_namelen must
3235 * be ignored, so returning EFAULT immediately is wrong.
3236 * Instead, pass a bad msg_name to the host kernel, and
3237 * let it decide whether to return EFAULT or not.
3238 */
3239 msg.msg_name = (void *)-1;
3240 } else if (ret) {
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003241 goto out2;
Arnaud Patard917507b2009-06-19 10:44:45 +03003242 }
bellard3532fa72006-06-24 15:06:03 +00003243 } else {
3244 msg.msg_name = NULL;
3245 msg.msg_namelen = 0;
3246 }
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003247 msg.msg_controllen = 2 * tswapal(msgp->msg_controllen);
bellard3532fa72006-06-24 15:06:03 +00003248 msg.msg_control = alloca(msg.msg_controllen);
Jonas Schievink1d3d1b22018-07-12 00:12:44 +02003249 memset(msg.msg_control, 0, msg.msg_controllen);
3250
bellard3532fa72006-06-24 15:06:03 +00003251 msg.msg_flags = tswap32(msgp->msg_flags);
ths3b46e622007-09-17 08:09:54 +00003252
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003253 count = tswapal(msgp->msg_iovlen);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003254 target_vec = tswapal(msgp->msg_iov);
Peter Maydell97b07972016-07-15 14:57:27 +01003255
3256 if (count > IOV_MAX) {
3257 /* sendrcvmsg returns a different errno for this condition than
3258 * readv/writev, so we must catch it here before lock_iovec() does.
3259 */
3260 ret = -TARGET_EMSGSIZE;
3261 goto out2;
3262 }
3263
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003264 vec = lock_iovec(send ? VERIFY_READ : VERIFY_WRITE,
3265 target_vec, count, send);
3266 if (vec == NULL) {
3267 ret = -host_to_target_errno(errno);
3268 goto out2;
3269 }
bellard3532fa72006-06-24 15:06:03 +00003270 msg.msg_iovlen = count;
3271 msg.msg_iov = vec;
ths3b46e622007-09-17 08:09:54 +00003272
bellard3532fa72006-06-24 15:06:03 +00003273 if (send) {
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003274 if (fd_trans_target_to_host_data(fd)) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003275 void *host_msg;
3276
3277 host_msg = g_malloc(msg.msg_iov->iov_len);
3278 memcpy(host_msg, msg.msg_iov->iov_base, msg.msg_iov->iov_len);
3279 ret = fd_trans_target_to_host_data(fd)(host_msg,
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003280 msg.msg_iov->iov_len);
Laurent Vivier7d61d892016-06-21 19:51:14 +02003281 if (ret >= 0) {
3282 msg.msg_iov->iov_base = host_msg;
3283 ret = get_errno(safe_sendmsg(fd, &msg, flags));
3284 }
3285 g_free(host_msg);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003286 } else {
3287 ret = target_to_host_cmsg(&msg, msgp);
Laurent Vivier7d61d892016-06-21 19:51:14 +02003288 if (ret == 0) {
3289 ret = get_errno(safe_sendmsg(fd, &msg, flags));
3290 }
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003291 }
bellard3532fa72006-06-24 15:06:03 +00003292 } else {
Peter Maydell66687532016-06-06 19:58:04 +01003293 ret = get_errno(safe_recvmsg(fd, &msg, flags));
balrog6de645c2008-10-28 10:26:29 +00003294 if (!is_error(ret)) {
3295 len = ret;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003296 if (fd_trans_host_to_target_data(fd)) {
3297 ret = fd_trans_host_to_target_data(fd)(msg.msg_iov->iov_base,
Laurent Vivier2a03d3e2018-08-20 19:15:54 +02003298 MIN(msg.msg_iov->iov_len, len));
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003299 } else {
3300 ret = host_to_target_cmsg(msgp, &msg);
3301 }
Jing Huangca619062012-07-24 13:58:02 +00003302 if (!is_error(ret)) {
3303 msgp->msg_namelen = tswap32(msg.msg_namelen);
Andreas Schwab24894f32019-02-12 17:34:35 +01003304 msgp->msg_flags = tswap32(msg.msg_flags);
Peter Maydell26a6fc92016-07-15 14:57:28 +01003305 if (msg.msg_name != NULL && msg.msg_name != (void *)-1) {
Jing Huangca619062012-07-24 13:58:02 +00003306 ret = host_to_target_sockaddr(tswapal(msgp->msg_name),
3307 msg.msg_name, msg.msg_namelen);
3308 if (ret) {
3309 goto out;
3310 }
3311 }
3312
balrog6de645c2008-10-28 10:26:29 +00003313 ret = len;
Jing Huangca619062012-07-24 13:58:02 +00003314 }
balrog6de645c2008-10-28 10:26:29 +00003315 }
bellard3532fa72006-06-24 15:06:03 +00003316 }
Jing Huangca619062012-07-24 13:58:02 +00003317
3318out:
bellard3532fa72006-06-24 15:06:03 +00003319 unlock_iovec(vec, target_vec, count, !send);
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003320out2:
Alexander Graff19e00d2014-03-02 19:36:42 +00003321 return ret;
3322}
3323
3324static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
3325 int flags, int send)
3326{
3327 abi_long ret;
3328 struct target_msghdr *msgp;
3329
3330 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
3331 msgp,
3332 target_msg,
3333 send ? 1 : 0)) {
3334 return -TARGET_EFAULT;
3335 }
3336 ret = do_sendrecvmsg_locked(fd, msgp, flags, send);
bellard579a97f2007-11-11 14:26:47 +00003337 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
bellard3532fa72006-06-24 15:06:03 +00003338 return ret;
3339}
3340
Alexander Graff19e00d2014-03-02 19:36:42 +00003341/* We don't rely on the C library to have sendmmsg/recvmmsg support,
3342 * so it might not have this *mmsg-specific flag either.
3343 */
3344#ifndef MSG_WAITFORONE
3345#define MSG_WAITFORONE 0x10000
3346#endif
3347
3348static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec,
3349 unsigned int vlen, unsigned int flags,
3350 int send)
3351{
3352 struct target_mmsghdr *mmsgp;
3353 abi_long ret = 0;
3354 int i;
3355
3356 if (vlen > UIO_MAXIOV) {
3357 vlen = UIO_MAXIOV;
3358 }
3359
3360 mmsgp = lock_user(VERIFY_WRITE, target_msgvec, sizeof(*mmsgp) * vlen, 1);
3361 if (!mmsgp) {
3362 return -TARGET_EFAULT;
3363 }
3364
3365 for (i = 0; i < vlen; i++) {
3366 ret = do_sendrecvmsg_locked(fd, &mmsgp[i].msg_hdr, flags, send);
3367 if (is_error(ret)) {
3368 break;
3369 }
3370 mmsgp[i].msg_len = tswap32(ret);
3371 /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
3372 if (flags & MSG_WAITFORONE) {
3373 flags |= MSG_DONTWAIT;
3374 }
3375 }
3376
3377 unlock_user(mmsgp, target_msgvec, sizeof(*mmsgp) * i);
3378
3379 /* Return number of datagrams sent if we sent any at all;
3380 * otherwise return the error.
3381 */
3382 if (i) {
3383 return i;
3384 }
3385 return ret;
3386}
Alexander Graff19e00d2014-03-02 19:36:42 +00003387
Peter Maydella94b4982013-02-08 04:35:04 +00003388/* do_accept4() Must return target values and target errnos. */
3389static abi_long do_accept4(int fd, abi_ulong target_addr,
3390 abi_ulong target_addrlen_addr, int flags)
pbrook1be9e1d2006-11-19 15:26:04 +00003391{
Andreas Schwabcd813362019-02-14 12:43:40 +01003392 socklen_t addrlen, ret_addrlen;
bellard2f619692007-11-16 10:46:05 +00003393 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00003394 abi_long ret;
Petar Jovanovicd25295d2014-03-31 17:41:23 +02003395 int host_flags;
3396
3397 host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
pbrook1be9e1d2006-11-19 15:26:04 +00003398
Peter Maydella94b4982013-02-08 04:35:04 +00003399 if (target_addr == 0) {
Peter Maydellff6dc132016-06-06 19:58:13 +01003400 return get_errno(safe_accept4(fd, NULL, NULL, host_flags));
Peter Maydella94b4982013-02-08 04:35:04 +00003401 }
Arnaud Patard917507b2009-06-19 10:44:45 +03003402
Matus Kysele554eb42020-09-30 17:16:16 +02003403 /* linux returns EFAULT if addrlen pointer is invalid */
bellard2f619692007-11-16 10:46:05 +00003404 if (get_user_u32(addrlen, target_addrlen_addr))
Matus Kysele554eb42020-09-30 17:16:16 +02003405 return -TARGET_EFAULT;
bellard2f619692007-11-16 10:46:05 +00003406
Blue Swirl38724252010-09-18 05:53:14 +00003407 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003408 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003409 }
aurel328f7aeaf2009-01-30 19:47:57 +00003410
Richard Hendersonc7169b02021-02-12 10:48:47 -08003411 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
Matus Kysele554eb42020-09-30 17:16:16 +02003412 return -TARGET_EFAULT;
Richard Hendersonc7169b02021-02-12 10:48:47 -08003413 }
Arnaud Patard917507b2009-06-19 10:44:45 +03003414
bellard2f619692007-11-16 10:46:05 +00003415 addr = alloca(addrlen);
3416
Andreas Schwabcd813362019-02-14 12:43:40 +01003417 ret_addrlen = addrlen;
3418 ret = get_errno(safe_accept4(fd, addr, &ret_addrlen, host_flags));
pbrook1be9e1d2006-11-19 15:26:04 +00003419 if (!is_error(ret)) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003420 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3421 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
bellard2f619692007-11-16 10:46:05 +00003422 ret = -TARGET_EFAULT;
Andreas Schwabcd813362019-02-14 12:43:40 +01003423 }
pbrook1be9e1d2006-11-19 15:26:04 +00003424 }
3425 return ret;
3426}
3427
ths0da46a62007-10-20 20:23:07 +00003428/* do_getpeername() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003429static abi_long do_getpeername(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00003430 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00003431{
Andreas Schwabcd813362019-02-14 12:43:40 +01003432 socklen_t addrlen, ret_addrlen;
bellard2f619692007-11-16 10:46:05 +00003433 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00003434 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003435
bellard2f619692007-11-16 10:46:05 +00003436 if (get_user_u32(addrlen, target_addrlen_addr))
3437 return -TARGET_EFAULT;
3438
Blue Swirl38724252010-09-18 05:53:14 +00003439 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003440 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003441 }
aurel328f7aeaf2009-01-30 19:47:57 +00003442
Richard Hendersonc7169b02021-02-12 10:48:47 -08003443 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
Arnaud Patard917507b2009-06-19 10:44:45 +03003444 return -TARGET_EFAULT;
Richard Hendersonc7169b02021-02-12 10:48:47 -08003445 }
Arnaud Patard917507b2009-06-19 10:44:45 +03003446
bellard2f619692007-11-16 10:46:05 +00003447 addr = alloca(addrlen);
3448
Andreas Schwabcd813362019-02-14 12:43:40 +01003449 ret_addrlen = addrlen;
3450 ret = get_errno(getpeername(fd, addr, &ret_addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003451 if (!is_error(ret)) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003452 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3453 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
bellard2f619692007-11-16 10:46:05 +00003454 ret = -TARGET_EFAULT;
Andreas Schwabcd813362019-02-14 12:43:40 +01003455 }
pbrook1be9e1d2006-11-19 15:26:04 +00003456 }
3457 return ret;
3458}
3459
ths0da46a62007-10-20 20:23:07 +00003460/* do_getsockname() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003461static abi_long do_getsockname(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00003462 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00003463{
Andreas Schwabcd813362019-02-14 12:43:40 +01003464 socklen_t addrlen, ret_addrlen;
bellard2f619692007-11-16 10:46:05 +00003465 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00003466 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003467
bellard2f619692007-11-16 10:46:05 +00003468 if (get_user_u32(addrlen, target_addrlen_addr))
3469 return -TARGET_EFAULT;
3470
Blue Swirl38724252010-09-18 05:53:14 +00003471 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003472 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003473 }
aurel328f7aeaf2009-01-30 19:47:57 +00003474
Richard Hendersonc7169b02021-02-12 10:48:47 -08003475 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
Arnaud Patard917507b2009-06-19 10:44:45 +03003476 return -TARGET_EFAULT;
Richard Hendersonc7169b02021-02-12 10:48:47 -08003477 }
Arnaud Patard917507b2009-06-19 10:44:45 +03003478
bellard2f619692007-11-16 10:46:05 +00003479 addr = alloca(addrlen);
3480
Andreas Schwabcd813362019-02-14 12:43:40 +01003481 ret_addrlen = addrlen;
3482 ret = get_errno(getsockname(fd, addr, &ret_addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003483 if (!is_error(ret)) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003484 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3485 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
bellard2f619692007-11-16 10:46:05 +00003486 ret = -TARGET_EFAULT;
Andreas Schwabcd813362019-02-14 12:43:40 +01003487 }
pbrook1be9e1d2006-11-19 15:26:04 +00003488 }
3489 return ret;
3490}
3491
ths0da46a62007-10-20 20:23:07 +00003492/* do_socketpair() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003493static abi_long do_socketpair(int domain, int type, int protocol,
bellard2f619692007-11-16 10:46:05 +00003494 abi_ulong target_tab_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00003495{
3496 int tab[2];
blueswir1992f48a2007-10-14 16:27:31 +00003497 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003498
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003499 target_to_host_sock_type(&type);
3500
pbrook1be9e1d2006-11-19 15:26:04 +00003501 ret = get_errno(socketpair(domain, type, protocol, tab));
3502 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00003503 if (put_user_s32(tab[0], target_tab_addr)
3504 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
3505 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00003506 }
3507 return ret;
3508}
3509
ths0da46a62007-10-20 20:23:07 +00003510/* do_sendto() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003511static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
3512 abi_ulong target_addr, socklen_t addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00003513{
3514 void *addr;
3515 void *host_msg;
Laurent Vivier7d61d892016-06-21 19:51:14 +02003516 void *copy_msg = NULL;
blueswir1992f48a2007-10-14 16:27:31 +00003517 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003518
Blue Swirl38724252010-09-18 05:53:14 +00003519 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003520 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003521 }
aurel328f7aeaf2009-01-30 19:47:57 +00003522
bellard579a97f2007-11-11 14:26:47 +00003523 host_msg = lock_user(VERIFY_READ, msg, len, 1);
3524 if (!host_msg)
3525 return -TARGET_EFAULT;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003526 if (fd_trans_target_to_host_data(fd)) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003527 copy_msg = host_msg;
3528 host_msg = g_malloc(len);
3529 memcpy(host_msg, copy_msg, len);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003530 ret = fd_trans_target_to_host_data(fd)(host_msg, len);
3531 if (ret < 0) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003532 goto fail;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003533 }
3534 }
pbrook1be9e1d2006-11-19 15:26:04 +00003535 if (target_addr) {
Joakim Tjernlund2dd08df2014-07-11 17:18:03 +02003536 addr = alloca(addrlen+1);
Laurent Vivier7b36f782015-10-28 21:40:44 +01003537 ret = target_to_host_sockaddr(fd, addr, target_addr, addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03003538 if (ret) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003539 goto fail;
Arnaud Patard917507b2009-06-19 10:44:45 +03003540 }
Peter Maydell66687532016-06-06 19:58:04 +01003541 ret = get_errno(safe_sendto(fd, host_msg, len, flags, addr, addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003542 } else {
Peter Maydell66687532016-06-06 19:58:04 +01003543 ret = get_errno(safe_sendto(fd, host_msg, len, flags, NULL, 0));
pbrook1be9e1d2006-11-19 15:26:04 +00003544 }
Laurent Vivier7d61d892016-06-21 19:51:14 +02003545fail:
3546 if (copy_msg) {
3547 g_free(host_msg);
3548 host_msg = copy_msg;
3549 }
pbrook1be9e1d2006-11-19 15:26:04 +00003550 unlock_user(host_msg, msg, 0);
3551 return ret;
3552}
3553
ths0da46a62007-10-20 20:23:07 +00003554/* do_recvfrom() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003555static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
3556 abi_ulong target_addr,
3557 abi_ulong target_addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00003558{
Andreas Schwabcd813362019-02-14 12:43:40 +01003559 socklen_t addrlen, ret_addrlen;
pbrook1be9e1d2006-11-19 15:26:04 +00003560 void *addr;
3561 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00003562 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003563
Zach Reizner4a1e6bc2021-03-26 22:11:16 -04003564 if (!msg) {
3565 host_msg = NULL;
3566 } else {
3567 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
3568 if (!host_msg) {
3569 return -TARGET_EFAULT;
3570 }
3571 }
pbrook1be9e1d2006-11-19 15:26:04 +00003572 if (target_addr) {
bellard2f619692007-11-16 10:46:05 +00003573 if (get_user_u32(addrlen, target_addrlen)) {
3574 ret = -TARGET_EFAULT;
3575 goto fail;
3576 }
Blue Swirl38724252010-09-18 05:53:14 +00003577 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003578 ret = -TARGET_EINVAL;
3579 goto fail;
3580 }
pbrook1be9e1d2006-11-19 15:26:04 +00003581 addr = alloca(addrlen);
Andreas Schwabcd813362019-02-14 12:43:40 +01003582 ret_addrlen = addrlen;
Peter Maydell66687532016-06-06 19:58:04 +01003583 ret = get_errno(safe_recvfrom(fd, host_msg, len, flags,
Andreas Schwabcd813362019-02-14 12:43:40 +01003584 addr, &ret_addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003585 } else {
3586 addr = NULL; /* To keep compiler quiet. */
Andreas Schwabcd813362019-02-14 12:43:40 +01003587 addrlen = 0; /* To keep compiler quiet. */
Peter Maydell66687532016-06-06 19:58:04 +01003588 ret = get_errno(safe_recvfrom(fd, host_msg, len, flags, NULL, 0));
pbrook1be9e1d2006-11-19 15:26:04 +00003589 }
3590 if (!is_error(ret)) {
Laurent Vivierc35e1f92016-06-21 19:51:15 +02003591 if (fd_trans_host_to_target_data(fd)) {
Laurent Vivier2a03d3e2018-08-20 19:15:54 +02003592 abi_long trans;
3593 trans = fd_trans_host_to_target_data(fd)(host_msg, MIN(ret, len));
3594 if (is_error(trans)) {
3595 ret = trans;
3596 goto fail;
3597 }
Laurent Vivierc35e1f92016-06-21 19:51:15 +02003598 }
pbrook1be9e1d2006-11-19 15:26:04 +00003599 if (target_addr) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003600 host_to_target_sockaddr(target_addr, addr,
3601 MIN(addrlen, ret_addrlen));
3602 if (put_user_u32(ret_addrlen, target_addrlen)) {
bellard2f619692007-11-16 10:46:05 +00003603 ret = -TARGET_EFAULT;
3604 goto fail;
3605 }
pbrook1be9e1d2006-11-19 15:26:04 +00003606 }
3607 unlock_user(host_msg, msg, len);
3608 } else {
bellard2f619692007-11-16 10:46:05 +00003609fail:
pbrook1be9e1d2006-11-19 15:26:04 +00003610 unlock_user(host_msg, msg, 0);
3611 }
3612 return ret;
3613}
3614
j_mayer32407102007-09-26 23:01:49 +00003615#ifdef TARGET_NR_socketcall
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003616/* do_socketcall() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003617static abi_long do_socketcall(int num, abi_ulong vptr)
bellard31e31b82003-02-18 22:55:36 +00003618{
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003619 static const unsigned nargs[] = { /* number of arguments per operation */
3620 [TARGET_SYS_SOCKET] = 3, /* domain, type, protocol */
3621 [TARGET_SYS_BIND] = 3, /* fd, addr, addrlen */
3622 [TARGET_SYS_CONNECT] = 3, /* fd, addr, addrlen */
3623 [TARGET_SYS_LISTEN] = 2, /* fd, backlog */
3624 [TARGET_SYS_ACCEPT] = 3, /* fd, addr, addrlen */
3625 [TARGET_SYS_GETSOCKNAME] = 3, /* fd, addr, addrlen */
3626 [TARGET_SYS_GETPEERNAME] = 3, /* fd, addr, addrlen */
3627 [TARGET_SYS_SOCKETPAIR] = 4, /* domain, type, protocol, tab */
3628 [TARGET_SYS_SEND] = 4, /* fd, msg, len, flags */
3629 [TARGET_SYS_RECV] = 4, /* fd, msg, len, flags */
3630 [TARGET_SYS_SENDTO] = 6, /* fd, msg, len, flags, addr, addrlen */
3631 [TARGET_SYS_RECVFROM] = 6, /* fd, msg, len, flags, addr, addrlen */
3632 [TARGET_SYS_SHUTDOWN] = 2, /* fd, how */
3633 [TARGET_SYS_SETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
3634 [TARGET_SYS_GETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
3635 [TARGET_SYS_SENDMSG] = 3, /* fd, msg, flags */
3636 [TARGET_SYS_RECVMSG] = 3, /* fd, msg, flags */
3637 [TARGET_SYS_ACCEPT4] = 4, /* fd, addr, addrlen, flags */
3638 [TARGET_SYS_RECVMMSG] = 4, /* fd, msgvec, vlen, flags */
3639 [TARGET_SYS_SENDMMSG] = 4, /* fd, msgvec, vlen, flags */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003640 };
3641 abi_long a[6]; /* max 6 args */
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003642 unsigned i;
bellard31e31b82003-02-18 22:55:36 +00003643
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003644 /* check the range of the first argument num */
3645 /* (TARGET_SYS_SENDMMSG is the highest among TARGET_SYS_xxx) */
3646 if (num < 1 || num > TARGET_SYS_SENDMMSG) {
3647 return -TARGET_EINVAL;
3648 }
3649 /* ensure we have space for args */
3650 if (nargs[num] > ARRAY_SIZE(a)) {
3651 return -TARGET_EINVAL;
3652 }
3653 /* collect the arguments in a[] according to nargs[] */
3654 for (i = 0; i < nargs[num]; ++i) {
3655 if (get_user_ual(a[i], vptr + i * sizeof(abi_long)) != 0) {
3656 return -TARGET_EFAULT;
André Hentschelb9d36eb2014-01-06 20:18:52 +01003657 }
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003658 }
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003659 /* now when we have the args, invoke the appropriate underlying function */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003660 switch (num) {
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003661 case TARGET_SYS_SOCKET: /* domain, type, protocol */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003662 return do_socket(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003663 case TARGET_SYS_BIND: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003664 return do_bind(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003665 case TARGET_SYS_CONNECT: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003666 return do_connect(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003667 case TARGET_SYS_LISTEN: /* sockfd, backlog */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003668 return get_errno(listen(a[0], a[1]));
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003669 case TARGET_SYS_ACCEPT: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003670 return do_accept4(a[0], a[1], a[2], 0);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003671 case TARGET_SYS_GETSOCKNAME: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003672 return do_getsockname(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003673 case TARGET_SYS_GETPEERNAME: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003674 return do_getpeername(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003675 case TARGET_SYS_SOCKETPAIR: /* domain, type, protocol, tab */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003676 return do_socketpair(a[0], a[1], a[2], a[3]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003677 case TARGET_SYS_SEND: /* sockfd, msg, len, flags */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003678 return do_sendto(a[0], a[1], a[2], a[3], 0, 0);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003679 case TARGET_SYS_RECV: /* sockfd, msg, len, flags */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003680 return do_recvfrom(a[0], a[1], a[2], a[3], 0, 0);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003681 case TARGET_SYS_SENDTO: /* sockfd, msg, len, flags, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003682 return do_sendto(a[0], a[1], a[2], a[3], a[4], a[5]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003683 case TARGET_SYS_RECVFROM: /* sockfd, msg, len, flags, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003684 return do_recvfrom(a[0], a[1], a[2], a[3], a[4], a[5]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003685 case TARGET_SYS_SHUTDOWN: /* sockfd, how */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003686 return get_errno(shutdown(a[0], a[1]));
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003687 case TARGET_SYS_SETSOCKOPT: /* sockfd, level, optname, optval, optlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003688 return do_setsockopt(a[0], a[1], a[2], a[3], a[4]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003689 case TARGET_SYS_GETSOCKOPT: /* sockfd, level, optname, optval, optlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003690 return do_getsockopt(a[0], a[1], a[2], a[3], a[4]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003691 case TARGET_SYS_SENDMSG: /* sockfd, msg, flags */
3692 return do_sendrecvmsg(a[0], a[1], a[2], 1);
3693 case TARGET_SYS_RECVMSG: /* sockfd, msg, flags */
3694 return do_sendrecvmsg(a[0], a[1], a[2], 0);
3695 case TARGET_SYS_ACCEPT4: /* sockfd, addr, addrlen, flags */
3696 return do_accept4(a[0], a[1], a[2], a[3]);
3697 case TARGET_SYS_RECVMMSG: /* sockfd, msgvec, vlen, flags */
3698 return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0);
3699 case TARGET_SYS_SENDMMSG: /* sockfd, msgvec, vlen, flags */
3700 return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 1);
bellard31e31b82003-02-18 22:55:36 +00003701 default:
Josh Kunz39be5352020-02-03 18:54:13 -08003702 qemu_log_mask(LOG_UNIMP, "Unsupported socketcall: %d\n", num);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003703 return -TARGET_EINVAL;
bellard31e31b82003-02-18 22:55:36 +00003704 }
bellard31e31b82003-02-18 22:55:36 +00003705}
j_mayer32407102007-09-26 23:01:49 +00003706#endif
bellard31e31b82003-02-18 22:55:36 +00003707
bellard8853f862004-02-22 14:57:26 +00003708#define N_SHM_REGIONS 32
3709
3710static struct shm_region {
Peter Maydellb6e17872016-02-09 15:57:11 +00003711 abi_ulong start;
3712 abi_ulong size;
3713 bool in_use;
bellard8853f862004-02-22 14:57:26 +00003714} shm_regions[N_SHM_REGIONS];
3715
Peter Maydell005eb2a2016-07-15 16:50:47 +01003716#ifndef TARGET_SEMID64_DS
3717/* asm-generic version of this struct */
3718struct target_semid64_ds
ths3eb6b042007-06-03 14:26:27 +00003719{
3720 struct target_ipc_perm sem_perm;
blueswir1992f48a2007-10-14 16:27:31 +00003721 abi_ulong sem_otime;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003722#if TARGET_ABI_BITS == 32
blueswir1992f48a2007-10-14 16:27:31 +00003723 abi_ulong __unused1;
Tom Musta03527342014-08-12 13:53:32 -05003724#endif
blueswir1992f48a2007-10-14 16:27:31 +00003725 abi_ulong sem_ctime;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003726#if TARGET_ABI_BITS == 32
blueswir1992f48a2007-10-14 16:27:31 +00003727 abi_ulong __unused2;
Tom Musta03527342014-08-12 13:53:32 -05003728#endif
blueswir1992f48a2007-10-14 16:27:31 +00003729 abi_ulong sem_nsems;
3730 abi_ulong __unused3;
3731 abi_ulong __unused4;
ths3eb6b042007-06-03 14:26:27 +00003732};
Peter Maydell005eb2a2016-07-15 16:50:47 +01003733#endif
ths3eb6b042007-06-03 14:26:27 +00003734
bellard579a97f2007-11-11 14:26:47 +00003735static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
3736 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00003737{
3738 struct target_ipc_perm *target_ip;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003739 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003740
bellard579a97f2007-11-11 14:26:47 +00003741 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
3742 return -TARGET_EFAULT;
Michael S. Tsirkine8bbe362009-09-30 18:56:44 +00003743 target_ip = &(target_sd->sem_perm);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003744 host_ip->__key = tswap32(target_ip->__key);
3745 host_ip->uid = tswap32(target_ip->uid);
3746 host_ip->gid = tswap32(target_ip->gid);
3747 host_ip->cuid = tswap32(target_ip->cuid);
3748 host_ip->cgid = tswap32(target_ip->cgid);
3749#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
3750 host_ip->mode = tswap32(target_ip->mode);
3751#else
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003752 host_ip->mode = tswap16(target_ip->mode);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003753#endif
3754#if defined(TARGET_PPC)
3755 host_ip->__seq = tswap32(target_ip->__seq);
3756#else
3757 host_ip->__seq = tswap16(target_ip->__seq);
3758#endif
ths3eb6b042007-06-03 14:26:27 +00003759 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00003760 return 0;
ths3eb6b042007-06-03 14:26:27 +00003761}
3762
bellard579a97f2007-11-11 14:26:47 +00003763static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
3764 struct ipc_perm *host_ip)
ths3eb6b042007-06-03 14:26:27 +00003765{
3766 struct target_ipc_perm *target_ip;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003767 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003768
bellard579a97f2007-11-11 14:26:47 +00003769 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3770 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00003771 target_ip = &(target_sd->sem_perm);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003772 target_ip->__key = tswap32(host_ip->__key);
3773 target_ip->uid = tswap32(host_ip->uid);
3774 target_ip->gid = tswap32(host_ip->gid);
3775 target_ip->cuid = tswap32(host_ip->cuid);
3776 target_ip->cgid = tswap32(host_ip->cgid);
3777#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
3778 target_ip->mode = tswap32(host_ip->mode);
3779#else
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003780 target_ip->mode = tswap16(host_ip->mode);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003781#endif
3782#if defined(TARGET_PPC)
3783 target_ip->__seq = tswap32(host_ip->__seq);
3784#else
3785 target_ip->__seq = tswap16(host_ip->__seq);
3786#endif
ths3eb6b042007-06-03 14:26:27 +00003787 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00003788 return 0;
ths3eb6b042007-06-03 14:26:27 +00003789}
3790
bellard579a97f2007-11-11 14:26:47 +00003791static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
3792 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00003793{
Peter Maydell005eb2a2016-07-15 16:50:47 +01003794 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003795
bellard579a97f2007-11-11 14:26:47 +00003796 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
3797 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00003798 if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
3799 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003800 host_sd->sem_nsems = tswapal(target_sd->sem_nsems);
3801 host_sd->sem_otime = tswapal(target_sd->sem_otime);
3802 host_sd->sem_ctime = tswapal(target_sd->sem_ctime);
ths3eb6b042007-06-03 14:26:27 +00003803 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00003804 return 0;
ths3eb6b042007-06-03 14:26:27 +00003805}
3806
bellard579a97f2007-11-11 14:26:47 +00003807static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
3808 struct semid_ds *host_sd)
ths3eb6b042007-06-03 14:26:27 +00003809{
Peter Maydell005eb2a2016-07-15 16:50:47 +01003810 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003811
bellard579a97f2007-11-11 14:26:47 +00003812 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3813 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00003814 if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
Dong Xu Wang3a931132011-11-29 16:52:38 +08003815 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003816 target_sd->sem_nsems = tswapal(host_sd->sem_nsems);
3817 target_sd->sem_otime = tswapal(host_sd->sem_otime);
3818 target_sd->sem_ctime = tswapal(host_sd->sem_ctime);
ths3eb6b042007-06-03 14:26:27 +00003819 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00003820 return 0;
ths3eb6b042007-06-03 14:26:27 +00003821}
3822
aurel32e5289082009-04-18 16:16:12 +00003823struct target_seminfo {
3824 int semmap;
3825 int semmni;
3826 int semmns;
3827 int semmnu;
3828 int semmsl;
3829 int semopm;
3830 int semume;
3831 int semusz;
3832 int semvmx;
3833 int semaem;
3834};
3835
3836static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
3837 struct seminfo *host_seminfo)
3838{
3839 struct target_seminfo *target_seminfo;
3840 if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
3841 return -TARGET_EFAULT;
3842 __put_user(host_seminfo->semmap, &target_seminfo->semmap);
3843 __put_user(host_seminfo->semmni, &target_seminfo->semmni);
3844 __put_user(host_seminfo->semmns, &target_seminfo->semmns);
3845 __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
3846 __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
3847 __put_user(host_seminfo->semopm, &target_seminfo->semopm);
3848 __put_user(host_seminfo->semume, &target_seminfo->semume);
3849 __put_user(host_seminfo->semusz, &target_seminfo->semusz);
3850 __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
3851 __put_user(host_seminfo->semaem, &target_seminfo->semaem);
3852 unlock_user_struct(target_seminfo, target_addr, 1);
3853 return 0;
3854}
3855
thsfa294812007-02-02 22:05:00 +00003856union semun {
3857 int val;
ths3eb6b042007-06-03 14:26:27 +00003858 struct semid_ds *buf;
thsfa294812007-02-02 22:05:00 +00003859 unsigned short *array;
aurel32e5289082009-04-18 16:16:12 +00003860 struct seminfo *__buf;
thsfa294812007-02-02 22:05:00 +00003861};
3862
ths3eb6b042007-06-03 14:26:27 +00003863union target_semun {
3864 int val;
aurel32e5289082009-04-18 16:16:12 +00003865 abi_ulong buf;
3866 abi_ulong array;
3867 abi_ulong __buf;
ths3eb6b042007-06-03 14:26:27 +00003868};
3869
aurel32e5289082009-04-18 16:16:12 +00003870static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
3871 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00003872{
aurel32e5289082009-04-18 16:16:12 +00003873 int nsems;
3874 unsigned short *array;
3875 union semun semun;
3876 struct semid_ds semid_ds;
3877 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00003878
aurel32e5289082009-04-18 16:16:12 +00003879 semun.buf = &semid_ds;
3880
3881 ret = semctl(semid, 0, IPC_STAT, semun);
3882 if (ret == -1)
3883 return get_errno(ret);
3884
3885 nsems = semid_ds.sem_nsems;
3886
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303887 *host_array = g_try_new(unsigned short, nsems);
Peter Maydell69d4c702014-02-17 18:55:34 +00003888 if (!*host_array) {
3889 return -TARGET_ENOMEM;
3890 }
aurel32e5289082009-04-18 16:16:12 +00003891 array = lock_user(VERIFY_READ, target_addr,
3892 nsems*sizeof(unsigned short), 1);
Peter Maydell69d4c702014-02-17 18:55:34 +00003893 if (!array) {
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303894 g_free(*host_array);
aurel32e5289082009-04-18 16:16:12 +00003895 return -TARGET_EFAULT;
Peter Maydell69d4c702014-02-17 18:55:34 +00003896 }
aurel32e5289082009-04-18 16:16:12 +00003897
3898 for(i=0; i<nsems; i++) {
3899 __get_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00003900 }
aurel32e5289082009-04-18 16:16:12 +00003901 unlock_user(array, target_addr, 0);
3902
bellard579a97f2007-11-11 14:26:47 +00003903 return 0;
ths3eb6b042007-06-03 14:26:27 +00003904}
3905
aurel32e5289082009-04-18 16:16:12 +00003906static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
3907 unsigned short **host_array)
ths3eb6b042007-06-03 14:26:27 +00003908{
aurel32e5289082009-04-18 16:16:12 +00003909 int nsems;
3910 unsigned short *array;
3911 union semun semun;
3912 struct semid_ds semid_ds;
3913 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00003914
aurel32e5289082009-04-18 16:16:12 +00003915 semun.buf = &semid_ds;
3916
3917 ret = semctl(semid, 0, IPC_STAT, semun);
3918 if (ret == -1)
3919 return get_errno(ret);
3920
3921 nsems = semid_ds.sem_nsems;
3922
3923 array = lock_user(VERIFY_WRITE, target_addr,
3924 nsems*sizeof(unsigned short), 0);
3925 if (!array)
3926 return -TARGET_EFAULT;
3927
3928 for(i=0; i<nsems; i++) {
3929 __put_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00003930 }
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303931 g_free(*host_array);
aurel32e5289082009-04-18 16:16:12 +00003932 unlock_user(array, target_addr, 1);
3933
bellard579a97f2007-11-11 14:26:47 +00003934 return 0;
ths3eb6b042007-06-03 14:26:27 +00003935}
3936
aurel32e5289082009-04-18 16:16:12 +00003937static inline abi_long do_semctl(int semid, int semnum, int cmd,
Stefan Weild1c002b2015-02-08 15:40:58 +01003938 abi_ulong target_arg)
ths3eb6b042007-06-03 14:26:27 +00003939{
Stefan Weild1c002b2015-02-08 15:40:58 +01003940 union target_semun target_su = { .buf = target_arg };
ths3eb6b042007-06-03 14:26:27 +00003941 union semun arg;
3942 struct semid_ds dsarg;
vibi sreenivasan7b8118e2009-06-19 13:34:39 +05303943 unsigned short *array = NULL;
aurel32e5289082009-04-18 16:16:12 +00003944 struct seminfo seminfo;
3945 abi_long ret = -TARGET_EINVAL;
3946 abi_long err;
3947 cmd &= 0xff;
ths3eb6b042007-06-03 14:26:27 +00003948
3949 switch( cmd ) {
3950 case GETVAL:
ths3eb6b042007-06-03 14:26:27 +00003951 case SETVAL:
Tom Musta5464bae2014-08-12 13:53:34 -05003952 /* In 64 bit cross-endian situations, we will erroneously pick up
3953 * the wrong half of the union for the "val" element. To rectify
3954 * this, the entire 8-byte structure is byteswapped, followed by
3955 * a swap of the 4 byte val field. In other cases, the data is
3956 * already in proper host byte order. */
3957 if (sizeof(target_su.val) != (sizeof(target_su.buf))) {
3958 target_su.buf = tswapal(target_su.buf);
3959 arg.val = tswap32(target_su.val);
3960 } else {
3961 arg.val = target_su.val;
3962 }
aurel32e5289082009-04-18 16:16:12 +00003963 ret = get_errno(semctl(semid, semnum, cmd, arg));
ths3eb6b042007-06-03 14:26:27 +00003964 break;
3965 case GETALL:
ths3eb6b042007-06-03 14:26:27 +00003966 case SETALL:
aurel32e5289082009-04-18 16:16:12 +00003967 err = target_to_host_semarray(semid, &array, target_su.array);
3968 if (err)
3969 return err;
3970 arg.array = array;
3971 ret = get_errno(semctl(semid, semnum, cmd, arg));
3972 err = host_to_target_semarray(semid, target_su.array, &array);
3973 if (err)
3974 return err;
ths3eb6b042007-06-03 14:26:27 +00003975 break;
3976 case IPC_STAT:
ths3eb6b042007-06-03 14:26:27 +00003977 case IPC_SET:
aurel32e5289082009-04-18 16:16:12 +00003978 case SEM_STAT:
3979 err = target_to_host_semid_ds(&dsarg, target_su.buf);
3980 if (err)
3981 return err;
3982 arg.buf = &dsarg;
3983 ret = get_errno(semctl(semid, semnum, cmd, arg));
3984 err = host_to_target_semid_ds(target_su.buf, &dsarg);
3985 if (err)
3986 return err;
ths3eb6b042007-06-03 14:26:27 +00003987 break;
aurel32e5289082009-04-18 16:16:12 +00003988 case IPC_INFO:
3989 case SEM_INFO:
3990 arg.__buf = &seminfo;
3991 ret = get_errno(semctl(semid, semnum, cmd, arg));
3992 err = host_to_target_seminfo(target_su.__buf, &seminfo);
3993 if (err)
3994 return err;
3995 break;
3996 case IPC_RMID:
3997 case GETPID:
3998 case GETNCNT:
3999 case GETZCNT:
4000 ret = get_errno(semctl(semid, semnum, cmd, NULL));
4001 break;
ths3eb6b042007-06-03 14:26:27 +00004002 }
4003
4004 return ret;
4005}
4006
aurel32e5289082009-04-18 16:16:12 +00004007struct target_sembuf {
4008 unsigned short sem_num;
4009 short sem_op;
4010 short sem_flg;
4011};
4012
4013static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
4014 abi_ulong target_addr,
4015 unsigned nsops)
4016{
4017 struct target_sembuf *target_sembuf;
4018 int i;
4019
4020 target_sembuf = lock_user(VERIFY_READ, target_addr,
4021 nsops*sizeof(struct target_sembuf), 1);
4022 if (!target_sembuf)
4023 return -TARGET_EFAULT;
4024
4025 for(i=0; i<nsops; i++) {
4026 __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
4027 __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
4028 __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
4029 }
4030
4031 unlock_user(target_sembuf, target_addr, 0);
4032
4033 return 0;
4034}
4035
Matus Kyseld8c08b12020-06-26 14:46:11 +02004036#if defined(TARGET_NR_ipc) || defined(TARGET_NR_semop) || \
Filip Bozutacac46eb2020-08-25 00:30:50 +02004037 defined(TARGET_NR_semtimedop) || defined(TARGET_NR_semtimedop_time64)
Matus Kyseld8c08b12020-06-26 14:46:11 +02004038
4039/*
4040 * This macro is required to handle the s390 variants, which passes the
4041 * arguments in a different order than default.
4042 */
4043#ifdef __s390x__
4044#define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
4045 (__nsops), (__timeout), (__sops)
4046#else
4047#define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
4048 (__nsops), 0, (__sops), (__timeout)
4049#endif
4050
4051static inline abi_long do_semtimedop(int semid,
4052 abi_long ptr,
4053 unsigned nsops,
Filip Bozutacac46eb2020-08-25 00:30:50 +02004054 abi_long timeout, bool time64)
aurel32e5289082009-04-18 16:16:12 +00004055{
Filip Bozuta0a7ec842020-08-18 20:07:22 +02004056 struct sembuf *sops;
Matus Kyseld8c08b12020-06-26 14:46:11 +02004057 struct timespec ts, *pts = NULL;
Laurent Vivier524fa342019-05-29 10:48:04 +02004058 abi_long ret;
aurel32e5289082009-04-18 16:16:12 +00004059
Matus Kyseld8c08b12020-06-26 14:46:11 +02004060 if (timeout) {
4061 pts = &ts;
Filip Bozutacac46eb2020-08-25 00:30:50 +02004062 if (time64) {
4063 if (target_to_host_timespec64(pts, timeout)) {
4064 return -TARGET_EFAULT;
4065 }
4066 } else {
4067 if (target_to_host_timespec(pts, timeout)) {
4068 return -TARGET_EFAULT;
4069 }
Matus Kyseld8c08b12020-06-26 14:46:11 +02004070 }
4071 }
4072
Filip Bozuta0a7ec842020-08-18 20:07:22 +02004073 if (nsops > TARGET_SEMOPM) {
4074 return -TARGET_E2BIG;
4075 }
4076
4077 sops = g_new(struct sembuf, nsops);
4078
4079 if (target_to_host_sembuf(sops, ptr, nsops)) {
4080 g_free(sops);
aurel32e5289082009-04-18 16:16:12 +00004081 return -TARGET_EFAULT;
Filip Bozuta0a7ec842020-08-18 20:07:22 +02004082 }
aurel32e5289082009-04-18 16:16:12 +00004083
Laurent Vivier524fa342019-05-29 10:48:04 +02004084 ret = -TARGET_ENOSYS;
4085#ifdef __NR_semtimedop
Matus Kyseld8c08b12020-06-26 14:46:11 +02004086 ret = get_errno(safe_semtimedop(semid, sops, nsops, pts));
Laurent Vivier524fa342019-05-29 10:48:04 +02004087#endif
4088#ifdef __NR_ipc
4089 if (ret == -TARGET_ENOSYS) {
Matus Kyseld8c08b12020-06-26 14:46:11 +02004090 ret = get_errno(safe_ipc(IPCOP_semtimedop, semid,
4091 SEMTIMEDOP_IPC_ARGS(nsops, sops, (long)pts)));
Laurent Vivier524fa342019-05-29 10:48:04 +02004092 }
4093#endif
Filip Bozuta0a7ec842020-08-18 20:07:22 +02004094 g_free(sops);
Laurent Vivier524fa342019-05-29 10:48:04 +02004095 return ret;
aurel32e5289082009-04-18 16:16:12 +00004096}
Matus Kyseld8c08b12020-06-26 14:46:11 +02004097#endif
aurel32e5289082009-04-18 16:16:12 +00004098
ths1bc012f2007-06-03 14:27:49 +00004099struct target_msqid_ds
4100{
aurel321c54ff92008-10-13 21:08:44 +00004101 struct target_ipc_perm msg_perm;
4102 abi_ulong msg_stime;
4103#if TARGET_ABI_BITS == 32
4104 abi_ulong __unused1;
4105#endif
4106 abi_ulong msg_rtime;
4107#if TARGET_ABI_BITS == 32
4108 abi_ulong __unused2;
4109#endif
4110 abi_ulong msg_ctime;
4111#if TARGET_ABI_BITS == 32
4112 abi_ulong __unused3;
4113#endif
4114 abi_ulong __msg_cbytes;
4115 abi_ulong msg_qnum;
4116 abi_ulong msg_qbytes;
4117 abi_ulong msg_lspid;
4118 abi_ulong msg_lrpid;
4119 abi_ulong __unused4;
4120 abi_ulong __unused5;
ths1bc012f2007-06-03 14:27:49 +00004121};
4122
bellard579a97f2007-11-11 14:26:47 +00004123static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
4124 abi_ulong target_addr)
ths1bc012f2007-06-03 14:27:49 +00004125{
4126 struct target_msqid_ds *target_md;
4127
bellard579a97f2007-11-11 14:26:47 +00004128 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
4129 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00004130 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
4131 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02004132 host_md->msg_stime = tswapal(target_md->msg_stime);
4133 host_md->msg_rtime = tswapal(target_md->msg_rtime);
4134 host_md->msg_ctime = tswapal(target_md->msg_ctime);
4135 host_md->__msg_cbytes = tswapal(target_md->__msg_cbytes);
4136 host_md->msg_qnum = tswapal(target_md->msg_qnum);
4137 host_md->msg_qbytes = tswapal(target_md->msg_qbytes);
4138 host_md->msg_lspid = tswapal(target_md->msg_lspid);
4139 host_md->msg_lrpid = tswapal(target_md->msg_lrpid);
ths1bc012f2007-06-03 14:27:49 +00004140 unlock_user_struct(target_md, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00004141 return 0;
ths1bc012f2007-06-03 14:27:49 +00004142}
4143
bellard579a97f2007-11-11 14:26:47 +00004144static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
4145 struct msqid_ds *host_md)
ths1bc012f2007-06-03 14:27:49 +00004146{
4147 struct target_msqid_ds *target_md;
4148
bellard579a97f2007-11-11 14:26:47 +00004149 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
4150 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00004151 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
4152 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02004153 target_md->msg_stime = tswapal(host_md->msg_stime);
4154 target_md->msg_rtime = tswapal(host_md->msg_rtime);
4155 target_md->msg_ctime = tswapal(host_md->msg_ctime);
4156 target_md->__msg_cbytes = tswapal(host_md->__msg_cbytes);
4157 target_md->msg_qnum = tswapal(host_md->msg_qnum);
4158 target_md->msg_qbytes = tswapal(host_md->msg_qbytes);
4159 target_md->msg_lspid = tswapal(host_md->msg_lspid);
4160 target_md->msg_lrpid = tswapal(host_md->msg_lrpid);
ths1bc012f2007-06-03 14:27:49 +00004161 unlock_user_struct(target_md, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00004162 return 0;
ths1bc012f2007-06-03 14:27:49 +00004163}
4164
aurel321c54ff92008-10-13 21:08:44 +00004165struct target_msginfo {
4166 int msgpool;
4167 int msgmap;
4168 int msgmax;
4169 int msgmnb;
4170 int msgmni;
4171 int msgssz;
4172 int msgtql;
4173 unsigned short int msgseg;
4174};
4175
4176static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
4177 struct msginfo *host_msginfo)
4178{
4179 struct target_msginfo *target_msginfo;
4180 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
4181 return -TARGET_EFAULT;
4182 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
4183 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
4184 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
4185 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
4186 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
4187 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
4188 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
4189 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
4190 unlock_user_struct(target_msginfo, target_addr, 1);
aurel3200b229a2008-10-24 13:12:52 +00004191 return 0;
aurel321c54ff92008-10-13 21:08:44 +00004192}
4193
4194static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
ths1bc012f2007-06-03 14:27:49 +00004195{
4196 struct msqid_ds dsarg;
aurel321c54ff92008-10-13 21:08:44 +00004197 struct msginfo msginfo;
4198 abi_long ret = -TARGET_EINVAL;
4199
4200 cmd &= 0xff;
4201
4202 switch (cmd) {
ths1bc012f2007-06-03 14:27:49 +00004203 case IPC_STAT:
4204 case IPC_SET:
aurel321c54ff92008-10-13 21:08:44 +00004205 case MSG_STAT:
4206 if (target_to_host_msqid_ds(&dsarg,ptr))
4207 return -TARGET_EFAULT;
4208 ret = get_errno(msgctl(msgid, cmd, &dsarg));
4209 if (host_to_target_msqid_ds(ptr,&dsarg))
4210 return -TARGET_EFAULT;
4211 break;
4212 case IPC_RMID:
4213 ret = get_errno(msgctl(msgid, cmd, NULL));
4214 break;
4215 case IPC_INFO:
4216 case MSG_INFO:
4217 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
4218 if (host_to_target_msginfo(ptr, &msginfo))
4219 return -TARGET_EFAULT;
4220 break;
ths1bc012f2007-06-03 14:27:49 +00004221 }
aurel321c54ff92008-10-13 21:08:44 +00004222
ths1bc012f2007-06-03 14:27:49 +00004223 return ret;
4224}
4225
4226struct target_msgbuf {
aurel321c54ff92008-10-13 21:08:44 +00004227 abi_long mtype;
4228 char mtext[1];
ths1bc012f2007-06-03 14:27:49 +00004229};
4230
blueswir1992f48a2007-10-14 16:27:31 +00004231static inline abi_long do_msgsnd(int msqid, abi_long msgp,
Tom Mustaedcc5f92014-08-12 13:53:37 -05004232 ssize_t msgsz, int msgflg)
ths1bc012f2007-06-03 14:27:49 +00004233{
4234 struct target_msgbuf *target_mb;
4235 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00004236 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00004237
Tom Mustaedcc5f92014-08-12 13:53:37 -05004238 if (msgsz < 0) {
4239 return -TARGET_EINVAL;
4240 }
4241
bellard579a97f2007-11-11 14:26:47 +00004242 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
4243 return -TARGET_EFAULT;
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304244 host_mb = g_try_malloc(msgsz + sizeof(long));
zhanghailiang29e03fc2014-08-14 15:29:18 +08004245 if (!host_mb) {
4246 unlock_user_struct(target_mb, msgp, 0);
4247 return -TARGET_ENOMEM;
4248 }
Matthias Brauncbb21ee2011-08-12 19:57:41 +02004249 host_mb->mtype = (abi_long) tswapal(target_mb->mtype);
aurel321c54ff92008-10-13 21:08:44 +00004250 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
Laurent Vivier524fa342019-05-29 10:48:04 +02004251 ret = -TARGET_ENOSYS;
4252#ifdef __NR_msgsnd
Peter Maydell89f9fe42016-06-06 19:58:05 +01004253 ret = get_errno(safe_msgsnd(msqid, host_mb, msgsz, msgflg));
Laurent Vivier524fa342019-05-29 10:48:04 +02004254#endif
4255#ifdef __NR_ipc
4256 if (ret == -TARGET_ENOSYS) {
Matus Kyseld8c08b12020-06-26 14:46:11 +02004257#ifdef __s390x__
4258 ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg,
4259 host_mb));
4260#else
Laurent Vivier524fa342019-05-29 10:48:04 +02004261 ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg,
4262 host_mb, 0));
Matus Kyseld8c08b12020-06-26 14:46:11 +02004263#endif
Laurent Vivier524fa342019-05-29 10:48:04 +02004264 }
4265#endif
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304266 g_free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00004267 unlock_user_struct(target_mb, msgp, 0);
4268
4269 return ret;
4270}
4271
Matus Kyseld8c08b12020-06-26 14:46:11 +02004272#ifdef __NR_ipc
4273#if defined(__sparc__)
4274/* SPARC for msgrcv it does not use the kludge on final 2 arguments. */
4275#define MSGRCV_ARGS(__msgp, __msgtyp) __msgp, __msgtyp
4276#elif defined(__s390x__)
4277/* The s390 sys_ipc variant has only five parameters. */
4278#define MSGRCV_ARGS(__msgp, __msgtyp) \
4279 ((long int[]){(long int)__msgp, __msgtyp})
4280#else
4281#define MSGRCV_ARGS(__msgp, __msgtyp) \
4282 ((long int[]){(long int)__msgp, __msgtyp}), 0
4283#endif
4284#endif
4285
blueswir1992f48a2007-10-14 16:27:31 +00004286static inline abi_long do_msgrcv(int msqid, abi_long msgp,
Peter Maydell99874f62016-05-20 19:00:56 +01004287 ssize_t msgsz, abi_long msgtyp,
blueswir1992f48a2007-10-14 16:27:31 +00004288 int msgflg)
ths1bc012f2007-06-03 14:27:49 +00004289{
4290 struct target_msgbuf *target_mb;
bellard579a97f2007-11-11 14:26:47 +00004291 char *target_mtext;
ths1bc012f2007-06-03 14:27:49 +00004292 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00004293 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00004294
Peter Maydell99874f62016-05-20 19:00:56 +01004295 if (msgsz < 0) {
4296 return -TARGET_EINVAL;
4297 }
4298
bellard579a97f2007-11-11 14:26:47 +00004299 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
4300 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00004301
Peter Maydell415d8472016-05-20 19:00:57 +01004302 host_mb = g_try_malloc(msgsz + sizeof(long));
4303 if (!host_mb) {
4304 ret = -TARGET_ENOMEM;
4305 goto end;
4306 }
Laurent Vivier524fa342019-05-29 10:48:04 +02004307 ret = -TARGET_ENOSYS;
4308#ifdef __NR_msgrcv
Peter Maydell89f9fe42016-06-06 19:58:05 +01004309 ret = get_errno(safe_msgrcv(msqid, host_mb, msgsz, msgtyp, msgflg));
Laurent Vivier524fa342019-05-29 10:48:04 +02004310#endif
4311#ifdef __NR_ipc
4312 if (ret == -TARGET_ENOSYS) {
4313 ret = get_errno(safe_ipc(IPCOP_CALL(1, IPCOP_msgrcv), msqid, msgsz,
Matus Kyseld8c08b12020-06-26 14:46:11 +02004314 msgflg, MSGRCV_ARGS(host_mb, msgtyp)));
Laurent Vivier524fa342019-05-29 10:48:04 +02004315 }
4316#endif
aurel321c54ff92008-10-13 21:08:44 +00004317
bellard579a97f2007-11-11 14:26:47 +00004318 if (ret > 0) {
4319 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
4320 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
4321 if (!target_mtext) {
4322 ret = -TARGET_EFAULT;
4323 goto end;
4324 }
aurel321c54ff92008-10-13 21:08:44 +00004325 memcpy(target_mb->mtext, host_mb->mtext, ret);
bellard579a97f2007-11-11 14:26:47 +00004326 unlock_user(target_mtext, target_mtext_addr, ret);
4327 }
aurel321c54ff92008-10-13 21:08:44 +00004328
Matthias Brauncbb21ee2011-08-12 19:57:41 +02004329 target_mb->mtype = tswapal(host_mb->mtype);
ths1bc012f2007-06-03 14:27:49 +00004330
bellard579a97f2007-11-11 14:26:47 +00004331end:
4332 if (target_mb)
4333 unlock_user_struct(target_mb, msgp, 1);
Jim Meyering0d07fe42012-08-22 13:55:53 +02004334 g_free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00004335 return ret;
4336}
4337
Riku Voipio88a8c982009-04-03 10:42:00 +03004338static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
4339 abi_ulong target_addr)
4340{
4341 struct target_shmid_ds *target_sd;
4342
4343 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
4344 return -TARGET_EFAULT;
4345 if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
4346 return -TARGET_EFAULT;
4347 __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
4348 __get_user(host_sd->shm_atime, &target_sd->shm_atime);
4349 __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
4350 __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
4351 __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
4352 __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
4353 __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
4354 unlock_user_struct(target_sd, target_addr, 0);
4355 return 0;
4356}
4357
4358static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
4359 struct shmid_ds *host_sd)
4360{
4361 struct target_shmid_ds *target_sd;
4362
4363 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
4364 return -TARGET_EFAULT;
4365 if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
4366 return -TARGET_EFAULT;
4367 __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
4368 __put_user(host_sd->shm_atime, &target_sd->shm_atime);
4369 __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
4370 __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
4371 __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
4372 __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
4373 __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
4374 unlock_user_struct(target_sd, target_addr, 1);
4375 return 0;
4376}
4377
4378struct target_shminfo {
4379 abi_ulong shmmax;
4380 abi_ulong shmmin;
4381 abi_ulong shmmni;
4382 abi_ulong shmseg;
4383 abi_ulong shmall;
4384};
4385
4386static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
4387 struct shminfo *host_shminfo)
4388{
4389 struct target_shminfo *target_shminfo;
4390 if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
4391 return -TARGET_EFAULT;
4392 __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
4393 __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
4394 __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
4395 __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
4396 __put_user(host_shminfo->shmall, &target_shminfo->shmall);
4397 unlock_user_struct(target_shminfo, target_addr, 1);
4398 return 0;
4399}
4400
4401struct target_shm_info {
4402 int used_ids;
4403 abi_ulong shm_tot;
4404 abi_ulong shm_rss;
4405 abi_ulong shm_swp;
4406 abi_ulong swap_attempts;
4407 abi_ulong swap_successes;
4408};
4409
4410static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
4411 struct shm_info *host_shm_info)
4412{
4413 struct target_shm_info *target_shm_info;
4414 if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
4415 return -TARGET_EFAULT;
4416 __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
4417 __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
4418 __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
4419 __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
4420 __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
4421 __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
4422 unlock_user_struct(target_shm_info, target_addr, 1);
4423 return 0;
4424}
4425
4426static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
4427{
4428 struct shmid_ds dsarg;
4429 struct shminfo shminfo;
4430 struct shm_info shm_info;
4431 abi_long ret = -TARGET_EINVAL;
4432
4433 cmd &= 0xff;
4434
4435 switch(cmd) {
4436 case IPC_STAT:
4437 case IPC_SET:
4438 case SHM_STAT:
4439 if (target_to_host_shmid_ds(&dsarg, buf))
4440 return -TARGET_EFAULT;
4441 ret = get_errno(shmctl(shmid, cmd, &dsarg));
4442 if (host_to_target_shmid_ds(buf, &dsarg))
4443 return -TARGET_EFAULT;
4444 break;
4445 case IPC_INFO:
4446 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
4447 if (host_to_target_shminfo(buf, &shminfo))
4448 return -TARGET_EFAULT;
4449 break;
4450 case SHM_INFO:
4451 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
4452 if (host_to_target_shm_info(buf, &shm_info))
4453 return -TARGET_EFAULT;
4454 break;
4455 case IPC_RMID:
4456 case SHM_LOCK:
4457 case SHM_UNLOCK:
4458 ret = get_errno(shmctl(shmid, cmd, NULL));
4459 break;
4460 }
4461
4462 return ret;
4463}
4464
Peter Maydellee8e7612016-07-11 16:48:11 +01004465#ifndef TARGET_FORCE_SHMLBA
4466/* For most architectures, SHMLBA is the same as the page size;
4467 * some architectures have larger values, in which case they should
4468 * define TARGET_FORCE_SHMLBA and provide a target_shmlba() function.
4469 * This corresponds to the kernel arch code defining __ARCH_FORCE_SHMLBA
4470 * and defining its own value for SHMLBA.
4471 *
4472 * The kernel also permits SHMLBA to be set by the architecture to a
4473 * value larger than the page size without setting __ARCH_FORCE_SHMLBA;
4474 * this means that addresses are rounded to the large size if
4475 * SHM_RND is set but addresses not aligned to that size are not rejected
4476 * as long as they are at least page-aligned. Since the only architecture
4477 * which uses this is ia64 this code doesn't provide for that oddity.
4478 */
4479static inline abi_ulong target_shmlba(CPUArchState *cpu_env)
4480{
4481 return TARGET_PAGE_SIZE;
4482}
4483#endif
4484
4485static inline abi_ulong do_shmat(CPUArchState *cpu_env,
4486 int shmid, abi_ulong shmaddr, int shmflg)
Riku Voipio88a8c982009-04-03 10:42:00 +03004487{
Richard Henderson228168c2021-06-11 23:08:28 -07004488 CPUState *cpu = env_cpu(cpu_env);
Riku Voipio88a8c982009-04-03 10:42:00 +03004489 abi_long raddr;
4490 void *host_raddr;
4491 struct shmid_ds shm_info;
4492 int i,ret;
Peter Maydellee8e7612016-07-11 16:48:11 +01004493 abi_ulong shmlba;
Riku Voipio88a8c982009-04-03 10:42:00 +03004494
Richard Hendersonee1bf832021-02-12 10:48:44 -08004495 /* shmat pointers are always untagged */
4496
Riku Voipio88a8c982009-04-03 10:42:00 +03004497 /* find out the length of the shared memory segment */
4498 ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
4499 if (is_error(ret)) {
4500 /* can't get length, bail out */
4501 return ret;
4502 }
4503
Peter Maydellee8e7612016-07-11 16:48:11 +01004504 shmlba = target_shmlba(cpu_env);
4505
4506 if (shmaddr & (shmlba - 1)) {
4507 if (shmflg & SHM_RND) {
4508 shmaddr &= ~(shmlba - 1);
4509 } else {
4510 return -TARGET_EINVAL;
4511 }
4512 }
Richard Henderson46b12f42021-02-12 10:48:46 -08004513 if (!guest_range_valid_untagged(shmaddr, shm_info.shm_segsz)) {
Max Filippovebf9a362018-03-07 13:50:10 -08004514 return -TARGET_EINVAL;
4515 }
Peter Maydellee8e7612016-07-11 16:48:11 +01004516
Riku Voipio88a8c982009-04-03 10:42:00 +03004517 mmap_lock();
4518
Richard Henderson228168c2021-06-11 23:08:28 -07004519 /*
4520 * We're mapping shared memory, so ensure we generate code for parallel
4521 * execution and flush old translations. This will work up to the level
4522 * supported by the host -- anything that requires EXCP_ATOMIC will not
4523 * be atomic with respect to an external process.
4524 */
4525 if (!(cpu->tcg_cflags & CF_PARALLEL)) {
4526 cpu->tcg_cflags |= CF_PARALLEL;
4527 tb_flush(cpu);
4528 }
4529
Riku Voipio88a8c982009-04-03 10:42:00 +03004530 if (shmaddr)
Richard Henderson3e8f1622021-02-12 10:48:43 -08004531 host_raddr = shmat(shmid, (void *)g2h_untagged(shmaddr), shmflg);
Riku Voipio88a8c982009-04-03 10:42:00 +03004532 else {
4533 abi_ulong mmap_start;
4534
Richard Henderson30ab9ef2019-05-19 13:19:52 -07004535 /* In order to use the host shmat, we need to honor host SHMLBA. */
4536 mmap_start = mmap_find_vma(0, shm_info.shm_segsz, MAX(SHMLBA, shmlba));
Riku Voipio88a8c982009-04-03 10:42:00 +03004537
4538 if (mmap_start == -1) {
4539 errno = ENOMEM;
4540 host_raddr = (void *)-1;
4541 } else
Richard Henderson3e8f1622021-02-12 10:48:43 -08004542 host_raddr = shmat(shmid, g2h_untagged(mmap_start),
4543 shmflg | SHM_REMAP);
Riku Voipio88a8c982009-04-03 10:42:00 +03004544 }
4545
4546 if (host_raddr == (void *)-1) {
4547 mmap_unlock();
4548 return get_errno((long)host_raddr);
4549 }
4550 raddr=h2g((unsigned long)host_raddr);
4551
4552 page_set_flags(raddr, raddr + shm_info.shm_segsz,
Richard Hendersond9c58582021-02-12 10:48:32 -08004553 PAGE_VALID | PAGE_RESET | PAGE_READ |
4554 (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
Riku Voipio88a8c982009-04-03 10:42:00 +03004555
4556 for (i = 0; i < N_SHM_REGIONS; i++) {
Peter Maydellb6e17872016-02-09 15:57:11 +00004557 if (!shm_regions[i].in_use) {
4558 shm_regions[i].in_use = true;
Riku Voipio88a8c982009-04-03 10:42:00 +03004559 shm_regions[i].start = raddr;
4560 shm_regions[i].size = shm_info.shm_segsz;
4561 break;
4562 }
4563 }
4564
4565 mmap_unlock();
4566 return raddr;
4567
4568}
4569
4570static inline abi_long do_shmdt(abi_ulong shmaddr)
4571{
4572 int i;
Max Filippov3c5f6a52018-02-28 14:16:04 -08004573 abi_long rv;
4574
Richard Hendersonee1bf832021-02-12 10:48:44 -08004575 /* shmdt pointers are always untagged */
4576
Max Filippov3c5f6a52018-02-28 14:16:04 -08004577 mmap_lock();
Riku Voipio88a8c982009-04-03 10:42:00 +03004578
4579 for (i = 0; i < N_SHM_REGIONS; ++i) {
Peter Maydellb6e17872016-02-09 15:57:11 +00004580 if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
4581 shm_regions[i].in_use = false;
takasi-y@ops.dti.ne.jpe00ac242010-04-11 02:09:57 +09004582 page_set_flags(shmaddr, shmaddr + shm_regions[i].size, 0);
Riku Voipio88a8c982009-04-03 10:42:00 +03004583 break;
4584 }
4585 }
Richard Henderson3e8f1622021-02-12 10:48:43 -08004586 rv = get_errno(shmdt(g2h_untagged(shmaddr)));
Riku Voipio88a8c982009-04-03 10:42:00 +03004587
Max Filippov3c5f6a52018-02-28 14:16:04 -08004588 mmap_unlock();
4589
4590 return rv;
Riku Voipio88a8c982009-04-03 10:42:00 +03004591}
4592
aurel321c54ff92008-10-13 21:08:44 +00004593#ifdef TARGET_NR_ipc
pbrook53a59602006-03-25 19:31:22 +00004594/* ??? This only works with linear mappings. */
ths0da46a62007-10-20 20:23:07 +00004595/* do_ipc() must return target values and target errnos. */
Peter Maydellee8e7612016-07-11 16:48:11 +01004596static abi_long do_ipc(CPUArchState *cpu_env,
4597 unsigned int call, abi_long first,
Tom Musta37ed0952014-08-12 13:53:35 -05004598 abi_long second, abi_long third,
blueswir1992f48a2007-10-14 16:27:31 +00004599 abi_long ptr, abi_long fifth)
bellard8853f862004-02-22 14:57:26 +00004600{
4601 int version;
blueswir1992f48a2007-10-14 16:27:31 +00004602 abi_long ret = 0;
bellard8853f862004-02-22 14:57:26 +00004603
4604 version = call >> 16;
4605 call &= 0xffff;
4606
4607 switch (call) {
thsfa294812007-02-02 22:05:00 +00004608 case IPCOP_semop:
Filip Bozutacac46eb2020-08-25 00:30:50 +02004609 ret = do_semtimedop(first, ptr, second, 0, false);
Matus Kyseld8c08b12020-06-26 14:46:11 +02004610 break;
4611 case IPCOP_semtimedop:
4612 /*
4613 * The s390 sys_ipc variant has only five parameters instead of six
4614 * (as for default variant) and the only difference is the handling of
4615 * SEMTIMEDOP where on s390 the third parameter is used as a pointer
4616 * to a struct timespec where the generic variant uses fifth parameter.
4617 */
4618#if defined(TARGET_S390X)
Filip Bozutacac46eb2020-08-25 00:30:50 +02004619 ret = do_semtimedop(first, ptr, second, third, TARGET_ABI_BITS == 64);
Matus Kyseld8c08b12020-06-26 14:46:11 +02004620#else
Filip Bozutacac46eb2020-08-25 00:30:50 +02004621 ret = do_semtimedop(first, ptr, second, fifth, TARGET_ABI_BITS == 64);
Matus Kyseld8c08b12020-06-26 14:46:11 +02004622#endif
thsfa294812007-02-02 22:05:00 +00004623 break;
4624
4625 case IPCOP_semget:
4626 ret = get_errno(semget(first, second, third));
4627 break;
4628
Tom Musta5d2fa8e2014-08-12 13:53:33 -05004629 case IPCOP_semctl: {
4630 /* The semun argument to semctl is passed by value, so dereference the
4631 * ptr argument. */
4632 abi_ulong atptr;
Tom Musta37ed0952014-08-12 13:53:35 -05004633 get_user_ual(atptr, ptr);
Stefan Weild1c002b2015-02-08 15:40:58 +01004634 ret = do_semctl(first, second, third, atptr);
thsfa294812007-02-02 22:05:00 +00004635 break;
Tom Musta5d2fa8e2014-08-12 13:53:33 -05004636 }
thsd96372e2007-02-02 22:05:44 +00004637
aurel321c54ff92008-10-13 21:08:44 +00004638 case IPCOP_msgget:
4639 ret = get_errno(msgget(first, second));
4640 break;
thsd96372e2007-02-02 22:05:44 +00004641
aurel321c54ff92008-10-13 21:08:44 +00004642 case IPCOP_msgsnd:
4643 ret = do_msgsnd(first, ptr, second, third);
4644 break;
thsd96372e2007-02-02 22:05:44 +00004645
aurel321c54ff92008-10-13 21:08:44 +00004646 case IPCOP_msgctl:
4647 ret = do_msgctl(first, second, ptr);
4648 break;
thsd96372e2007-02-02 22:05:44 +00004649
aurel321c54ff92008-10-13 21:08:44 +00004650 case IPCOP_msgrcv:
4651 switch (version) {
4652 case 0:
4653 {
4654 struct target_ipc_kludge {
4655 abi_long msgp;
4656 abi_long msgtyp;
4657 } *tmp;
thsd96372e2007-02-02 22:05:44 +00004658
aurel321c54ff92008-10-13 21:08:44 +00004659 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
4660 ret = -TARGET_EFAULT;
4661 break;
ths1bc012f2007-06-03 14:27:49 +00004662 }
aurel321c54ff92008-10-13 21:08:44 +00004663
Laurent Vivier79dd77d2012-12-20 11:00:11 +00004664 ret = do_msgrcv(first, tswapal(tmp->msgp), second, tswapal(tmp->msgtyp), third);
aurel321c54ff92008-10-13 21:08:44 +00004665
4666 unlock_user_struct(tmp, ptr, 0);
4667 break;
4668 }
4669 default:
4670 ret = do_msgrcv(first, ptr, second, fifth, third);
4671 }
4672 break;
thsd96372e2007-02-02 22:05:44 +00004673
bellard8853f862004-02-22 14:57:26 +00004674 case IPCOP_shmat:
Riku Voipio88a8c982009-04-03 10:42:00 +03004675 switch (version) {
4676 default:
bellard5a4a8982007-11-11 17:39:18 +00004677 {
4678 abi_ulong raddr;
Peter Maydellee8e7612016-07-11 16:48:11 +01004679 raddr = do_shmat(cpu_env, first, ptr, second);
Riku Voipio88a8c982009-04-03 10:42:00 +03004680 if (is_error(raddr))
4681 return get_errno(raddr);
bellard2f619692007-11-16 10:46:05 +00004682 if (put_user_ual(raddr, third))
bellard5a4a8982007-11-11 17:39:18 +00004683 return -TARGET_EFAULT;
Riku Voipio88a8c982009-04-03 10:42:00 +03004684 break;
4685 }
4686 case 1:
4687 ret = -TARGET_EINVAL;
4688 break;
bellard5a4a8982007-11-11 17:39:18 +00004689 }
bellard8853f862004-02-22 14:57:26 +00004690 break;
4691 case IPCOP_shmdt:
Riku Voipio88a8c982009-04-03 10:42:00 +03004692 ret = do_shmdt(ptr);
bellard8853f862004-02-22 14:57:26 +00004693 break;
4694
4695 case IPCOP_shmget:
4696 /* IPC_* flag values are the same on all linux platforms */
4697 ret = get_errno(shmget(first, second, third));
4698 break;
4699
4700 /* IPC_* and SHM_* command values are the same on all linux platforms */
4701 case IPCOP_shmctl:
Petar Jovanovica2926782013-10-30 14:46:32 +01004702 ret = do_shmctl(first, second, ptr);
bellard8853f862004-02-22 14:57:26 +00004703 break;
4704 default:
Josh Kunz39be5352020-02-03 18:54:13 -08004705 qemu_log_mask(LOG_UNIMP, "Unsupported ipc call: %d (version %d)\n",
4706 call, version);
ths0da46a62007-10-20 20:23:07 +00004707 ret = -TARGET_ENOSYS;
bellard8853f862004-02-22 14:57:26 +00004708 break;
4709 }
4710 return ret;
4711}
j_mayer32407102007-09-26 23:01:49 +00004712#endif
bellard8853f862004-02-22 14:57:26 +00004713
bellard31e31b82003-02-18 22:55:36 +00004714/* kernel structure types definitions */
bellard31e31b82003-02-18 22:55:36 +00004715
Blue Swirl001faf32009-05-13 17:53:17 +00004716#define STRUCT(name, ...) STRUCT_ ## name,
bellard31e31b82003-02-18 22:55:36 +00004717#define STRUCT_SPECIAL(name) STRUCT_ ## name,
4718enum {
4719#include "syscall_types.h"
Alexander Graf8be656b2015-05-06 23:47:32 +02004720STRUCT_MAX
bellard31e31b82003-02-18 22:55:36 +00004721};
4722#undef STRUCT
4723#undef STRUCT_SPECIAL
4724
Blue Swirl001faf32009-05-13 17:53:17 +00004725#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
bellard31e31b82003-02-18 22:55:36 +00004726#define STRUCT_SPECIAL(name)
4727#include "syscall_types.h"
4728#undef STRUCT
4729#undef STRUCT_SPECIAL
4730
bellard31e31b82003-02-18 22:55:36 +00004731#define MAX_STRUCT_SIZE 4096
4732
Peter Maydelldace20d2011-01-10 13:11:24 +00004733#ifdef CONFIG_FIEMAP
Peter Maydell285da2b2011-01-06 15:04:18 +00004734/* So fiemap access checks don't overflow on 32 bit systems.
4735 * This is very slightly smaller than the limit imposed by
4736 * the underlying kernel.
4737 */
4738#define FIEMAP_MAX_EXTENTS ((UINT_MAX - sizeof(struct fiemap)) \
4739 / sizeof(struct fiemap_extent))
4740
4741static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004742 int fd, int cmd, abi_long arg)
Peter Maydell285da2b2011-01-06 15:04:18 +00004743{
4744 /* The parameter for this ioctl is a struct fiemap followed
4745 * by an array of struct fiemap_extent whose size is set
4746 * in fiemap->fm_extent_count. The array is filled in by the
4747 * ioctl.
4748 */
4749 int target_size_in, target_size_out;
4750 struct fiemap *fm;
4751 const argtype *arg_type = ie->arg_type;
4752 const argtype extent_arg_type[] = { MK_STRUCT(STRUCT_fiemap_extent) };
4753 void *argptr, *p;
4754 abi_long ret;
4755 int i, extent_size = thunk_type_size(extent_arg_type, 0);
4756 uint32_t outbufsz;
4757 int free_fm = 0;
4758
4759 assert(arg_type[0] == TYPE_PTR);
4760 assert(ie->access == IOC_RW);
4761 arg_type++;
4762 target_size_in = thunk_type_size(arg_type, 0);
4763 argptr = lock_user(VERIFY_READ, arg, target_size_in, 1);
4764 if (!argptr) {
4765 return -TARGET_EFAULT;
4766 }
4767 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4768 unlock_user(argptr, arg, 0);
4769 fm = (struct fiemap *)buf_temp;
4770 if (fm->fm_extent_count > FIEMAP_MAX_EXTENTS) {
4771 return -TARGET_EINVAL;
4772 }
4773
4774 outbufsz = sizeof (*fm) +
4775 (sizeof(struct fiemap_extent) * fm->fm_extent_count);
4776
4777 if (outbufsz > MAX_STRUCT_SIZE) {
4778 /* We can't fit all the extents into the fixed size buffer.
4779 * Allocate one that is large enough and use it instead.
4780 */
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304781 fm = g_try_malloc(outbufsz);
Peter Maydell285da2b2011-01-06 15:04:18 +00004782 if (!fm) {
4783 return -TARGET_ENOMEM;
4784 }
4785 memcpy(fm, buf_temp, sizeof(struct fiemap));
4786 free_fm = 1;
4787 }
Peter Maydell49ca6f32016-06-06 19:58:14 +01004788 ret = get_errno(safe_ioctl(fd, ie->host_cmd, fm));
Peter Maydell285da2b2011-01-06 15:04:18 +00004789 if (!is_error(ret)) {
4790 target_size_out = target_size_in;
4791 /* An extent_count of 0 means we were only counting the extents
4792 * so there are no structs to copy
4793 */
4794 if (fm->fm_extent_count != 0) {
4795 target_size_out += fm->fm_mapped_extents * extent_size;
4796 }
4797 argptr = lock_user(VERIFY_WRITE, arg, target_size_out, 0);
4798 if (!argptr) {
4799 ret = -TARGET_EFAULT;
4800 } else {
4801 /* Convert the struct fiemap */
4802 thunk_convert(argptr, fm, arg_type, THUNK_TARGET);
4803 if (fm->fm_extent_count != 0) {
4804 p = argptr + target_size_in;
4805 /* ...and then all the struct fiemap_extents */
4806 for (i = 0; i < fm->fm_mapped_extents; i++) {
4807 thunk_convert(p, &fm->fm_extents[i], extent_arg_type,
4808 THUNK_TARGET);
4809 p += extent_size;
4810 }
4811 }
4812 unlock_user(argptr, arg, target_size_out);
4813 }
4814 }
4815 if (free_fm) {
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304816 g_free(fm);
Peter Maydell285da2b2011-01-06 15:04:18 +00004817 }
4818 return ret;
4819}
Peter Maydelldace20d2011-01-10 13:11:24 +00004820#endif
Peter Maydell285da2b2011-01-06 15:04:18 +00004821
Laurent Vivier059c2f22011-03-30 00:12:12 +02004822static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004823 int fd, int cmd, abi_long arg)
Laurent Vivier059c2f22011-03-30 00:12:12 +02004824{
4825 const argtype *arg_type = ie->arg_type;
4826 int target_size;
4827 void *argptr;
4828 int ret;
4829 struct ifconf *host_ifconf;
4830 uint32_t outbufsz;
4831 const argtype ifreq_arg_type[] = { MK_STRUCT(STRUCT_sockaddr_ifreq) };
Stefan4df7b7f2021-01-09 19:59:42 +01004832 const argtype ifreq_max_type[] = { MK_STRUCT(STRUCT_ifmap_ifreq) };
Laurent Vivier059c2f22011-03-30 00:12:12 +02004833 int target_ifreq_size;
4834 int nb_ifreq;
4835 int free_buf = 0;
4836 int i;
4837 int target_ifc_len;
4838 abi_long target_ifc_buf;
4839 int host_ifc_len;
4840 char *host_ifc_buf;
4841
4842 assert(arg_type[0] == TYPE_PTR);
4843 assert(ie->access == IOC_RW);
4844
4845 arg_type++;
4846 target_size = thunk_type_size(arg_type, 0);
4847
4848 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4849 if (!argptr)
4850 return -TARGET_EFAULT;
4851 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4852 unlock_user(argptr, arg, 0);
4853
4854 host_ifconf = (struct ifconf *)(unsigned long)buf_temp;
Laurent Vivier059c2f22011-03-30 00:12:12 +02004855 target_ifc_buf = (abi_long)(unsigned long)host_ifconf->ifc_buf;
Stefan4df7b7f2021-01-09 19:59:42 +01004856 target_ifreq_size = thunk_type_size(ifreq_max_type, 0);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004857
Kan Li22e4a2672018-10-24 20:13:03 +00004858 if (target_ifc_buf != 0) {
4859 target_ifc_len = host_ifconf->ifc_len;
4860 nb_ifreq = target_ifc_len / target_ifreq_size;
4861 host_ifc_len = nb_ifreq * sizeof(struct ifreq);
4862
4863 outbufsz = sizeof(*host_ifconf) + host_ifc_len;
4864 if (outbufsz > MAX_STRUCT_SIZE) {
4865 /*
4866 * We can't fit all the extents into the fixed size buffer.
4867 * Allocate one that is large enough and use it instead.
4868 */
Ahmed Abouzied7a5626a2022-01-04 16:38:41 +02004869 host_ifconf = g_try_malloc(outbufsz);
Kan Li22e4a2672018-10-24 20:13:03 +00004870 if (!host_ifconf) {
4871 return -TARGET_ENOMEM;
4872 }
4873 memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf));
4874 free_buf = 1;
Laurent Vivier059c2f22011-03-30 00:12:12 +02004875 }
Kan Li22e4a2672018-10-24 20:13:03 +00004876 host_ifc_buf = (char *)host_ifconf + sizeof(*host_ifconf);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004877
Kan Li22e4a2672018-10-24 20:13:03 +00004878 host_ifconf->ifc_len = host_ifc_len;
4879 } else {
4880 host_ifc_buf = NULL;
4881 }
Laurent Vivier059c2f22011-03-30 00:12:12 +02004882 host_ifconf->ifc_buf = host_ifc_buf;
4883
Peter Maydell49ca6f32016-06-06 19:58:14 +01004884 ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_ifconf));
Laurent Vivier059c2f22011-03-30 00:12:12 +02004885 if (!is_error(ret)) {
4886 /* convert host ifc_len to target ifc_len */
4887
4888 nb_ifreq = host_ifconf->ifc_len / sizeof(struct ifreq);
4889 target_ifc_len = nb_ifreq * target_ifreq_size;
4890 host_ifconf->ifc_len = target_ifc_len;
4891
4892 /* restore target ifc_buf */
4893
4894 host_ifconf->ifc_buf = (char *)(unsigned long)target_ifc_buf;
4895
4896 /* copy struct ifconf to target user */
4897
4898 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
4899 if (!argptr)
4900 return -TARGET_EFAULT;
4901 thunk_convert(argptr, host_ifconf, arg_type, THUNK_TARGET);
4902 unlock_user(argptr, arg, target_size);
4903
Kan Li22e4a2672018-10-24 20:13:03 +00004904 if (target_ifc_buf != 0) {
4905 /* copy ifreq[] to target user */
4906 argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0);
4907 for (i = 0; i < nb_ifreq ; i++) {
4908 thunk_convert(argptr + i * target_ifreq_size,
4909 host_ifc_buf + i * sizeof(struct ifreq),
4910 ifreq_arg_type, THUNK_TARGET);
4911 }
4912 unlock_user(argptr, target_ifc_buf, target_ifc_len);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004913 }
Laurent Vivier059c2f22011-03-30 00:12:12 +02004914 }
4915
4916 if (free_buf) {
Ahmed Abouzied7a5626a2022-01-04 16:38:41 +02004917 g_free(host_ifconf);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004918 }
4919
4920 return ret;
4921}
4922
Cortland Tölvaa1333672018-10-08 09:35:21 -07004923#if defined(CONFIG_USBFS)
4924#if HOST_LONG_BITS > 64
4925#error USBDEVFS thunks do not support >64 bit hosts yet.
4926#endif
4927struct live_urb {
4928 uint64_t target_urb_adr;
4929 uint64_t target_buf_adr;
4930 char *target_buf_ptr;
4931 struct usbdevfs_urb host_urb;
4932};
4933
4934static GHashTable *usbdevfs_urb_hashtable(void)
4935{
4936 static GHashTable *urb_hashtable;
4937
4938 if (!urb_hashtable) {
4939 urb_hashtable = g_hash_table_new(g_int64_hash, g_int64_equal);
4940 }
4941 return urb_hashtable;
4942}
4943
4944static void urb_hashtable_insert(struct live_urb *urb)
4945{
4946 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
4947 g_hash_table_insert(urb_hashtable, urb, urb);
4948}
4949
4950static struct live_urb *urb_hashtable_lookup(uint64_t target_urb_adr)
4951{
4952 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
4953 return g_hash_table_lookup(urb_hashtable, &target_urb_adr);
4954}
4955
4956static void urb_hashtable_remove(struct live_urb *urb)
4957{
4958 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
4959 g_hash_table_remove(urb_hashtable, urb);
4960}
4961
4962static abi_long
4963do_ioctl_usbdevfs_reapurb(const IOCTLEntry *ie, uint8_t *buf_temp,
4964 int fd, int cmd, abi_long arg)
4965{
4966 const argtype usbfsurb_arg_type[] = { MK_STRUCT(STRUCT_usbdevfs_urb) };
4967 const argtype ptrvoid_arg_type[] = { TYPE_PTRVOID, 0, 0 };
4968 struct live_urb *lurb;
4969 void *argptr;
4970 uint64_t hurb;
4971 int target_size;
4972 uintptr_t target_urb_adr;
4973 abi_long ret;
4974
4975 target_size = thunk_type_size(usbfsurb_arg_type, THUNK_TARGET);
4976
4977 memset(buf_temp, 0, sizeof(uint64_t));
4978 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
4979 if (is_error(ret)) {
4980 return ret;
4981 }
4982
4983 memcpy(&hurb, buf_temp, sizeof(uint64_t));
4984 lurb = (void *)((uintptr_t)hurb - offsetof(struct live_urb, host_urb));
4985 if (!lurb->target_urb_adr) {
4986 return -TARGET_EFAULT;
4987 }
4988 urb_hashtable_remove(lurb);
4989 unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr,
4990 lurb->host_urb.buffer_length);
4991 lurb->target_buf_ptr = NULL;
4992
4993 /* restore the guest buffer pointer */
4994 lurb->host_urb.buffer = (void *)(uintptr_t)lurb->target_buf_adr;
4995
4996 /* update the guest urb struct */
4997 argptr = lock_user(VERIFY_WRITE, lurb->target_urb_adr, target_size, 0);
4998 if (!argptr) {
4999 g_free(lurb);
5000 return -TARGET_EFAULT;
5001 }
5002 thunk_convert(argptr, &lurb->host_urb, usbfsurb_arg_type, THUNK_TARGET);
5003 unlock_user(argptr, lurb->target_urb_adr, target_size);
5004
5005 target_size = thunk_type_size(ptrvoid_arg_type, THUNK_TARGET);
5006 /* write back the urb handle */
5007 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5008 if (!argptr) {
5009 g_free(lurb);
5010 return -TARGET_EFAULT;
5011 }
5012
5013 /* GHashTable uses 64-bit keys but thunk_convert expects uintptr_t */
5014 target_urb_adr = lurb->target_urb_adr;
5015 thunk_convert(argptr, &target_urb_adr, ptrvoid_arg_type, THUNK_TARGET);
5016 unlock_user(argptr, arg, target_size);
5017
5018 g_free(lurb);
5019 return ret;
5020}
5021
5022static abi_long
5023do_ioctl_usbdevfs_discardurb(const IOCTLEntry *ie,
5024 uint8_t *buf_temp __attribute__((unused)),
5025 int fd, int cmd, abi_long arg)
5026{
5027 struct live_urb *lurb;
5028
5029 /* map target address back to host URB with metadata. */
5030 lurb = urb_hashtable_lookup(arg);
5031 if (!lurb) {
5032 return -TARGET_EFAULT;
5033 }
5034 return get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
5035}
5036
5037static abi_long
5038do_ioctl_usbdevfs_submiturb(const IOCTLEntry *ie, uint8_t *buf_temp,
5039 int fd, int cmd, abi_long arg)
5040{
5041 const argtype *arg_type = ie->arg_type;
5042 int target_size;
5043 abi_long ret;
5044 void *argptr;
5045 int rw_dir;
5046 struct live_urb *lurb;
5047
5048 /*
5049 * each submitted URB needs to map to a unique ID for the
5050 * kernel, and that unique ID needs to be a pointer to
5051 * host memory. hence, we need to malloc for each URB.
5052 * isochronous transfers have a variable length struct.
5053 */
5054 arg_type++;
5055 target_size = thunk_type_size(arg_type, THUNK_TARGET);
5056
5057 /* construct host copy of urb and metadata */
Markus Armbrusterb21e2382022-03-15 15:41:56 +01005058 lurb = g_try_new0(struct live_urb, 1);
Cortland Tölvaa1333672018-10-08 09:35:21 -07005059 if (!lurb) {
5060 return -TARGET_ENOMEM;
5061 }
5062
5063 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5064 if (!argptr) {
5065 g_free(lurb);
5066 return -TARGET_EFAULT;
5067 }
5068 thunk_convert(&lurb->host_urb, argptr, arg_type, THUNK_HOST);
5069 unlock_user(argptr, arg, 0);
5070
5071 lurb->target_urb_adr = arg;
5072 lurb->target_buf_adr = (uintptr_t)lurb->host_urb.buffer;
5073
5074 /* buffer space used depends on endpoint type so lock the entire buffer */
5075 /* control type urbs should check the buffer contents for true direction */
5076 rw_dir = lurb->host_urb.endpoint & USB_DIR_IN ? VERIFY_WRITE : VERIFY_READ;
5077 lurb->target_buf_ptr = lock_user(rw_dir, lurb->target_buf_adr,
5078 lurb->host_urb.buffer_length, 1);
5079 if (lurb->target_buf_ptr == NULL) {
5080 g_free(lurb);
5081 return -TARGET_EFAULT;
5082 }
5083
5084 /* update buffer pointer in host copy */
5085 lurb->host_urb.buffer = lurb->target_buf_ptr;
5086
5087 ret = get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
5088 if (is_error(ret)) {
5089 unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr, 0);
5090 g_free(lurb);
5091 } else {
5092 urb_hashtable_insert(lurb);
5093 }
5094
5095 return ret;
5096}
5097#endif /* CONFIG_USBFS */
5098
Alexander Graf56e904e2012-01-31 18:42:06 +01005099static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
Laurent Vivier45c874e2015-06-16 00:35:28 +02005100 int cmd, abi_long arg)
Alexander Graf56e904e2012-01-31 18:42:06 +01005101{
5102 void *argptr;
5103 struct dm_ioctl *host_dm;
5104 abi_long guest_data;
5105 uint32_t guest_data_size;
5106 int target_size;
5107 const argtype *arg_type = ie->arg_type;
5108 abi_long ret;
5109 void *big_buf = NULL;
5110 char *host_data;
5111
5112 arg_type++;
5113 target_size = thunk_type_size(arg_type, 0);
5114 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5115 if (!argptr) {
5116 ret = -TARGET_EFAULT;
5117 goto out;
5118 }
5119 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5120 unlock_user(argptr, arg, 0);
5121
5122 /* buf_temp is too small, so fetch things into a bigger buffer */
5123 big_buf = g_malloc0(((struct dm_ioctl*)buf_temp)->data_size * 2);
5124 memcpy(big_buf, buf_temp, target_size);
5125 buf_temp = big_buf;
5126 host_dm = big_buf;
5127
5128 guest_data = arg + host_dm->data_start;
5129 if ((guest_data - arg) < 0) {
Peter Maydellf9757b12016-07-12 13:02:14 +01005130 ret = -TARGET_EINVAL;
Alexander Graf56e904e2012-01-31 18:42:06 +01005131 goto out;
5132 }
5133 guest_data_size = host_dm->data_size - host_dm->data_start;
5134 host_data = (char*)host_dm + host_dm->data_start;
5135
5136 argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1);
Peter Maydell32112152016-07-12 13:02:13 +01005137 if (!argptr) {
5138 ret = -TARGET_EFAULT;
5139 goto out;
5140 }
5141
Alexander Graf56e904e2012-01-31 18:42:06 +01005142 switch (ie->host_cmd) {
5143 case DM_REMOVE_ALL:
5144 case DM_LIST_DEVICES:
5145 case DM_DEV_CREATE:
5146 case DM_DEV_REMOVE:
5147 case DM_DEV_SUSPEND:
5148 case DM_DEV_STATUS:
5149 case DM_DEV_WAIT:
5150 case DM_TABLE_STATUS:
5151 case DM_TABLE_CLEAR:
5152 case DM_TABLE_DEPS:
5153 case DM_LIST_VERSIONS:
5154 /* no input data */
5155 break;
5156 case DM_DEV_RENAME:
5157 case DM_DEV_SET_GEOMETRY:
5158 /* data contains only strings */
5159 memcpy(host_data, argptr, guest_data_size);
5160 break;
5161 case DM_TARGET_MSG:
5162 memcpy(host_data, argptr, guest_data_size);
5163 *(uint64_t*)host_data = tswap64(*(uint64_t*)argptr);
5164 break;
5165 case DM_TABLE_LOAD:
5166 {
5167 void *gspec = argptr;
5168 void *cur_data = host_data;
5169 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
5170 int spec_size = thunk_type_size(arg_type, 0);
5171 int i;
5172
5173 for (i = 0; i < host_dm->target_count; i++) {
5174 struct dm_target_spec *spec = cur_data;
5175 uint32_t next;
5176 int slen;
5177
5178 thunk_convert(spec, gspec, arg_type, THUNK_HOST);
5179 slen = strlen((char*)gspec + spec_size) + 1;
5180 next = spec->next;
5181 spec->next = sizeof(*spec) + slen;
5182 strcpy((char*)&spec[1], gspec + spec_size);
5183 gspec += next;
5184 cur_data += spec->next;
5185 }
5186 break;
5187 }
5188 default:
5189 ret = -TARGET_EINVAL;
Chen Gang Sdec04732015-01-25 08:00:42 +08005190 unlock_user(argptr, guest_data, 0);
Alexander Graf56e904e2012-01-31 18:42:06 +01005191 goto out;
5192 }
5193 unlock_user(argptr, guest_data, 0);
5194
Peter Maydell49ca6f32016-06-06 19:58:14 +01005195 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
Alexander Graf56e904e2012-01-31 18:42:06 +01005196 if (!is_error(ret)) {
5197 guest_data = arg + host_dm->data_start;
5198 guest_data_size = host_dm->data_size - host_dm->data_start;
5199 argptr = lock_user(VERIFY_WRITE, guest_data, guest_data_size, 0);
5200 switch (ie->host_cmd) {
5201 case DM_REMOVE_ALL:
5202 case DM_DEV_CREATE:
5203 case DM_DEV_REMOVE:
5204 case DM_DEV_RENAME:
5205 case DM_DEV_SUSPEND:
5206 case DM_DEV_STATUS:
5207 case DM_TABLE_LOAD:
5208 case DM_TABLE_CLEAR:
5209 case DM_TARGET_MSG:
5210 case DM_DEV_SET_GEOMETRY:
5211 /* no return data */
5212 break;
5213 case DM_LIST_DEVICES:
5214 {
5215 struct dm_name_list *nl = (void*)host_dm + host_dm->data_start;
5216 uint32_t remaining_data = guest_data_size;
5217 void *cur_data = argptr;
5218 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
5219 int nl_size = 12; /* can't use thunk_size due to alignment */
5220
5221 while (1) {
5222 uint32_t next = nl->next;
5223 if (next) {
5224 nl->next = nl_size + (strlen(nl->name) + 1);
5225 }
5226 if (remaining_data < nl->next) {
5227 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5228 break;
5229 }
5230 thunk_convert(cur_data, nl, arg_type, THUNK_TARGET);
5231 strcpy(cur_data + nl_size, nl->name);
5232 cur_data += nl->next;
5233 remaining_data -= nl->next;
5234 if (!next) {
5235 break;
5236 }
5237 nl = (void*)nl + next;
5238 }
5239 break;
5240 }
5241 case DM_DEV_WAIT:
5242 case DM_TABLE_STATUS:
5243 {
5244 struct dm_target_spec *spec = (void*)host_dm + host_dm->data_start;
5245 void *cur_data = argptr;
5246 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
5247 int spec_size = thunk_type_size(arg_type, 0);
5248 int i;
5249
5250 for (i = 0; i < host_dm->target_count; i++) {
5251 uint32_t next = spec->next;
5252 int slen = strlen((char*)&spec[1]) + 1;
5253 spec->next = (cur_data - argptr) + spec_size + slen;
5254 if (guest_data_size < spec->next) {
5255 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5256 break;
5257 }
5258 thunk_convert(cur_data, spec, arg_type, THUNK_TARGET);
5259 strcpy(cur_data + spec_size, (char*)&spec[1]);
5260 cur_data = argptr + spec->next;
5261 spec = (void*)host_dm + host_dm->data_start + next;
5262 }
5263 break;
5264 }
5265 case DM_TABLE_DEPS:
5266 {
5267 void *hdata = (void*)host_dm + host_dm->data_start;
5268 int count = *(uint32_t*)hdata;
5269 uint64_t *hdev = hdata + 8;
5270 uint64_t *gdev = argptr + 8;
5271 int i;
5272
5273 *(uint32_t*)argptr = tswap32(count);
5274 for (i = 0; i < count; i++) {
5275 *gdev = tswap64(*hdev);
5276 gdev++;
5277 hdev++;
5278 }
5279 break;
5280 }
5281 case DM_LIST_VERSIONS:
5282 {
5283 struct dm_target_versions *vers = (void*)host_dm + host_dm->data_start;
5284 uint32_t remaining_data = guest_data_size;
5285 void *cur_data = argptr;
5286 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_versions) };
5287 int vers_size = thunk_type_size(arg_type, 0);
5288
5289 while (1) {
5290 uint32_t next = vers->next;
5291 if (next) {
5292 vers->next = vers_size + (strlen(vers->name) + 1);
5293 }
5294 if (remaining_data < vers->next) {
5295 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5296 break;
5297 }
5298 thunk_convert(cur_data, vers, arg_type, THUNK_TARGET);
5299 strcpy(cur_data + vers_size, vers->name);
5300 cur_data += vers->next;
5301 remaining_data -= vers->next;
5302 if (!next) {
5303 break;
5304 }
5305 vers = (void*)vers + next;
5306 }
5307 break;
5308 }
5309 default:
Chen Gang Sdec04732015-01-25 08:00:42 +08005310 unlock_user(argptr, guest_data, 0);
Alexander Graf56e904e2012-01-31 18:42:06 +01005311 ret = -TARGET_EINVAL;
5312 goto out;
5313 }
5314 unlock_user(argptr, guest_data, guest_data_size);
5315
5316 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5317 if (!argptr) {
5318 ret = -TARGET_EFAULT;
5319 goto out;
5320 }
5321 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5322 unlock_user(argptr, arg, target_size);
5323 }
5324out:
Stefan Weilad11ad72012-09-04 22:14:19 +02005325 g_free(big_buf);
Alexander Graf56e904e2012-01-31 18:42:06 +01005326 return ret;
5327}
5328
Alexander Grafa59b5e32014-08-22 13:15:50 +02005329static abi_long do_ioctl_blkpg(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
Laurent Vivier45c874e2015-06-16 00:35:28 +02005330 int cmd, abi_long arg)
Alexander Grafa59b5e32014-08-22 13:15:50 +02005331{
5332 void *argptr;
5333 int target_size;
5334 const argtype *arg_type = ie->arg_type;
5335 const argtype part_arg_type[] = { MK_STRUCT(STRUCT_blkpg_partition) };
5336 abi_long ret;
5337
5338 struct blkpg_ioctl_arg *host_blkpg = (void*)buf_temp;
5339 struct blkpg_partition host_part;
5340
5341 /* Read and convert blkpg */
5342 arg_type++;
5343 target_size = thunk_type_size(arg_type, 0);
5344 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5345 if (!argptr) {
5346 ret = -TARGET_EFAULT;
5347 goto out;
5348 }
5349 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5350 unlock_user(argptr, arg, 0);
5351
5352 switch (host_blkpg->op) {
5353 case BLKPG_ADD_PARTITION:
5354 case BLKPG_DEL_PARTITION:
5355 /* payload is struct blkpg_partition */
5356 break;
5357 default:
5358 /* Unknown opcode */
5359 ret = -TARGET_EINVAL;
5360 goto out;
5361 }
5362
5363 /* Read and convert blkpg->data */
5364 arg = (abi_long)(uintptr_t)host_blkpg->data;
5365 target_size = thunk_type_size(part_arg_type, 0);
5366 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5367 if (!argptr) {
5368 ret = -TARGET_EFAULT;
5369 goto out;
5370 }
5371 thunk_convert(&host_part, argptr, part_arg_type, THUNK_HOST);
5372 unlock_user(argptr, arg, 0);
5373
5374 /* Swizzle the data pointer to our local copy and call! */
5375 host_blkpg->data = &host_part;
Peter Maydell49ca6f32016-06-06 19:58:14 +01005376 ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_blkpg));
Alexander Grafa59b5e32014-08-22 13:15:50 +02005377
5378out:
5379 return ret;
5380}
5381
Laurent Vivier7ff7b662013-07-02 14:04:12 +01005382static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02005383 int fd, int cmd, abi_long arg)
Laurent Vivier7ff7b662013-07-02 14:04:12 +01005384{
5385 const argtype *arg_type = ie->arg_type;
5386 const StructEntry *se;
5387 const argtype *field_types;
5388 const int *dst_offsets, *src_offsets;
5389 int target_size;
5390 void *argptr;
Marc-André Lureaub78c5222019-03-05 16:15:00 +01005391 abi_ulong *target_rt_dev_ptr = NULL;
5392 unsigned long *host_rt_dev_ptr = NULL;
Laurent Vivier7ff7b662013-07-02 14:04:12 +01005393 abi_long ret;
5394 int i;
5395
5396 assert(ie->access == IOC_W);
5397 assert(*arg_type == TYPE_PTR);
5398 arg_type++;
5399 assert(*arg_type == TYPE_STRUCT);
5400 target_size = thunk_type_size(arg_type, 0);
5401 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5402 if (!argptr) {
5403 return -TARGET_EFAULT;
5404 }
5405 arg_type++;
5406 assert(*arg_type == (int)STRUCT_rtentry);
5407 se = struct_entries + *arg_type++;
5408 assert(se->convert[0] == NULL);
5409 /* convert struct here to be able to catch rt_dev string */
5410 field_types = se->field_types;
5411 dst_offsets = se->field_offsets[THUNK_HOST];
5412 src_offsets = se->field_offsets[THUNK_TARGET];
5413 for (i = 0; i < se->nb_fields; i++) {
5414 if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) {
5415 assert(*field_types == TYPE_PTRVOID);
5416 target_rt_dev_ptr = (abi_ulong *)(argptr + src_offsets[i]);
5417 host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]);
5418 if (*target_rt_dev_ptr != 0) {
5419 *host_rt_dev_ptr = (unsigned long)lock_user_string(
5420 tswapal(*target_rt_dev_ptr));
5421 if (!*host_rt_dev_ptr) {
5422 unlock_user(argptr, arg, 0);
5423 return -TARGET_EFAULT;
5424 }
5425 } else {
5426 *host_rt_dev_ptr = 0;
5427 }
5428 field_types++;
5429 continue;
5430 }
5431 field_types = thunk_convert(buf_temp + dst_offsets[i],
5432 argptr + src_offsets[i],
5433 field_types, THUNK_HOST);
5434 }
5435 unlock_user(argptr, arg, 0);
5436
Peter Maydell49ca6f32016-06-06 19:58:14 +01005437 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
Marc-André Lureaub78c5222019-03-05 16:15:00 +01005438
5439 assert(host_rt_dev_ptr != NULL);
5440 assert(target_rt_dev_ptr != NULL);
Laurent Vivier7ff7b662013-07-02 14:04:12 +01005441 if (*host_rt_dev_ptr != 0) {
5442 unlock_user((void *)*host_rt_dev_ptr,
5443 *target_rt_dev_ptr, 0);
5444 }
5445 return ret;
5446}
5447
Paul Burtonca56f5b2014-06-22 11:25:47 +01005448static abi_long do_ioctl_kdsigaccept(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02005449 int fd, int cmd, abi_long arg)
Paul Burtonca56f5b2014-06-22 11:25:47 +01005450{
5451 int sig = target_to_host_signal(arg);
Peter Maydell49ca6f32016-06-06 19:58:14 +01005452 return get_errno(safe_ioctl(fd, ie->host_cmd, sig));
Paul Burtonca56f5b2014-06-22 11:25:47 +01005453}
5454
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02005455static abi_long do_ioctl_SIOCGSTAMP(const IOCTLEntry *ie, uint8_t *buf_temp,
5456 int fd, int cmd, abi_long arg)
5457{
5458 struct timeval tv;
5459 abi_long ret;
5460
5461 ret = get_errno(safe_ioctl(fd, SIOCGSTAMP, &tv));
5462 if (is_error(ret)) {
5463 return ret;
5464 }
5465
5466 if (cmd == (int)TARGET_SIOCGSTAMP_OLD) {
5467 if (copy_to_user_timeval(arg, &tv)) {
5468 return -TARGET_EFAULT;
5469 }
5470 } else {
5471 if (copy_to_user_timeval64(arg, &tv)) {
5472 return -TARGET_EFAULT;
5473 }
5474 }
5475
5476 return ret;
5477}
5478
5479static abi_long do_ioctl_SIOCGSTAMPNS(const IOCTLEntry *ie, uint8_t *buf_temp,
5480 int fd, int cmd, abi_long arg)
5481{
5482 struct timespec ts;
5483 abi_long ret;
5484
5485 ret = get_errno(safe_ioctl(fd, SIOCGSTAMPNS, &ts));
5486 if (is_error(ret)) {
5487 return ret;
5488 }
5489
5490 if (cmd == (int)TARGET_SIOCGSTAMPNS_OLD) {
5491 if (host_to_target_timespec(arg, &ts)) {
5492 return -TARGET_EFAULT;
5493 }
5494 } else{
5495 if (host_to_target_timespec64(arg, &ts)) {
5496 return -TARGET_EFAULT;
5497 }
5498 }
5499
5500 return ret;
5501}
5502
Andreas Schwab2b74f622018-01-29 11:47:06 +01005503#ifdef TIOCGPTPEER
5504static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry *ie, uint8_t *buf_temp,
5505 int fd, int cmd, abi_long arg)
5506{
5507 int flags = target_to_host_bitmask(arg, fcntl_flags_tbl);
5508 return get_errno(safe_ioctl(fd, ie->host_cmd, flags));
5509}
5510#endif
5511
Chen Gange865b972020-06-05 09:32:21 +08005512#ifdef HAVE_DRM_H
5513
5514static void unlock_drm_version(struct drm_version *host_ver,
5515 struct target_drm_version *target_ver,
5516 bool copy)
5517{
5518 unlock_user(host_ver->name, target_ver->name,
5519 copy ? host_ver->name_len : 0);
5520 unlock_user(host_ver->date, target_ver->date,
5521 copy ? host_ver->date_len : 0);
5522 unlock_user(host_ver->desc, target_ver->desc,
5523 copy ? host_ver->desc_len : 0);
5524}
5525
5526static inline abi_long target_to_host_drmversion(struct drm_version *host_ver,
5527 struct target_drm_version *target_ver)
5528{
5529 memset(host_ver, 0, sizeof(*host_ver));
5530
5531 __get_user(host_ver->name_len, &target_ver->name_len);
5532 if (host_ver->name_len) {
5533 host_ver->name = lock_user(VERIFY_WRITE, target_ver->name,
5534 target_ver->name_len, 0);
5535 if (!host_ver->name) {
5536 return -EFAULT;
5537 }
5538 }
5539
5540 __get_user(host_ver->date_len, &target_ver->date_len);
5541 if (host_ver->date_len) {
5542 host_ver->date = lock_user(VERIFY_WRITE, target_ver->date,
5543 target_ver->date_len, 0);
5544 if (!host_ver->date) {
5545 goto err;
5546 }
5547 }
5548
5549 __get_user(host_ver->desc_len, &target_ver->desc_len);
5550 if (host_ver->desc_len) {
5551 host_ver->desc = lock_user(VERIFY_WRITE, target_ver->desc,
5552 target_ver->desc_len, 0);
5553 if (!host_ver->desc) {
5554 goto err;
5555 }
5556 }
5557
5558 return 0;
5559err:
5560 unlock_drm_version(host_ver, target_ver, false);
5561 return -EFAULT;
5562}
5563
5564static inline void host_to_target_drmversion(
5565 struct target_drm_version *target_ver,
5566 struct drm_version *host_ver)
5567{
5568 __put_user(host_ver->version_major, &target_ver->version_major);
5569 __put_user(host_ver->version_minor, &target_ver->version_minor);
5570 __put_user(host_ver->version_patchlevel, &target_ver->version_patchlevel);
5571 __put_user(host_ver->name_len, &target_ver->name_len);
5572 __put_user(host_ver->date_len, &target_ver->date_len);
5573 __put_user(host_ver->desc_len, &target_ver->desc_len);
5574 unlock_drm_version(host_ver, target_ver, true);
5575}
5576
5577static abi_long do_ioctl_drm(const IOCTLEntry *ie, uint8_t *buf_temp,
5578 int fd, int cmd, abi_long arg)
5579{
5580 struct drm_version *ver;
5581 struct target_drm_version *target_ver;
5582 abi_long ret;
5583
5584 switch (ie->host_cmd) {
5585 case DRM_IOCTL_VERSION:
5586 if (!lock_user_struct(VERIFY_WRITE, target_ver, arg, 0)) {
5587 return -TARGET_EFAULT;
5588 }
5589 ver = (struct drm_version *)buf_temp;
5590 ret = target_to_host_drmversion(ver, target_ver);
5591 if (!is_error(ret)) {
5592 ret = get_errno(safe_ioctl(fd, ie->host_cmd, ver));
5593 if (is_error(ret)) {
5594 unlock_drm_version(ver, target_ver, false);
5595 } else {
5596 host_to_target_drmversion(target_ver, ver);
5597 }
5598 }
5599 unlock_user_struct(target_ver, arg, 0);
5600 return ret;
5601 }
5602 return -TARGET_ENOSYS;
5603}
5604
Chen Gang913b03c2020-08-02 21:39:38 +08005605static abi_long do_ioctl_drm_i915_getparam(const IOCTLEntry *ie,
5606 struct drm_i915_getparam *gparam,
5607 int fd, abi_long arg)
5608{
5609 abi_long ret;
5610 int value;
5611 struct target_drm_i915_getparam *target_gparam;
5612
5613 if (!lock_user_struct(VERIFY_READ, target_gparam, arg, 0)) {
5614 return -TARGET_EFAULT;
5615 }
5616
5617 __get_user(gparam->param, &target_gparam->param);
5618 gparam->value = &value;
5619 ret = get_errno(safe_ioctl(fd, ie->host_cmd, gparam));
5620 put_user_s32(value, target_gparam->value);
5621
5622 unlock_user_struct(target_gparam, arg, 0);
5623 return ret;
5624}
5625
5626static abi_long do_ioctl_drm_i915(const IOCTLEntry *ie, uint8_t *buf_temp,
5627 int fd, int cmd, abi_long arg)
5628{
5629 switch (ie->host_cmd) {
5630 case DRM_IOCTL_I915_GETPARAM:
5631 return do_ioctl_drm_i915_getparam(ie,
5632 (struct drm_i915_getparam *)buf_temp,
5633 fd, arg);
5634 default:
5635 return -TARGET_ENOSYS;
5636 }
5637}
5638
Chen Gange865b972020-06-05 09:32:21 +08005639#endif
5640
Shu-Chun Weng6addf062020-09-28 18:48:01 -07005641static abi_long do_ioctl_TUNSETTXFILTER(const IOCTLEntry *ie, uint8_t *buf_temp,
5642 int fd, int cmd, abi_long arg)
5643{
5644 struct tun_filter *filter = (struct tun_filter *)buf_temp;
5645 struct tun_filter *target_filter;
5646 char *target_addr;
5647
5648 assert(ie->access == IOC_W);
5649
5650 target_filter = lock_user(VERIFY_READ, arg, sizeof(*target_filter), 1);
5651 if (!target_filter) {
5652 return -TARGET_EFAULT;
5653 }
5654 filter->flags = tswap16(target_filter->flags);
5655 filter->count = tswap16(target_filter->count);
5656 unlock_user(target_filter, arg, 0);
5657
5658 if (filter->count) {
5659 if (offsetof(struct tun_filter, addr) + filter->count * ETH_ALEN >
5660 MAX_STRUCT_SIZE) {
5661 return -TARGET_EFAULT;
5662 }
5663
5664 target_addr = lock_user(VERIFY_READ,
5665 arg + offsetof(struct tun_filter, addr),
5666 filter->count * ETH_ALEN, 1);
5667 if (!target_addr) {
5668 return -TARGET_EFAULT;
5669 }
5670 memcpy(filter->addr, target_addr, filter->count * ETH_ALEN);
5671 unlock_user(target_addr, arg + offsetof(struct tun_filter, addr), 0);
5672 }
5673
5674 return get_errno(safe_ioctl(fd, ie->host_cmd, filter));
5675}
5676
Filip Bozuta79482e592020-06-19 14:47:27 +02005677IOCTLEntry ioctl_entries[] = {
Blue Swirl001faf32009-05-13 17:53:17 +00005678#define IOCTL(cmd, access, ...) \
Peter Maydelld2ef05b2011-01-06 15:04:17 +00005679 { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
5680#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
5681 { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
Helge Deller8cb762f2016-12-06 16:24:03 +01005682#define IOCTL_IGNORE(cmd) \
5683 { TARGET_ ## cmd, 0, #cmd },
bellard31e31b82003-02-18 22:55:36 +00005684#include "ioctls.h"
5685 { 0, 0, },
5686};
5687
pbrook53a59602006-03-25 19:31:22 +00005688/* ??? Implement proper locking for ioctls. */
ths0da46a62007-10-20 20:23:07 +00005689/* do_ioctl() Must return target values and target errnos. */
Laurent Vivier45c874e2015-06-16 00:35:28 +02005690static abi_long do_ioctl(int fd, int cmd, abi_long arg)
bellard31e31b82003-02-18 22:55:36 +00005691{
5692 const IOCTLEntry *ie;
5693 const argtype *arg_type;
blueswir1992f48a2007-10-14 16:27:31 +00005694 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00005695 uint8_t buf_temp[MAX_STRUCT_SIZE];
pbrook53a59602006-03-25 19:31:22 +00005696 int target_size;
5697 void *argptr;
bellard31e31b82003-02-18 22:55:36 +00005698
5699 ie = ioctl_entries;
5700 for(;;) {
5701 if (ie->target_cmd == 0) {
Josh Kunz39be5352020-02-03 18:54:13 -08005702 qemu_log_mask(
5703 LOG_UNIMP, "Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
ths0da46a62007-10-20 20:23:07 +00005704 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00005705 }
5706 if (ie->target_cmd == cmd)
5707 break;
5708 ie++;
5709 }
5710 arg_type = ie->arg_type;
Peter Maydelld2ef05b2011-01-06 15:04:17 +00005711 if (ie->do_ioctl) {
5712 return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
Helge Deller8cb762f2016-12-06 16:24:03 +01005713 } else if (!ie->host_cmd) {
5714 /* Some architectures define BSD ioctls in their headers
5715 that are not implemented in Linux. */
5716 return -TARGET_ENOSYS;
Peter Maydelld2ef05b2011-01-06 15:04:17 +00005717 }
5718
bellard31e31b82003-02-18 22:55:36 +00005719 switch(arg_type[0]) {
5720 case TYPE_NULL:
5721 /* no argument */
Peter Maydell49ca6f32016-06-06 19:58:14 +01005722 ret = get_errno(safe_ioctl(fd, ie->host_cmd));
bellard31e31b82003-02-18 22:55:36 +00005723 break;
5724 case TYPE_PTRVOID:
5725 case TYPE_INT:
Filip Bozutac858e532020-01-15 20:36:47 +01005726 case TYPE_LONG:
5727 case TYPE_ULONG:
Peter Maydell49ca6f32016-06-06 19:58:14 +01005728 ret = get_errno(safe_ioctl(fd, ie->host_cmd, arg));
bellard31e31b82003-02-18 22:55:36 +00005729 break;
5730 case TYPE_PTR:
5731 arg_type++;
pbrook53a59602006-03-25 19:31:22 +00005732 target_size = thunk_type_size(arg_type, 0);
bellard31e31b82003-02-18 22:55:36 +00005733 switch(ie->access) {
5734 case IOC_R:
Peter Maydell49ca6f32016-06-06 19:58:14 +01005735 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
bellard31e31b82003-02-18 22:55:36 +00005736 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005737 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5738 if (!argptr)
5739 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005740 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5741 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00005742 }
5743 break;
5744 case IOC_W:
bellard579a97f2007-11-11 14:26:47 +00005745 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5746 if (!argptr)
5747 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005748 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5749 unlock_user(argptr, arg, 0);
Peter Maydell49ca6f32016-06-06 19:58:14 +01005750 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
bellard31e31b82003-02-18 22:55:36 +00005751 break;
5752 default:
5753 case IOC_RW:
bellard579a97f2007-11-11 14:26:47 +00005754 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5755 if (!argptr)
5756 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005757 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5758 unlock_user(argptr, arg, 0);
Peter Maydell49ca6f32016-06-06 19:58:14 +01005759 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
bellard31e31b82003-02-18 22:55:36 +00005760 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005761 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5762 if (!argptr)
5763 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005764 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5765 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00005766 }
5767 break;
5768 }
5769 break;
5770 default:
Josh Kunz39be5352020-02-03 18:54:13 -08005771 qemu_log_mask(LOG_UNIMP,
5772 "Unsupported ioctl type: cmd=0x%04lx type=%d\n",
5773 (long)cmd, arg_type[0]);
ths0da46a62007-10-20 20:23:07 +00005774 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00005775 break;
5776 }
5777 return ret;
5778}
5779
blueswir1b39bc502008-10-05 10:51:10 +00005780static const bitmask_transtbl iflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00005781 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
5782 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
5783 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
5784 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
5785 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
5786 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
5787 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
5788 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
5789 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
5790 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
5791 { TARGET_IXON, TARGET_IXON, IXON, IXON },
5792 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
5793 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
5794 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
Filip Bozutac218b4e2020-07-23 23:02:32 +02005795 { TARGET_IUTF8, TARGET_IUTF8, IUTF8, IUTF8},
bellard31e31b82003-02-18 22:55:36 +00005796 { 0, 0, 0, 0 }
5797};
5798
blueswir1b39bc502008-10-05 10:51:10 +00005799static const bitmask_transtbl oflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00005800 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
5801 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
5802 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
5803 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
5804 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
5805 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
5806 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
5807 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
5808 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
5809 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
5810 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
5811 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
5812 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
5813 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
5814 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
5815 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
5816 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
5817 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
5818 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
5819 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
5820 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
5821 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
5822 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
5823 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
5824 { 0, 0, 0, 0 }
5825};
5826
blueswir1b39bc502008-10-05 10:51:10 +00005827static const bitmask_transtbl cflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00005828 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
5829 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
5830 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
5831 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
5832 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
5833 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
5834 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
5835 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
5836 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
5837 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
5838 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
5839 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
5840 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
5841 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
5842 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
5843 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
5844 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
5845 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
5846 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
5847 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
5848 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
5849 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
5850 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
5851 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
5852 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
5853 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
5854 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
5855 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
5856 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
5857 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
5858 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
5859 { 0, 0, 0, 0 }
5860};
5861
blueswir1b39bc502008-10-05 10:51:10 +00005862static const bitmask_transtbl lflag_tbl[] = {
Filip Bozutac218b4e2020-07-23 23:02:32 +02005863 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
5864 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
5865 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
5866 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
5867 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
5868 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
5869 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
5870 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
5871 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
5872 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
5873 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
5874 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
5875 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
5876 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
5877 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
5878 { TARGET_EXTPROC, TARGET_EXTPROC, EXTPROC, EXTPROC},
5879 { 0, 0, 0, 0 }
bellard31e31b82003-02-18 22:55:36 +00005880};
5881
5882static void target_to_host_termios (void *dst, const void *src)
5883{
5884 struct host_termios *host = dst;
5885 const struct target_termios *target = src;
ths3b46e622007-09-17 08:09:54 +00005886
ths5fafdf22007-09-16 21:08:06 +00005887 host->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00005888 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00005889 host->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00005890 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00005891 host->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00005892 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00005893 host->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00005894 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
5895 host->c_line = target->c_line;
ths3b46e622007-09-17 08:09:54 +00005896
Arnaud Patard44607122009-04-21 17:39:08 +03005897 memset(host->c_cc, 0, sizeof(host->c_cc));
ths5fafdf22007-09-16 21:08:06 +00005898 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
5899 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
ths3b46e622007-09-17 08:09:54 +00005900 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
ths5fafdf22007-09-16 21:08:06 +00005901 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
ths3b46e622007-09-17 08:09:54 +00005902 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
ths5fafdf22007-09-16 21:08:06 +00005903 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
ths3b46e622007-09-17 08:09:54 +00005904 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
ths5fafdf22007-09-16 21:08:06 +00005905 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
ths3b46e622007-09-17 08:09:54 +00005906 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
ths5fafdf22007-09-16 21:08:06 +00005907 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
5908 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
ths3b46e622007-09-17 08:09:54 +00005909 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
5910 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
5911 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
5912 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
5913 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
ths5fafdf22007-09-16 21:08:06 +00005914 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
bellard31e31b82003-02-18 22:55:36 +00005915}
ths3b46e622007-09-17 08:09:54 +00005916
bellard31e31b82003-02-18 22:55:36 +00005917static void host_to_target_termios (void *dst, const void *src)
5918{
5919 struct target_termios *target = dst;
5920 const struct host_termios *host = src;
5921
ths5fafdf22007-09-16 21:08:06 +00005922 target->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00005923 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00005924 target->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00005925 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00005926 target->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00005927 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00005928 target->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00005929 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
5930 target->c_line = host->c_line;
ths3b46e622007-09-17 08:09:54 +00005931
Arnaud Patard44607122009-04-21 17:39:08 +03005932 memset(target->c_cc, 0, sizeof(target->c_cc));
bellard31e31b82003-02-18 22:55:36 +00005933 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
5934 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
5935 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
5936 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
5937 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
5938 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
5939 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
5940 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
5941 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
5942 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
5943 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
5944 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
5945 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
5946 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
5947 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
5948 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
5949 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
5950}
5951
blueswir18e853dc2008-10-05 10:49:32 +00005952static const StructEntry struct_termios_def = {
bellard31e31b82003-02-18 22:55:36 +00005953 .convert = { host_to_target_termios, target_to_host_termios },
5954 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
5955 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
Filip Bozuta888468d2020-07-23 23:02:33 +02005956 .print = print_termios,
bellard31e31b82003-02-18 22:55:36 +00005957};
5958
Philippe Mathieu-Daudé180d4ef2021-05-17 07:52:43 +02005959static const bitmask_transtbl mmap_flags_tbl[] = {
Helge Deller541e1692017-10-31 13:53:58 +01005960 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
5961 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
5962 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
5963 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS,
5964 MAP_ANONYMOUS, MAP_ANONYMOUS },
5965 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN,
5966 MAP_GROWSDOWN, MAP_GROWSDOWN },
5967 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE,
5968 MAP_DENYWRITE, MAP_DENYWRITE },
5969 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE,
5970 MAP_EXECUTABLE, MAP_EXECUTABLE },
5971 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
5972 { TARGET_MAP_NORESERVE, TARGET_MAP_NORESERVE,
5973 MAP_NORESERVE, MAP_NORESERVE },
5974 { TARGET_MAP_HUGETLB, TARGET_MAP_HUGETLB, MAP_HUGETLB, MAP_HUGETLB },
5975 /* MAP_STACK had been ignored by the kernel for quite some time.
5976 Recognize it for the target insofar as we do not want to pass
5977 it through to the host. */
5978 { TARGET_MAP_STACK, TARGET_MAP_STACK, 0, 0 },
5979 { 0, 0, 0, 0 }
bellard5286db72003-06-05 00:57:30 +00005980};
5981
Laurent Vivier9d12f792020-03-10 11:33:55 +01005982/*
5983 * NOTE: TARGET_ABI32 is defined for TARGET_I386 (but not for TARGET_X86_64)
5984 * TARGET_I386 is defined if TARGET_X86_64 is defined
5985 */
bellard2ab83ea2003-06-15 19:56:46 +00005986#if defined(TARGET_I386)
bellard6dbad632003-03-16 18:05:05 +00005987
5988/* NOTE: there is really one LDT for all the threads */
blueswir1b1d8e522008-10-26 13:43:07 +00005989static uint8_t *ldt_table;
bellard6dbad632003-03-16 18:05:05 +00005990
bellard03acab62007-11-11 14:57:14 +00005991static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00005992{
5993 int size;
pbrook53a59602006-03-25 19:31:22 +00005994 void *p;
bellard6dbad632003-03-16 18:05:05 +00005995
5996 if (!ldt_table)
5997 return 0;
5998 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
5999 if (size > bytecount)
6000 size = bytecount;
bellard579a97f2007-11-11 14:26:47 +00006001 p = lock_user(VERIFY_WRITE, ptr, size, 0);
6002 if (!p)
bellard03acab62007-11-11 14:57:14 +00006003 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00006004 /* ??? Should this by byteswapped? */
pbrook53a59602006-03-25 19:31:22 +00006005 memcpy(p, ldt_table, size);
6006 unlock_user(p, ptr, size);
bellard6dbad632003-03-16 18:05:05 +00006007 return size;
6008}
6009
6010/* XXX: add locking support */
bellard03acab62007-11-11 14:57:14 +00006011static abi_long write_ldt(CPUX86State *env,
6012 abi_ulong ptr, unsigned long bytecount, int oldmode)
bellard6dbad632003-03-16 18:05:05 +00006013{
6014 struct target_modify_ldt_ldt_s ldt_info;
pbrook53a59602006-03-25 19:31:22 +00006015 struct target_modify_ldt_ldt_s *target_ldt_info;
bellard6dbad632003-03-16 18:05:05 +00006016 int seg_32bit, contents, read_exec_only, limit_in_pages;
bellard8d18e892007-11-14 15:18:40 +00006017 int seg_not_present, useable, lm;
bellard6dbad632003-03-16 18:05:05 +00006018 uint32_t *lp, entry_1, entry_2;
6019
6020 if (bytecount != sizeof(ldt_info))
bellard03acab62007-11-11 14:57:14 +00006021 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +00006022 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
bellard03acab62007-11-11 14:57:14 +00006023 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00006024 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02006025 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
pbrook53a59602006-03-25 19:31:22 +00006026 ldt_info.limit = tswap32(target_ldt_info->limit);
6027 ldt_info.flags = tswap32(target_ldt_info->flags);
6028 unlock_user_struct(target_ldt_info, ptr, 0);
ths3b46e622007-09-17 08:09:54 +00006029
bellard6dbad632003-03-16 18:05:05 +00006030 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
bellard03acab62007-11-11 14:57:14 +00006031 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00006032 seg_32bit = ldt_info.flags & 1;
6033 contents = (ldt_info.flags >> 1) & 3;
6034 read_exec_only = (ldt_info.flags >> 3) & 1;
6035 limit_in_pages = (ldt_info.flags >> 4) & 1;
6036 seg_not_present = (ldt_info.flags >> 5) & 1;
6037 useable = (ldt_info.flags >> 6) & 1;
bellard8d18e892007-11-14 15:18:40 +00006038#ifdef TARGET_ABI32
6039 lm = 0;
6040#else
6041 lm = (ldt_info.flags >> 7) & 1;
6042#endif
bellard6dbad632003-03-16 18:05:05 +00006043 if (contents == 3) {
6044 if (oldmode)
bellard03acab62007-11-11 14:57:14 +00006045 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00006046 if (seg_not_present == 0)
bellard03acab62007-11-11 14:57:14 +00006047 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00006048 }
6049 /* allocate the LDT */
6050 if (!ldt_table) {
balroge4415702008-11-10 02:55:33 +00006051 env->ldt.base = target_mmap(0,
6052 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
6053 PROT_READ|PROT_WRITE,
6054 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
6055 if (env->ldt.base == -1)
bellard03acab62007-11-11 14:57:14 +00006056 return -TARGET_ENOMEM;
Richard Henderson3e8f1622021-02-12 10:48:43 -08006057 memset(g2h_untagged(env->ldt.base), 0,
balroge4415702008-11-10 02:55:33 +00006058 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
bellard6dbad632003-03-16 18:05:05 +00006059 env->ldt.limit = 0xffff;
Richard Henderson3e8f1622021-02-12 10:48:43 -08006060 ldt_table = g2h_untagged(env->ldt.base);
bellard6dbad632003-03-16 18:05:05 +00006061 }
6062
6063 /* NOTE: same code as Linux kernel */
6064 /* Allow LDTs to be cleared by the user. */
6065 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
6066 if (oldmode ||
6067 (contents == 0 &&
6068 read_exec_only == 1 &&
6069 seg_32bit == 0 &&
6070 limit_in_pages == 0 &&
6071 seg_not_present == 1 &&
6072 useable == 0 )) {
6073 entry_1 = 0;
6074 entry_2 = 0;
6075 goto install;
6076 }
6077 }
ths3b46e622007-09-17 08:09:54 +00006078
bellard6dbad632003-03-16 18:05:05 +00006079 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
6080 (ldt_info.limit & 0x0ffff);
6081 entry_2 = (ldt_info.base_addr & 0xff000000) |
6082 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
6083 (ldt_info.limit & 0xf0000) |
6084 ((read_exec_only ^ 1) << 9) |
6085 (contents << 10) |
6086 ((seg_not_present ^ 1) << 15) |
6087 (seg_32bit << 22) |
6088 (limit_in_pages << 23) |
bellard8d18e892007-11-14 15:18:40 +00006089 (lm << 21) |
bellard6dbad632003-03-16 18:05:05 +00006090 0x7000;
6091 if (!oldmode)
6092 entry_2 |= (useable << 20);
bellard14ae3ba2003-05-27 23:25:06 +00006093
bellard6dbad632003-03-16 18:05:05 +00006094 /* Install the new entry ... */
6095install:
6096 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
6097 lp[0] = tswap32(entry_1);
6098 lp[1] = tswap32(entry_2);
6099 return 0;
6100}
6101
6102/* specific and weird i386 syscalls */
blueswir18fcd3692008-08-17 20:26:25 +00006103static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
6104 unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00006105{
bellard03acab62007-11-11 14:57:14 +00006106 abi_long ret;
ths3b46e622007-09-17 08:09:54 +00006107
bellard6dbad632003-03-16 18:05:05 +00006108 switch (func) {
6109 case 0:
6110 ret = read_ldt(ptr, bytecount);
6111 break;
6112 case 1:
6113 ret = write_ldt(env, ptr, bytecount, 1);
6114 break;
6115 case 0x11:
6116 ret = write_ldt(env, ptr, bytecount, 0);
6117 break;
bellard03acab62007-11-11 14:57:14 +00006118 default:
6119 ret = -TARGET_ENOSYS;
6120 break;
bellard6dbad632003-03-16 18:05:05 +00006121 }
6122 return ret;
6123}
bellard1b6b0292003-03-22 17:31:38 +00006124
Laurent Vivier9d12f792020-03-10 11:33:55 +01006125#if defined(TARGET_ABI32)
Alexander Grafbc22eb42013-07-16 18:44:58 +01006126abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00006127{
Richard Henderson3e8f1622021-02-12 10:48:43 -08006128 uint64_t *gdt_table = g2h_untagged(env->gdt.base);
bellard8d18e892007-11-14 15:18:40 +00006129 struct target_modify_ldt_ldt_s ldt_info;
6130 struct target_modify_ldt_ldt_s *target_ldt_info;
6131 int seg_32bit, contents, read_exec_only, limit_in_pages;
6132 int seg_not_present, useable, lm;
6133 uint32_t *lp, entry_1, entry_2;
6134 int i;
6135
6136 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
6137 if (!target_ldt_info)
6138 return -TARGET_EFAULT;
6139 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02006140 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
bellard8d18e892007-11-14 15:18:40 +00006141 ldt_info.limit = tswap32(target_ldt_info->limit);
6142 ldt_info.flags = tswap32(target_ldt_info->flags);
6143 if (ldt_info.entry_number == -1) {
6144 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
6145 if (gdt_table[i] == 0) {
6146 ldt_info.entry_number = i;
6147 target_ldt_info->entry_number = tswap32(i);
6148 break;
6149 }
6150 }
6151 }
6152 unlock_user_struct(target_ldt_info, ptr, 1);
6153
6154 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
6155 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
6156 return -TARGET_EINVAL;
6157 seg_32bit = ldt_info.flags & 1;
6158 contents = (ldt_info.flags >> 1) & 3;
6159 read_exec_only = (ldt_info.flags >> 3) & 1;
6160 limit_in_pages = (ldt_info.flags >> 4) & 1;
6161 seg_not_present = (ldt_info.flags >> 5) & 1;
6162 useable = (ldt_info.flags >> 6) & 1;
6163#ifdef TARGET_ABI32
6164 lm = 0;
6165#else
6166 lm = (ldt_info.flags >> 7) & 1;
6167#endif
6168
6169 if (contents == 3) {
6170 if (seg_not_present == 0)
6171 return -TARGET_EINVAL;
6172 }
6173
6174 /* NOTE: same code as Linux kernel */
6175 /* Allow LDTs to be cleared by the user. */
6176 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
6177 if ((contents == 0 &&
6178 read_exec_only == 1 &&
6179 seg_32bit == 0 &&
6180 limit_in_pages == 0 &&
6181 seg_not_present == 1 &&
6182 useable == 0 )) {
6183 entry_1 = 0;
6184 entry_2 = 0;
6185 goto install;
6186 }
6187 }
6188
6189 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
6190 (ldt_info.limit & 0x0ffff);
6191 entry_2 = (ldt_info.base_addr & 0xff000000) |
6192 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
6193 (ldt_info.limit & 0xf0000) |
6194 ((read_exec_only ^ 1) << 9) |
6195 (contents << 10) |
6196 ((seg_not_present ^ 1) << 15) |
6197 (seg_32bit << 22) |
6198 (limit_in_pages << 23) |
6199 (useable << 20) |
6200 (lm << 21) |
6201 0x7000;
6202
6203 /* Install the new entry ... */
6204install:
6205 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
6206 lp[0] = tswap32(entry_1);
6207 lp[1] = tswap32(entry_2);
6208 return 0;
6209}
6210
blueswir18fcd3692008-08-17 20:26:25 +00006211static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00006212{
6213 struct target_modify_ldt_ldt_s *target_ldt_info;
Richard Henderson3e8f1622021-02-12 10:48:43 -08006214 uint64_t *gdt_table = g2h_untagged(env->gdt.base);
bellard8d18e892007-11-14 15:18:40 +00006215 uint32_t base_addr, limit, flags;
6216 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
6217 int seg_not_present, useable, lm;
6218 uint32_t *lp, entry_1, entry_2;
6219
6220 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
6221 if (!target_ldt_info)
6222 return -TARGET_EFAULT;
6223 idx = tswap32(target_ldt_info->entry_number);
6224 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
6225 idx > TARGET_GDT_ENTRY_TLS_MAX) {
6226 unlock_user_struct(target_ldt_info, ptr, 1);
6227 return -TARGET_EINVAL;
6228 }
6229 lp = (uint32_t *)(gdt_table + idx);
6230 entry_1 = tswap32(lp[0]);
6231 entry_2 = tswap32(lp[1]);
6232
6233 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
6234 contents = (entry_2 >> 10) & 3;
6235 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
6236 seg_32bit = (entry_2 >> 22) & 1;
6237 limit_in_pages = (entry_2 >> 23) & 1;
6238 useable = (entry_2 >> 20) & 1;
6239#ifdef TARGET_ABI32
6240 lm = 0;
6241#else
6242 lm = (entry_2 >> 21) & 1;
6243#endif
6244 flags = (seg_32bit << 0) | (contents << 1) |
6245 (read_exec_only << 3) | (limit_in_pages << 4) |
6246 (seg_not_present << 5) | (useable << 6) | (lm << 7);
6247 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
6248 base_addr = (entry_1 >> 16) |
6249 (entry_2 & 0xff000000) |
6250 ((entry_2 & 0xff) << 16);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02006251 target_ldt_info->base_addr = tswapal(base_addr);
bellard8d18e892007-11-14 15:18:40 +00006252 target_ldt_info->limit = tswap32(limit);
6253 target_ldt_info->flags = tswap32(flags);
6254 unlock_user_struct(target_ldt_info, ptr, 1);
6255 return 0;
6256}
6257
Laurent Vivier9d12f792020-03-10 11:33:55 +01006258abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
6259{
Helge Deller538fabc2020-04-25 00:00:33 +02006260 return -TARGET_ENOSYS;
Laurent Vivier9d12f792020-03-10 11:33:55 +01006261}
6262#else
Peter Maydell2667e712013-07-16 18:44:59 +01006263abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
bellardd2fd1af2007-11-14 18:08:56 +00006264{
Juan Quintela1add8692011-06-16 17:37:09 +01006265 abi_long ret = 0;
bellardd2fd1af2007-11-14 18:08:56 +00006266 abi_ulong val;
6267 int idx;
Juan Quintela1add8692011-06-16 17:37:09 +01006268
bellardd2fd1af2007-11-14 18:08:56 +00006269 switch(code) {
6270 case TARGET_ARCH_SET_GS:
6271 case TARGET_ARCH_SET_FS:
6272 if (code == TARGET_ARCH_SET_GS)
6273 idx = R_GS;
6274 else
6275 idx = R_FS;
6276 cpu_x86_load_seg(env, idx, 0);
6277 env->segs[idx].base = addr;
6278 break;
6279 case TARGET_ARCH_GET_GS:
6280 case TARGET_ARCH_GET_FS:
6281 if (code == TARGET_ARCH_GET_GS)
6282 idx = R_GS;
6283 else
6284 idx = R_FS;
6285 val = env->segs[idx].base;
6286 if (put_user(val, addr, abi_ulong))
Juan Quintela1add8692011-06-16 17:37:09 +01006287 ret = -TARGET_EFAULT;
bellardd2fd1af2007-11-14 18:08:56 +00006288 break;
6289 default:
6290 ret = -TARGET_EINVAL;
6291 break;
6292 }
Juan Quintela1add8692011-06-16 17:37:09 +01006293 return ret;
bellardd2fd1af2007-11-14 18:08:56 +00006294}
Laurent Vivier9d12f792020-03-10 11:33:55 +01006295#endif /* defined(TARGET_ABI32 */
bellard2ab83ea2003-06-15 19:56:46 +00006296#endif /* defined(TARGET_I386) */
6297
Richard Henderson87e9bf22021-12-27 07:01:22 -08006298/*
6299 * These constants are generic. Supply any that are missing from the host.
6300 */
6301#ifndef PR_SET_NAME
6302# define PR_SET_NAME 15
6303# define PR_GET_NAME 16
6304#endif
6305#ifndef PR_SET_FP_MODE
6306# define PR_SET_FP_MODE 45
6307# define PR_GET_FP_MODE 46
6308# define PR_FP_MODE_FR (1 << 0)
6309# define PR_FP_MODE_FRE (1 << 1)
6310#endif
6311#ifndef PR_SVE_SET_VL
6312# define PR_SVE_SET_VL 50
6313# define PR_SVE_GET_VL 51
6314# define PR_SVE_VL_LEN_MASK 0xffff
6315# define PR_SVE_VL_INHERIT (1 << 17)
6316#endif
6317#ifndef PR_PAC_RESET_KEYS
6318# define PR_PAC_RESET_KEYS 54
6319# define PR_PAC_APIAKEY (1 << 0)
6320# define PR_PAC_APIBKEY (1 << 1)
6321# define PR_PAC_APDAKEY (1 << 2)
6322# define PR_PAC_APDBKEY (1 << 3)
6323# define PR_PAC_APGAKEY (1 << 4)
6324#endif
6325#ifndef PR_SET_TAGGED_ADDR_CTRL
6326# define PR_SET_TAGGED_ADDR_CTRL 55
6327# define PR_GET_TAGGED_ADDR_CTRL 56
6328# define PR_TAGGED_ADDR_ENABLE (1UL << 0)
6329#endif
6330#ifndef PR_MTE_TCF_SHIFT
6331# define PR_MTE_TCF_SHIFT 1
6332# define PR_MTE_TCF_NONE (0UL << PR_MTE_TCF_SHIFT)
6333# define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT)
6334# define PR_MTE_TCF_ASYNC (2UL << PR_MTE_TCF_SHIFT)
6335# define PR_MTE_TCF_MASK (3UL << PR_MTE_TCF_SHIFT)
6336# define PR_MTE_TAG_SHIFT 3
6337# define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT)
6338#endif
Richard Henderson220717a2021-12-27 07:01:23 -08006339#ifndef PR_SET_IO_FLUSHER
6340# define PR_SET_IO_FLUSHER 57
6341# define PR_GET_IO_FLUSHER 58
6342#endif
6343#ifndef PR_SET_SYSCALL_USER_DISPATCH
6344# define PR_SET_SYSCALL_USER_DISPATCH 59
6345#endif
Richard Henderson87e9bf22021-12-27 07:01:22 -08006346
6347#include "target_prctl.h"
6348
6349static abi_long do_prctl_inval0(CPUArchState *env)
6350{
6351 return -TARGET_EINVAL;
6352}
6353
6354static abi_long do_prctl_inval1(CPUArchState *env, abi_long arg2)
6355{
6356 return -TARGET_EINVAL;
6357}
6358
6359#ifndef do_prctl_get_fp_mode
6360#define do_prctl_get_fp_mode do_prctl_inval0
6361#endif
6362#ifndef do_prctl_set_fp_mode
6363#define do_prctl_set_fp_mode do_prctl_inval1
6364#endif
6365#ifndef do_prctl_get_vl
6366#define do_prctl_get_vl do_prctl_inval0
6367#endif
6368#ifndef do_prctl_set_vl
6369#define do_prctl_set_vl do_prctl_inval1
6370#endif
6371#ifndef do_prctl_reset_keys
6372#define do_prctl_reset_keys do_prctl_inval1
6373#endif
6374#ifndef do_prctl_set_tagged_addr_ctrl
6375#define do_prctl_set_tagged_addr_ctrl do_prctl_inval1
6376#endif
6377#ifndef do_prctl_get_tagged_addr_ctrl
6378#define do_prctl_get_tagged_addr_ctrl do_prctl_inval0
6379#endif
Richard Henderson6e8dcac2021-12-27 07:01:24 -08006380#ifndef do_prctl_get_unalign
6381#define do_prctl_get_unalign do_prctl_inval1
6382#endif
6383#ifndef do_prctl_set_unalign
6384#define do_prctl_set_unalign do_prctl_inval1
6385#endif
Richard Henderson87e9bf22021-12-27 07:01:22 -08006386
6387static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
6388 abi_long arg3, abi_long arg4, abi_long arg5)
6389{
6390 abi_long ret;
6391
6392 switch (option) {
6393 case PR_GET_PDEATHSIG:
6394 {
6395 int deathsig;
6396 ret = get_errno(prctl(PR_GET_PDEATHSIG, &deathsig,
6397 arg3, arg4, arg5));
Richard Henderson1edebb32022-01-06 14:57:36 -08006398 if (!is_error(ret) &&
6399 put_user_s32(host_to_target_signal(deathsig), arg2)) {
Richard Henderson87e9bf22021-12-27 07:01:22 -08006400 return -TARGET_EFAULT;
6401 }
6402 return ret;
6403 }
Richard Hendersonf746c652022-01-06 14:57:37 -08006404 case PR_SET_PDEATHSIG:
6405 return get_errno(prctl(PR_SET_PDEATHSIG, target_to_host_signal(arg2),
6406 arg3, arg4, arg5));
Richard Henderson87e9bf22021-12-27 07:01:22 -08006407 case PR_GET_NAME:
6408 {
6409 void *name = lock_user(VERIFY_WRITE, arg2, 16, 1);
6410 if (!name) {
6411 return -TARGET_EFAULT;
6412 }
6413 ret = get_errno(prctl(PR_GET_NAME, (uintptr_t)name,
6414 arg3, arg4, arg5));
6415 unlock_user(name, arg2, 16);
6416 return ret;
6417 }
6418 case PR_SET_NAME:
6419 {
6420 void *name = lock_user(VERIFY_READ, arg2, 16, 1);
6421 if (!name) {
6422 return -TARGET_EFAULT;
6423 }
6424 ret = get_errno(prctl(PR_SET_NAME, (uintptr_t)name,
6425 arg3, arg4, arg5));
6426 unlock_user(name, arg2, 0);
6427 return ret;
6428 }
6429 case PR_GET_FP_MODE:
6430 return do_prctl_get_fp_mode(env);
6431 case PR_SET_FP_MODE:
6432 return do_prctl_set_fp_mode(env, arg2);
6433 case PR_SVE_GET_VL:
6434 return do_prctl_get_vl(env);
6435 case PR_SVE_SET_VL:
6436 return do_prctl_set_vl(env, arg2);
6437 case PR_PAC_RESET_KEYS:
6438 if (arg3 || arg4 || arg5) {
6439 return -TARGET_EINVAL;
6440 }
6441 return do_prctl_reset_keys(env, arg2);
6442 case PR_SET_TAGGED_ADDR_CTRL:
6443 if (arg3 || arg4 || arg5) {
6444 return -TARGET_EINVAL;
6445 }
6446 return do_prctl_set_tagged_addr_ctrl(env, arg2);
6447 case PR_GET_TAGGED_ADDR_CTRL:
6448 if (arg2 || arg3 || arg4 || arg5) {
6449 return -TARGET_EINVAL;
6450 }
6451 return do_prctl_get_tagged_addr_ctrl(env);
Richard Henderson220717a2021-12-27 07:01:23 -08006452
Richard Henderson6e8dcac2021-12-27 07:01:24 -08006453 case PR_GET_UNALIGN:
6454 return do_prctl_get_unalign(env, arg2);
6455 case PR_SET_UNALIGN:
6456 return do_prctl_set_unalign(env, arg2);
6457
Richard Henderson4f4e5562022-01-06 14:57:38 -08006458 case PR_CAP_AMBIENT:
6459 case PR_CAPBSET_READ:
6460 case PR_CAPBSET_DROP:
Richard Henderson220717a2021-12-27 07:01:23 -08006461 case PR_GET_DUMPABLE:
6462 case PR_SET_DUMPABLE:
6463 case PR_GET_KEEPCAPS:
6464 case PR_SET_KEEPCAPS:
Richard Henderson4f4e5562022-01-06 14:57:38 -08006465 case PR_GET_SECUREBITS:
6466 case PR_SET_SECUREBITS:
Richard Henderson220717a2021-12-27 07:01:23 -08006467 case PR_GET_TIMING:
6468 case PR_SET_TIMING:
6469 case PR_GET_TIMERSLACK:
6470 case PR_SET_TIMERSLACK:
6471 case PR_MCE_KILL:
6472 case PR_MCE_KILL_GET:
6473 case PR_GET_NO_NEW_PRIVS:
6474 case PR_SET_NO_NEW_PRIVS:
6475 case PR_GET_IO_FLUSHER:
6476 case PR_SET_IO_FLUSHER:
6477 /* Some prctl options have no pointer arguments and we can pass on. */
6478 return get_errno(prctl(option, arg2, arg3, arg4, arg5));
6479
6480 case PR_GET_CHILD_SUBREAPER:
6481 case PR_SET_CHILD_SUBREAPER:
6482 case PR_GET_SPECULATION_CTRL:
6483 case PR_SET_SPECULATION_CTRL:
6484 case PR_GET_TID_ADDRESS:
6485 /* TODO */
6486 return -TARGET_EINVAL;
6487
6488 case PR_GET_FPEXC:
6489 case PR_SET_FPEXC:
6490 /* Was used for SPE on PowerPC. */
6491 return -TARGET_EINVAL;
6492
6493 case PR_GET_ENDIAN:
6494 case PR_SET_ENDIAN:
6495 case PR_GET_FPEMU:
6496 case PR_SET_FPEMU:
6497 case PR_SET_MM:
Richard Henderson87e9bf22021-12-27 07:01:22 -08006498 case PR_GET_SECCOMP:
6499 case PR_SET_SECCOMP:
Richard Henderson220717a2021-12-27 07:01:23 -08006500 case PR_SET_SYSCALL_USER_DISPATCH:
6501 case PR_GET_THP_DISABLE:
6502 case PR_SET_THP_DISABLE:
6503 case PR_GET_TSC:
6504 case PR_SET_TSC:
Richard Henderson220717a2021-12-27 07:01:23 -08006505 /* Disable to prevent the target disabling stuff we need. */
Richard Henderson87e9bf22021-12-27 07:01:22 -08006506 return -TARGET_EINVAL;
Richard Henderson220717a2021-12-27 07:01:23 -08006507
Richard Henderson87e9bf22021-12-27 07:01:22 -08006508 default:
Richard Henderson220717a2021-12-27 07:01:23 -08006509 qemu_log_mask(LOG_UNIMP, "Unsupported prctl: " TARGET_ABI_FMT_ld "\n",
6510 option);
6511 return -TARGET_EINVAL;
Richard Henderson87e9bf22021-12-27 07:01:22 -08006512 }
6513}
6514
Riku Voipio05098a92011-03-04 15:27:29 +02006515#define NEW_STACK_SIZE 0x40000
pbrookd865bab2008-06-07 22:12:17 +00006516
pbrookd865bab2008-06-07 22:12:17 +00006517
6518static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
6519typedef struct {
Andreas Färber9349b4f2012-03-14 01:38:32 +01006520 CPUArchState *env;
pbrookd865bab2008-06-07 22:12:17 +00006521 pthread_mutex_t mutex;
6522 pthread_cond_t cond;
6523 pthread_t thread;
6524 uint32_t tid;
6525 abi_ulong child_tidptr;
6526 abi_ulong parent_tidptr;
6527 sigset_t sigmask;
6528} new_thread_info;
6529
6530static void *clone_func(void *arg)
6531{
6532 new_thread_info *info = arg;
Andreas Färber9349b4f2012-03-14 01:38:32 +01006533 CPUArchState *env;
Andreas Färber0d342822012-12-17 07:12:13 +01006534 CPUState *cpu;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03006535 TaskState *ts;
pbrookd865bab2008-06-07 22:12:17 +00006536
Emilio G. Cota70903762015-08-23 20:23:41 -04006537 rcu_register_thread();
Emilio G. Cota3468b592017-07-19 18:57:58 -04006538 tcg_register_thread();
pbrookd865bab2008-06-07 22:12:17 +00006539 env = info->env;
Richard Henderson29a0af62019-03-22 16:07:18 -07006540 cpu = env_cpu(env);
Andreas Färbera2247f82013-06-09 19:47:04 +02006541 thread_cpu = cpu;
Andreas Färber0429a972013-08-26 18:14:44 +02006542 ts = (TaskState *)cpu->opaque;
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +00006543 info->tid = sys_gettid();
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03006544 task_settid(ts);
pbrookd865bab2008-06-07 22:12:17 +00006545 if (info->child_tidptr)
6546 put_user_u32(info->tid, info->child_tidptr);
6547 if (info->parent_tidptr)
6548 put_user_u32(info->tid, info->parent_tidptr);
Richard Henderson5ebdd772019-03-14 13:10:53 -07006549 qemu_guest_random_seed_thread_part2(cpu->random_seed);
pbrookd865bab2008-06-07 22:12:17 +00006550 /* Enable signals. */
6551 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
6552 /* Signal to the parent that we're ready. */
6553 pthread_mutex_lock(&info->mutex);
6554 pthread_cond_broadcast(&info->cond);
6555 pthread_mutex_unlock(&info->mutex);
Emilio G. Cotaa4dd3d52017-10-18 18:01:41 -04006556 /* Wait until the parent has finished initializing the tls state. */
pbrookd865bab2008-06-07 22:12:17 +00006557 pthread_mutex_lock(&clone_lock);
6558 pthread_mutex_unlock(&clone_lock);
6559 cpu_loop(env);
6560 /* never exits */
6561 return NULL;
6562}
bellard1b6b0292003-03-22 17:31:38 +00006563
ths0da46a62007-10-20 20:23:07 +00006564/* do_fork() Must return host values and target errnos (unlike most
6565 do_*() functions). */
Andreas Färber9349b4f2012-03-14 01:38:32 +01006566static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
pbrookd865bab2008-06-07 22:12:17 +00006567 abi_ulong parent_tidptr, target_ulong newtls,
6568 abi_ulong child_tidptr)
bellard1b6b0292003-03-22 17:31:38 +00006569{
Richard Henderson29a0af62019-03-22 16:07:18 -07006570 CPUState *cpu = env_cpu(env);
bellard1b6b0292003-03-22 17:31:38 +00006571 int ret;
bellard5cd43932003-03-29 16:54:36 +00006572 TaskState *ts;
Andreas Färber0429a972013-08-26 18:14:44 +02006573 CPUState *new_cpu;
Andreas Färber9349b4f2012-03-14 01:38:32 +01006574 CPUArchState *new_env;
pbrookd865bab2008-06-07 22:12:17 +00006575 sigset_t sigmask;
ths3b46e622007-09-17 08:09:54 +00006576
Peter Maydell5ea2fc82016-08-02 18:41:27 +01006577 flags &= ~CLONE_IGNORED_FLAGS;
6578
balrog436d1242008-09-21 02:39:45 +00006579 /* Emulate vfork() with fork() */
6580 if (flags & CLONE_VFORK)
6581 flags &= ~(CLONE_VFORK | CLONE_VM);
6582
bellard1b6b0292003-03-22 17:31:38 +00006583 if (flags & CLONE_VM) {
Andreas Färber0429a972013-08-26 18:14:44 +02006584 TaskState *parent_ts = (TaskState *)cpu->opaque;
pbrookd865bab2008-06-07 22:12:17 +00006585 new_thread_info info;
6586 pthread_attr_t attr;
Peter Maydell24cb36a2013-07-16 18:45:00 +01006587
Peter Maydell5ea2fc82016-08-02 18:41:27 +01006588 if (((flags & CLONE_THREAD_FLAGS) != CLONE_THREAD_FLAGS) ||
6589 (flags & CLONE_INVALID_THREAD_FLAGS)) {
6590 return -TARGET_EINVAL;
6591 }
6592
Markus Armbrusterc78d65e2015-09-14 13:53:03 +02006593 ts = g_new0(TaskState, 1);
pbrook624f7972008-05-31 16:11:38 +00006594 init_task_state(ts);
Max Filippov73a988d2018-03-30 06:19:58 -07006595
6596 /* Grab a mutex so that thread setup appears atomic. */
6597 pthread_mutex_lock(&clone_lock);
6598
Richard Henderson6cc9d672021-03-01 19:21:08 -08006599 /*
6600 * If this is our first additional thread, we need to ensure we
6601 * generate code for parallel execution and flush old translations.
6602 * Do this now so that the copy gets CF_PARALLEL too.
6603 */
6604 if (!(cpu->tcg_cflags & CF_PARALLEL)) {
6605 cpu->tcg_cflags |= CF_PARALLEL;
6606 tb_flush(cpu);
6607 }
6608
bellard1b6b0292003-03-22 17:31:38 +00006609 /* we create a new CPU instance. */
thsc5be9f02007-02-28 20:20:53 +00006610 new_env = cpu_copy(env);
pbrook6e68e072008-05-30 17:22:15 +00006611 /* Init regs that differ from the parent. */
Richard Henderson608999d2019-11-06 12:33:15 +01006612 cpu_clone_regs_child(new_env, newsp, flags);
Richard Henderson07a6ecf2019-11-06 12:33:16 +01006613 cpu_clone_regs_parent(env, flags);
Richard Henderson29a0af62019-03-22 16:07:18 -07006614 new_cpu = env_cpu(new_env);
Andreas Färber0429a972013-08-26 18:14:44 +02006615 new_cpu->opaque = ts;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03006616 ts->bprm = parent_ts->bprm;
6617 ts->info = parent_ts->info;
Peter Maydell3d3efba2016-05-27 15:51:49 +01006618 ts->signal_mask = parent_ts->signal_mask;
pbrookd865bab2008-06-07 22:12:17 +00006619
Peter Maydell7cfbd382016-08-02 18:41:26 +01006620 if (flags & CLONE_CHILD_CLEARTID) {
pbrookc2764712009-03-07 15:24:59 +00006621 ts->child_tidptr = child_tidptr;
6622 }
6623
Peter Maydell7cfbd382016-08-02 18:41:26 +01006624 if (flags & CLONE_SETTLS) {
pbrookd865bab2008-06-07 22:12:17 +00006625 cpu_set_tls (new_env, newtls);
Peter Maydell7cfbd382016-08-02 18:41:26 +01006626 }
pbrookd865bab2008-06-07 22:12:17 +00006627
pbrookd865bab2008-06-07 22:12:17 +00006628 memset(&info, 0, sizeof(info));
6629 pthread_mutex_init(&info.mutex, NULL);
6630 pthread_mutex_lock(&info.mutex);
6631 pthread_cond_init(&info.cond, NULL);
6632 info.env = new_env;
Peter Maydell7cfbd382016-08-02 18:41:26 +01006633 if (flags & CLONE_CHILD_SETTID) {
pbrookd865bab2008-06-07 22:12:17 +00006634 info.child_tidptr = child_tidptr;
Peter Maydell7cfbd382016-08-02 18:41:26 +01006635 }
6636 if (flags & CLONE_PARENT_SETTID) {
pbrookd865bab2008-06-07 22:12:17 +00006637 info.parent_tidptr = parent_tidptr;
Peter Maydell7cfbd382016-08-02 18:41:26 +01006638 }
pbrookd865bab2008-06-07 22:12:17 +00006639
6640 ret = pthread_attr_init(&attr);
Nathan Froyd48e15fc2010-10-29 07:48:57 -07006641 ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE);
6642 ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pbrookd865bab2008-06-07 22:12:17 +00006643 /* It is not safe to deliver signals until the child has finished
6644 initializing, so temporarily block all signals. */
6645 sigfillset(&sigmask);
6646 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
Richard Henderson5ebdd772019-03-14 13:10:53 -07006647 cpu->random_seed = qemu_guest_random_seed_thread_part1();
pbrookd865bab2008-06-07 22:12:17 +00006648
6649 ret = pthread_create(&info.thread, &attr, clone_func, &info);
pbrookc2764712009-03-07 15:24:59 +00006650 /* TODO: Free new CPU state if thread creation failed. */
pbrookd865bab2008-06-07 22:12:17 +00006651
6652 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
6653 pthread_attr_destroy(&attr);
6654 if (ret == 0) {
6655 /* Wait for the child to initialize. */
6656 pthread_cond_wait(&info.cond, &info.mutex);
6657 ret = info.tid;
pbrookd865bab2008-06-07 22:12:17 +00006658 } else {
6659 ret = -1;
6660 }
6661 pthread_mutex_unlock(&info.mutex);
6662 pthread_cond_destroy(&info.cond);
6663 pthread_mutex_destroy(&info.mutex);
6664 pthread_mutex_unlock(&clone_lock);
bellard1b6b0292003-03-22 17:31:38 +00006665 } else {
6666 /* if no CLONE_VM, we consider it is a fork */
Peter Maydell5ea2fc82016-08-02 18:41:27 +01006667 if (flags & CLONE_INVALID_FORK_FLAGS) {
6668 return -TARGET_EINVAL;
6669 }
6670
6671 /* We can't support custom termination signals */
6672 if ((flags & CSIGNAL) != TARGET_SIGCHLD) {
Timothy E Baldwin93b4eff2015-08-31 00:26:21 +01006673 return -TARGET_EINVAL;
6674 }
Timothy E Baldwin7d92d342016-05-27 15:51:58 +01006675
6676 if (block_signals()) {
Richard Hendersonaf254a22021-11-22 19:47:33 +01006677 return -QEMU_ERESTARTSYS;
Timothy E Baldwin7d92d342016-05-27 15:51:58 +01006678 }
6679
pbrookd865bab2008-06-07 22:12:17 +00006680 fork_start();
bellard1b6b0292003-03-22 17:31:38 +00006681 ret = fork();
pbrookd865bab2008-06-07 22:12:17 +00006682 if (ret == 0) {
aurel322b1319c2008-12-18 22:44:04 +00006683 /* Child Process. */
Richard Henderson608999d2019-11-06 12:33:15 +01006684 cpu_clone_regs_child(env, newsp, flags);
pbrookd865bab2008-06-07 22:12:17 +00006685 fork_end(1);
aurel322b1319c2008-12-18 22:44:04 +00006686 /* There is a race condition here. The parent process could
6687 theoretically read the TID in the child process before the child
6688 tid is set. This would require using either ptrace
6689 (not implemented) or having *_tidptr to point at a shared memory
6690 mapping. We can't repeat the spinlock hack used above because
6691 the child process gets its own copy of the lock. */
pbrookd865bab2008-06-07 22:12:17 +00006692 if (flags & CLONE_CHILD_SETTID)
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +00006693 put_user_u32(sys_gettid(), child_tidptr);
pbrookd865bab2008-06-07 22:12:17 +00006694 if (flags & CLONE_PARENT_SETTID)
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +00006695 put_user_u32(sys_gettid(), parent_tidptr);
Andreas Färber0429a972013-08-26 18:14:44 +02006696 ts = (TaskState *)cpu->opaque;
pbrookd865bab2008-06-07 22:12:17 +00006697 if (flags & CLONE_SETTLS)
6698 cpu_set_tls (env, newtls);
pbrookc2764712009-03-07 15:24:59 +00006699 if (flags & CLONE_CHILD_CLEARTID)
6700 ts->child_tidptr = child_tidptr;
pbrookd865bab2008-06-07 22:12:17 +00006701 } else {
Richard Henderson07a6ecf2019-11-06 12:33:16 +01006702 cpu_clone_regs_parent(env, flags);
pbrookd865bab2008-06-07 22:12:17 +00006703 fork_end(0);
6704 }
bellard1b6b0292003-03-22 17:31:38 +00006705 }
6706 return ret;
6707}
6708
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006709/* warning : doesn't handle linux specific flags... */
6710static int target_to_host_fcntl_cmd(int cmd)
6711{
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006712 int ret;
6713
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006714 switch(cmd) {
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006715 case TARGET_F_DUPFD:
6716 case TARGET_F_GETFD:
6717 case TARGET_F_SETFD:
6718 case TARGET_F_GETFL:
6719 case TARGET_F_SETFL:
Andreas Schwab2d92c682020-05-25 09:59:28 +02006720 case TARGET_F_OFD_GETLK:
6721 case TARGET_F_OFD_SETLK:
6722 case TARGET_F_OFD_SETLKW:
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006723 ret = cmd;
6724 break;
6725 case TARGET_F_GETLK:
6726 ret = F_GETLK64;
6727 break;
6728 case TARGET_F_SETLK:
6729 ret = F_SETLK64;
6730 break;
6731 case TARGET_F_SETLKW:
6732 ret = F_SETLKW64;
6733 break;
6734 case TARGET_F_GETOWN:
6735 ret = F_GETOWN;
6736 break;
6737 case TARGET_F_SETOWN:
6738 ret = F_SETOWN;
6739 break;
6740 case TARGET_F_GETSIG:
6741 ret = F_GETSIG;
6742 break;
6743 case TARGET_F_SETSIG:
6744 ret = F_SETSIG;
6745 break;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006746#if TARGET_ABI_BITS == 32
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006747 case TARGET_F_GETLK64:
6748 ret = F_GETLK64;
6749 break;
6750 case TARGET_F_SETLK64:
6751 ret = F_SETLK64;
6752 break;
6753 case TARGET_F_SETLKW64:
6754 ret = F_SETLKW64;
6755 break;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006756#endif
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006757 case TARGET_F_SETLEASE:
6758 ret = F_SETLEASE;
6759 break;
6760 case TARGET_F_GETLEASE:
6761 ret = F_GETLEASE;
6762 break;
malcfbd5de92009-09-06 06:31:59 +04006763#ifdef F_DUPFD_CLOEXEC
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006764 case TARGET_F_DUPFD_CLOEXEC:
6765 ret = F_DUPFD_CLOEXEC;
6766 break;
malcfbd5de92009-09-06 06:31:59 +04006767#endif
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006768 case TARGET_F_NOTIFY:
6769 ret = F_NOTIFY;
6770 break;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006771#ifdef F_GETOWN_EX
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006772 case TARGET_F_GETOWN_EX:
6773 ret = F_GETOWN_EX;
6774 break;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006775#endif
6776#ifdef F_SETOWN_EX
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006777 case TARGET_F_SETOWN_EX:
6778 ret = F_SETOWN_EX;
6779 break;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006780#endif
Peter Maydellddf31aa2016-06-30 17:33:49 +01006781#ifdef F_SETPIPE_SZ
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006782 case TARGET_F_SETPIPE_SZ:
6783 ret = F_SETPIPE_SZ;
6784 break;
6785 case TARGET_F_GETPIPE_SZ:
6786 ret = F_GETPIPE_SZ;
6787 break;
Peter Maydellddf31aa2016-06-30 17:33:49 +01006788#endif
Shu-Chun Weng2bb963f2020-12-18 11:32:10 -08006789#ifdef F_ADD_SEALS
6790 case TARGET_F_ADD_SEALS:
6791 ret = F_ADD_SEALS;
6792 break;
6793 case TARGET_F_GET_SEALS:
6794 ret = F_GET_SEALS;
6795 break;
6796#endif
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006797 default:
6798 ret = -TARGET_EINVAL;
6799 break;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006800 }
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006801
6802#if defined(__powerpc64__)
6803 /* On PPC64, glibc headers has the F_*LK* defined to 12, 13 and 14 and
6804 * is not supported by kernel. The glibc fcntl call actually adjusts
6805 * them to 5, 6 and 7 before making the syscall(). Since we make the
6806 * syscall directly, adjust to what is supported by the kernel.
6807 */
6808 if (ret >= F_GETLK64 && ret <= F_SETLKW64) {
6809 ret -= F_GETLK64 - 5;
6810 }
6811#endif
6812
6813 return ret;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006814}
6815
Laurent Vivierae68ad92018-05-10 01:11:21 +02006816#define FLOCK_TRANSTBL \
6817 switch (type) { \
6818 TRANSTBL_CONVERT(F_RDLCK); \
6819 TRANSTBL_CONVERT(F_WRLCK); \
6820 TRANSTBL_CONVERT(F_UNLCK); \
Laurent Vivierae68ad92018-05-10 01:11:21 +02006821 }
6822
6823static int target_to_host_flock(int type)
6824{
6825#define TRANSTBL_CONVERT(a) case TARGET_##a: return a
6826 FLOCK_TRANSTBL
6827#undef TRANSTBL_CONVERT
6828 return -TARGET_EINVAL;
6829}
6830
6831static int host_to_target_flock(int type)
6832{
6833#define TRANSTBL_CONVERT(a) case a: return TARGET_##a
6834 FLOCK_TRANSTBL
6835#undef TRANSTBL_CONVERT
6836 /* if we don't know how to convert the value coming
6837 * from the host we copy to the target field as-is
6838 */
6839 return type;
6840}
Laurent Vivier2ba7f732013-01-10 21:42:48 +01006841
Peter Maydell213d3e92016-06-13 11:22:05 +01006842static inline abi_long copy_from_user_flock(struct flock64 *fl,
6843 abi_ulong target_flock_addr)
6844{
6845 struct target_flock *target_fl;
Laurent Vivierae68ad92018-05-10 01:11:21 +02006846 int l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006847
6848 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
6849 return -TARGET_EFAULT;
6850 }
6851
6852 __get_user(l_type, &target_fl->l_type);
Laurent Vivierae68ad92018-05-10 01:11:21 +02006853 l_type = target_to_host_flock(l_type);
6854 if (l_type < 0) {
6855 return l_type;
6856 }
6857 fl->l_type = l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006858 __get_user(fl->l_whence, &target_fl->l_whence);
6859 __get_user(fl->l_start, &target_fl->l_start);
6860 __get_user(fl->l_len, &target_fl->l_len);
6861 __get_user(fl->l_pid, &target_fl->l_pid);
6862 unlock_user_struct(target_fl, target_flock_addr, 0);
6863 return 0;
6864}
6865
6866static inline abi_long copy_to_user_flock(abi_ulong target_flock_addr,
6867 const struct flock64 *fl)
6868{
6869 struct target_flock *target_fl;
6870 short l_type;
6871
6872 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
6873 return -TARGET_EFAULT;
6874 }
6875
Laurent Vivierae68ad92018-05-10 01:11:21 +02006876 l_type = host_to_target_flock(fl->l_type);
Peter Maydell213d3e92016-06-13 11:22:05 +01006877 __put_user(l_type, &target_fl->l_type);
6878 __put_user(fl->l_whence, &target_fl->l_whence);
6879 __put_user(fl->l_start, &target_fl->l_start);
6880 __put_user(fl->l_len, &target_fl->l_len);
6881 __put_user(fl->l_pid, &target_fl->l_pid);
6882 unlock_user_struct(target_fl, target_flock_addr, 1);
6883 return 0;
6884}
6885
6886typedef abi_long from_flock64_fn(struct flock64 *fl, abi_ulong target_addr);
6887typedef abi_long to_flock64_fn(abi_ulong target_addr, const struct flock64 *fl);
6888
6889#if defined(TARGET_ARM) && TARGET_ABI_BITS == 32
Richard Hendersonffe81d42022-01-06 20:25:59 -08006890struct target_oabi_flock64 {
6891 abi_short l_type;
6892 abi_short l_whence;
6893 abi_llong l_start;
6894 abi_llong l_len;
6895 abi_int l_pid;
6896} QEMU_PACKED;
6897
Laurent Vivier7f254c52018-05-02 23:57:30 +02006898static inline abi_long copy_from_user_oabi_flock64(struct flock64 *fl,
Peter Maydell213d3e92016-06-13 11:22:05 +01006899 abi_ulong target_flock_addr)
6900{
Laurent Vivier7f254c52018-05-02 23:57:30 +02006901 struct target_oabi_flock64 *target_fl;
Laurent Vivierae68ad92018-05-10 01:11:21 +02006902 int l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006903
6904 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
6905 return -TARGET_EFAULT;
6906 }
6907
6908 __get_user(l_type, &target_fl->l_type);
Laurent Vivierae68ad92018-05-10 01:11:21 +02006909 l_type = target_to_host_flock(l_type);
6910 if (l_type < 0) {
6911 return l_type;
6912 }
6913 fl->l_type = l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006914 __get_user(fl->l_whence, &target_fl->l_whence);
6915 __get_user(fl->l_start, &target_fl->l_start);
6916 __get_user(fl->l_len, &target_fl->l_len);
6917 __get_user(fl->l_pid, &target_fl->l_pid);
6918 unlock_user_struct(target_fl, target_flock_addr, 0);
6919 return 0;
6920}
6921
Laurent Vivier7f254c52018-05-02 23:57:30 +02006922static inline abi_long copy_to_user_oabi_flock64(abi_ulong target_flock_addr,
Peter Maydell213d3e92016-06-13 11:22:05 +01006923 const struct flock64 *fl)
6924{
Laurent Vivier7f254c52018-05-02 23:57:30 +02006925 struct target_oabi_flock64 *target_fl;
Peter Maydell213d3e92016-06-13 11:22:05 +01006926 short l_type;
6927
6928 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
6929 return -TARGET_EFAULT;
6930 }
6931
Laurent Vivierae68ad92018-05-10 01:11:21 +02006932 l_type = host_to_target_flock(fl->l_type);
Peter Maydell213d3e92016-06-13 11:22:05 +01006933 __put_user(l_type, &target_fl->l_type);
6934 __put_user(fl->l_whence, &target_fl->l_whence);
6935 __put_user(fl->l_start, &target_fl->l_start);
6936 __put_user(fl->l_len, &target_fl->l_len);
6937 __put_user(fl->l_pid, &target_fl->l_pid);
6938 unlock_user_struct(target_fl, target_flock_addr, 1);
6939 return 0;
6940}
6941#endif
6942
6943static inline abi_long copy_from_user_flock64(struct flock64 *fl,
6944 abi_ulong target_flock_addr)
6945{
6946 struct target_flock64 *target_fl;
Laurent Vivierae68ad92018-05-10 01:11:21 +02006947 int l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006948
6949 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
6950 return -TARGET_EFAULT;
6951 }
6952
6953 __get_user(l_type, &target_fl->l_type);
Laurent Vivierae68ad92018-05-10 01:11:21 +02006954 l_type = target_to_host_flock(l_type);
6955 if (l_type < 0) {
6956 return l_type;
6957 }
6958 fl->l_type = l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006959 __get_user(fl->l_whence, &target_fl->l_whence);
6960 __get_user(fl->l_start, &target_fl->l_start);
6961 __get_user(fl->l_len, &target_fl->l_len);
6962 __get_user(fl->l_pid, &target_fl->l_pid);
6963 unlock_user_struct(target_fl, target_flock_addr, 0);
6964 return 0;
6965}
6966
6967static inline abi_long copy_to_user_flock64(abi_ulong target_flock_addr,
6968 const struct flock64 *fl)
6969{
6970 struct target_flock64 *target_fl;
6971 short l_type;
6972
6973 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
6974 return -TARGET_EFAULT;
6975 }
6976
Laurent Vivierae68ad92018-05-10 01:11:21 +02006977 l_type = host_to_target_flock(fl->l_type);
Peter Maydell213d3e92016-06-13 11:22:05 +01006978 __put_user(l_type, &target_fl->l_type);
6979 __put_user(fl->l_whence, &target_fl->l_whence);
6980 __put_user(fl->l_start, &target_fl->l_start);
6981 __put_user(fl->l_len, &target_fl->l_len);
6982 __put_user(fl->l_pid, &target_fl->l_pid);
6983 unlock_user_struct(target_fl, target_flock_addr, 1);
6984 return 0;
6985}
6986
blueswir1992f48a2007-10-14 16:27:31 +00006987static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
bellard7775e9e2003-05-14 22:46:48 +00006988{
ths43f238d2007-01-05 20:55:49 +00006989 struct flock64 fl64;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006990#ifdef F_GETOWN_EX
6991 struct f_owner_ex fox;
6992 struct target_f_owner_ex *target_fox;
6993#endif
blueswir1992f48a2007-10-14 16:27:31 +00006994 abi_long ret;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006995 int host_cmd = target_to_host_fcntl_cmd(cmd);
6996
6997 if (host_cmd == -TARGET_EINVAL)
6998 return host_cmd;
pbrook53a59602006-03-25 19:31:22 +00006999
bellard7775e9e2003-05-14 22:46:48 +00007000 switch(cmd) {
7001 case TARGET_F_GETLK:
Peter Maydell213d3e92016-06-13 11:22:05 +01007002 ret = copy_from_user_flock(&fl64, arg);
7003 if (ret) {
7004 return ret;
7005 }
Peter Maydell435da5e2016-06-13 11:22:05 +01007006 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00007007 if (ret == 0) {
Peter Maydell213d3e92016-06-13 11:22:05 +01007008 ret = copy_to_user_flock(arg, &fl64);
bellard7775e9e2003-05-14 22:46:48 +00007009 }
7010 break;
ths3b46e622007-09-17 08:09:54 +00007011
bellard7775e9e2003-05-14 22:46:48 +00007012 case TARGET_F_SETLK:
7013 case TARGET_F_SETLKW:
Peter Maydell213d3e92016-06-13 11:22:05 +01007014 ret = copy_from_user_flock(&fl64, arg);
7015 if (ret) {
7016 return ret;
7017 }
Peter Maydell435da5e2016-06-13 11:22:05 +01007018 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00007019 break;
ths3b46e622007-09-17 08:09:54 +00007020
bellard7775e9e2003-05-14 22:46:48 +00007021 case TARGET_F_GETLK64:
Andreas Schwab2d92c682020-05-25 09:59:28 +02007022 case TARGET_F_OFD_GETLK:
Peter Maydell213d3e92016-06-13 11:22:05 +01007023 ret = copy_from_user_flock64(&fl64, arg);
7024 if (ret) {
7025 return ret;
7026 }
Peter Maydell435da5e2016-06-13 11:22:05 +01007027 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
ths43f238d2007-01-05 20:55:49 +00007028 if (ret == 0) {
Peter Maydell213d3e92016-06-13 11:22:05 +01007029 ret = copy_to_user_flock64(arg, &fl64);
ths43f238d2007-01-05 20:55:49 +00007030 }
bellard9ee1fa22007-11-11 15:11:19 +00007031 break;
bellard7775e9e2003-05-14 22:46:48 +00007032 case TARGET_F_SETLK64:
7033 case TARGET_F_SETLKW64:
Andreas Schwab2d92c682020-05-25 09:59:28 +02007034 case TARGET_F_OFD_SETLK:
7035 case TARGET_F_OFD_SETLKW:
Peter Maydell213d3e92016-06-13 11:22:05 +01007036 ret = copy_from_user_flock64(&fl64, arg);
7037 if (ret) {
7038 return ret;
7039 }
Peter Maydell435da5e2016-06-13 11:22:05 +01007040 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00007041 break;
7042
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007043 case TARGET_F_GETFL:
Peter Maydell435da5e2016-06-13 11:22:05 +01007044 ret = get_errno(safe_fcntl(fd, host_cmd, arg));
bellard9ee1fa22007-11-11 15:11:19 +00007045 if (ret >= 0) {
7046 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
7047 }
bellardffa65c32004-01-04 23:57:22 +00007048 break;
7049
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007050 case TARGET_F_SETFL:
Peter Maydell435da5e2016-06-13 11:22:05 +01007051 ret = get_errno(safe_fcntl(fd, host_cmd,
7052 target_to_host_bitmask(arg,
7053 fcntl_flags_tbl)));
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007054 break;
7055
Andreas Schwab8d5d3002014-03-07 15:24:08 +01007056#ifdef F_GETOWN_EX
7057 case TARGET_F_GETOWN_EX:
Peter Maydell435da5e2016-06-13 11:22:05 +01007058 ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
Andreas Schwab8d5d3002014-03-07 15:24:08 +01007059 if (ret >= 0) {
7060 if (!lock_user_struct(VERIFY_WRITE, target_fox, arg, 0))
7061 return -TARGET_EFAULT;
7062 target_fox->type = tswap32(fox.type);
7063 target_fox->pid = tswap32(fox.pid);
7064 unlock_user_struct(target_fox, arg, 1);
7065 }
7066 break;
7067#endif
7068
7069#ifdef F_SETOWN_EX
7070 case TARGET_F_SETOWN_EX:
7071 if (!lock_user_struct(VERIFY_READ, target_fox, arg, 1))
7072 return -TARGET_EFAULT;
7073 fox.type = tswap32(target_fox->type);
7074 fox.pid = tswap32(target_fox->pid);
7075 unlock_user_struct(target_fox, arg, 0);
Peter Maydell435da5e2016-06-13 11:22:05 +01007076 ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
Andreas Schwab8d5d3002014-03-07 15:24:08 +01007077 break;
7078#endif
7079
Timothy Baldwina7b4c9b2020-07-29 21:06:44 +01007080 case TARGET_F_SETSIG:
7081 ret = get_errno(safe_fcntl(fd, host_cmd, target_to_host_signal(arg)));
7082 break;
7083
7084 case TARGET_F_GETSIG:
7085 ret = host_to_target_signal(get_errno(safe_fcntl(fd, host_cmd, arg)));
7086 break;
7087
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007088 case TARGET_F_SETOWN:
7089 case TARGET_F_GETOWN:
Ulrich Hecht7e22e542009-07-24 19:10:27 +02007090 case TARGET_F_SETLEASE:
7091 case TARGET_F_GETLEASE:
Peter Maydell7e3b92e2016-06-20 15:50:37 +01007092 case TARGET_F_SETPIPE_SZ:
7093 case TARGET_F_GETPIPE_SZ:
Shu-Chun Weng2bb963f2020-12-18 11:32:10 -08007094 case TARGET_F_ADD_SEALS:
7095 case TARGET_F_GET_SEALS:
Peter Maydell435da5e2016-06-13 11:22:05 +01007096 ret = get_errno(safe_fcntl(fd, host_cmd, arg));
bellardffa65c32004-01-04 23:57:22 +00007097 break;
7098
bellard7775e9e2003-05-14 22:46:48 +00007099 default:
Peter Maydell435da5e2016-06-13 11:22:05 +01007100 ret = get_errno(safe_fcntl(fd, cmd, arg));
bellard7775e9e2003-05-14 22:46:48 +00007101 break;
7102 }
7103 return ret;
7104}
7105
bellard67867302003-11-23 17:05:30 +00007106#ifdef USE_UID16
bellard7775e9e2003-05-14 22:46:48 +00007107
bellard67867302003-11-23 17:05:30 +00007108static inline int high2lowuid(int uid)
7109{
7110 if (uid > 65535)
7111 return 65534;
7112 else
7113 return uid;
7114}
7115
7116static inline int high2lowgid(int gid)
7117{
7118 if (gid > 65535)
7119 return 65534;
7120 else
7121 return gid;
7122}
7123
7124static inline int low2highuid(int uid)
7125{
7126 if ((int16_t)uid == -1)
7127 return -1;
7128 else
7129 return uid;
7130}
7131
7132static inline int low2highgid(int gid)
7133{
7134 if ((int16_t)gid == -1)
7135 return -1;
7136 else
7137 return gid;
7138}
Riku Voipio0c866a72011-04-18 15:23:06 +03007139static inline int tswapid(int id)
7140{
7141 return tswap16(id);
7142}
Peter Maydell76ca3102014-03-02 19:36:41 +00007143
7144#define put_user_id(x, gaddr) put_user_u16(x, gaddr)
7145
Riku Voipio0c866a72011-04-18 15:23:06 +03007146#else /* !USE_UID16 */
7147static inline int high2lowuid(int uid)
7148{
7149 return uid;
7150}
7151static inline int high2lowgid(int gid)
7152{
7153 return gid;
7154}
7155static inline int low2highuid(int uid)
7156{
7157 return uid;
7158}
7159static inline int low2highgid(int gid)
7160{
7161 return gid;
7162}
7163static inline int tswapid(int id)
7164{
7165 return tswap32(id);
7166}
Peter Maydell76ca3102014-03-02 19:36:41 +00007167
7168#define put_user_id(x, gaddr) put_user_u32(x, gaddr)
7169
bellard67867302003-11-23 17:05:30 +00007170#endif /* USE_UID16 */
bellard1b6b0292003-03-22 17:31:38 +00007171
Peter Maydellfd6f7792016-03-01 16:33:02 +00007172/* We must do direct syscalls for setting UID/GID, because we want to
7173 * implement the Linux system call semantics of "change only for this thread",
7174 * not the libc/POSIX semantics of "change for all threads in process".
7175 * (See http://ewontfix.com/17/ for more details.)
7176 * We use the 32-bit version of the syscalls if present; if it is not
7177 * then either the host architecture supports 32-bit UIDs natively with
7178 * the standard syscall, or the 16-bit UID is the best we can do.
7179 */
7180#ifdef __NR_setuid32
7181#define __NR_sys_setuid __NR_setuid32
7182#else
7183#define __NR_sys_setuid __NR_setuid
7184#endif
7185#ifdef __NR_setgid32
7186#define __NR_sys_setgid __NR_setgid32
7187#else
7188#define __NR_sys_setgid __NR_setgid
7189#endif
7190#ifdef __NR_setresuid32
7191#define __NR_sys_setresuid __NR_setresuid32
7192#else
7193#define __NR_sys_setresuid __NR_setresuid
7194#endif
7195#ifdef __NR_setresgid32
7196#define __NR_sys_setresgid __NR_setresgid32
7197#else
7198#define __NR_sys_setresgid __NR_setresgid
7199#endif
7200
7201_syscall1(int, sys_setuid, uid_t, uid)
7202_syscall1(int, sys_setgid, gid_t, gid)
7203_syscall3(int, sys_setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
7204_syscall3(int, sys_setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
7205
bellard31e31b82003-02-18 22:55:36 +00007206void syscall_init(void)
7207{
bellard2ab83ea2003-06-15 19:56:46 +00007208 IOCTLEntry *ie;
7209 const argtype *arg_type;
7210 int size;
7211
Alexander Graf8be656b2015-05-06 23:47:32 +02007212 thunk_init(STRUCT_MAX);
7213
Blue Swirl001faf32009-05-13 17:53:17 +00007214#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
ths5fafdf22007-09-16 21:08:06 +00007215#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
bellard31e31b82003-02-18 22:55:36 +00007216#include "syscall_types.h"
7217#undef STRUCT
7218#undef STRUCT_SPECIAL
bellard2ab83ea2003-06-15 19:56:46 +00007219
7220 /* we patch the ioctl size if necessary. We rely on the fact that
7221 no ioctl has all the bits at '1' in the size field */
7222 ie = ioctl_entries;
7223 while (ie->target_cmd != 0) {
7224 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
7225 TARGET_IOC_SIZEMASK) {
7226 arg_type = ie->arg_type;
7227 if (arg_type[0] != TYPE_PTR) {
ths5fafdf22007-09-16 21:08:06 +00007228 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00007229 ie->target_cmd);
7230 exit(1);
7231 }
7232 arg_type++;
7233 size = thunk_type_size(arg_type, 0);
ths5fafdf22007-09-16 21:08:06 +00007234 ie->target_cmd = (ie->target_cmd &
bellard2ab83ea2003-06-15 19:56:46 +00007235 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
7236 (size << TARGET_IOC_SIZESHIFT);
7237 }
thsb92c47c2007-11-01 00:07:38 +00007238
bellard2ab83ea2003-06-15 19:56:46 +00007239 /* automatic consistency check if same arch */
balrog872ea0c2008-09-21 02:31:19 +00007240#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
7241 (defined(__x86_64__) && defined(TARGET_X86_64))
7242 if (unlikely(ie->target_cmd != ie->host_cmd)) {
7243 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
7244 ie->name, ie->target_cmd, ie->host_cmd);
bellard2ab83ea2003-06-15 19:56:46 +00007245 }
7246#endif
7247 ie++;
7248 }
bellard31e31b82003-02-18 22:55:36 +00007249}
bellardc573ff62004-01-04 15:51:36 +00007250
pbrookce4defa2006-02-09 16:49:55 +00007251#ifdef TARGET_NR_truncate64
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02007252static inline abi_long target_truncate64(CPUArchState *cpu_env, const char *arg1,
blueswir1992f48a2007-10-14 16:27:31 +00007253 abi_long arg2,
7254 abi_long arg3,
7255 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00007256{
James Clarke8bf8e9d2017-09-15 20:33:13 +01007257 if (regpairs_aligned(cpu_env, TARGET_NR_truncate64)) {
pbrookce4defa2006-02-09 16:49:55 +00007258 arg2 = arg3;
7259 arg3 = arg4;
Riku Voipio48e515d2011-07-12 15:40:51 +03007260 }
pbrookce4defa2006-02-09 16:49:55 +00007261 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
7262}
7263#endif
7264
7265#ifdef TARGET_NR_ftruncate64
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02007266static inline abi_long target_ftruncate64(CPUArchState *cpu_env, abi_long arg1,
blueswir1992f48a2007-10-14 16:27:31 +00007267 abi_long arg2,
7268 abi_long arg3,
7269 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00007270{
James Clarke8bf8e9d2017-09-15 20:33:13 +01007271 if (regpairs_aligned(cpu_env, TARGET_NR_ftruncate64)) {
pbrookce4defa2006-02-09 16:49:55 +00007272 arg2 = arg3;
7273 arg3 = arg4;
Riku Voipio48e515d2011-07-12 15:40:51 +03007274 }
pbrookce4defa2006-02-09 16:49:55 +00007275 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
7276}
7277#endif
7278
Alistair Francis859e8a82020-03-12 15:13:49 -07007279#if defined(TARGET_NR_timer_settime) || \
7280 (defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD))
Filip Bozuta2c86c902020-07-22 17:34:20 +02007281static inline abi_long target_to_host_itimerspec(struct itimerspec *host_its,
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007282 abi_ulong target_addr)
7283{
Filip Bozuta2c86c902020-07-22 17:34:20 +02007284 if (target_to_host_timespec(&host_its->it_interval, target_addr +
7285 offsetof(struct target_itimerspec,
7286 it_interval)) ||
7287 target_to_host_timespec(&host_its->it_value, target_addr +
7288 offsetof(struct target_itimerspec,
7289 it_value))) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007290 return -TARGET_EFAULT;
7291 }
7292
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007293 return 0;
7294}
Alistair Francis859e8a82020-03-12 15:13:49 -07007295#endif
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007296
Filip Bozuta828cb3a2020-07-22 17:34:21 +02007297#if defined(TARGET_NR_timer_settime64) || \
7298 (defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD))
7299static inline abi_long target_to_host_itimerspec64(struct itimerspec *host_its,
7300 abi_ulong target_addr)
7301{
7302 if (target_to_host_timespec64(&host_its->it_interval, target_addr +
7303 offsetof(struct target__kernel_itimerspec,
7304 it_interval)) ||
7305 target_to_host_timespec64(&host_its->it_value, target_addr +
7306 offsetof(struct target__kernel_itimerspec,
7307 it_value))) {
7308 return -TARGET_EFAULT;
7309 }
7310
7311 return 0;
7312}
7313#endif
7314
Alistair Francis859e8a82020-03-12 15:13:49 -07007315#if ((defined(TARGET_NR_timerfd_gettime) || \
7316 defined(TARGET_NR_timerfd_settime)) && defined(CONFIG_TIMERFD)) || \
Filip Bozuta2c86c902020-07-22 17:34:20 +02007317 defined(TARGET_NR_timer_gettime) || defined(TARGET_NR_timer_settime)
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007318static inline abi_long host_to_target_itimerspec(abi_ulong target_addr,
Filip Bozuta2c86c902020-07-22 17:34:20 +02007319 struct itimerspec *host_its)
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007320{
Filip Bozuta2c86c902020-07-22 17:34:20 +02007321 if (host_to_target_timespec(target_addr + offsetof(struct target_itimerspec,
7322 it_interval),
7323 &host_its->it_interval) ||
7324 host_to_target_timespec(target_addr + offsetof(struct target_itimerspec,
7325 it_value),
7326 &host_its->it_value)) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007327 return -TARGET_EFAULT;
7328 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007329 return 0;
7330}
Alistair Francis859e8a82020-03-12 15:13:49 -07007331#endif
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007332
Filip Bozuta828cb3a2020-07-22 17:34:21 +02007333#if ((defined(TARGET_NR_timerfd_gettime64) || \
7334 defined(TARGET_NR_timerfd_settime64)) && defined(CONFIG_TIMERFD)) || \
7335 defined(TARGET_NR_timer_gettime64) || defined(TARGET_NR_timer_settime64)
7336static inline abi_long host_to_target_itimerspec64(abi_ulong target_addr,
7337 struct itimerspec *host_its)
7338{
7339 if (host_to_target_timespec64(target_addr +
7340 offsetof(struct target__kernel_itimerspec,
7341 it_interval),
7342 &host_its->it_interval) ||
7343 host_to_target_timespec64(target_addr +
7344 offsetof(struct target__kernel_itimerspec,
7345 it_value),
7346 &host_its->it_value)) {
7347 return -TARGET_EFAULT;
7348 }
7349 return 0;
7350}
7351#endif
7352
Alistair Francis859e8a82020-03-12 15:13:49 -07007353#if defined(TARGET_NR_adjtimex) || \
7354 (defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME))
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +02007355static inline abi_long target_to_host_timex(struct timex *host_tx,
7356 abi_long target_addr)
7357{
7358 struct target_timex *target_tx;
7359
7360 if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) {
7361 return -TARGET_EFAULT;
7362 }
7363
7364 __get_user(host_tx->modes, &target_tx->modes);
7365 __get_user(host_tx->offset, &target_tx->offset);
7366 __get_user(host_tx->freq, &target_tx->freq);
7367 __get_user(host_tx->maxerror, &target_tx->maxerror);
7368 __get_user(host_tx->esterror, &target_tx->esterror);
7369 __get_user(host_tx->status, &target_tx->status);
7370 __get_user(host_tx->constant, &target_tx->constant);
7371 __get_user(host_tx->precision, &target_tx->precision);
7372 __get_user(host_tx->tolerance, &target_tx->tolerance);
7373 __get_user(host_tx->time.tv_sec, &target_tx->time.tv_sec);
7374 __get_user(host_tx->time.tv_usec, &target_tx->time.tv_usec);
7375 __get_user(host_tx->tick, &target_tx->tick);
7376 __get_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7377 __get_user(host_tx->jitter, &target_tx->jitter);
7378 __get_user(host_tx->shift, &target_tx->shift);
7379 __get_user(host_tx->stabil, &target_tx->stabil);
7380 __get_user(host_tx->jitcnt, &target_tx->jitcnt);
7381 __get_user(host_tx->calcnt, &target_tx->calcnt);
7382 __get_user(host_tx->errcnt, &target_tx->errcnt);
7383 __get_user(host_tx->stbcnt, &target_tx->stbcnt);
7384 __get_user(host_tx->tai, &target_tx->tai);
7385
7386 unlock_user_struct(target_tx, target_addr, 0);
7387 return 0;
7388}
7389
7390static inline abi_long host_to_target_timex(abi_long target_addr,
7391 struct timex *host_tx)
7392{
7393 struct target_timex *target_tx;
7394
7395 if (!lock_user_struct(VERIFY_WRITE, target_tx, target_addr, 0)) {
7396 return -TARGET_EFAULT;
7397 }
7398
7399 __put_user(host_tx->modes, &target_tx->modes);
7400 __put_user(host_tx->offset, &target_tx->offset);
7401 __put_user(host_tx->freq, &target_tx->freq);
7402 __put_user(host_tx->maxerror, &target_tx->maxerror);
7403 __put_user(host_tx->esterror, &target_tx->esterror);
7404 __put_user(host_tx->status, &target_tx->status);
7405 __put_user(host_tx->constant, &target_tx->constant);
7406 __put_user(host_tx->precision, &target_tx->precision);
7407 __put_user(host_tx->tolerance, &target_tx->tolerance);
7408 __put_user(host_tx->time.tv_sec, &target_tx->time.tv_sec);
7409 __put_user(host_tx->time.tv_usec, &target_tx->time.tv_usec);
7410 __put_user(host_tx->tick, &target_tx->tick);
7411 __put_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7412 __put_user(host_tx->jitter, &target_tx->jitter);
7413 __put_user(host_tx->shift, &target_tx->shift);
7414 __put_user(host_tx->stabil, &target_tx->stabil);
7415 __put_user(host_tx->jitcnt, &target_tx->jitcnt);
7416 __put_user(host_tx->calcnt, &target_tx->calcnt);
7417 __put_user(host_tx->errcnt, &target_tx->errcnt);
7418 __put_user(host_tx->stbcnt, &target_tx->stbcnt);
7419 __put_user(host_tx->tai, &target_tx->tai);
7420
7421 unlock_user_struct(target_tx, target_addr, 1);
7422 return 0;
7423}
Alistair Francis859e8a82020-03-12 15:13:49 -07007424#endif
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +02007425
Filip Bozuta6ac03b22020-08-24 21:21:15 +02007426
7427#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
7428static inline abi_long target_to_host_timex64(struct timex *host_tx,
7429 abi_long target_addr)
7430{
7431 struct target__kernel_timex *target_tx;
7432
7433 if (copy_from_user_timeval64(&host_tx->time, target_addr +
7434 offsetof(struct target__kernel_timex,
7435 time))) {
7436 return -TARGET_EFAULT;
7437 }
7438
7439 if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) {
7440 return -TARGET_EFAULT;
7441 }
7442
7443 __get_user(host_tx->modes, &target_tx->modes);
7444 __get_user(host_tx->offset, &target_tx->offset);
7445 __get_user(host_tx->freq, &target_tx->freq);
7446 __get_user(host_tx->maxerror, &target_tx->maxerror);
7447 __get_user(host_tx->esterror, &target_tx->esterror);
7448 __get_user(host_tx->status, &target_tx->status);
7449 __get_user(host_tx->constant, &target_tx->constant);
7450 __get_user(host_tx->precision, &target_tx->precision);
7451 __get_user(host_tx->tolerance, &target_tx->tolerance);
7452 __get_user(host_tx->tick, &target_tx->tick);
7453 __get_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7454 __get_user(host_tx->jitter, &target_tx->jitter);
7455 __get_user(host_tx->shift, &target_tx->shift);
7456 __get_user(host_tx->stabil, &target_tx->stabil);
7457 __get_user(host_tx->jitcnt, &target_tx->jitcnt);
7458 __get_user(host_tx->calcnt, &target_tx->calcnt);
7459 __get_user(host_tx->errcnt, &target_tx->errcnt);
7460 __get_user(host_tx->stbcnt, &target_tx->stbcnt);
7461 __get_user(host_tx->tai, &target_tx->tai);
7462
7463 unlock_user_struct(target_tx, target_addr, 0);
7464 return 0;
7465}
7466
7467static inline abi_long host_to_target_timex64(abi_long target_addr,
7468 struct timex *host_tx)
7469{
7470 struct target__kernel_timex *target_tx;
7471
7472 if (copy_to_user_timeval64(target_addr +
7473 offsetof(struct target__kernel_timex, time),
7474 &host_tx->time)) {
7475 return -TARGET_EFAULT;
7476 }
7477
7478 if (!lock_user_struct(VERIFY_WRITE, target_tx, target_addr, 0)) {
7479 return -TARGET_EFAULT;
7480 }
7481
7482 __put_user(host_tx->modes, &target_tx->modes);
7483 __put_user(host_tx->offset, &target_tx->offset);
7484 __put_user(host_tx->freq, &target_tx->freq);
7485 __put_user(host_tx->maxerror, &target_tx->maxerror);
7486 __put_user(host_tx->esterror, &target_tx->esterror);
7487 __put_user(host_tx->status, &target_tx->status);
7488 __put_user(host_tx->constant, &target_tx->constant);
7489 __put_user(host_tx->precision, &target_tx->precision);
7490 __put_user(host_tx->tolerance, &target_tx->tolerance);
7491 __put_user(host_tx->tick, &target_tx->tick);
7492 __put_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7493 __put_user(host_tx->jitter, &target_tx->jitter);
7494 __put_user(host_tx->shift, &target_tx->shift);
7495 __put_user(host_tx->stabil, &target_tx->stabil);
7496 __put_user(host_tx->jitcnt, &target_tx->jitcnt);
7497 __put_user(host_tx->calcnt, &target_tx->calcnt);
7498 __put_user(host_tx->errcnt, &target_tx->errcnt);
7499 __put_user(host_tx->stbcnt, &target_tx->stbcnt);
7500 __put_user(host_tx->tai, &target_tx->tai);
7501
7502 unlock_user_struct(target_tx, target_addr, 1);
7503 return 0;
7504}
7505#endif
7506
Michael Forney96ff7582021-05-25 20:55:56 -07007507#ifndef HAVE_SIGEV_NOTIFY_THREAD_ID
7508#define sigev_notify_thread_id _sigev_un._tid
7509#endif
7510
Peter Maydellc0659762014-08-09 15:42:32 +01007511static inline abi_long target_to_host_sigevent(struct sigevent *host_sevp,
7512 abi_ulong target_addr)
7513{
7514 struct target_sigevent *target_sevp;
7515
7516 if (!lock_user_struct(VERIFY_READ, target_sevp, target_addr, 1)) {
7517 return -TARGET_EFAULT;
7518 }
7519
7520 /* This union is awkward on 64 bit systems because it has a 32 bit
7521 * integer and a pointer in it; we follow the conversion approach
7522 * used for handling sigval types in signal.c so the guest should get
7523 * the correct value back even if we did a 64 bit byteswap and it's
7524 * using the 32 bit integer.
7525 */
7526 host_sevp->sigev_value.sival_ptr =
7527 (void *)(uintptr_t)tswapal(target_sevp->sigev_value.sival_ptr);
7528 host_sevp->sigev_signo =
7529 target_to_host_signal(tswap32(target_sevp->sigev_signo));
7530 host_sevp->sigev_notify = tswap32(target_sevp->sigev_notify);
Michael Forney96ff7582021-05-25 20:55:56 -07007531 host_sevp->sigev_notify_thread_id = tswap32(target_sevp->_sigev_un._tid);
Peter Maydellc0659762014-08-09 15:42:32 +01007532
7533 unlock_user_struct(target_sevp, target_addr, 1);
7534 return 0;
7535}
7536
Tom Musta6f6a4032014-08-12 13:53:42 -05007537#if defined(TARGET_NR_mlockall)
7538static inline int target_to_host_mlockall_arg(int arg)
7539{
7540 int result = 0;
7541
Filip Bozuta02e5d7d2020-08-11 18:45:51 +02007542 if (arg & TARGET_MCL_CURRENT) {
Tom Musta6f6a4032014-08-12 13:53:42 -05007543 result |= MCL_CURRENT;
7544 }
Filip Bozuta02e5d7d2020-08-11 18:45:51 +02007545 if (arg & TARGET_MCL_FUTURE) {
Tom Musta6f6a4032014-08-12 13:53:42 -05007546 result |= MCL_FUTURE;
7547 }
Filip Bozuta02e5d7d2020-08-11 18:45:51 +02007548#ifdef MCL_ONFAULT
7549 if (arg & TARGET_MCL_ONFAULT) {
7550 result |= MCL_ONFAULT;
7551 }
7552#endif
7553
Tom Musta6f6a4032014-08-12 13:53:42 -05007554 return result;
7555}
7556#endif
7557
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02007558#if (defined(TARGET_NR_stat64) || defined(TARGET_NR_lstat64) || \
7559 defined(TARGET_NR_fstat64) || defined(TARGET_NR_fstatat64) || \
7560 defined(TARGET_NR_newfstatat))
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02007561static inline abi_long host_to_target_stat64(CPUArchState *cpu_env,
balrog6a24a772008-09-20 02:23:36 +00007562 abi_ulong target_addr,
7563 struct stat *host_st)
7564{
Alexander Graf09701192013-09-03 20:12:15 +01007565#if defined(TARGET_ARM) && defined(TARGET_ABI32)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02007566 if (cpu_env->eabi) {
balrog6a24a772008-09-20 02:23:36 +00007567 struct target_eabi_stat64 *target_st;
7568
7569 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
7570 return -TARGET_EFAULT;
7571 memset(target_st, 0, sizeof(struct target_eabi_stat64));
7572 __put_user(host_st->st_dev, &target_st->st_dev);
7573 __put_user(host_st->st_ino, &target_st->st_ino);
7574#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
7575 __put_user(host_st->st_ino, &target_st->__st_ino);
7576#endif
7577 __put_user(host_st->st_mode, &target_st->st_mode);
7578 __put_user(host_st->st_nlink, &target_st->st_nlink);
7579 __put_user(host_st->st_uid, &target_st->st_uid);
7580 __put_user(host_st->st_gid, &target_st->st_gid);
7581 __put_user(host_st->st_rdev, &target_st->st_rdev);
7582 __put_user(host_st->st_size, &target_st->st_size);
7583 __put_user(host_st->st_blksize, &target_st->st_blksize);
7584 __put_user(host_st->st_blocks, &target_st->st_blocks);
7585 __put_user(host_st->st_atime, &target_st->target_st_atime);
7586 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
7587 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
Michael Forneyfebf6fa2021-05-25 20:55:31 -07007588#ifdef HAVE_STRUCT_STAT_ST_ATIM
Chen-Yu Tsai5f992db2019-05-23 00:21:47 +08007589 __put_user(host_st->st_atim.tv_nsec, &target_st->target_st_atime_nsec);
7590 __put_user(host_st->st_mtim.tv_nsec, &target_st->target_st_mtime_nsec);
7591 __put_user(host_st->st_ctim.tv_nsec, &target_st->target_st_ctime_nsec);
7592#endif
balrog6a24a772008-09-20 02:23:36 +00007593 unlock_user_struct(target_st, target_addr, 1);
7594 } else
7595#endif
7596 {
Stefan Weil20d155b2013-10-30 22:52:24 +01007597#if defined(TARGET_HAS_STRUCT_STAT64)
balrog6a24a772008-09-20 02:23:36 +00007598 struct target_stat64 *target_st;
Stefan Weil20d155b2013-10-30 22:52:24 +01007599#else
7600 struct target_stat *target_st;
aurel329d33b762009-04-08 23:07:05 +00007601#endif
balrog6a24a772008-09-20 02:23:36 +00007602
7603 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
7604 return -TARGET_EFAULT;
aurel329d33b762009-04-08 23:07:05 +00007605 memset(target_st, 0, sizeof(*target_st));
balrog6a24a772008-09-20 02:23:36 +00007606 __put_user(host_st->st_dev, &target_st->st_dev);
7607 __put_user(host_st->st_ino, &target_st->st_ino);
7608#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
7609 __put_user(host_st->st_ino, &target_st->__st_ino);
7610#endif
7611 __put_user(host_st->st_mode, &target_st->st_mode);
7612 __put_user(host_st->st_nlink, &target_st->st_nlink);
7613 __put_user(host_st->st_uid, &target_st->st_uid);
7614 __put_user(host_st->st_gid, &target_st->st_gid);
7615 __put_user(host_st->st_rdev, &target_st->st_rdev);
7616 /* XXX: better use of kernel struct */
7617 __put_user(host_st->st_size, &target_st->st_size);
7618 __put_user(host_st->st_blksize, &target_st->st_blksize);
7619 __put_user(host_st->st_blocks, &target_st->st_blocks);
7620 __put_user(host_st->st_atime, &target_st->target_st_atime);
7621 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
7622 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
Michael Forneyfebf6fa2021-05-25 20:55:31 -07007623#ifdef HAVE_STRUCT_STAT_ST_ATIM
Chen-Yu Tsai5f992db2019-05-23 00:21:47 +08007624 __put_user(host_st->st_atim.tv_nsec, &target_st->target_st_atime_nsec);
7625 __put_user(host_st->st_mtim.tv_nsec, &target_st->target_st_mtime_nsec);
7626 __put_user(host_st->st_ctim.tv_nsec, &target_st->target_st_ctime_nsec);
7627#endif
balrog6a24a772008-09-20 02:23:36 +00007628 unlock_user_struct(target_st, target_addr, 1);
7629 }
7630
7631 return 0;
7632}
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02007633#endif
balrog6a24a772008-09-20 02:23:36 +00007634
Aleksandar Rikaloefa92182019-06-28 12:43:34 +02007635#if defined(TARGET_NR_statx) && defined(__NR_statx)
7636static inline abi_long host_to_target_statx(struct target_statx *host_stx,
7637 abi_ulong target_addr)
7638{
7639 struct target_statx *target_stx;
7640
7641 if (!lock_user_struct(VERIFY_WRITE, target_stx, target_addr, 0)) {
7642 return -TARGET_EFAULT;
7643 }
7644 memset(target_stx, 0, sizeof(*target_stx));
7645
7646 __put_user(host_stx->stx_mask, &target_stx->stx_mask);
7647 __put_user(host_stx->stx_blksize, &target_stx->stx_blksize);
7648 __put_user(host_stx->stx_attributes, &target_stx->stx_attributes);
7649 __put_user(host_stx->stx_nlink, &target_stx->stx_nlink);
7650 __put_user(host_stx->stx_uid, &target_stx->stx_uid);
7651 __put_user(host_stx->stx_gid, &target_stx->stx_gid);
7652 __put_user(host_stx->stx_mode, &target_stx->stx_mode);
7653 __put_user(host_stx->stx_ino, &target_stx->stx_ino);
7654 __put_user(host_stx->stx_size, &target_stx->stx_size);
7655 __put_user(host_stx->stx_blocks, &target_stx->stx_blocks);
7656 __put_user(host_stx->stx_attributes_mask, &target_stx->stx_attributes_mask);
7657 __put_user(host_stx->stx_atime.tv_sec, &target_stx->stx_atime.tv_sec);
7658 __put_user(host_stx->stx_atime.tv_nsec, &target_stx->stx_atime.tv_nsec);
Ariadne Conilld1e26702019-11-22 11:40:40 -06007659 __put_user(host_stx->stx_btime.tv_sec, &target_stx->stx_btime.tv_sec);
7660 __put_user(host_stx->stx_btime.tv_nsec, &target_stx->stx_btime.tv_nsec);
7661 __put_user(host_stx->stx_ctime.tv_sec, &target_stx->stx_ctime.tv_sec);
7662 __put_user(host_stx->stx_ctime.tv_nsec, &target_stx->stx_ctime.tv_nsec);
7663 __put_user(host_stx->stx_mtime.tv_sec, &target_stx->stx_mtime.tv_sec);
7664 __put_user(host_stx->stx_mtime.tv_nsec, &target_stx->stx_mtime.tv_nsec);
Aleksandar Rikaloefa92182019-06-28 12:43:34 +02007665 __put_user(host_stx->stx_rdev_major, &target_stx->stx_rdev_major);
7666 __put_user(host_stx->stx_rdev_minor, &target_stx->stx_rdev_minor);
7667 __put_user(host_stx->stx_dev_major, &target_stx->stx_dev_major);
7668 __put_user(host_stx->stx_dev_minor, &target_stx->stx_dev_minor);
7669
7670 unlock_user_struct(target_stx, target_addr, 1);
7671
7672 return 0;
7673}
7674#endif
7675
Alistair Francis14690292020-03-18 15:47:01 -07007676static int do_sys_futex(int *uaddr, int op, int val,
7677 const struct timespec *timeout, int *uaddr2,
7678 int val3)
7679{
7680#if HOST_LONG_BITS == 64
7681#if defined(__NR_futex)
7682 /* always a 64-bit time_t, it doesn't define _time64 version */
7683 return sys_futex(uaddr, op, val, timeout, uaddr2, val3);
7684
7685#endif
7686#else /* HOST_LONG_BITS == 64 */
7687#if defined(__NR_futex_time64)
7688 if (sizeof(timeout->tv_sec) == 8) {
7689 /* _time64 function on 32bit arch */
7690 return sys_futex_time64(uaddr, op, val, timeout, uaddr2, val3);
7691 }
7692#endif
7693#if defined(__NR_futex)
7694 /* old function on 32bit arch */
7695 return sys_futex(uaddr, op, val, timeout, uaddr2, val3);
7696#endif
7697#endif /* HOST_LONG_BITS == 64 */
7698 g_assert_not_reached();
7699}
7700
7701static int do_safe_futex(int *uaddr, int op, int val,
7702 const struct timespec *timeout, int *uaddr2,
7703 int val3)
7704{
7705#if HOST_LONG_BITS == 64
7706#if defined(__NR_futex)
7707 /* always a 64-bit time_t, it doesn't define _time64 version */
7708 return get_errno(safe_futex(uaddr, op, val, timeout, uaddr2, val3));
7709#endif
7710#else /* HOST_LONG_BITS == 64 */
7711#if defined(__NR_futex_time64)
7712 if (sizeof(timeout->tv_sec) == 8) {
7713 /* _time64 function on 32bit arch */
7714 return get_errno(safe_futex_time64(uaddr, op, val, timeout, uaddr2,
7715 val3));
7716 }
7717#endif
7718#if defined(__NR_futex)
7719 /* old function on 32bit arch */
7720 return get_errno(safe_futex(uaddr, op, val, timeout, uaddr2, val3));
7721#endif
7722#endif /* HOST_LONG_BITS == 64 */
7723 return -TARGET_ENOSYS;
7724}
Aleksandar Rikaloefa92182019-06-28 12:43:34 +02007725
pbrookbd0c5662008-05-29 14:34:11 +00007726/* ??? Using host futex calls even when target atomic operations
7727 are not really atomic probably breaks things. However implementing
7728 futexes locally would make futexes shared between multiple processes
7729 tricky. However they're probably useless because guest atomic
7730 operations won't work either. */
Alistair Francis859e8a82020-03-12 15:13:49 -07007731#if defined(TARGET_NR_futex)
Richard Henderson3e8f1622021-02-12 10:48:43 -08007732static int do_futex(CPUState *cpu, target_ulong uaddr, int op, int val,
7733 target_ulong timeout, target_ulong uaddr2, int val3)
pbrookbd0c5662008-05-29 14:34:11 +00007734{
7735 struct timespec ts, *pts;
Nathan Froyda16aae02009-08-03 08:43:29 -07007736 int base_op;
pbrookbd0c5662008-05-29 14:34:11 +00007737
7738 /* ??? We assume FUTEX_* constants are the same on both host
7739 and target. */
Martin Mohringa29ccd62009-05-04 21:34:56 +03007740#ifdef FUTEX_CMD_MASK
Nathan Froyda16aae02009-08-03 08:43:29 -07007741 base_op = op & FUTEX_CMD_MASK;
Martin Mohringa29ccd62009-05-04 21:34:56 +03007742#else
Nathan Froyda16aae02009-08-03 08:43:29 -07007743 base_op = op;
Martin Mohringa29ccd62009-05-04 21:34:56 +03007744#endif
Nathan Froyda16aae02009-08-03 08:43:29 -07007745 switch (base_op) {
pbrookbd0c5662008-05-29 14:34:11 +00007746 case FUTEX_WAIT:
John Rigbycce246e2013-02-23 16:14:07 -07007747 case FUTEX_WAIT_BITSET:
pbrookbd0c5662008-05-29 14:34:11 +00007748 if (timeout) {
7749 pts = &ts;
7750 target_to_host_timespec(pts, timeout);
7751 } else {
7752 pts = NULL;
7753 }
Richard Henderson3e8f1622021-02-12 10:48:43 -08007754 return do_safe_futex(g2h(cpu, uaddr),
7755 op, tswap32(val), pts, NULL, val3);
pbrookbd0c5662008-05-29 14:34:11 +00007756 case FUTEX_WAKE:
Richard Henderson3e8f1622021-02-12 10:48:43 -08007757 return do_safe_futex(g2h(cpu, uaddr),
7758 op, val, NULL, NULL, 0);
pbrookbd0c5662008-05-29 14:34:11 +00007759 case FUTEX_FD:
Richard Henderson3e8f1622021-02-12 10:48:43 -08007760 return do_safe_futex(g2h(cpu, uaddr),
7761 op, val, NULL, NULL, 0);
pbrookbd0c5662008-05-29 14:34:11 +00007762 case FUTEX_REQUEUE:
pbrookbd0c5662008-05-29 14:34:11 +00007763 case FUTEX_CMP_REQUEUE:
Nathan Froyda16aae02009-08-03 08:43:29 -07007764 case FUTEX_WAKE_OP:
7765 /* For FUTEX_REQUEUE, FUTEX_CMP_REQUEUE, and FUTEX_WAKE_OP, the
7766 TIMEOUT parameter is interpreted as a uint32_t by the kernel.
7767 But the prototype takes a `struct timespec *'; insert casts
7768 to satisfy the compiler. We do not need to tswap TIMEOUT
7769 since it's not compared to guest memory. */
7770 pts = (struct timespec *)(uintptr_t) timeout;
Richard Henderson3e8f1622021-02-12 10:48:43 -08007771 return do_safe_futex(g2h(cpu, uaddr), op, val, pts, g2h(cpu, uaddr2),
Alistair Francis14690292020-03-18 15:47:01 -07007772 (base_op == FUTEX_CMP_REQUEUE
Richard Henderson3e8f1622021-02-12 10:48:43 -08007773 ? tswap32(val3) : val3));
pbrookbd0c5662008-05-29 14:34:11 +00007774 default:
7775 return -TARGET_ENOSYS;
7776 }
7777}
Alistair Francis859e8a82020-03-12 15:13:49 -07007778#endif
Alistair Francis14690292020-03-18 15:47:01 -07007779
7780#if defined(TARGET_NR_futex_time64)
Richard Henderson3e8f1622021-02-12 10:48:43 -08007781static int do_futex_time64(CPUState *cpu, target_ulong uaddr, int op,
7782 int val, target_ulong timeout,
Alistair Francis14690292020-03-18 15:47:01 -07007783 target_ulong uaddr2, int val3)
7784{
7785 struct timespec ts, *pts;
7786 int base_op;
7787
7788 /* ??? We assume FUTEX_* constants are the same on both host
7789 and target. */
7790#ifdef FUTEX_CMD_MASK
7791 base_op = op & FUTEX_CMD_MASK;
7792#else
7793 base_op = op;
7794#endif
7795 switch (base_op) {
7796 case FUTEX_WAIT:
7797 case FUTEX_WAIT_BITSET:
7798 if (timeout) {
7799 pts = &ts;
Alistair Francise4ce1782020-11-03 11:48:44 -08007800 if (target_to_host_timespec64(pts, timeout)) {
7801 return -TARGET_EFAULT;
7802 }
Alistair Francis14690292020-03-18 15:47:01 -07007803 } else {
7804 pts = NULL;
7805 }
Richard Henderson3e8f1622021-02-12 10:48:43 -08007806 return do_safe_futex(g2h(cpu, uaddr), op,
7807 tswap32(val), pts, NULL, val3);
Alistair Francis14690292020-03-18 15:47:01 -07007808 case FUTEX_WAKE:
Richard Henderson3e8f1622021-02-12 10:48:43 -08007809 return do_safe_futex(g2h(cpu, uaddr), op, val, NULL, NULL, 0);
Alistair Francis14690292020-03-18 15:47:01 -07007810 case FUTEX_FD:
Richard Henderson3e8f1622021-02-12 10:48:43 -08007811 return do_safe_futex(g2h(cpu, uaddr), op, val, NULL, NULL, 0);
Alistair Francis14690292020-03-18 15:47:01 -07007812 case FUTEX_REQUEUE:
7813 case FUTEX_CMP_REQUEUE:
7814 case FUTEX_WAKE_OP:
7815 /* For FUTEX_REQUEUE, FUTEX_CMP_REQUEUE, and FUTEX_WAKE_OP, the
7816 TIMEOUT parameter is interpreted as a uint32_t by the kernel.
7817 But the prototype takes a `struct timespec *'; insert casts
7818 to satisfy the compiler. We do not need to tswap TIMEOUT
7819 since it's not compared to guest memory. */
7820 pts = (struct timespec *)(uintptr_t) timeout;
Richard Henderson3e8f1622021-02-12 10:48:43 -08007821 return do_safe_futex(g2h(cpu, uaddr), op, val, pts, g2h(cpu, uaddr2),
Alistair Francis14690292020-03-18 15:47:01 -07007822 (base_op == FUTEX_CMP_REQUEUE
Richard Henderson3e8f1622021-02-12 10:48:43 -08007823 ? tswap32(val3) : val3));
Alistair Francis14690292020-03-18 15:47:01 -07007824 default:
7825 return -TARGET_ENOSYS;
7826 }
7827}
7828#endif
7829
Laurent Vivier0f0426f2015-09-01 22:27:33 +02007830#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
7831static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname,
7832 abi_long handle, abi_long mount_id,
7833 abi_long flags)
7834{
7835 struct file_handle *target_fh;
7836 struct file_handle *fh;
7837 int mid = 0;
7838 abi_long ret;
7839 char *name;
7840 unsigned int size, total_size;
7841
7842 if (get_user_s32(size, handle)) {
7843 return -TARGET_EFAULT;
7844 }
7845
7846 name = lock_user_string(pathname);
7847 if (!name) {
7848 return -TARGET_EFAULT;
7849 }
7850
7851 total_size = sizeof(struct file_handle) + size;
7852 target_fh = lock_user(VERIFY_WRITE, handle, total_size, 0);
7853 if (!target_fh) {
7854 unlock_user(name, pathname, 0);
7855 return -TARGET_EFAULT;
7856 }
7857
7858 fh = g_malloc0(total_size);
7859 fh->handle_bytes = size;
7860
7861 ret = get_errno(name_to_handle_at(dirfd, path(name), fh, &mid, flags));
7862 unlock_user(name, pathname, 0);
7863
7864 /* man name_to_handle_at(2):
7865 * Other than the use of the handle_bytes field, the caller should treat
7866 * the file_handle structure as an opaque data type
7867 */
7868
7869 memcpy(target_fh, fh, total_size);
7870 target_fh->handle_bytes = tswap32(fh->handle_bytes);
7871 target_fh->handle_type = tswap32(fh->handle_type);
7872 g_free(fh);
7873 unlock_user(target_fh, handle, total_size);
7874
7875 if (put_user_s32(mid, mount_id)) {
7876 return -TARGET_EFAULT;
7877 }
7878
7879 return ret;
7880
7881}
7882#endif
7883
7884#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
7885static abi_long do_open_by_handle_at(abi_long mount_fd, abi_long handle,
7886 abi_long flags)
7887{
7888 struct file_handle *target_fh;
7889 struct file_handle *fh;
7890 unsigned int size, total_size;
7891 abi_long ret;
7892
7893 if (get_user_s32(size, handle)) {
7894 return -TARGET_EFAULT;
7895 }
7896
7897 total_size = sizeof(struct file_handle) + size;
7898 target_fh = lock_user(VERIFY_READ, handle, total_size, 1);
7899 if (!target_fh) {
7900 return -TARGET_EFAULT;
7901 }
7902
Thomas Huthe9d49d52015-10-09 17:56:38 +02007903 fh = g_memdup(target_fh, total_size);
Laurent Vivier0f0426f2015-09-01 22:27:33 +02007904 fh->handle_bytes = size;
7905 fh->handle_type = tswap32(target_fh->handle_type);
7906
7907 ret = get_errno(open_by_handle_at(mount_fd, fh,
7908 target_to_host_bitmask(flags, fcntl_flags_tbl)));
7909
7910 g_free(fh);
7911
7912 unlock_user(target_fh, handle, total_size);
7913
7914 return ret;
7915}
7916#endif
pbrookbd0c5662008-05-29 14:34:11 +00007917
Laurent Viviere36800c2015-10-02 14:48:09 +02007918#if defined(TARGET_NR_signalfd) || defined(TARGET_NR_signalfd4)
7919
Laurent Viviere36800c2015-10-02 14:48:09 +02007920static abi_long do_signalfd4(int fd, abi_long mask, int flags)
7921{
7922 int host_flags;
7923 target_sigset_t *target_mask;
7924 sigset_t host_mask;
7925 abi_long ret;
7926
Helge Deller78721302021-02-10 07:12:14 +01007927 if (flags & ~(TARGET_O_NONBLOCK_MASK | TARGET_O_CLOEXEC)) {
Laurent Viviere36800c2015-10-02 14:48:09 +02007928 return -TARGET_EINVAL;
7929 }
7930 if (!lock_user_struct(VERIFY_READ, target_mask, mask, 1)) {
7931 return -TARGET_EFAULT;
7932 }
7933
7934 target_to_host_sigset(&host_mask, target_mask);
7935
7936 host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
7937
7938 ret = get_errno(signalfd(fd, &host_mask, host_flags));
7939 if (ret >= 0) {
7940 fd_trans_register(ret, &target_signalfd_trans);
7941 }
7942
7943 unlock_user_struct(target_mask, mask, 0);
7944
7945 return ret;
7946}
7947#endif
7948
pbrook1d9d8b52009-04-16 15:17:02 +00007949/* Map host to target signal numbers for the wait family of syscalls.
7950 Assume all other status bits are the same. */
Richard Hendersona05c6402012-09-15 11:34:20 -07007951int host_to_target_waitstatus(int status)
pbrook1d9d8b52009-04-16 15:17:02 +00007952{
7953 if (WIFSIGNALED(status)) {
7954 return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
7955 }
7956 if (WIFSTOPPED(status)) {
7957 return (host_to_target_signal(WSTOPSIG(status)) << 8)
7958 | (status & 0xff);
7959 }
7960 return status;
7961}
7962
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02007963static int open_self_cmdline(CPUArchState *cpu_env, int fd)
Wim Vander Schelden76b94242014-06-18 11:02:39 +02007964{
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02007965 CPUState *cpu = env_cpu(cpu_env);
Andreas Schwab58de8b92017-03-20 12:31:55 +01007966 struct linux_binprm *bprm = ((TaskState *)cpu->opaque)->bprm;
7967 int i;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02007968
Andreas Schwab58de8b92017-03-20 12:31:55 +01007969 for (i = 0; i < bprm->argc; i++) {
7970 size_t len = strlen(bprm->argv[i]) + 1;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02007971
Andreas Schwab58de8b92017-03-20 12:31:55 +01007972 if (write(fd, bprm->argv[i], len) != len) {
Wim Vander Schelden76b94242014-06-18 11:02:39 +02007973 return -1;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02007974 }
7975 }
7976
Andreas Schwab58de8b92017-03-20 12:31:55 +01007977 return 0;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02007978}
7979
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02007980static int open_self_maps(CPUArchState *cpu_env, int fd)
Alexander Graf36c08d42011-11-02 20:23:24 +01007981{
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02007982 CPUState *cpu = env_cpu(cpu_env);
Andreas Färber0429a972013-08-26 18:14:44 +02007983 TaskState *ts = cpu->opaque;
Alex Bennée01ef6b92020-04-03 20:11:46 +01007984 GSList *map_info = read_self_maps();
7985 GSList *s;
Alex Bennéebb551732020-04-03 20:11:47 +01007986 int count;
Alexander Graf36c08d42011-11-02 20:23:24 +01007987
Alex Bennée01ef6b92020-04-03 20:11:46 +01007988 for (s = map_info; s; s = g_slist_next(s)) {
7989 MapInfo *e = (MapInfo *) s->data;
Alexander Graf1a49ef22012-05-01 16:30:28 +01007990
Alex Bennée01ef6b92020-04-03 20:11:46 +01007991 if (h2g_valid(e->start)) {
7992 unsigned long min = e->start;
7993 unsigned long max = e->end;
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04007994 int flags = page_get_flags(h2g(min));
Alex Bennée01ef6b92020-04-03 20:11:46 +01007995 const char *path;
7996
7997 max = h2g_valid(max - 1) ?
Richard Henderson3e8f1622021-02-12 10:48:43 -08007998 max : (uintptr_t) g2h_untagged(GUEST_ADDR_MAX) + 1;
Alex Bennée01ef6b92020-04-03 20:11:46 +01007999
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04008000 if (page_check_range(h2g(min), max - min, flags) == -1) {
8001 continue;
8002 }
Alex Bennée01ef6b92020-04-03 20:11:46 +01008003
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04008004 if (h2g(min) == ts->info->stack_limit) {
Alex Bennéebb551732020-04-03 20:11:47 +01008005 path = "[stack]";
Alex Bennée01ef6b92020-04-03 20:11:46 +01008006 } else {
8007 path = e->path;
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04008008 }
Alex Bennée01ef6b92020-04-03 20:11:46 +01008009
Alex Bennéebb551732020-04-03 20:11:47 +01008010 count = dprintf(fd, TARGET_ABI_FMT_ptr "-" TARGET_ABI_FMT_ptr
8011 " %c%c%c%c %08" PRIx64 " %s %"PRId64,
8012 h2g(min), h2g(max - 1) + 1,
Nicolas Surbayrole08f3a962021-03-08 10:19:59 +01008013 (flags & PAGE_READ) ? 'r' : '-',
8014 (flags & PAGE_WRITE_ORG) ? 'w' : '-',
8015 (flags & PAGE_EXEC) ? 'x' : '-',
Andrey Kazmine13685a2021-12-27 15:50:48 +03008016 e->is_priv ? 'p' : 's',
Alex Bennéebb551732020-04-03 20:11:47 +01008017 (uint64_t) e->offset, e->dev, e->inode);
8018 if (path) {
8019 dprintf(fd, "%*s%s\n", 73 - count, "", path);
8020 } else {
8021 dprintf(fd, "\n");
8022 }
Alexander Graf1a49ef22012-05-01 16:30:28 +01008023 }
8024 }
8025
Alex Bennée01ef6b92020-04-03 20:11:46 +01008026 free_self_maps(map_info);
8027
Richard Hendersonbf02adc2020-02-12 19:22:22 -08008028#ifdef TARGET_VSYSCALL_PAGE
8029 /*
8030 * We only support execution from the vsyscall page.
8031 * This is as if CONFIG_LEGACY_VSYSCALL_XONLY=y from v5.3.
8032 */
Alex Bennéebb551732020-04-03 20:11:47 +01008033 count = dprintf(fd, TARGET_FMT_lx "-" TARGET_FMT_lx
8034 " --xp 00000000 00:00 0",
8035 TARGET_VSYSCALL_PAGE, TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE);
8036 dprintf(fd, "%*s%s\n", 73 - count, "", "[vsyscall]");
Richard Hendersonbf02adc2020-02-12 19:22:22 -08008037#endif
8038
Alexander Graf36c08d42011-11-02 20:23:24 +01008039 return 0;
8040}
8041
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008042static int open_self_stat(CPUArchState *cpu_env, int fd)
Alexander Graf480b8e72011-11-02 20:23:25 +01008043{
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02008044 CPUState *cpu = env_cpu(cpu_env);
Andreas Färber0429a972013-08-26 18:14:44 +02008045 TaskState *ts = cpu->opaque;
Alex Bennée7ad4d5a2020-04-14 21:06:23 +01008046 g_autoptr(GString) buf = g_string_new(NULL);
Alexander Graf480b8e72011-11-02 20:23:25 +01008047 int i;
8048
8049 for (i = 0; i < 44; i++) {
Alex Bennée7ad4d5a2020-04-14 21:06:23 +01008050 if (i == 0) {
8051 /* pid */
8052 g_string_printf(buf, FMT_pid " ", getpid());
8053 } else if (i == 1) {
8054 /* app name */
8055 gchar *bin = g_strrstr(ts->bprm->argv[0], "/");
8056 bin = bin ? bin + 1 : ts->bprm->argv[0];
8057 g_string_printf(buf, "(%.15s) ", bin);
Andreas Schwab7aa9fe32021-06-21 11:32:59 +02008058 } else if (i == 3) {
8059 /* ppid */
8060 g_string_printf(buf, FMT_pid " ", getppid());
Cameron Esfahanieb33cda2022-01-27 16:12:51 -08008061 } else if (i == 21) {
8062 /* starttime */
8063 g_string_printf(buf, "%" PRIu64 " ", ts->start_boottime);
Alex Bennée7ad4d5a2020-04-14 21:06:23 +01008064 } else if (i == 27) {
8065 /* stack bottom */
8066 g_string_printf(buf, TARGET_ABI_FMT_ld " ", ts->info->start_stack);
8067 } else {
8068 /* for the rest, there is MasterCard */
8069 g_string_printf(buf, "0%c", i == 43 ? '\n' : ' ');
8070 }
Alexander Graf480b8e72011-11-02 20:23:25 +01008071
Alex Bennée7ad4d5a2020-04-14 21:06:23 +01008072 if (write(fd, buf->str, buf->len) != buf->len) {
8073 return -1;
8074 }
Alexander Graf480b8e72011-11-02 20:23:25 +01008075 }
8076
8077 return 0;
8078}
8079
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008080static int open_self_auxv(CPUArchState *cpu_env, int fd)
Alexander Graf257450e2011-11-02 20:23:26 +01008081{
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02008082 CPUState *cpu = env_cpu(cpu_env);
Andreas Färber0429a972013-08-26 18:14:44 +02008083 TaskState *ts = cpu->opaque;
Alexander Graf257450e2011-11-02 20:23:26 +01008084 abi_ulong auxv = ts->info->saved_auxv;
8085 abi_ulong len = ts->info->auxv_len;
8086 char *ptr;
8087
8088 /*
8089 * Auxiliary vector is stored in target process stack.
8090 * read in whole auxv vector and copy it to file
8091 */
8092 ptr = lock_user(VERIFY_READ, auxv, len, 0);
8093 if (ptr != NULL) {
8094 while (len > 0) {
8095 ssize_t r;
8096 r = write(fd, ptr, len);
8097 if (r <= 0) {
8098 break;
8099 }
8100 len -= r;
8101 ptr += r;
8102 }
8103 lseek(fd, 0, SEEK_SET);
8104 unlock_user(ptr, auxv, len);
8105 }
8106
8107 return 0;
8108}
8109
Andreas Schwab463d8e72013-07-02 14:04:12 +01008110static int is_proc_myself(const char *filename, const char *entry)
8111{
8112 if (!strncmp(filename, "/proc/", strlen("/proc/"))) {
8113 filename += strlen("/proc/");
8114 if (!strncmp(filename, "self/", strlen("self/"))) {
8115 filename += strlen("self/");
8116 } else if (*filename >= '1' && *filename <= '9') {
8117 char myself[80];
8118 snprintf(myself, sizeof(myself), "%d/", getpid());
8119 if (!strncmp(filename, myself, strlen(myself))) {
8120 filename += strlen(myself);
8121 } else {
8122 return 0;
8123 }
8124 } else {
8125 return 0;
8126 }
8127 if (!strcmp(filename, entry)) {
8128 return 1;
8129 }
8130 }
8131 return 0;
8132}
8133
Marc-André Lureauee3eb3a2022-03-23 19:57:18 +04008134#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN || \
Helge Deller93a56612020-04-24 23:06:48 +02008135 defined(TARGET_SPARC) || defined(TARGET_M68K) || defined(TARGET_HPPA)
Laurent Vivierde6b9932013-08-30 01:46:40 +02008136static int is_proc(const char *filename, const char *entry)
8137{
8138 return strcmp(filename, entry) == 0;
8139}
Laurent Vivierfff69382019-05-17 15:31:48 +02008140#endif
Laurent Vivierde6b9932013-08-30 01:46:40 +02008141
Marc-André Lureauee3eb3a2022-03-23 19:57:18 +04008142#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008143static int open_net_route(CPUArchState *cpu_env, int fd)
Laurent Vivierde6b9932013-08-30 01:46:40 +02008144{
8145 FILE *fp;
8146 char *line = NULL;
8147 size_t len = 0;
8148 ssize_t read;
8149
8150 fp = fopen("/proc/net/route", "r");
8151 if (fp == NULL) {
Peter Maydella3ca7bb2016-05-12 18:47:26 +01008152 return -1;
Laurent Vivierde6b9932013-08-30 01:46:40 +02008153 }
8154
8155 /* read header */
8156
8157 read = getline(&line, &len, fp);
8158 dprintf(fd, "%s", line);
8159
8160 /* read routes */
8161
8162 while ((read = getline(&line, &len, fp)) != -1) {
8163 char iface[16];
8164 uint32_t dest, gw, mask;
8165 unsigned int flags, refcnt, use, metric, mtu, window, irtt;
Peter Maydell9d0bd0c2019-02-05 17:42:07 +00008166 int fields;
8167
8168 fields = sscanf(line,
8169 "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
8170 iface, &dest, &gw, &flags, &refcnt, &use, &metric,
8171 &mask, &mtu, &window, &irtt);
8172 if (fields != 11) {
8173 continue;
8174 }
Laurent Vivierde6b9932013-08-30 01:46:40 +02008175 dprintf(fd, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
8176 iface, tswap32(dest), tswap32(gw), flags, refcnt, use,
8177 metric, tswap32(mask), mtu, window, irtt);
8178 }
8179
8180 free(line);
8181 fclose(fp);
8182
8183 return 0;
8184}
8185#endif
8186
Laurent Vivierfff69382019-05-17 15:31:48 +02008187#if defined(TARGET_SPARC)
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008188static int open_cpuinfo(CPUArchState *cpu_env, int fd)
Laurent Vivierfff69382019-05-17 15:31:48 +02008189{
8190 dprintf(fd, "type\t\t: sun4u\n");
8191 return 0;
8192}
8193#endif
8194
Helge Deller93a56612020-04-24 23:06:48 +02008195#if defined(TARGET_HPPA)
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008196static int open_cpuinfo(CPUArchState *cpu_env, int fd)
Helge Deller93a56612020-04-24 23:06:48 +02008197{
8198 dprintf(fd, "cpu family\t: PA-RISC 1.1e\n");
8199 dprintf(fd, "cpu\t\t: PA7300LC (PCX-L2)\n");
8200 dprintf(fd, "capabilities\t: os32\n");
8201 dprintf(fd, "model\t\t: 9000/778/B160L\n");
8202 dprintf(fd, "model name\t: Merlin L2 160 QEMU (9000/778/B160L)\n");
8203 return 0;
8204}
8205#endif
8206
Laurent Vivier4ab67132019-05-17 15:31:49 +02008207#if defined(TARGET_M68K)
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008208static int open_hardware(CPUArchState *cpu_env, int fd)
Laurent Vivier4ab67132019-05-17 15:31:49 +02008209{
8210 dprintf(fd, "Model:\t\tqemu-m68k\n");
8211 return 0;
8212}
8213#endif
8214
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008215static int do_openat(CPUArchState *cpu_env, int dirfd, const char *pathname, int flags, mode_t mode)
Alexander Graf3be14d02011-11-02 20:23:23 +01008216{
8217 struct fake_open {
8218 const char *filename;
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008219 int (*fill)(CPUArchState *cpu_env, int fd);
Laurent Vivierde6b9932013-08-30 01:46:40 +02008220 int (*cmp)(const char *s1, const char *s2);
Alexander Graf3be14d02011-11-02 20:23:23 +01008221 };
8222 const struct fake_open *fake_open;
8223 static const struct fake_open fakes[] = {
Laurent Vivierde6b9932013-08-30 01:46:40 +02008224 { "maps", open_self_maps, is_proc_myself },
8225 { "stat", open_self_stat, is_proc_myself },
8226 { "auxv", open_self_auxv, is_proc_myself },
Wim Vander Schelden76b94242014-06-18 11:02:39 +02008227 { "cmdline", open_self_cmdline, is_proc_myself },
Marc-André Lureauee3eb3a2022-03-23 19:57:18 +04008228#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN
Laurent Vivierde6b9932013-08-30 01:46:40 +02008229 { "/proc/net/route", open_net_route, is_proc },
8230#endif
Helge Deller93a56612020-04-24 23:06:48 +02008231#if defined(TARGET_SPARC) || defined(TARGET_HPPA)
Laurent Vivierfff69382019-05-17 15:31:48 +02008232 { "/proc/cpuinfo", open_cpuinfo, is_proc },
8233#endif
Laurent Vivier4ab67132019-05-17 15:31:49 +02008234#if defined(TARGET_M68K)
8235 { "/proc/hardware", open_hardware, is_proc },
8236#endif
Laurent Vivierde6b9932013-08-30 01:46:40 +02008237 { NULL, NULL, NULL }
Alexander Graf3be14d02011-11-02 20:23:23 +01008238 };
8239
Maxim Ostapenkoaa07f5e2014-05-02 11:17:07 +03008240 if (is_proc_myself(pathname, "exe")) {
8241 int execfd = qemu_getauxval(AT_EXECFD);
Timothy E Baldwinc10a0732016-05-12 18:47:48 +01008242 return execfd ? execfd : safe_openat(dirfd, exec_path, flags, mode);
Maxim Ostapenkoaa07f5e2014-05-02 11:17:07 +03008243 }
8244
Alexander Graf3be14d02011-11-02 20:23:23 +01008245 for (fake_open = fakes; fake_open->filename; fake_open++) {
Laurent Vivierde6b9932013-08-30 01:46:40 +02008246 if (fake_open->cmp(pathname, fake_open->filename)) {
Alexander Graf3be14d02011-11-02 20:23:23 +01008247 break;
8248 }
8249 }
8250
8251 if (fake_open->filename) {
8252 const char *tmpdir;
8253 char filename[PATH_MAX];
8254 int fd, r;
8255
8256 /* create temporary file to map stat to */
8257 tmpdir = getenv("TMPDIR");
8258 if (!tmpdir)
8259 tmpdir = "/tmp";
8260 snprintf(filename, sizeof(filename), "%s/qemu-open.XXXXXX", tmpdir);
8261 fd = mkstemp(filename);
8262 if (fd < 0) {
8263 return fd;
8264 }
8265 unlink(filename);
8266
8267 if ((r = fake_open->fill(cpu_env, fd))) {
Peter Maydella3ca7bb2016-05-12 18:47:26 +01008268 int e = errno;
Alexander Graf3be14d02011-11-02 20:23:23 +01008269 close(fd);
Peter Maydella3ca7bb2016-05-12 18:47:26 +01008270 errno = e;
Alexander Graf3be14d02011-11-02 20:23:23 +01008271 return r;
8272 }
8273 lseek(fd, 0, SEEK_SET);
8274
8275 return fd;
8276 }
8277
Timothy E Baldwinc10a0732016-05-12 18:47:48 +01008278 return safe_openat(dirfd, path(pathname), flags, mode);
Alexander Graf3be14d02011-11-02 20:23:23 +01008279}
8280
Alexander Grafaecc8862014-11-10 21:33:03 +01008281#define TIMER_MAGIC 0x0caf0000
8282#define TIMER_MAGIC_MASK 0xffff0000
8283
8284/* Convert QEMU provided timer ID back to internal 16bit index format */
8285static target_timer_t get_timer_id(abi_long arg)
8286{
8287 target_timer_t timerid = arg;
8288
8289 if ((timerid & TIMER_MAGIC_MASK) != TIMER_MAGIC) {
8290 return -TARGET_EINVAL;
8291 }
8292
8293 timerid &= 0xffff;
8294
8295 if (timerid >= ARRAY_SIZE(g_posix_timers)) {
8296 return -TARGET_EINVAL;
8297 }
8298
8299 return timerid;
8300}
8301
Samuel Thibault2e0a8712018-01-09 21:16:43 +01008302static int target_to_host_cpu_mask(unsigned long *host_mask,
8303 size_t host_size,
8304 abi_ulong target_addr,
8305 size_t target_size)
8306{
8307 unsigned target_bits = sizeof(abi_ulong) * 8;
8308 unsigned host_bits = sizeof(*host_mask) * 8;
8309 abi_ulong *target_mask;
8310 unsigned i, j;
8311
8312 assert(host_size >= target_size);
8313
8314 target_mask = lock_user(VERIFY_READ, target_addr, target_size, 1);
8315 if (!target_mask) {
8316 return -TARGET_EFAULT;
8317 }
8318 memset(host_mask, 0, host_size);
8319
8320 for (i = 0 ; i < target_size / sizeof(abi_ulong); i++) {
8321 unsigned bit = i * target_bits;
8322 abi_ulong val;
8323
8324 __get_user(val, &target_mask[i]);
8325 for (j = 0; j < target_bits; j++, bit++) {
8326 if (val & (1UL << j)) {
8327 host_mask[bit / host_bits] |= 1UL << (bit % host_bits);
8328 }
8329 }
8330 }
8331
8332 unlock_user(target_mask, target_addr, 0);
8333 return 0;
8334}
8335
8336static int host_to_target_cpu_mask(const unsigned long *host_mask,
8337 size_t host_size,
8338 abi_ulong target_addr,
8339 size_t target_size)
8340{
8341 unsigned target_bits = sizeof(abi_ulong) * 8;
8342 unsigned host_bits = sizeof(*host_mask) * 8;
8343 abi_ulong *target_mask;
8344 unsigned i, j;
8345
8346 assert(host_size >= target_size);
8347
8348 target_mask = lock_user(VERIFY_WRITE, target_addr, target_size, 0);
8349 if (!target_mask) {
8350 return -TARGET_EFAULT;
8351 }
8352
8353 for (i = 0 ; i < target_size / sizeof(abi_ulong); i++) {
8354 unsigned bit = i * target_bits;
8355 abi_ulong val = 0;
8356
8357 for (j = 0; j < target_bits; j++, bit++) {
8358 if (host_mask[bit / host_bits] & (1UL << (bit % host_bits))) {
8359 val |= 1UL << j;
8360 }
8361 }
8362 __put_user(val, &target_mask[i]);
8363 }
8364
8365 unlock_user(target_mask, target_addr, target_size);
8366 return 0;
8367}
8368
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008369#ifdef TARGET_NR_getdents
Richard Hendersonaee14c72021-11-14 11:35:39 +01008370static int do_getdents(abi_long dirfd, abi_long arg2, abi_long count)
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008371{
Richard Hendersonaee14c72021-11-14 11:35:39 +01008372 g_autofree void *hdirp = NULL;
8373 void *tdirp;
8374 int hlen, hoff, toff;
8375 int hreclen, treclen;
8376 off64_t prev_diroff = 0;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008377
Richard Hendersonaee14c72021-11-14 11:35:39 +01008378 hdirp = g_try_malloc(count);
8379 if (!hdirp) {
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008380 return -TARGET_ENOMEM;
8381 }
8382
Richard Hendersonaee14c72021-11-14 11:35:39 +01008383#ifdef EMULATE_GETDENTS_WITH_GETDENTS
8384 hlen = sys_getdents(dirfd, hdirp, count);
8385#else
8386 hlen = sys_getdents64(dirfd, hdirp, count);
8387#endif
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008388
Richard Hendersonaee14c72021-11-14 11:35:39 +01008389 hlen = get_errno(hlen);
8390 if (is_error(hlen)) {
8391 return hlen;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008392 }
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008393
Richard Hendersonaee14c72021-11-14 11:35:39 +01008394 tdirp = lock_user(VERIFY_WRITE, arg2, count, 0);
8395 if (!tdirp) {
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008396 return -TARGET_EFAULT;
8397 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008398
8399 for (hoff = toff = 0; hoff < hlen; hoff += hreclen, toff += treclen) {
8400#ifdef EMULATE_GETDENTS_WITH_GETDENTS
8401 struct linux_dirent *hde = hdirp + hoff;
8402#else
8403 struct linux_dirent64 *hde = hdirp + hoff;
8404#endif
8405 struct target_dirent *tde = tdirp + toff;
8406 int namelen;
8407 uint8_t type;
8408
8409 namelen = strlen(hde->d_name);
8410 hreclen = hde->d_reclen;
8411 treclen = offsetof(struct target_dirent, d_name) + namelen + 2;
8412 treclen = QEMU_ALIGN_UP(treclen, __alignof(struct target_dirent));
8413
8414 if (toff + treclen > count) {
8415 /*
8416 * If the host struct is smaller than the target struct, or
8417 * requires less alignment and thus packs into less space,
8418 * then the host can return more entries than we can pass
8419 * on to the guest.
8420 */
8421 if (toff == 0) {
8422 toff = -TARGET_EINVAL; /* result buffer is too small */
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008423 break;
8424 }
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008425 /*
Richard Hendersonaee14c72021-11-14 11:35:39 +01008426 * Return what we have, resetting the file pointer to the
8427 * location of the first record not returned.
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008428 */
Richard Hendersonaee14c72021-11-14 11:35:39 +01008429 lseek64(dirfd, prev_diroff, SEEK_SET);
8430 break;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008431 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008432
8433 prev_diroff = hde->d_off;
8434 tde->d_ino = tswapal(hde->d_ino);
8435 tde->d_off = tswapal(hde->d_off);
8436 tde->d_reclen = tswap16(treclen);
8437 memcpy(tde->d_name, hde->d_name, namelen + 1);
8438
8439 /*
8440 * The getdents type is in what was formerly a padding byte at the
8441 * end of the structure.
8442 */
8443#ifdef EMULATE_GETDENTS_WITH_GETDENTS
8444 type = *((uint8_t *)hde + hreclen - 1);
8445#else
8446 type = hde->d_type;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008447#endif
Richard Hendersonaee14c72021-11-14 11:35:39 +01008448 *((uint8_t *)tde + treclen - 1) = type;
8449 }
8450
8451 unlock_user(tdirp, arg2, toff);
8452 return toff;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008453}
8454#endif /* TARGET_NR_getdents */
8455
8456#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
Richard Hendersonaee14c72021-11-14 11:35:39 +01008457static int do_getdents64(abi_long dirfd, abi_long arg2, abi_long count)
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008458{
Richard Hendersonaee14c72021-11-14 11:35:39 +01008459 g_autofree void *hdirp = NULL;
8460 void *tdirp;
8461 int hlen, hoff, toff;
8462 int hreclen, treclen;
8463 off64_t prev_diroff = 0;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008464
Richard Hendersonaee14c72021-11-14 11:35:39 +01008465 hdirp = g_try_malloc(count);
8466 if (!hdirp) {
8467 return -TARGET_ENOMEM;
8468 }
8469
8470 hlen = get_errno(sys_getdents64(dirfd, hdirp, count));
8471 if (is_error(hlen)) {
8472 return hlen;
8473 }
8474
8475 tdirp = lock_user(VERIFY_WRITE, arg2, count, 0);
8476 if (!tdirp) {
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008477 return -TARGET_EFAULT;
8478 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008479
8480 for (hoff = toff = 0; hoff < hlen; hoff += hreclen, toff += treclen) {
8481 struct linux_dirent64 *hde = hdirp + hoff;
8482 struct target_dirent64 *tde = tdirp + toff;
8483 int namelen;
8484
8485 namelen = strlen(hde->d_name) + 1;
8486 hreclen = hde->d_reclen;
8487 treclen = offsetof(struct target_dirent64, d_name) + namelen;
8488 treclen = QEMU_ALIGN_UP(treclen, __alignof(struct target_dirent64));
8489
8490 if (toff + treclen > count) {
8491 /*
8492 * If the host struct is smaller than the target struct, or
8493 * requires less alignment and thus packs into less space,
8494 * then the host can return more entries than we can pass
8495 * on to the guest.
8496 */
8497 if (toff == 0) {
8498 toff = -TARGET_EINVAL; /* result buffer is too small */
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008499 break;
8500 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008501 /*
8502 * Return what we have, resetting the file pointer to the
8503 * location of the first record not returned.
8504 */
8505 lseek64(dirfd, prev_diroff, SEEK_SET);
8506 break;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008507 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008508
8509 prev_diroff = hde->d_off;
8510 tde->d_ino = tswap64(hde->d_ino);
8511 tde->d_off = tswap64(hde->d_off);
8512 tde->d_reclen = tswap16(treclen);
8513 tde->d_type = hde->d_type;
8514 memcpy(tde->d_name, hde->d_name, namelen);
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008515 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008516
8517 unlock_user(tdirp, arg2, toff);
8518 return toff;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008519}
8520#endif /* TARGET_NR_getdents64 */
8521
YAMAMOTO Takashie10fbe82021-05-31 14:50:12 +09008522#if defined(TARGET_NR_pivot_root) && defined(__NR_pivot_root)
8523_syscall2(int, pivot_root, const char *, new_root, const char *, put_old)
8524#endif
8525
Richard Hendersondc1ce182018-08-18 12:01:04 -07008526/* This is an internal helper for do_syscall so that it is easier
8527 * to have a single return point, so that actions, such as logging
8528 * of syscall results, can be performed.
8529 * All errnos that do_syscall() returns must be -TARGET_<errcode>.
8530 */
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008531static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
Richard Hendersondc1ce182018-08-18 12:01:04 -07008532 abi_long arg2, abi_long arg3, abi_long arg4,
8533 abi_long arg5, abi_long arg6, abi_long arg7,
8534 abi_long arg8)
bellard31e31b82003-02-18 22:55:36 +00008535{
Richard Henderson29a0af62019-03-22 16:07:18 -07008536 CPUState *cpu = env_cpu(cpu_env);
blueswir1992f48a2007-10-14 16:27:31 +00008537 abi_long ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008538#if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) \
8539 || defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64) \
Aleksandar Rikaloefa92182019-06-28 12:43:34 +02008540 || defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64) \
8541 || defined(TARGET_NR_statx)
bellard31e31b82003-02-18 22:55:36 +00008542 struct stat st;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008543#endif
8544#if defined(TARGET_NR_statfs) || defined(TARGET_NR_statfs64) \
8545 || defined(TARGET_NR_fstatfs)
bellard56c8f682005-11-28 22:28:41 +00008546 struct statfs stfs;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008547#endif
pbrook53a59602006-03-25 19:31:22 +00008548 void *p;
ths3b46e622007-09-17 08:09:54 +00008549
bellard31e31b82003-02-18 22:55:36 +00008550 switch(num) {
8551 case TARGET_NR_exit:
Andreas Färber9b056fc2013-06-24 23:53:10 +02008552 /* In old applications this may be used to implement _exit(2).
zhaolichang6f9ff552020-09-17 15:50:25 +08008553 However in threaded applications it is used for thread termination,
Andreas Färber9b056fc2013-06-24 23:53:10 +02008554 and _exit_group is used for application termination.
8555 Do thread termination if we have more then one thread. */
Timothy E Baldwina0995882016-05-27 15:51:56 +01008556
8557 if (block_signals()) {
Richard Hendersonaf254a22021-11-22 19:47:33 +01008558 return -QEMU_ERESTARTSYS;
Timothy E Baldwina0995882016-05-27 15:51:56 +01008559 }
8560
Alex Bennée1f81ce92020-05-20 15:05:39 +01008561 pthread_mutex_lock(&clone_lock);
Alex Bennéedd1f6342016-09-30 22:31:01 +01008562
Andreas Färberbdc44642013-06-24 23:50:24 +02008563 if (CPU_NEXT(first_cpu)) {
Alex Bennée1f81ce92020-05-20 15:05:39 +01008564 TaskState *ts = cpu->opaque;
pbrookc2764712009-03-07 15:24:59 +00008565
Markus Armbruster5325cc32020-07-07 18:05:54 +02008566 object_property_set_bool(OBJECT(cpu), "realized", false, NULL);
Alex Bennée1f81ce92020-05-20 15:05:39 +01008567 object_unref(OBJECT(cpu));
8568 /*
8569 * At this point the CPU should be unrealized and removed
8570 * from cpu lists. We can clean-up the rest of the thread
8571 * data without the lock held.
8572 */
Alex Bennéedd1f6342016-09-30 22:31:01 +01008573
Alex Bennée1f81ce92020-05-20 15:05:39 +01008574 pthread_mutex_unlock(&clone_lock);
Alex Bennéedd1f6342016-09-30 22:31:01 +01008575
Andreas Färber9b056fc2013-06-24 23:53:10 +02008576 if (ts->child_tidptr) {
8577 put_user_u32(0, ts->child_tidptr);
Richard Henderson3e8f1622021-02-12 10:48:43 -08008578 do_sys_futex(g2h(cpu, ts->child_tidptr),
8579 FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
Andreas Färber9b056fc2013-06-24 23:53:10 +02008580 }
Andreas Färbera2247f82013-06-09 19:47:04 +02008581 thread_cpu = NULL;
Andreas Färber9b056fc2013-06-24 23:53:10 +02008582 g_free(ts);
Emilio G. Cota70903762015-08-23 20:23:41 -04008583 rcu_unregister_thread();
Andreas Färber9b056fc2013-06-24 23:53:10 +02008584 pthread_exit(NULL);
8585 }
Alex Bennéedd1f6342016-09-30 22:31:01 +01008586
Alex Bennée1f81ce92020-05-20 15:05:39 +01008587 pthread_mutex_unlock(&clone_lock);
Alex Bennée708b6a62018-06-22 17:09:10 +01008588 preexit_cleanup(cpu_env, arg1);
pbrookc2764712009-03-07 15:24:59 +00008589 _exit(arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008590 return 0; /* avoid warning */
bellard31e31b82003-02-18 22:55:36 +00008591 case TARGET_NR_read:
Andreas Schwabba584f12019-03-05 17:45:05 +01008592 if (arg2 == 0 && arg3 == 0) {
8593 return get_errno(safe_read(arg1, 0, 0));
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008594 } else {
aurel3238d840e2009-01-30 19:48:17 +00008595 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008596 return -TARGET_EFAULT;
Timothy E Baldwin50afd022016-05-12 18:47:47 +01008597 ret = get_errno(safe_read(arg1, p, arg3));
Laurent Viviere36800c2015-10-02 14:48:09 +02008598 if (ret >= 0 &&
Laurent Vivier5d4d3662015-10-28 21:40:43 +01008599 fd_trans_host_to_target_data(arg1)) {
8600 ret = fd_trans_host_to_target_data(arg1)(p, ret);
Laurent Viviere36800c2015-10-02 14:48:09 +02008601 }
aurel3238d840e2009-01-30 19:48:17 +00008602 unlock_user(p, arg2, ret);
8603 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008604 return ret;
bellard31e31b82003-02-18 22:55:36 +00008605 case TARGET_NR_write:
Tony Garnock-Jones58cfa6c2018-09-08 19:22:05 +01008606 if (arg2 == 0 && arg3 == 0) {
8607 return get_errno(safe_write(arg1, 0, 0));
8608 }
bellard579a97f2007-11-11 14:26:47 +00008609 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008610 return -TARGET_EFAULT;
Laurent Vivier04b9bcf2017-03-01 10:37:47 +01008611 if (fd_trans_target_to_host_data(arg1)) {
8612 void *copy = g_malloc(arg3);
8613 memcpy(copy, p, arg3);
8614 ret = fd_trans_target_to_host_data(arg1)(copy, arg3);
8615 if (ret >= 0) {
8616 ret = get_errno(safe_write(arg1, copy, ret));
8617 }
8618 g_free(copy);
8619 } else {
8620 ret = get_errno(safe_write(arg1, p, arg3));
8621 }
pbrook53a59602006-03-25 19:31:22 +00008622 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008623 return ret;
8624
Chen Gang704eff62015-08-21 05:37:33 +08008625#ifdef TARGET_NR_open
bellard31e31b82003-02-18 22:55:36 +00008626 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00008627 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008628 return -TARGET_EFAULT;
Riku Voipio0b2effd2014-08-06 10:36:37 +03008629 ret = get_errno(do_openat(cpu_env, AT_FDCWD, p,
8630 target_to_host_bitmask(arg2, fcntl_flags_tbl),
8631 arg3));
Laurent Viviere36800c2015-10-02 14:48:09 +02008632 fd_trans_unregister(ret);
pbrook53a59602006-03-25 19:31:22 +00008633 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008634 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008635#endif
ths82424832007-09-24 09:21:55 +00008636 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00008637 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008638 return -TARGET_EFAULT;
Riku Voipio0b2effd2014-08-06 10:36:37 +03008639 ret = get_errno(do_openat(cpu_env, arg1, p,
8640 target_to_host_bitmask(arg3, fcntl_flags_tbl),
8641 arg4));
Laurent Viviere36800c2015-10-02 14:48:09 +02008642 fd_trans_unregister(ret);
bellard579a97f2007-11-11 14:26:47 +00008643 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008644 return ret;
Laurent Vivier0f0426f2015-09-01 22:27:33 +02008645#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
8646 case TARGET_NR_name_to_handle_at:
8647 ret = do_name_to_handle_at(arg1, arg2, arg3, arg4, arg5);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008648 return ret;
Laurent Vivier0f0426f2015-09-01 22:27:33 +02008649#endif
8650#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
8651 case TARGET_NR_open_by_handle_at:
8652 ret = do_open_by_handle_at(arg1, arg2, arg3);
Laurent Viviere36800c2015-10-02 14:48:09 +02008653 fd_trans_unregister(ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008654 return ret;
Laurent Vivier0f0426f2015-09-01 22:27:33 +02008655#endif
bellard31e31b82003-02-18 22:55:36 +00008656 case TARGET_NR_close:
Laurent Viviere36800c2015-10-02 14:48:09 +02008657 fd_trans_unregister(arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008658 return get_errno(close(arg1));
8659
bellard31e31b82003-02-18 22:55:36 +00008660 case TARGET_NR_brk:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008661 return do_brk(arg1);
Chen Gang704eff62015-08-21 05:37:33 +08008662#ifdef TARGET_NR_fork
bellard31e31b82003-02-18 22:55:36 +00008663 case TARGET_NR_fork:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008664 return get_errno(do_fork(cpu_env, TARGET_SIGCHLD, 0, 0, 0, 0));
Chen Gang704eff62015-08-21 05:37:33 +08008665#endif
thse5febef2007-04-01 18:31:35 +00008666#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00008667 case TARGET_NR_waitpid:
8668 {
pbrook53a59602006-03-25 19:31:22 +00008669 int status;
Timothy E Baldwin4af80a32016-05-12 18:47:49 +01008670 ret = get_errno(safe_wait4(arg1, &status, arg3, 0));
Alexander Graf53795572011-11-24 00:44:43 +01008671 if (!is_error(ret) && arg2 && ret
pbrook1d9d8b52009-04-16 15:17:02 +00008672 && put_user_s32(host_to_target_waitstatus(status), arg2))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008673 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00008674 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008675 return ret;
thse5febef2007-04-01 18:31:35 +00008676#endif
pbrookf0cbb612008-05-30 18:20:05 +00008677#ifdef TARGET_NR_waitid
8678 case TARGET_NR_waitid:
8679 {
8680 siginfo_t info;
8681 info.si_pid = 0;
Timothy E Baldwin4af80a32016-05-12 18:47:49 +01008682 ret = get_errno(safe_waitid(arg1, arg2, &info, arg4, NULL));
pbrookf0cbb612008-05-30 18:20:05 +00008683 if (!is_error(ret) && arg3 && info.si_pid != 0) {
Anthony Liguoric227f092009-10-01 16:12:16 -05008684 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008685 return -TARGET_EFAULT;
pbrookf0cbb612008-05-30 18:20:05 +00008686 host_to_target_siginfo(p, &info);
Anthony Liguoric227f092009-10-01 16:12:16 -05008687 unlock_user(p, arg3, sizeof(target_siginfo_t));
pbrookf0cbb612008-05-30 18:20:05 +00008688 }
8689 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008690 return ret;
pbrookf0cbb612008-05-30 18:20:05 +00008691#endif
j_mayer7a3148a2007-04-05 07:13:51 +00008692#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00008693 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00008694 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008695 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008696 ret = get_errno(creat(p, arg2));
Laurent Viviere36800c2015-10-02 14:48:09 +02008697 fd_trans_unregister(ret);
pbrook53a59602006-03-25 19:31:22 +00008698 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008699 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00008700#endif
Chen Gang704eff62015-08-21 05:37:33 +08008701#ifdef TARGET_NR_link
bellard31e31b82003-02-18 22:55:36 +00008702 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00008703 {
8704 void * p2;
8705 p = lock_user_string(arg1);
8706 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00008707 if (!p || !p2)
8708 ret = -TARGET_EFAULT;
8709 else
8710 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00008711 unlock_user(p2, arg2, 0);
8712 unlock_user(p, arg1, 0);
8713 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008714 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008715#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01008716#if defined(TARGET_NR_linkat)
ths64f0ce42007-09-24 09:25:06 +00008717 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00008718 {
8719 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00008720 if (!arg2 || !arg4)
Richard Henderson2852aaf2018-08-18 12:01:06 -07008721 return -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00008722 p = lock_user_string(arg2);
8723 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00008724 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00008725 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00008726 else
Peter Maydellc0d472b2013-06-12 16:20:21 +01008727 ret = get_errno(linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00008728 unlock_user(p, arg2, 0);
8729 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00008730 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008731 return ret;
ths64f0ce42007-09-24 09:25:06 +00008732#endif
Chen Gang704eff62015-08-21 05:37:33 +08008733#ifdef TARGET_NR_unlink
bellard31e31b82003-02-18 22:55:36 +00008734 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00008735 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008736 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008737 ret = get_errno(unlink(p));
8738 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008739 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008740#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01008741#if defined(TARGET_NR_unlinkat)
ths8170f562007-09-24 09:24:11 +00008742 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00008743 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008744 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01008745 ret = get_errno(unlinkat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00008746 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008747 return ret;
balrogb7d35e62007-12-12 00:40:24 +00008748#endif
bellard31e31b82003-02-18 22:55:36 +00008749 case TARGET_NR_execve:
bellard7854b052003-03-29 17:22:23 +00008750 {
8751 char **argp, **envp;
bellardf7341ff2003-03-30 21:00:25 +00008752 int argc, envc;
blueswir1992f48a2007-10-14 16:27:31 +00008753 abi_ulong gp;
8754 abi_ulong guest_argp;
8755 abi_ulong guest_envp;
8756 abi_ulong addr;
bellard7854b052003-03-29 17:22:23 +00008757 char **q;
8758
bellardf7341ff2003-03-30 21:00:25 +00008759 argc = 0;
pbrook53a59602006-03-25 19:31:22 +00008760 guest_argp = arg2;
pbrookda94d262008-05-30 18:24:00 +00008761 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00008762 if (get_user_ual(addr, gp))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008763 return -TARGET_EFAULT;
ths03aa1972007-12-02 06:28:08 +00008764 if (!addr)
bellard2f619692007-11-16 10:46:05 +00008765 break;
bellard7854b052003-03-29 17:22:23 +00008766 argc++;
bellard2f619692007-11-16 10:46:05 +00008767 }
bellardf7341ff2003-03-30 21:00:25 +00008768 envc = 0;
pbrook53a59602006-03-25 19:31:22 +00008769 guest_envp = arg3;
pbrookda94d262008-05-30 18:24:00 +00008770 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00008771 if (get_user_ual(addr, gp))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008772 return -TARGET_EFAULT;
ths03aa1972007-12-02 06:28:08 +00008773 if (!addr)
bellard2f619692007-11-16 10:46:05 +00008774 break;
bellard7854b052003-03-29 17:22:23 +00008775 envc++;
bellard2f619692007-11-16 10:46:05 +00008776 }
bellard7854b052003-03-29 17:22:23 +00008777
Prasad J Panditb936cb52017-03-07 12:51:47 +05308778 argp = g_new0(char *, argc + 1);
8779 envp = g_new0(char *, envc + 1);
bellard7854b052003-03-29 17:22:23 +00008780
pbrookda94d262008-05-30 18:24:00 +00008781 for (gp = guest_argp, q = argp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00008782 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00008783 if (get_user_ual(addr, gp))
8784 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00008785 if (!addr)
8786 break;
bellard2f619692007-11-16 10:46:05 +00008787 if (!(*q = lock_user_string(addr)))
8788 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00008789 }
bellardf7341ff2003-03-30 21:00:25 +00008790 *q = NULL;
8791
pbrookda94d262008-05-30 18:24:00 +00008792 for (gp = guest_envp, q = envp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00008793 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00008794 if (get_user_ual(addr, gp))
8795 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00008796 if (!addr)
8797 break;
bellard2f619692007-11-16 10:46:05 +00008798 if (!(*q = lock_user_string(addr)))
8799 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00008800 }
bellardf7341ff2003-03-30 21:00:25 +00008801 *q = NULL;
bellard7854b052003-03-29 17:22:23 +00008802
bellard2f619692007-11-16 10:46:05 +00008803 if (!(p = lock_user_string(arg1)))
8804 goto execve_efault;
Timothy E Baldwinffdcbe22016-05-12 18:47:50 +01008805 /* Although execve() is not an interruptible syscall it is
8806 * a special case where we must use the safe_syscall wrapper:
8807 * if we allow a signal to happen before we make the host
8808 * syscall then we will 'lose' it, because at the point of
8809 * execve the process leaves QEMU's control. So we use the
8810 * safe syscall wrapper to ensure that we either take the
8811 * signal as a guest signal, or else it does not happen
8812 * before the execve completes and makes it the other
8813 * program's problem.
8814 */
8815 ret = get_errno(safe_execve(p, argp, envp));
pbrook53a59602006-03-25 19:31:22 +00008816 unlock_user(p, arg1, 0);
8817
bellard2f619692007-11-16 10:46:05 +00008818 goto execve_end;
8819
8820 execve_efault:
8821 ret = -TARGET_EFAULT;
8822
8823 execve_end:
pbrook53a59602006-03-25 19:31:22 +00008824 for (gp = guest_argp, q = argp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00008825 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00008826 if (get_user_ual(addr, gp)
8827 || !addr)
8828 break;
pbrook53a59602006-03-25 19:31:22 +00008829 unlock_user(*q, addr, 0);
8830 }
8831 for (gp = guest_envp, q = envp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00008832 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00008833 if (get_user_ual(addr, gp)
8834 || !addr)
8835 break;
pbrook53a59602006-03-25 19:31:22 +00008836 unlock_user(*q, addr, 0);
8837 }
Prasad J Panditb936cb52017-03-07 12:51:47 +05308838
8839 g_free(argp);
8840 g_free(envp);
bellard7854b052003-03-29 17:22:23 +00008841 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008842 return ret;
bellard31e31b82003-02-18 22:55:36 +00008843 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00008844 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008845 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008846 ret = get_errno(chdir(p));
8847 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008848 return ret;
bellarda315a142005-01-30 22:59:18 +00008849#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00008850 case TARGET_NR_time:
8851 {
pbrook53a59602006-03-25 19:31:22 +00008852 time_t host_time;
8853 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00008854 if (!is_error(ret)
8855 && arg1
8856 && put_user_sal(host_time, arg1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008857 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00008858 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008859 return ret;
bellarda315a142005-01-30 22:59:18 +00008860#endif
Chen Gang704eff62015-08-21 05:37:33 +08008861#ifdef TARGET_NR_mknod
bellard31e31b82003-02-18 22:55:36 +00008862 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00008863 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008864 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008865 ret = get_errno(mknod(p, arg2, arg3));
8866 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008867 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008868#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01008869#if defined(TARGET_NR_mknodat)
ths75ac37a2007-09-24 09:23:05 +00008870 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00008871 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008872 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01008873 ret = get_errno(mknodat(arg1, p, arg3, arg4));
bellard579a97f2007-11-11 14:26:47 +00008874 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008875 return ret;
ths75ac37a2007-09-24 09:23:05 +00008876#endif
Chen Gang704eff62015-08-21 05:37:33 +08008877#ifdef TARGET_NR_chmod
bellard31e31b82003-02-18 22:55:36 +00008878 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00008879 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008880 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008881 ret = get_errno(chmod(p, arg2));
8882 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008883 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008884#endif
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008885#ifdef TARGET_NR_lseek
bellard31e31b82003-02-18 22:55:36 +00008886 case TARGET_NR_lseek:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008887 return get_errno(lseek(arg1, arg2, arg3));
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008888#endif
Richard Henderson92317332010-05-03 10:07:53 -07008889#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA)
8890 /* Alpha specific */
j_mayer7a3148a2007-04-05 07:13:51 +00008891 case TARGET_NR_getxpid:
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02008892 cpu_env->ir[IR_A4] = getppid();
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008893 return get_errno(getpid());
Richard Henderson92317332010-05-03 10:07:53 -07008894#endif
8895#ifdef TARGET_NR_getpid
8896 case TARGET_NR_getpid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008897 return get_errno(getpid());
Richard Henderson92317332010-05-03 10:07:53 -07008898#endif
bellard31e31b82003-02-18 22:55:36 +00008899 case TARGET_NR_mount:
Paul Burton356d7712014-06-22 11:25:37 +01008900 {
8901 /* need to look at the data field */
8902 void *p2, *p3;
8903
8904 if (arg1) {
8905 p = lock_user_string(arg1);
8906 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008907 return -TARGET_EFAULT;
Paul Burton356d7712014-06-22 11:25:37 +01008908 }
8909 } else {
8910 p = NULL;
8911 }
8912
8913 p2 = lock_user_string(arg2);
8914 if (!p2) {
8915 if (arg1) {
8916 unlock_user(p, arg1, 0);
8917 }
Richard Henderson2852aaf2018-08-18 12:01:06 -07008918 return -TARGET_EFAULT;
Paul Burton356d7712014-06-22 11:25:37 +01008919 }
8920
8921 if (arg3) {
8922 p3 = lock_user_string(arg3);
8923 if (!p3) {
8924 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00008925 unlock_user(p, arg1, 0);
Paul Burton356d7712014-06-22 11:25:37 +01008926 }
8927 unlock_user(p2, arg2, 0);
Richard Henderson2852aaf2018-08-18 12:01:06 -07008928 return -TARGET_EFAULT;
Paul Burton356d7712014-06-22 11:25:37 +01008929 }
8930 } else {
8931 p3 = NULL;
8932 }
8933
8934 /* FIXME - arg5 should be locked, but it isn't clear how to
8935 * do that since it's not guaranteed to be a NULL-terminated
8936 * string.
8937 */
8938 if (!arg5) {
8939 ret = mount(p, p2, p3, (unsigned long)arg4, NULL);
8940 } else {
Richard Henderson3e8f1622021-02-12 10:48:43 -08008941 ret = mount(p, p2, p3, (unsigned long)arg4, g2h(cpu, arg5));
Paul Burton356d7712014-06-22 11:25:37 +01008942 }
8943 ret = get_errno(ret);
8944
8945 if (arg1) {
8946 unlock_user(p, arg1, 0);
8947 }
8948 unlock_user(p2, arg2, 0);
8949 if (arg3) {
8950 unlock_user(p3, arg3, 0);
8951 }
8952 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008953 return ret;
Laurent Vivier6eb9dbf2020-05-02 21:46:42 +02008954#if defined(TARGET_NR_umount) || defined(TARGET_NR_oldumount)
8955#if defined(TARGET_NR_umount)
bellard31e31b82003-02-18 22:55:36 +00008956 case TARGET_NR_umount:
Laurent Vivier6eb9dbf2020-05-02 21:46:42 +02008957#endif
8958#if defined(TARGET_NR_oldumount)
8959 case TARGET_NR_oldumount:
8960#endif
bellard579a97f2007-11-11 14:26:47 +00008961 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008962 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008963 ret = get_errno(umount(p));
8964 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008965 return ret;
thse5febef2007-04-01 18:31:35 +00008966#endif
j_mayer7a3148a2007-04-05 07:13:51 +00008967#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00008968 case TARGET_NR_stime:
8969 {
Laurent Vivier0f1f2d42019-11-12 15:25:56 +01008970 struct timespec ts;
8971 ts.tv_nsec = 0;
8972 if (get_user_sal(ts.tv_sec, arg1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008973 return -TARGET_EFAULT;
Laurent Vivier0f1f2d42019-11-12 15:25:56 +01008974 }
8975 return get_errno(clock_settime(CLOCK_REALTIME, &ts));
bellard31e31b82003-02-18 22:55:36 +00008976 }
j_mayer7a3148a2007-04-05 07:13:51 +00008977#endif
j_mayer7a3148a2007-04-05 07:13:51 +00008978#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00008979 case TARGET_NR_alarm:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008980 return alarm(arg1);
j_mayer7a3148a2007-04-05 07:13:51 +00008981#endif
j_mayer7a3148a2007-04-05 07:13:51 +00008982#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00008983 case TARGET_NR_pause:
Timothy E Baldwinf59ec602016-05-27 15:51:55 +01008984 if (!block_signals()) {
8985 sigsuspend(&((TaskState *)cpu->opaque)->signal_mask);
8986 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008987 return -TARGET_EINTR;
j_mayer7a3148a2007-04-05 07:13:51 +00008988#endif
thse5febef2007-04-01 18:31:35 +00008989#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00008990 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00008991 {
pbrook53a59602006-03-25 19:31:22 +00008992 struct utimbuf tbuf, *host_tbuf;
8993 struct target_utimbuf *target_tbuf;
8994 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00008995 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008996 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02008997 tbuf.actime = tswapal(target_tbuf->actime);
8998 tbuf.modtime = tswapal(target_tbuf->modtime);
pbrook53a59602006-03-25 19:31:22 +00008999 unlock_user_struct(target_tbuf, arg2, 0);
9000 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00009001 } else {
pbrook53a59602006-03-25 19:31:22 +00009002 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00009003 }
bellard579a97f2007-11-11 14:26:47 +00009004 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009005 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009006 ret = get_errno(utime(p, host_tbuf));
9007 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00009008 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009009 return ret;
thse5febef2007-04-01 18:31:35 +00009010#endif
Chen Gang704eff62015-08-21 05:37:33 +08009011#ifdef TARGET_NR_utimes
bellard978a66f2004-12-06 22:58:05 +00009012 case TARGET_NR_utimes:
9013 {
bellard978a66f2004-12-06 22:58:05 +00009014 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00009015 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00009016 if (copy_from_user_timeval(&tv[0], arg2)
9017 || copy_from_user_timeval(&tv[1],
9018 arg2 + sizeof(struct target_timeval)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009019 return -TARGET_EFAULT;
bellard978a66f2004-12-06 22:58:05 +00009020 tvp = tv;
9021 } else {
9022 tvp = NULL;
9023 }
bellard579a97f2007-11-11 14:26:47 +00009024 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009025 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009026 ret = get_errno(utimes(p, tvp));
9027 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00009028 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009029 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009030#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01009031#if defined(TARGET_NR_futimesat)
balrogac8a6552008-09-20 02:25:39 +00009032 case TARGET_NR_futimesat:
9033 {
9034 struct timeval *tvp, tv[2];
9035 if (arg3) {
9036 if (copy_from_user_timeval(&tv[0], arg3)
9037 || copy_from_user_timeval(&tv[1],
9038 arg3 + sizeof(struct target_timeval)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009039 return -TARGET_EFAULT;
balrogac8a6552008-09-20 02:25:39 +00009040 tvp = tv;
9041 } else {
9042 tvp = NULL;
9043 }
Richard Henderson2852aaf2018-08-18 12:01:06 -07009044 if (!(p = lock_user_string(arg2))) {
9045 return -TARGET_EFAULT;
9046 }
Peter Maydellc0d472b2013-06-12 16:20:21 +01009047 ret = get_errno(futimesat(arg1, path(p), tvp));
balrogac8a6552008-09-20 02:25:39 +00009048 unlock_user(p, arg2, 0);
9049 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009050 return ret;
balrogac8a6552008-09-20 02:25:39 +00009051#endif
Chen Gang704eff62015-08-21 05:37:33 +08009052#ifdef TARGET_NR_access
bellard31e31b82003-02-18 22:55:36 +00009053 case TARGET_NR_access:
Richard Henderson2852aaf2018-08-18 12:01:06 -07009054 if (!(p = lock_user_string(arg1))) {
9055 return -TARGET_EFAULT;
9056 }
Ulrich Hecht719f9082009-07-03 17:09:29 +02009057 ret = get_errno(access(path(p), arg2));
pbrook53a59602006-03-25 19:31:22 +00009058 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009059 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009060#endif
ths92a34c12007-09-24 09:27:49 +00009061#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
9062 case TARGET_NR_faccessat:
Richard Henderson2852aaf2018-08-18 12:01:06 -07009063 if (!(p = lock_user_string(arg2))) {
9064 return -TARGET_EFAULT;
9065 }
Peter Maydellc0d472b2013-06-12 16:20:21 +01009066 ret = get_errno(faccessat(arg1, p, arg3, 0));
bellard579a97f2007-11-11 14:26:47 +00009067 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009068 return ret;
ths92a34c12007-09-24 09:27:49 +00009069#endif
j_mayer7a3148a2007-04-05 07:13:51 +00009070#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009071 case TARGET_NR_nice:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009072 return get_errno(nice(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +00009073#endif
bellard31e31b82003-02-18 22:55:36 +00009074 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00009075 sync();
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009076 return 0;
Aleksandar Markovic5a03cd02016-10-10 13:23:30 +02009077#if defined(TARGET_NR_syncfs) && defined(CONFIG_SYNCFS)
9078 case TARGET_NR_syncfs:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009079 return get_errno(syncfs(arg1));
Aleksandar Markovic5a03cd02016-10-10 13:23:30 +02009080#endif
bellard31e31b82003-02-18 22:55:36 +00009081 case TARGET_NR_kill:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009082 return get_errno(safe_kill(arg1, target_to_host_signal(arg2)));
Chen Gang704eff62015-08-21 05:37:33 +08009083#ifdef TARGET_NR_rename
bellard31e31b82003-02-18 22:55:36 +00009084 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00009085 {
9086 void *p2;
9087 p = lock_user_string(arg1);
9088 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00009089 if (!p || !p2)
9090 ret = -TARGET_EFAULT;
9091 else
9092 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00009093 unlock_user(p2, arg2, 0);
9094 unlock_user(p, arg1, 0);
9095 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009096 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009097#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01009098#if defined(TARGET_NR_renameat)
ths722183f2007-09-24 09:24:37 +00009099 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00009100 {
bellard579a97f2007-11-11 14:26:47 +00009101 void *p2;
ths722183f2007-09-24 09:24:37 +00009102 p = lock_user_string(arg2);
9103 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00009104 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00009105 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00009106 else
Peter Maydellc0d472b2013-06-12 16:20:21 +01009107 ret = get_errno(renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00009108 unlock_user(p2, arg4, 0);
9109 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00009110 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009111 return ret;
ths722183f2007-09-24 09:24:37 +00009112#endif
Andreas Schwab95d03072018-01-23 11:53:31 +01009113#if defined(TARGET_NR_renameat2)
9114 case TARGET_NR_renameat2:
9115 {
9116 void *p2;
9117 p = lock_user_string(arg2);
9118 p2 = lock_user_string(arg4);
9119 if (!p || !p2) {
9120 ret = -TARGET_EFAULT;
9121 } else {
9122 ret = get_errno(sys_renameat2(arg1, p, arg3, p2, arg5));
9123 }
9124 unlock_user(p2, arg4, 0);
9125 unlock_user(p, arg2, 0);
9126 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009127 return ret;
Andreas Schwab95d03072018-01-23 11:53:31 +01009128#endif
Chen Gang704eff62015-08-21 05:37:33 +08009129#ifdef TARGET_NR_mkdir
bellard31e31b82003-02-18 22:55:36 +00009130 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00009131 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009132 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009133 ret = get_errno(mkdir(p, arg2));
9134 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009135 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009136#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01009137#if defined(TARGET_NR_mkdirat)
ths4472ad02007-09-24 09:22:32 +00009138 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00009139 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009140 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01009141 ret = get_errno(mkdirat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00009142 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009143 return ret;
ths4472ad02007-09-24 09:22:32 +00009144#endif
Chen Gang704eff62015-08-21 05:37:33 +08009145#ifdef TARGET_NR_rmdir
bellard31e31b82003-02-18 22:55:36 +00009146 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00009147 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009148 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009149 ret = get_errno(rmdir(p));
9150 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009151 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009152#endif
bellard31e31b82003-02-18 22:55:36 +00009153 case TARGET_NR_dup:
9154 ret = get_errno(dup(arg1));
Laurent Viviere36800c2015-10-02 14:48:09 +02009155 if (ret >= 0) {
9156 fd_trans_dup(arg1, ret);
9157 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009158 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009159#ifdef TARGET_NR_pipe
bellard31e31b82003-02-18 22:55:36 +00009160 case TARGET_NR_pipe:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009161 return do_pipe(cpu_env, arg1, 0, 0);
Chen Gang704eff62015-08-21 05:37:33 +08009162#endif
Riku Voipio099d6b02009-05-05 12:10:04 +03009163#ifdef TARGET_NR_pipe2
9164 case TARGET_NR_pipe2:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009165 return do_pipe(cpu_env, arg1,
9166 target_to_host_bitmask(arg2, fcntl_flags_tbl), 1);
Riku Voipio099d6b02009-05-05 12:10:04 +03009167#endif
bellard31e31b82003-02-18 22:55:36 +00009168 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00009169 {
pbrook53a59602006-03-25 19:31:22 +00009170 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00009171 struct tms tms;
9172 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00009173 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00009174 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
9175 if (!tmsp)
Richard Henderson2852aaf2018-08-18 12:01:06 -07009176 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02009177 tmsp->tms_utime = tswapal(host_to_target_clock_t(tms.tms_utime));
9178 tmsp->tms_stime = tswapal(host_to_target_clock_t(tms.tms_stime));
9179 tmsp->tms_cutime = tswapal(host_to_target_clock_t(tms.tms_cutime));
9180 tmsp->tms_cstime = tswapal(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00009181 }
bellardc596ed12003-07-13 17:32:31 +00009182 if (!is_error(ret))
9183 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00009184 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009185 return ret;
bellard31e31b82003-02-18 22:55:36 +00009186 case TARGET_NR_acct:
aurel3238d840e2009-01-30 19:48:17 +00009187 if (arg1 == 0) {
9188 ret = get_errno(acct(NULL));
9189 } else {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009190 if (!(p = lock_user_string(arg1))) {
9191 return -TARGET_EFAULT;
9192 }
aurel3238d840e2009-01-30 19:48:17 +00009193 ret = get_errno(acct(path(p)));
9194 unlock_user(p, arg1, 0);
9195 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009196 return ret;
Richard Henderson8070e7b2013-07-24 09:50:00 -10009197#ifdef TARGET_NR_umount2
bellard31e31b82003-02-18 22:55:36 +00009198 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00009199 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009200 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009201 ret = get_errno(umount2(p, arg2));
9202 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009203 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00009204#endif
bellard31e31b82003-02-18 22:55:36 +00009205 case TARGET_NR_ioctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009206 return do_ioctl(arg1, arg2, arg3);
Michael Clark47ae93c2018-03-03 01:31:11 +13009207#ifdef TARGET_NR_fcntl
bellard31e31b82003-02-18 22:55:36 +00009208 case TARGET_NR_fcntl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009209 return do_fcntl(arg1, arg2, arg3);
Michael Clark47ae93c2018-03-03 01:31:11 +13009210#endif
bellard31e31b82003-02-18 22:55:36 +00009211 case TARGET_NR_setpgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009212 return get_errno(setpgid(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00009213 case TARGET_NR_umask:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009214 return get_errno(umask(arg1));
bellard31e31b82003-02-18 22:55:36 +00009215 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00009216 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009217 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009218 ret = get_errno(chroot(p));
9219 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009220 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009221#ifdef TARGET_NR_dup2
bellard31e31b82003-02-18 22:55:36 +00009222 case TARGET_NR_dup2:
9223 ret = get_errno(dup2(arg1, arg2));
Laurent Viviere36800c2015-10-02 14:48:09 +02009224 if (ret >= 0) {
9225 fd_trans_dup(arg1, arg2);
9226 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009227 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009228#endif
Ulrich Hechtd0927932009-09-17 20:22:14 +03009229#if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3)
9230 case TARGET_NR_dup3:
Peter Maydell10fa9932017-12-15 15:18:00 +00009231 {
9232 int host_flags;
9233
9234 if ((arg3 & ~TARGET_O_CLOEXEC) != 0) {
9235 return -EINVAL;
9236 }
9237 host_flags = target_to_host_bitmask(arg3, fcntl_flags_tbl);
9238 ret = get_errno(dup3(arg1, arg2, host_flags));
Laurent Viviere36800c2015-10-02 14:48:09 +02009239 if (ret >= 0) {
9240 fd_trans_dup(arg1, arg2);
9241 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009242 return ret;
Peter Maydell10fa9932017-12-15 15:18:00 +00009243 }
Ulrich Hechtd0927932009-09-17 20:22:14 +03009244#endif
j_mayer7a3148a2007-04-05 07:13:51 +00009245#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009246 case TARGET_NR_getppid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009247 return get_errno(getppid());
j_mayer7a3148a2007-04-05 07:13:51 +00009248#endif
Chen Gang704eff62015-08-21 05:37:33 +08009249#ifdef TARGET_NR_getpgrp
bellard31e31b82003-02-18 22:55:36 +00009250 case TARGET_NR_getpgrp:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009251 return get_errno(getpgrp());
Chen Gang704eff62015-08-21 05:37:33 +08009252#endif
bellard31e31b82003-02-18 22:55:36 +00009253 case TARGET_NR_setsid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009254 return get_errno(setsid());
thse5febef2007-04-01 18:31:35 +00009255#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00009256 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00009257 {
Richard Henderson02d0de12021-04-22 16:02:26 -07009258#if defined(TARGET_MIPS)
bellard106ec872006-06-27 21:08:10 +00009259 struct target_sigaction act, oact, *pact, *old_act;
9260
9261 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00009262 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009263 return -TARGET_EFAULT;
bellard106ec872006-06-27 21:08:10 +00009264 act._sa_handler = old_act->_sa_handler;
9265 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
9266 act.sa_flags = old_act->sa_flags;
9267 unlock_user_struct(old_act, arg2, 0);
9268 pact = &act;
9269 } else {
9270 pact = NULL;
9271 }
9272
Richard Henderson02fb28e2021-04-22 16:02:23 -07009273 ret = get_errno(do_sigaction(arg1, pact, &oact, 0));
bellard106ec872006-06-27 21:08:10 +00009274
9275 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00009276 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009277 return -TARGET_EFAULT;
bellard106ec872006-06-27 21:08:10 +00009278 old_act->_sa_handler = oact._sa_handler;
9279 old_act->sa_flags = oact.sa_flags;
9280 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
9281 old_act->sa_mask.sig[1] = 0;
9282 old_act->sa_mask.sig[2] = 0;
9283 old_act->sa_mask.sig[3] = 0;
9284 unlock_user_struct(old_act, arg3, 1);
9285 }
Richard Henderson6049f4f2009-12-27 18:30:03 -08009286#else
9287 struct target_old_sigaction *old_act;
9288 struct target_sigaction act, oact, *pact;
9289 if (arg2) {
9290 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009291 return -TARGET_EFAULT;
Richard Henderson6049f4f2009-12-27 18:30:03 -08009292 act._sa_handler = old_act->_sa_handler;
9293 target_siginitset(&act.sa_mask, old_act->sa_mask);
9294 act.sa_flags = old_act->sa_flags;
Richard Hendersonca192272021-04-22 16:02:24 -07009295#ifdef TARGET_ARCH_HAS_SA_RESTORER
Richard Henderson6049f4f2009-12-27 18:30:03 -08009296 act.sa_restorer = old_act->sa_restorer;
Richard Hendersonca192272021-04-22 16:02:24 -07009297#endif
Richard Henderson6049f4f2009-12-27 18:30:03 -08009298 unlock_user_struct(old_act, arg2, 0);
9299 pact = &act;
9300 } else {
9301 pact = NULL;
9302 }
Richard Henderson02fb28e2021-04-22 16:02:23 -07009303 ret = get_errno(do_sigaction(arg1, pact, &oact, 0));
Richard Henderson6049f4f2009-12-27 18:30:03 -08009304 if (!is_error(ret) && arg3) {
9305 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009306 return -TARGET_EFAULT;
Richard Henderson6049f4f2009-12-27 18:30:03 -08009307 old_act->_sa_handler = oact._sa_handler;
9308 old_act->sa_mask = oact.sa_mask.sig[0];
9309 old_act->sa_flags = oact.sa_flags;
Richard Hendersonca192272021-04-22 16:02:24 -07009310#ifdef TARGET_ARCH_HAS_SA_RESTORER
Richard Henderson6049f4f2009-12-27 18:30:03 -08009311 old_act->sa_restorer = oact.sa_restorer;
Richard Hendersonca192272021-04-22 16:02:24 -07009312#endif
Richard Henderson6049f4f2009-12-27 18:30:03 -08009313 unlock_user_struct(old_act, arg3, 1);
9314 }
ths388bb212007-05-13 13:58:00 +00009315#endif
bellard31e31b82003-02-18 22:55:36 +00009316 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009317 return ret;
thse5febef2007-04-01 18:31:35 +00009318#endif
bellard66fb9762003-03-23 01:06:05 +00009319 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00009320 {
Richard Henderson0f6f9902021-04-22 16:02:25 -07009321 /*
9322 * For Alpha and SPARC this is a 5 argument syscall, with
Peter Maydell78bfef72017-11-06 18:33:26 +00009323 * a 'restorer' parameter which must be copied into the
9324 * sa_restorer field of the sigaction struct.
9325 * For Alpha that 'restorer' is arg5; for SPARC it is arg4,
9326 * and arg5 is the sigsetsize.
Peter Maydell78bfef72017-11-06 18:33:26 +00009327 */
Richard Henderson0f6f9902021-04-22 16:02:25 -07009328#if defined(TARGET_ALPHA)
9329 target_ulong sigsetsize = arg4;
9330 target_ulong restorer = arg5;
9331#elif defined(TARGET_SPARC)
Peter Maydell78bfef72017-11-06 18:33:26 +00009332 target_ulong restorer = arg4;
9333 target_ulong sigsetsize = arg5;
9334#else
9335 target_ulong sigsetsize = arg4;
Richard Henderson02fb28e2021-04-22 16:02:23 -07009336 target_ulong restorer = 0;
Peter Maydell78bfef72017-11-06 18:33:26 +00009337#endif
Richard Hendersonfb804392021-04-22 16:02:27 -07009338 struct target_sigaction *act = NULL;
9339 struct target_sigaction *oact = NULL;
pbrook53a59602006-03-25 19:31:22 +00009340
Peter Maydell78bfef72017-11-06 18:33:26 +00009341 if (sigsetsize != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009342 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01009343 }
Richard Hendersonfb804392021-04-22 16:02:27 -07009344 if (arg2 && !lock_user_struct(VERIFY_READ, act, arg2, 1)) {
9345 return -TARGET_EFAULT;
Peter Maydell78bfef72017-11-06 18:33:26 +00009346 }
Richard Hendersonfb804392021-04-22 16:02:27 -07009347 if (arg3 && !lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
9348 ret = -TARGET_EFAULT;
9349 } else {
9350 ret = get_errno(do_sigaction(arg1, act, oact, restorer));
9351 if (oact) {
9352 unlock_user_struct(oact, arg3, 1);
bellard579a97f2007-11-11 14:26:47 +00009353 }
Richard Hendersonfb804392021-04-22 16:02:27 -07009354 }
9355 if (act) {
pbrook53a59602006-03-25 19:31:22 +00009356 unlock_user_struct(act, arg2, 0);
Richard Hendersonfb804392021-04-22 16:02:27 -07009357 }
pbrook53a59602006-03-25 19:31:22 +00009358 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009359 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00009360#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009361 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00009362 {
9363 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00009364 abi_ulong target_set;
Peter Maydell3d3efba2016-05-27 15:51:49 +01009365 ret = do_sigprocmask(0, NULL, &cur_set);
9366 if (!ret) {
9367 host_to_target_old_sigset(&target_set, &cur_set);
9368 ret = target_set;
9369 }
bellard66fb9762003-03-23 01:06:05 +00009370 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009371 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00009372#endif
9373#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009374 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00009375 {
Miloš Stojanovića8617d82017-05-15 16:59:43 +02009376 sigset_t set, oset;
blueswir1992f48a2007-10-14 16:27:31 +00009377 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00009378 target_to_host_old_sigset(&set, &target_set);
Peter Maydell3d3efba2016-05-27 15:51:49 +01009379 ret = do_sigprocmask(SIG_SETMASK, &set, &oset);
9380 if (!ret) {
9381 host_to_target_old_sigset(&target_set, &oset);
9382 ret = target_set;
9383 }
bellard66fb9762003-03-23 01:06:05 +00009384 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009385 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00009386#endif
thse5febef2007-04-01 18:31:35 +00009387#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00009388 case TARGET_NR_sigprocmask:
9389 {
Richard Hendersona5b3b132010-05-03 10:07:55 -07009390#if defined(TARGET_ALPHA)
9391 sigset_t set, oldset;
9392 abi_ulong mask;
9393 int how;
9394
9395 switch (arg1) {
9396 case TARGET_SIG_BLOCK:
9397 how = SIG_BLOCK;
9398 break;
9399 case TARGET_SIG_UNBLOCK:
9400 how = SIG_UNBLOCK;
9401 break;
9402 case TARGET_SIG_SETMASK:
9403 how = SIG_SETMASK;
9404 break;
9405 default:
Richard Henderson259841c2018-08-18 12:01:09 -07009406 return -TARGET_EINVAL;
Richard Hendersona5b3b132010-05-03 10:07:55 -07009407 }
9408 mask = arg2;
9409 target_to_host_old_sigset(&set, &mask);
9410
Peter Maydell3d3efba2016-05-27 15:51:49 +01009411 ret = do_sigprocmask(how, &set, &oldset);
Richard Hendersona5b3b132010-05-03 10:07:55 -07009412 if (!is_error(ret)) {
9413 host_to_target_old_sigset(&mask, &oldset);
9414 ret = mask;
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02009415 cpu_env->ir[IR_V0] = 0; /* force no error */
Richard Hendersona5b3b132010-05-03 10:07:55 -07009416 }
9417#else
bellard66fb9762003-03-23 01:06:05 +00009418 sigset_t set, oldset, *set_ptr;
Richard Hendersona5b3b132010-05-03 10:07:55 -07009419 int how;
ths3b46e622007-09-17 08:09:54 +00009420
pbrook53a59602006-03-25 19:31:22 +00009421 if (arg2) {
Patrick Ventureebce1712022-01-26 13:25:59 -08009422 p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1);
9423 if (!p) {
9424 return -TARGET_EFAULT;
9425 }
9426 target_to_host_old_sigset(&set, p);
9427 unlock_user(p, arg2, 0);
9428 set_ptr = &set;
Richard Hendersona5b3b132010-05-03 10:07:55 -07009429 switch (arg1) {
bellard66fb9762003-03-23 01:06:05 +00009430 case TARGET_SIG_BLOCK:
9431 how = SIG_BLOCK;
9432 break;
9433 case TARGET_SIG_UNBLOCK:
9434 how = SIG_UNBLOCK;
9435 break;
9436 case TARGET_SIG_SETMASK:
9437 how = SIG_SETMASK;
9438 break;
9439 default:
Richard Henderson259841c2018-08-18 12:01:09 -07009440 return -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00009441 }
bellard66fb9762003-03-23 01:06:05 +00009442 } else {
9443 how = 0;
9444 set_ptr = NULL;
9445 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01009446 ret = do_sigprocmask(how, set_ptr, &oldset);
pbrook53a59602006-03-25 19:31:22 +00009447 if (!is_error(ret) && arg3) {
Anthony Liguoric227f092009-10-01 16:12:16 -05009448 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009449 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009450 host_to_target_old_sigset(p, &oldset);
Anthony Liguoric227f092009-10-01 16:12:16 -05009451 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00009452 }
Richard Hendersona5b3b132010-05-03 10:07:55 -07009453#endif
bellard66fb9762003-03-23 01:06:05 +00009454 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009455 return ret;
thse5febef2007-04-01 18:31:35 +00009456#endif
bellard66fb9762003-03-23 01:06:05 +00009457 case TARGET_NR_rt_sigprocmask:
9458 {
9459 int how = arg1;
9460 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00009461
Peter Maydellc8157012016-06-30 14:23:24 +01009462 if (arg4 != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009463 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01009464 }
9465
pbrook53a59602006-03-25 19:31:22 +00009466 if (arg2) {
Shu-Chun Wengd3ced2a2022-01-26 13:25:58 -08009467 p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1);
9468 if (!p) {
9469 return -TARGET_EFAULT;
9470 }
9471 target_to_host_sigset(&set, p);
9472 unlock_user(p, arg2, 0);
9473 set_ptr = &set;
bellard66fb9762003-03-23 01:06:05 +00009474 switch(how) {
9475 case TARGET_SIG_BLOCK:
9476 how = SIG_BLOCK;
9477 break;
9478 case TARGET_SIG_UNBLOCK:
9479 how = SIG_UNBLOCK;
9480 break;
9481 case TARGET_SIG_SETMASK:
9482 how = SIG_SETMASK;
9483 break;
9484 default:
Richard Henderson259841c2018-08-18 12:01:09 -07009485 return -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00009486 }
bellard66fb9762003-03-23 01:06:05 +00009487 } else {
9488 how = 0;
9489 set_ptr = NULL;
9490 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01009491 ret = do_sigprocmask(how, set_ptr, &oldset);
pbrook53a59602006-03-25 19:31:22 +00009492 if (!is_error(ret) && arg3) {
Anthony Liguoric227f092009-10-01 16:12:16 -05009493 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009494 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009495 host_to_target_sigset(p, &oldset);
Anthony Liguoric227f092009-10-01 16:12:16 -05009496 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00009497 }
9498 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009499 return ret;
thse5febef2007-04-01 18:31:35 +00009500#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00009501 case TARGET_NR_sigpending:
9502 {
9503 sigset_t set;
9504 ret = get_errno(sigpending(&set));
9505 if (!is_error(ret)) {
Anthony Liguoric227f092009-10-01 16:12:16 -05009506 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009507 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009508 host_to_target_old_sigset(p, &set);
Anthony Liguoric227f092009-10-01 16:12:16 -05009509 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00009510 }
9511 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009512 return ret;
thse5febef2007-04-01 18:31:35 +00009513#endif
bellard66fb9762003-03-23 01:06:05 +00009514 case TARGET_NR_rt_sigpending:
9515 {
9516 sigset_t set;
Peter Maydellc8157012016-06-30 14:23:24 +01009517
9518 /* Yes, this check is >, not != like most. We follow the kernel's
9519 * logic and it does it like this because it implements
9520 * NR_sigpending through the same code path, and in that case
9521 * the old_sigset_t is smaller in size.
9522 */
9523 if (arg2 > sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009524 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01009525 }
9526
bellard66fb9762003-03-23 01:06:05 +00009527 ret = get_errno(sigpending(&set));
9528 if (!is_error(ret)) {
Anthony Liguoric227f092009-10-01 16:12:16 -05009529 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009530 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009531 host_to_target_sigset(p, &set);
Anthony Liguoric227f092009-10-01 16:12:16 -05009532 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00009533 }
9534 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009535 return ret;
thse5febef2007-04-01 18:31:35 +00009536#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00009537 case TARGET_NR_sigsuspend:
9538 {
Richard Henderson0a99f092022-03-15 01:43:05 -07009539 sigset_t *set;
9540
Richard Hendersonf43ce122010-05-03 10:07:54 -07009541#if defined(TARGET_ALPHA)
Richard Henderson0a99f092022-03-15 01:43:05 -07009542 TaskState *ts = cpu->opaque;
Richard Henderson7fb5ef32022-03-15 01:43:04 -07009543 /* target_to_host_old_sigset will bswap back */
9544 abi_ulong mask = tswapal(arg1);
Richard Henderson0a99f092022-03-15 01:43:05 -07009545 set = &ts->sigsuspend_mask;
9546 target_to_host_old_sigset(set, &mask);
Richard Hendersonf43ce122010-05-03 10:07:54 -07009547#else
Richard Henderson0a99f092022-03-15 01:43:05 -07009548 ret = process_sigsuspend_mask(&set, arg1, sizeof(target_sigset_t));
9549 if (ret != 0) {
9550 return ret;
Peter Maydell3d3efba2016-05-27 15:51:49 +01009551 }
Richard Henderson0a99f092022-03-15 01:43:05 -07009552#endif
9553 ret = get_errno(safe_rt_sigsuspend(set, SIGSET_T_SIZE));
9554 finish_sigsuspend_mask(ret);
bellard66fb9762003-03-23 01:06:05 +00009555 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009556 return ret;
thse5febef2007-04-01 18:31:35 +00009557#endif
bellard66fb9762003-03-23 01:06:05 +00009558 case TARGET_NR_rt_sigsuspend:
9559 {
Richard Henderson0a99f092022-03-15 01:43:05 -07009560 sigset_t *set;
Peter Maydellc8157012016-06-30 14:23:24 +01009561
Richard Henderson0a99f092022-03-15 01:43:05 -07009562 ret = process_sigsuspend_mask(&set, arg1, arg2);
9563 if (ret != 0) {
9564 return ret;
Peter Maydellc8157012016-06-30 14:23:24 +01009565 }
Richard Henderson0a99f092022-03-15 01:43:05 -07009566 ret = get_errno(safe_rt_sigsuspend(set, SIGSET_T_SIZE));
9567 finish_sigsuspend_mask(ret);
bellard66fb9762003-03-23 01:06:05 +00009568 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009569 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -07009570#ifdef TARGET_NR_rt_sigtimedwait
bellard66fb9762003-03-23 01:06:05 +00009571 case TARGET_NR_rt_sigtimedwait:
9572 {
bellard66fb9762003-03-23 01:06:05 +00009573 sigset_t set;
9574 struct timespec uts, *puts;
9575 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00009576
Peter Maydellc8157012016-06-30 14:23:24 +01009577 if (arg4 != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009578 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01009579 }
9580
Anthony Liguoric227f092009-10-01 16:12:16 -05009581 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009582 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009583 target_to_host_sigset(&set, p);
9584 unlock_user(p, arg1, 0);
9585 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00009586 puts = &uts;
Filip Bozuta4d213002020-07-24 20:16:51 +02009587 if (target_to_host_timespec(puts, arg3)) {
9588 return -TARGET_EFAULT;
9589 }
bellard66fb9762003-03-23 01:06:05 +00009590 } else {
9591 puts = NULL;
9592 }
Peter Maydellb3f82332016-06-06 19:58:08 +01009593 ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts,
9594 SIGSET_T_SIZE));
Petar Jovanovic974a1962014-03-03 15:07:41 +01009595 if (!is_error(ret)) {
9596 if (arg2) {
9597 p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t),
9598 0);
9599 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009600 return -TARGET_EFAULT;
Petar Jovanovic974a1962014-03-03 15:07:41 +01009601 }
9602 host_to_target_siginfo(p, &uinfo);
9603 unlock_user(p, arg2, sizeof(target_siginfo_t));
9604 }
9605 ret = host_to_target_signal(ret);
bellard66fb9762003-03-23 01:06:05 +00009606 }
9607 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009608 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -07009609#endif
Filip Bozutaddcbde12020-08-24 21:21:16 +02009610#ifdef TARGET_NR_rt_sigtimedwait_time64
9611 case TARGET_NR_rt_sigtimedwait_time64:
9612 {
9613 sigset_t set;
9614 struct timespec uts, *puts;
9615 siginfo_t uinfo;
9616
9617 if (arg4 != sizeof(target_sigset_t)) {
9618 return -TARGET_EINVAL;
9619 }
9620
9621 p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
9622 if (!p) {
9623 return -TARGET_EFAULT;
9624 }
9625 target_to_host_sigset(&set, p);
9626 unlock_user(p, arg1, 0);
9627 if (arg3) {
9628 puts = &uts;
9629 if (target_to_host_timespec64(puts, arg3)) {
9630 return -TARGET_EFAULT;
9631 }
9632 } else {
9633 puts = NULL;
9634 }
9635 ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts,
9636 SIGSET_T_SIZE));
9637 if (!is_error(ret)) {
9638 if (arg2) {
9639 p = lock_user(VERIFY_WRITE, arg2,
9640 sizeof(target_siginfo_t), 0);
9641 if (!p) {
9642 return -TARGET_EFAULT;
9643 }
9644 host_to_target_siginfo(p, &uinfo);
9645 unlock_user(p, arg2, sizeof(target_siginfo_t));
9646 }
9647 ret = host_to_target_signal(ret);
9648 }
9649 }
9650 return ret;
9651#endif
bellard66fb9762003-03-23 01:06:05 +00009652 case TARGET_NR_rt_sigqueueinfo:
9653 {
9654 siginfo_t uinfo;
Peter Maydell4debae62016-06-20 15:50:36 +01009655
9656 p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
9657 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009658 return -TARGET_EFAULT;
Peter Maydell4debae62016-06-20 15:50:36 +01009659 }
pbrook53a59602006-03-25 19:31:22 +00009660 target_to_host_siginfo(&uinfo, p);
Miloš Stojanovićd8b6d892017-05-15 16:59:44 +02009661 unlock_user(p, arg3, 0);
bellard66fb9762003-03-23 01:06:05 +00009662 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
9663 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009664 return ret;
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +02009665 case TARGET_NR_rt_tgsigqueueinfo:
9666 {
9667 siginfo_t uinfo;
9668
9669 p = lock_user(VERIFY_READ, arg4, sizeof(target_siginfo_t), 1);
9670 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009671 return -TARGET_EFAULT;
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +02009672 }
9673 target_to_host_siginfo(&uinfo, p);
9674 unlock_user(p, arg4, 0);
9675 ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, arg3, &uinfo));
9676 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009677 return ret;
thse5febef2007-04-01 18:31:35 +00009678#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00009679 case TARGET_NR_sigreturn:
Peter Maydell3d3efba2016-05-27 15:51:49 +01009680 if (block_signals()) {
Richard Hendersonaf254a22021-11-22 19:47:33 +01009681 return -QEMU_ERESTARTSYS;
Peter Maydell3d3efba2016-05-27 15:51:49 +01009682 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009683 return do_sigreturn(cpu_env);
thse5febef2007-04-01 18:31:35 +00009684#endif
bellard66fb9762003-03-23 01:06:05 +00009685 case TARGET_NR_rt_sigreturn:
Peter Maydell3d3efba2016-05-27 15:51:49 +01009686 if (block_signals()) {
Richard Hendersonaf254a22021-11-22 19:47:33 +01009687 return -QEMU_ERESTARTSYS;
Peter Maydell3d3efba2016-05-27 15:51:49 +01009688 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009689 return do_rt_sigreturn(cpu_env);
bellard31e31b82003-02-18 22:55:36 +00009690 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00009691 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009692 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009693 ret = get_errno(sethostname(p, arg2));
9694 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009695 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009696#ifdef TARGET_NR_setrlimit
bellard31e31b82003-02-18 22:55:36 +00009697 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +00009698 {
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03009699 int resource = target_to_host_resource(arg1);
pbrook53a59602006-03-25 19:31:22 +00009700 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00009701 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +00009702 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009703 return -TARGET_EFAULT;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09009704 rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
9705 rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00009706 unlock_user_struct(target_rlim, arg2, 0);
Max Filippov5dfa88f2018-09-17 11:13:14 -07009707 /*
9708 * If we just passed through resource limit settings for memory then
9709 * they would also apply to QEMU's own allocations, and QEMU will
9710 * crash or hang or die if its allocations fail. Ideally we would
9711 * track the guest allocations in QEMU and apply the limits ourselves.
9712 * For now, just tell the guest the call succeeded but don't actually
9713 * limit anything.
9714 */
9715 if (resource != RLIMIT_AS &&
9716 resource != RLIMIT_DATA &&
9717 resource != RLIMIT_STACK) {
9718 return get_errno(setrlimit(resource, &rlim));
9719 } else {
9720 return 0;
9721 }
bellard9de5e442003-03-23 16:49:39 +00009722 }
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009723#endif
9724#ifdef TARGET_NR_getrlimit
bellard31e31b82003-02-18 22:55:36 +00009725 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00009726 {
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03009727 int resource = target_to_host_resource(arg1);
pbrook53a59602006-03-25 19:31:22 +00009728 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00009729 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00009730
bellard9de5e442003-03-23 16:49:39 +00009731 ret = get_errno(getrlimit(resource, &rlim));
9732 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00009733 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009734 return -TARGET_EFAULT;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09009735 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
9736 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00009737 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00009738 }
9739 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009740 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009741#endif
bellard31e31b82003-02-18 22:55:36 +00009742 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00009743 {
9744 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00009745 ret = get_errno(getrusage(arg1, &rusage));
9746 if (!is_error(ret)) {
Petar Jovanovica39fb272014-04-08 19:24:30 +02009747 ret = host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00009748 }
9749 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009750 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -07009751#if defined(TARGET_NR_gettimeofday)
bellard31e31b82003-02-18 22:55:36 +00009752 case TARGET_NR_gettimeofday:
9753 {
bellard31e31b82003-02-18 22:55:36 +00009754 struct timeval tv;
Richard Hendersona52f5f82020-02-12 19:22:23 -08009755 struct timezone tz;
9756
9757 ret = get_errno(gettimeofday(&tv, &tz));
bellard31e31b82003-02-18 22:55:36 +00009758 if (!is_error(ret)) {
Richard Hendersona52f5f82020-02-12 19:22:23 -08009759 if (arg1 && copy_to_user_timeval(arg1, &tv)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009760 return -TARGET_EFAULT;
Richard Hendersona52f5f82020-02-12 19:22:23 -08009761 }
9762 if (arg2 && copy_to_user_timezone(arg2, &tz)) {
9763 return -TARGET_EFAULT;
9764 }
bellard31e31b82003-02-18 22:55:36 +00009765 }
9766 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009767 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -07009768#endif
9769#if defined(TARGET_NR_settimeofday)
bellard31e31b82003-02-18 22:55:36 +00009770 case TARGET_NR_settimeofday:
9771 {
Paul Burtonb67d8032014-06-22 11:25:41 +01009772 struct timeval tv, *ptv = NULL;
Paul Burtonef4467e2014-06-22 11:25:40 +01009773 struct timezone tz, *ptz = NULL;
9774
Paul Burtonb67d8032014-06-22 11:25:41 +01009775 if (arg1) {
9776 if (copy_from_user_timeval(&tv, arg1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009777 return -TARGET_EFAULT;
Paul Burtonb67d8032014-06-22 11:25:41 +01009778 }
9779 ptv = &tv;
9780 }
Paul Burtonef4467e2014-06-22 11:25:40 +01009781
9782 if (arg2) {
9783 if (copy_from_user_timezone(&tz, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009784 return -TARGET_EFAULT;
Paul Burtonef4467e2014-06-22 11:25:40 +01009785 }
9786 ptz = &tz;
9787 }
9788
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009789 return get_errno(settimeofday(ptv, ptz));
bellard31e31b82003-02-18 22:55:36 +00009790 }
Alistair Francis859e8a82020-03-12 15:13:49 -07009791#endif
Laurent Vivier9468a5d2013-01-10 22:30:50 +01009792#if defined(TARGET_NR_select)
bellard31e31b82003-02-18 22:55:36 +00009793 case TARGET_NR_select:
Laurent Vivier5457dc92016-07-08 01:17:27 +02009794#if defined(TARGET_WANT_NI_OLD_SELECT)
9795 /* some architectures used to have old_select here
9796 * but now ENOSYS it.
9797 */
9798 ret = -TARGET_ENOSYS;
9799#elif defined(TARGET_WANT_OLD_SYS_SELECT)
9800 ret = do_old_select(arg1);
Laurent Vivier9468a5d2013-01-10 22:30:50 +01009801#else
Laurent Vivier5457dc92016-07-08 01:17:27 +02009802 ret = do_select(arg1, arg2, arg3, arg4, arg5);
Laurent Vivier9468a5d2013-01-10 22:30:50 +01009803#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009804 return ret;
bellard048f6b42005-11-26 18:47:20 +00009805#endif
Riku Voipio9e423822010-05-07 12:28:05 +00009806#ifdef TARGET_NR_pselect6
9807 case TARGET_NR_pselect6:
Filip Bozutae5ce9682020-08-25 00:30:49 +02009808 return do_pselect6(arg1, arg2, arg3, arg4, arg5, arg6, false);
9809#endif
9810#ifdef TARGET_NR_pselect6_time64
9811 case TARGET_NR_pselect6_time64:
9812 return do_pselect6(arg1, arg2, arg3, arg4, arg5, arg6, true);
Riku Voipio9e423822010-05-07 12:28:05 +00009813#endif
Chen Gang704eff62015-08-21 05:37:33 +08009814#ifdef TARGET_NR_symlink
bellard31e31b82003-02-18 22:55:36 +00009815 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00009816 {
9817 void *p2;
9818 p = lock_user_string(arg1);
9819 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00009820 if (!p || !p2)
9821 ret = -TARGET_EFAULT;
9822 else
9823 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00009824 unlock_user(p2, arg2, 0);
9825 unlock_user(p, arg1, 0);
9826 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009827 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009828#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01009829#if defined(TARGET_NR_symlinkat)
thsf0b62432007-09-24 09:25:40 +00009830 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00009831 {
bellard579a97f2007-11-11 14:26:47 +00009832 void *p2;
thsf0b62432007-09-24 09:25:40 +00009833 p = lock_user_string(arg1);
9834 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00009835 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00009836 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00009837 else
Peter Maydellc0d472b2013-06-12 16:20:21 +01009838 ret = get_errno(symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00009839 unlock_user(p2, arg3, 0);
9840 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00009841 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009842 return ret;
thsf0b62432007-09-24 09:25:40 +00009843#endif
Chen Gang704eff62015-08-21 05:37:33 +08009844#ifdef TARGET_NR_readlink
bellard31e31b82003-02-18 22:55:36 +00009845 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00009846 {
Andreas Schwab463d8e72013-07-02 14:04:12 +01009847 void *p2;
pbrook53a59602006-03-25 19:31:22 +00009848 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00009849 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
Andreas Schwab463d8e72013-07-02 14:04:12 +01009850 if (!p || !p2) {
bellard579a97f2007-11-11 14:26:47 +00009851 ret = -TARGET_EFAULT;
Mike Frysingerf17f4982014-08-08 09:40:25 +09009852 } else if (!arg3) {
9853 /* Short circuit this for the magic exe check. */
9854 ret = -TARGET_EINVAL;
Andreas Schwab463d8e72013-07-02 14:04:12 +01009855 } else if (is_proc_myself((const char *)p, "exe")) {
9856 char real[PATH_MAX], *temp;
9857 temp = realpath(exec_path, real);
Mike Frysingerf17f4982014-08-08 09:40:25 +09009858 /* Return value is # of bytes that we wrote to the buffer. */
9859 if (temp == NULL) {
9860 ret = get_errno(-1);
9861 } else {
9862 /* Don't worry about sign mismatch as earlier mapping
9863 * logic would have thrown a bad address error. */
9864 ret = MIN(strlen(real), arg3);
9865 /* We cannot NUL terminate the string. */
9866 memcpy(p2, real, ret);
9867 }
Andreas Schwab463d8e72013-07-02 14:04:12 +01009868 } else {
9869 ret = get_errno(readlink(path(p), p2, arg3));
aurel32d088d662009-01-30 20:09:01 +00009870 }
pbrook53a59602006-03-25 19:31:22 +00009871 unlock_user(p2, arg2, ret);
9872 unlock_user(p, arg1, 0);
9873 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009874 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009875#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01009876#if defined(TARGET_NR_readlinkat)
ths5e0ccb12007-09-24 09:26:10 +00009877 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +00009878 {
bellard579a97f2007-11-11 14:26:47 +00009879 void *p2;
ths5e0ccb12007-09-24 09:26:10 +00009880 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00009881 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
Andreas Schwab463d8e72013-07-02 14:04:12 +01009882 if (!p || !p2) {
9883 ret = -TARGET_EFAULT;
9884 } else if (is_proc_myself((const char *)p, "exe")) {
9885 char real[PATH_MAX], *temp;
9886 temp = realpath(exec_path, real);
9887 ret = temp == NULL ? get_errno(-1) : strlen(real) ;
9888 snprintf((char *)p2, arg4, "%s", real);
9889 } else {
Peter Maydellc0d472b2013-06-12 16:20:21 +01009890 ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
Andreas Schwab463d8e72013-07-02 14:04:12 +01009891 }
bellard579a97f2007-11-11 14:26:47 +00009892 unlock_user(p2, arg3, ret);
9893 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +00009894 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009895 return ret;
ths5e0ccb12007-09-24 09:26:10 +00009896#endif
thse5febef2007-04-01 18:31:35 +00009897#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +00009898 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +00009899 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009900 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009901 ret = get_errno(swapon(p, arg2));
9902 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009903 return ret;
thse5febef2007-04-01 18:31:35 +00009904#endif
bellard31e31b82003-02-18 22:55:36 +00009905 case TARGET_NR_reboot:
Laurent Vivierc07ecc62013-01-07 11:40:06 +00009906 if (arg3 == LINUX_REBOOT_CMD_RESTART2) {
9907 /* arg4 must be ignored in all other cases */
9908 p = lock_user_string(arg4);
9909 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009910 return -TARGET_EFAULT;
Laurent Vivierc07ecc62013-01-07 11:40:06 +00009911 }
9912 ret = get_errno(reboot(arg1, arg2, arg3, p));
9913 unlock_user(p, arg4, 0);
9914 } else {
9915 ret = get_errno(reboot(arg1, arg2, arg3, NULL));
9916 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009917 return ret;
thse5febef2007-04-01 18:31:35 +00009918#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +00009919 case TARGET_NR_mmap:
Alexander Graf09701192013-09-03 20:12:15 +01009920#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
9921 (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
Ulrich Hechta4c075f2009-07-24 16:57:31 +02009922 defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \
9923 || defined(TARGET_S390X)
bellard31e31b82003-02-18 22:55:36 +00009924 {
blueswir1992f48a2007-10-14 16:27:31 +00009925 abi_ulong *v;
9926 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +00009927 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009928 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02009929 v1 = tswapal(v[0]);
9930 v2 = tswapal(v[1]);
9931 v3 = tswapal(v[2]);
9932 v4 = tswapal(v[3]);
9933 v5 = tswapal(v[4]);
9934 v6 = tswapal(v[5]);
pbrook53a59602006-03-25 19:31:22 +00009935 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +00009936 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +00009937 target_to_host_bitmask(v4, mmap_flags_tbl),
9938 v5, v6));
bellard31e31b82003-02-18 22:55:36 +00009939 }
bellard31e31b82003-02-18 22:55:36 +00009940#else
Richard Hendersonee1bf832021-02-12 10:48:44 -08009941 /* mmap pointers are always untagged */
ths5fafdf22007-09-16 21:08:06 +00009942 ret = get_errno(target_mmap(arg1, arg2, arg3,
9943 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +00009944 arg5,
9945 arg6));
bellard31e31b82003-02-18 22:55:36 +00009946#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009947 return ret;
thse5febef2007-04-01 18:31:35 +00009948#endif
bellarda315a142005-01-30 22:59:18 +00009949#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +00009950 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +00009951#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +00009952#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +00009953#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009954 ret = target_mmap(arg1, arg2, arg3,
9955 target_to_host_bitmask(arg4, mmap_flags_tbl),
9956 arg5, arg6 << MMAP_SHIFT);
9957 return get_errno(ret);
bellarda315a142005-01-30 22:59:18 +00009958#endif
bellard31e31b82003-02-18 22:55:36 +00009959 case TARGET_NR_munmap:
Richard Hendersonee1bf832021-02-12 10:48:44 -08009960 arg1 = cpu_untagged_addr(cpu, arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009961 return get_errno(target_munmap(arg1, arg2));
bellard9de5e442003-03-23 16:49:39 +00009962 case TARGET_NR_mprotect:
Richard Hendersonee1bf832021-02-12 10:48:44 -08009963 arg1 = cpu_untagged_addr(cpu, arg1);
Paul Brook97374d32010-06-16 13:03:51 +01009964 {
Andreas Färber0429a972013-08-26 18:14:44 +02009965 TaskState *ts = cpu->opaque;
Paul Brook97374d32010-06-16 13:03:51 +01009966 /* Special hack to detect libc making the stack executable. */
9967 if ((arg3 & PROT_GROWSDOWN)
9968 && arg1 >= ts->info->stack_limit
9969 && arg1 <= ts->info->start_stack) {
9970 arg3 &= ~PROT_GROWSDOWN;
9971 arg2 = arg2 + arg1 - ts->info->stack_limit;
9972 arg1 = ts->info->stack_limit;
9973 }
9974 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009975 return get_errno(target_mprotect(arg1, arg2, arg3));
thse5febef2007-04-01 18:31:35 +00009976#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +00009977 case TARGET_NR_mremap:
Richard Hendersonee1bf832021-02-12 10:48:44 -08009978 arg1 = cpu_untagged_addr(cpu, arg1);
9979 /* mremap new_addr (arg5) is always untagged */
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009980 return get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
thse5febef2007-04-01 18:31:35 +00009981#endif
pbrook53a59602006-03-25 19:31:22 +00009982 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +00009983#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +00009984 case TARGET_NR_msync:
Richard Henderson3e8f1622021-02-12 10:48:43 -08009985 return get_errno(msync(g2h(cpu, arg1), arg2, arg3));
thse5febef2007-04-01 18:31:35 +00009986#endif
9987#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +00009988 case TARGET_NR_mlock:
Richard Henderson3e8f1622021-02-12 10:48:43 -08009989 return get_errno(mlock(g2h(cpu, arg1), arg2));
thse5febef2007-04-01 18:31:35 +00009990#endif
9991#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +00009992 case TARGET_NR_munlock:
Richard Henderson3e8f1622021-02-12 10:48:43 -08009993 return get_errno(munlock(g2h(cpu, arg1), arg2));
thse5febef2007-04-01 18:31:35 +00009994#endif
9995#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +00009996 case TARGET_NR_mlockall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009997 return get_errno(mlockall(target_to_host_mlockall_arg(arg1)));
thse5febef2007-04-01 18:31:35 +00009998#endif
9999#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +000010000 case TARGET_NR_munlockall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010001 return get_errno(munlockall());
thse5febef2007-04-01 18:31:35 +000010002#endif
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010003#ifdef TARGET_NR_truncate
bellard31e31b82003-02-18 22:55:36 +000010004 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +000010005 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010006 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010007 ret = get_errno(truncate(p, arg2));
10008 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010009 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010010#endif
10011#ifdef TARGET_NR_ftruncate
bellard31e31b82003-02-18 22:55:36 +000010012 case TARGET_NR_ftruncate:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010013 return get_errno(ftruncate(arg1, arg2));
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010014#endif
bellard31e31b82003-02-18 22:55:36 +000010015 case TARGET_NR_fchmod:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010016 return get_errno(fchmod(arg1, arg2));
Peter Maydellc0d472b2013-06-12 16:20:21 +010010017#if defined(TARGET_NR_fchmodat)
ths814d7972007-09-24 09:26:51 +000010018 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +000010019 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010020 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +010010021 ret = get_errno(fchmodat(arg1, p, arg3, 0));
bellard579a97f2007-11-11 14:26:47 +000010022 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010023 return ret;
ths814d7972007-09-24 09:26:51 +000010024#endif
bellard31e31b82003-02-18 22:55:36 +000010025 case TARGET_NR_getpriority:
Richard Henderson95c09822012-06-07 15:14:50 -070010026 /* Note that negative values are valid for getpriority, so we must
10027 differentiate based on errno settings. */
10028 errno = 0;
10029 ret = getpriority(arg1, arg2);
10030 if (ret == -1 && errno != 0) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010031 return -host_to_target_errno(errno);
Richard Henderson95c09822012-06-07 15:14:50 -070010032 }
10033#ifdef TARGET_ALPHA
10034 /* Return value is the unbiased priority. Signal no error. */
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020010035 cpu_env->ir[IR_V0] = 0;
Richard Henderson95c09822012-06-07 15:14:50 -070010036#else
10037 /* Return value is a biased priority to avoid negative numbers. */
10038 ret = 20 - ret;
10039#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010040 return ret;
bellard31e31b82003-02-18 22:55:36 +000010041 case TARGET_NR_setpriority:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010042 return get_errno(setpriority(arg1, arg2, arg3));
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010043#ifdef TARGET_NR_statfs
bellard31e31b82003-02-18 22:55:36 +000010044 case TARGET_NR_statfs:
Richard Henderson2852aaf2018-08-18 12:01:06 -070010045 if (!(p = lock_user_string(arg1))) {
10046 return -TARGET_EFAULT;
10047 }
pbrook53a59602006-03-25 19:31:22 +000010048 ret = get_errno(statfs(path(p), &stfs));
10049 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +000010050 convert_statfs:
10051 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +000010052 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +000010053
bellard579a97f2007-11-11 14:26:47 +000010054 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010055 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000010056 __put_user(stfs.f_type, &target_stfs->f_type);
10057 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
10058 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
10059 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
10060 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
10061 __put_user(stfs.f_files, &target_stfs->f_files);
10062 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
10063 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
10064 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
10065 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
Alexander Graf229d3372012-09-19 04:39:53 +020010066 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
Shea Levyd4247ec2018-03-01 06:15:00 -050010067#ifdef _STATFS_F_FLAGS
10068 __put_user(stfs.f_flags, &target_stfs->f_flags);
10069#else
10070 __put_user(0, &target_stfs->f_flags);
10071#endif
Alexander Graf229d3372012-09-19 04:39:53 +020010072 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
pbrook53a59602006-03-25 19:31:22 +000010073 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +000010074 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010075 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010076#endif
10077#ifdef TARGET_NR_fstatfs
bellard31e31b82003-02-18 22:55:36 +000010078 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +000010079 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +000010080 goto convert_statfs;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010081#endif
bellard56c8f682005-11-28 22:28:41 +000010082#ifdef TARGET_NR_statfs64
10083 case TARGET_NR_statfs64:
Richard Henderson2852aaf2018-08-18 12:01:06 -070010084 if (!(p = lock_user_string(arg1))) {
10085 return -TARGET_EFAULT;
10086 }
pbrook53a59602006-03-25 19:31:22 +000010087 ret = get_errno(statfs(path(p), &stfs));
10088 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +000010089 convert_statfs64:
10090 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +000010091 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +000010092
bellard579a97f2007-11-11 14:26:47 +000010093 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010094 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000010095 __put_user(stfs.f_type, &target_stfs->f_type);
10096 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
10097 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
10098 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
10099 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
10100 __put_user(stfs.f_files, &target_stfs->f_files);
10101 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
10102 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
10103 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
10104 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
Alexander Graf229d3372012-09-19 04:39:53 +020010105 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
Frajob94e2b42020-01-30 15:00:30 +020010106#ifdef _STATFS_F_FLAGS
10107 __put_user(stfs.f_flags, &target_stfs->f_flags);
10108#else
10109 __put_user(0, &target_stfs->f_flags);
10110#endif
Alexander Graf229d3372012-09-19 04:39:53 +020010111 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
bellard579a97f2007-11-11 14:26:47 +000010112 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +000010113 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010114 return ret;
bellard56c8f682005-11-28 22:28:41 +000010115 case TARGET_NR_fstatfs64:
10116 ret = get_errno(fstatfs(arg1, &stfs));
10117 goto convert_statfs64;
10118#endif
thse5febef2007-04-01 18:31:35 +000010119#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +000010120 case TARGET_NR_socketcall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010121 return do_socketcall(arg1, arg2);
thse5febef2007-04-01 18:31:35 +000010122#endif
bellard3532fa72006-06-24 15:06:03 +000010123#ifdef TARGET_NR_accept
10124 case TARGET_NR_accept:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010125 return do_accept4(arg1, arg2, arg3, 0);
Peter Maydella94b4982013-02-08 04:35:04 +000010126#endif
10127#ifdef TARGET_NR_accept4
10128 case TARGET_NR_accept4:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010129 return do_accept4(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +000010130#endif
10131#ifdef TARGET_NR_bind
10132 case TARGET_NR_bind:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010133 return do_bind(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +000010134#endif
10135#ifdef TARGET_NR_connect
10136 case TARGET_NR_connect:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010137 return do_connect(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +000010138#endif
10139#ifdef TARGET_NR_getpeername
10140 case TARGET_NR_getpeername:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010141 return do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +000010142#endif
10143#ifdef TARGET_NR_getsockname
10144 case TARGET_NR_getsockname:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010145 return do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +000010146#endif
10147#ifdef TARGET_NR_getsockopt
10148 case TARGET_NR_getsockopt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010149 return do_getsockopt(arg1, arg2, arg3, arg4, arg5);
bellard3532fa72006-06-24 15:06:03 +000010150#endif
10151#ifdef TARGET_NR_listen
10152 case TARGET_NR_listen:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010153 return get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +000010154#endif
10155#ifdef TARGET_NR_recv
10156 case TARGET_NR_recv:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010157 return do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +000010158#endif
10159#ifdef TARGET_NR_recvfrom
10160 case TARGET_NR_recvfrom:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010161 return do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +000010162#endif
10163#ifdef TARGET_NR_recvmsg
10164 case TARGET_NR_recvmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010165 return do_sendrecvmsg(arg1, arg2, arg3, 0);
bellard3532fa72006-06-24 15:06:03 +000010166#endif
10167#ifdef TARGET_NR_send
10168 case TARGET_NR_send:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010169 return do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +000010170#endif
10171#ifdef TARGET_NR_sendmsg
10172 case TARGET_NR_sendmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010173 return do_sendrecvmsg(arg1, arg2, arg3, 1);
bellard3532fa72006-06-24 15:06:03 +000010174#endif
Alexander Graff19e00d2014-03-02 19:36:42 +000010175#ifdef TARGET_NR_sendmmsg
10176 case TARGET_NR_sendmmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010177 return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1);
Alistair Francis859e8a82020-03-12 15:13:49 -070010178#endif
10179#ifdef TARGET_NR_recvmmsg
Alexander Graff19e00d2014-03-02 19:36:42 +000010180 case TARGET_NR_recvmmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010181 return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0);
Alexander Graff19e00d2014-03-02 19:36:42 +000010182#endif
bellard3532fa72006-06-24 15:06:03 +000010183#ifdef TARGET_NR_sendto
10184 case TARGET_NR_sendto:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010185 return do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +000010186#endif
10187#ifdef TARGET_NR_shutdown
10188 case TARGET_NR_shutdown:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010189 return get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +000010190#endif
Laurent Vivierf894efd2016-02-21 10:56:23 +010010191#if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
10192 case TARGET_NR_getrandom:
10193 p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
10194 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010195 return -TARGET_EFAULT;
Laurent Vivierf894efd2016-02-21 10:56:23 +010010196 }
10197 ret = get_errno(getrandom(p, arg2, arg3));
10198 unlock_user(p, arg1, ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010199 return ret;
Laurent Vivierf894efd2016-02-21 10:56:23 +010010200#endif
bellard3532fa72006-06-24 15:06:03 +000010201#ifdef TARGET_NR_socket
10202 case TARGET_NR_socket:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010203 return do_socket(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +000010204#endif
10205#ifdef TARGET_NR_socketpair
10206 case TARGET_NR_socketpair:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010207 return do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +000010208#endif
10209#ifdef TARGET_NR_setsockopt
10210 case TARGET_NR_setsockopt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010211 return do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
bellard3532fa72006-06-24 15:06:03 +000010212#endif
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010213#if defined(TARGET_NR_syslog)
bellard31e31b82003-02-18 22:55:36 +000010214 case TARGET_NR_syslog:
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010215 {
10216 int len = arg2;
ths7494b0f2007-02-11 18:26:53 +000010217
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010218 switch (arg1) {
10219 case TARGET_SYSLOG_ACTION_CLOSE: /* Close log */
10220 case TARGET_SYSLOG_ACTION_OPEN: /* Open log */
10221 case TARGET_SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
10222 case TARGET_SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging */
10223 case TARGET_SYSLOG_ACTION_CONSOLE_ON: /* Enable logging */
10224 case TARGET_SYSLOG_ACTION_CONSOLE_LEVEL: /* Set messages level */
10225 case TARGET_SYSLOG_ACTION_SIZE_UNREAD: /* Number of chars */
10226 case TARGET_SYSLOG_ACTION_SIZE_BUFFER: /* Size of the buffer */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010227 return get_errno(sys_syslog((int)arg1, NULL, (int)arg3));
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010228 case TARGET_SYSLOG_ACTION_READ: /* Read from log */
10229 case TARGET_SYSLOG_ACTION_READ_CLEAR: /* Read/clear msgs */
10230 case TARGET_SYSLOG_ACTION_READ_ALL: /* Read last messages */
10231 {
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010232 if (len < 0) {
Richard Henderson259841c2018-08-18 12:01:09 -070010233 return -TARGET_EINVAL;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010234 }
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010235 if (len == 0) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010236 return 0;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010237 }
10238 p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
10239 if (!p) {
Richard Henderson259841c2018-08-18 12:01:09 -070010240 return -TARGET_EFAULT;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010241 }
10242 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
10243 unlock_user(p, arg2, arg3);
10244 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010245 return ret;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010246 default:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010247 return -TARGET_EINVAL;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010248 }
10249 }
10250 break;
10251#endif
bellard31e31b82003-02-18 22:55:36 +000010252 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +000010253 {
bellard66fb9762003-03-23 01:06:05 +000010254 struct itimerval value, ovalue, *pvalue;
10255
pbrook53a59602006-03-25 19:31:22 +000010256 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +000010257 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +000010258 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
10259 || copy_from_user_timeval(&pvalue->it_value,
10260 arg2 + sizeof(struct target_timeval)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010261 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +000010262 } else {
10263 pvalue = NULL;
10264 }
10265 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +000010266 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +000010267 if (copy_to_user_timeval(arg3,
10268 &ovalue.it_interval)
10269 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
10270 &ovalue.it_value))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010271 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +000010272 }
10273 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010274 return ret;
bellard31e31b82003-02-18 22:55:36 +000010275 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +000010276 {
bellard66fb9762003-03-23 01:06:05 +000010277 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +000010278
bellard66fb9762003-03-23 01:06:05 +000010279 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +000010280 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +000010281 if (copy_to_user_timeval(arg2,
10282 &value.it_interval)
10283 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
10284 &value.it_value))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010285 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +000010286 }
10287 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010288 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080010289#ifdef TARGET_NR_stat
bellard31e31b82003-02-18 22:55:36 +000010290 case TARGET_NR_stat:
Richard Henderson2852aaf2018-08-18 12:01:06 -070010291 if (!(p = lock_user_string(arg1))) {
10292 return -TARGET_EFAULT;
10293 }
pbrook53a59602006-03-25 19:31:22 +000010294 ret = get_errno(stat(path(p), &st));
10295 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +000010296 goto do_stat;
Chen Gang704eff62015-08-21 05:37:33 +080010297#endif
10298#ifdef TARGET_NR_lstat
bellard31e31b82003-02-18 22:55:36 +000010299 case TARGET_NR_lstat:
Richard Henderson2852aaf2018-08-18 12:01:06 -070010300 if (!(p = lock_user_string(arg1))) {
10301 return -TARGET_EFAULT;
10302 }
pbrook53a59602006-03-25 19:31:22 +000010303 ret = get_errno(lstat(path(p), &st));
10304 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +000010305 goto do_stat;
Chen Gang704eff62015-08-21 05:37:33 +080010306#endif
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010307#ifdef TARGET_NR_fstat
bellard31e31b82003-02-18 22:55:36 +000010308 case TARGET_NR_fstat:
10309 {
10310 ret = get_errno(fstat(arg1, &st));
Chen Gang704eff62015-08-21 05:37:33 +080010311#if defined(TARGET_NR_stat) || defined(TARGET_NR_lstat)
bellard31e31b82003-02-18 22:55:36 +000010312 do_stat:
Chen Gang704eff62015-08-21 05:37:33 +080010313#endif
bellard31e31b82003-02-18 22:55:36 +000010314 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +000010315 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +000010316
bellard579a97f2007-11-11 14:26:47 +000010317 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010318 return -TARGET_EFAULT;
Ulrich Hecht12727912009-07-24 19:10:32 +020010319 memset(target_st, 0, sizeof(*target_st));
bellardd2fd1af2007-11-14 18:08:56 +000010320 __put_user(st.st_dev, &target_st->st_dev);
10321 __put_user(st.st_ino, &target_st->st_ino);
10322 __put_user(st.st_mode, &target_st->st_mode);
10323 __put_user(st.st_uid, &target_st->st_uid);
10324 __put_user(st.st_gid, &target_st->st_gid);
10325 __put_user(st.st_nlink, &target_st->st_nlink);
10326 __put_user(st.st_rdev, &target_st->st_rdev);
10327 __put_user(st.st_size, &target_st->st_size);
10328 __put_user(st.st_blksize, &target_st->st_blksize);
10329 __put_user(st.st_blocks, &target_st->st_blocks);
10330 __put_user(st.st_atime, &target_st->target_st_atime);
10331 __put_user(st.st_mtime, &target_st->target_st_mtime);
10332 __put_user(st.st_ctime, &target_st->target_st_ctime);
Michael Forneyfebf6fa2021-05-25 20:55:31 -070010333#if defined(HAVE_STRUCT_STAT_ST_ATIM) && defined(TARGET_STAT_HAVE_NSEC)
Chen-Yu Tsai5f992db2019-05-23 00:21:47 +080010334 __put_user(st.st_atim.tv_nsec,
10335 &target_st->target_st_atime_nsec);
10336 __put_user(st.st_mtim.tv_nsec,
10337 &target_st->target_st_mtime_nsec);
10338 __put_user(st.st_ctim.tv_nsec,
10339 &target_st->target_st_ctime_nsec);
10340#endif
pbrook53a59602006-03-25 19:31:22 +000010341 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +000010342 }
10343 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010344 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010345#endif
bellard31e31b82003-02-18 22:55:36 +000010346 case TARGET_NR_vhangup:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010347 return get_errno(vhangup());
bellard42ad6ae2005-01-03 22:48:11 +000010348#ifdef TARGET_NR_syscall
10349 case TARGET_NR_syscall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010350 return do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5,
10351 arg6, arg7, arg8, 0);
bellard42ad6ae2005-01-03 22:48:11 +000010352#endif
Alistair Francis859e8a82020-03-12 15:13:49 -070010353#if defined(TARGET_NR_wait4)
bellard31e31b82003-02-18 22:55:36 +000010354 case TARGET_NR_wait4:
10355 {
10356 int status;
blueswir1992f48a2007-10-14 16:27:31 +000010357 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +000010358 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +000010359 abi_ulong target_rusage = arg4;
Petar Jovanovica39fb272014-04-08 19:24:30 +020010360 abi_long rusage_err;
bellard31e31b82003-02-18 22:55:36 +000010361 if (target_rusage)
10362 rusage_ptr = &rusage;
10363 else
10364 rusage_ptr = NULL;
Timothy E Baldwin4af80a32016-05-12 18:47:49 +010010365 ret = get_errno(safe_wait4(arg1, &status, arg3, rusage_ptr));
bellard31e31b82003-02-18 22:55:36 +000010366 if (!is_error(ret)) {
Alexander Graf53795572011-11-24 00:44:43 +010010367 if (status_ptr && ret) {
pbrook1d9d8b52009-04-16 15:17:02 +000010368 status = host_to_target_waitstatus(status);
bellard2f619692007-11-16 10:46:05 +000010369 if (put_user_s32(status, status_ptr))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010370 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +000010371 }
Petar Jovanovica39fb272014-04-08 19:24:30 +020010372 if (target_rusage) {
10373 rusage_err = host_to_target_rusage(target_rusage, &rusage);
10374 if (rusage_err) {
10375 ret = rusage_err;
10376 }
10377 }
bellard31e31b82003-02-18 22:55:36 +000010378 }
10379 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010380 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070010381#endif
thse5febef2007-04-01 18:31:35 +000010382#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +000010383 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +000010384 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010385 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010386 ret = get_errno(swapoff(p));
10387 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010388 return ret;
thse5febef2007-04-01 18:31:35 +000010389#endif
bellard31e31b82003-02-18 22:55:36 +000010390 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +000010391 {
pbrook53a59602006-03-25 19:31:22 +000010392 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +000010393 struct sysinfo value;
10394 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +000010395 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +000010396 {
bellard579a97f2007-11-11 14:26:47 +000010397 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010398 return -TARGET_EFAULT;
bellarda5448a72004-06-19 16:59:03 +000010399 __put_user(value.uptime, &target_value->uptime);
10400 __put_user(value.loads[0], &target_value->loads[0]);
10401 __put_user(value.loads[1], &target_value->loads[1]);
10402 __put_user(value.loads[2], &target_value->loads[2]);
10403 __put_user(value.totalram, &target_value->totalram);
10404 __put_user(value.freeram, &target_value->freeram);
10405 __put_user(value.sharedram, &target_value->sharedram);
10406 __put_user(value.bufferram, &target_value->bufferram);
10407 __put_user(value.totalswap, &target_value->totalswap);
10408 __put_user(value.freeswap, &target_value->freeswap);
10409 __put_user(value.procs, &target_value->procs);
10410 __put_user(value.totalhigh, &target_value->totalhigh);
10411 __put_user(value.freehigh, &target_value->freehigh);
10412 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +000010413 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +000010414 }
10415 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010416 return ret;
thse5febef2007-04-01 18:31:35 +000010417#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +000010418 case TARGET_NR_ipc:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010419 return do_ipc(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
thse5febef2007-04-01 18:31:35 +000010420#endif
aurel32e5289082009-04-18 16:16:12 +000010421#ifdef TARGET_NR_semget
10422 case TARGET_NR_semget:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010423 return get_errno(semget(arg1, arg2, arg3));
aurel32e5289082009-04-18 16:16:12 +000010424#endif
10425#ifdef TARGET_NR_semop
10426 case TARGET_NR_semop:
Filip Bozutacac46eb2020-08-25 00:30:50 +020010427 return do_semtimedop(arg1, arg2, arg3, 0, false);
Matus Kyseld8c08b12020-06-26 14:46:11 +020010428#endif
10429#ifdef TARGET_NR_semtimedop
10430 case TARGET_NR_semtimedop:
Filip Bozutacac46eb2020-08-25 00:30:50 +020010431 return do_semtimedop(arg1, arg2, arg3, arg4, false);
10432#endif
10433#ifdef TARGET_NR_semtimedop_time64
10434 case TARGET_NR_semtimedop_time64:
10435 return do_semtimedop(arg1, arg2, arg3, arg4, true);
aurel32e5289082009-04-18 16:16:12 +000010436#endif
10437#ifdef TARGET_NR_semctl
10438 case TARGET_NR_semctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010439 return do_semctl(arg1, arg2, arg3, arg4);
aurel32e5289082009-04-18 16:16:12 +000010440#endif
aurel32eeb438c2008-10-13 21:08:55 +000010441#ifdef TARGET_NR_msgctl
10442 case TARGET_NR_msgctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010443 return do_msgctl(arg1, arg2, arg3);
aurel32eeb438c2008-10-13 21:08:55 +000010444#endif
10445#ifdef TARGET_NR_msgget
10446 case TARGET_NR_msgget:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010447 return get_errno(msgget(arg1, arg2));
aurel32eeb438c2008-10-13 21:08:55 +000010448#endif
10449#ifdef TARGET_NR_msgrcv
10450 case TARGET_NR_msgrcv:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010451 return do_msgrcv(arg1, arg2, arg3, arg4, arg5);
aurel32eeb438c2008-10-13 21:08:55 +000010452#endif
10453#ifdef TARGET_NR_msgsnd
10454 case TARGET_NR_msgsnd:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010455 return do_msgsnd(arg1, arg2, arg3, arg4);
aurel32eeb438c2008-10-13 21:08:55 +000010456#endif
Riku Voipio88a8c982009-04-03 10:42:00 +030010457#ifdef TARGET_NR_shmget
10458 case TARGET_NR_shmget:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010459 return get_errno(shmget(arg1, arg2, arg3));
Riku Voipio88a8c982009-04-03 10:42:00 +030010460#endif
10461#ifdef TARGET_NR_shmctl
10462 case TARGET_NR_shmctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010463 return do_shmctl(arg1, arg2, arg3);
Riku Voipio88a8c982009-04-03 10:42:00 +030010464#endif
10465#ifdef TARGET_NR_shmat
10466 case TARGET_NR_shmat:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010467 return do_shmat(cpu_env, arg1, arg2, arg3);
Riku Voipio88a8c982009-04-03 10:42:00 +030010468#endif
10469#ifdef TARGET_NR_shmdt
10470 case TARGET_NR_shmdt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010471 return do_shmdt(arg1);
Riku Voipio88a8c982009-04-03 10:42:00 +030010472#endif
bellard31e31b82003-02-18 22:55:36 +000010473 case TARGET_NR_fsync:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010474 return get_errno(fsync(arg1));
bellard31e31b82003-02-18 22:55:36 +000010475 case TARGET_NR_clone:
Peter Maydell4ce62432013-07-16 18:44:57 +010010476 /* Linux manages to have three different orderings for its
10477 * arguments to clone(); the BACKWARDS and BACKWARDS2 defines
10478 * match the kernel's CONFIG_CLONE_* settings.
10479 * Microblaze is further special in that it uses a sixth
10480 * implicit argument to clone for the TLS pointer.
10481 */
10482#if defined(TARGET_MICROBLAZE)
Edgar E. Iglesiasa5b3bdc2012-04-26 14:17:41 +020010483 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5));
Peter Maydell4ce62432013-07-16 18:44:57 +010010484#elif defined(TARGET_CLONE_BACKWARDS)
10485 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
10486#elif defined(TARGET_CLONE_BACKWARDS2)
Ulrich Hechta4c075f2009-07-24 16:57:31 +020010487 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
aurel320b6d3ae2008-09-15 07:43:43 +000010488#else
Peter Maydell4ce62432013-07-16 18:44:57 +010010489 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
aurel320b6d3ae2008-09-15 07:43:43 +000010490#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010491 return ret;
bellardec86b0f2003-04-11 00:15:04 +000010492#ifdef __NR_exit_group
10493 /* new thread calls */
10494 case TARGET_NR_exit_group:
Alex Bennée708b6a62018-06-22 17:09:10 +010010495 preexit_cleanup(cpu_env, arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010496 return get_errno(exit_group(arg1));
bellardec86b0f2003-04-11 00:15:04 +000010497#endif
bellard31e31b82003-02-18 22:55:36 +000010498 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +000010499 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010500 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010501 ret = get_errno(setdomainname(p, arg2));
10502 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010503 return ret;
bellard31e31b82003-02-18 22:55:36 +000010504 case TARGET_NR_uname:
10505 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +000010506 {
10507 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +000010508
bellard579a97f2007-11-11 14:26:47 +000010509 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010510 return -TARGET_EFAULT;
bellard29e619b2004-09-13 21:41:04 +000010511 ret = get_errno(sys_uname(buf));
10512 if (!is_error(ret)) {
Peter Maydell332c9782016-07-12 13:02:16 +010010513 /* Overwrite the native machine name with whatever is being
bellard29e619b2004-09-13 21:41:04 +000010514 emulated. */
Philippe Mathieu-Daudé871f95c2017-07-24 15:27:47 -030010515 g_strlcpy(buf->machine, cpu_to_uname_machine(cpu_env),
10516 sizeof(buf->machine));
pbrookc5937222006-05-14 11:30:38 +000010517 /* Allow the user to override the reported release. */
Peter Maydell332c9782016-07-12 13:02:16 +010010518 if (qemu_uname_release && *qemu_uname_release) {
10519 g_strlcpy(buf->release, qemu_uname_release,
10520 sizeof(buf->release));
10521 }
bellard29e619b2004-09-13 21:41:04 +000010522 }
pbrook53a59602006-03-25 19:31:22 +000010523 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +000010524 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010525 return ret;
bellard6dbad632003-03-16 18:05:05 +000010526#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +000010527 case TARGET_NR_modify_ldt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010528 return do_modify_ldt(cpu_env, arg1, arg2, arg3);
j_mayer84409dd2007-04-06 08:56:50 +000010529#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +000010530 case TARGET_NR_vm86:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010531 return do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +000010532#endif
j_mayer84409dd2007-04-06 08:56:50 +000010533#endif
Alistair Francis859e8a82020-03-12 15:13:49 -070010534#if defined(TARGET_NR_adjtimex)
bellard31e31b82003-02-18 22:55:36 +000010535 case TARGET_NR_adjtimex:
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +020010536 {
10537 struct timex host_buf;
10538
10539 if (target_to_host_timex(&host_buf, arg1) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010540 return -TARGET_EFAULT;
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +020010541 }
10542 ret = get_errno(adjtimex(&host_buf));
10543 if (!is_error(ret)) {
10544 if (host_to_target_timex(arg1, &host_buf) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010545 return -TARGET_EFAULT;
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +020010546 }
10547 }
10548 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010549 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070010550#endif
Aleksandar Markovic38860a02016-10-10 13:23:29 +020010551#if defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME)
10552 case TARGET_NR_clock_adjtime:
10553 {
10554 struct timex htx, *phtx = &htx;
10555
10556 if (target_to_host_timex(phtx, arg2) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010557 return -TARGET_EFAULT;
Aleksandar Markovic38860a02016-10-10 13:23:29 +020010558 }
10559 ret = get_errno(clock_adjtime(arg1, phtx));
10560 if (!is_error(ret) && phtx) {
10561 if (host_to_target_timex(arg2, phtx) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010562 return -TARGET_EFAULT;
Aleksandar Markovic38860a02016-10-10 13:23:29 +020010563 }
10564 }
10565 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010566 return ret;
Aleksandar Markovic38860a02016-10-10 13:23:29 +020010567#endif
Filip Bozuta6ac03b22020-08-24 21:21:15 +020010568#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
10569 case TARGET_NR_clock_adjtime64:
10570 {
10571 struct timex htx;
10572
10573 if (target_to_host_timex64(&htx, arg2) != 0) {
10574 return -TARGET_EFAULT;
10575 }
10576 ret = get_errno(clock_adjtime(arg1, &htx));
10577 if (!is_error(ret) && host_to_target_timex64(arg2, &htx)) {
10578 return -TARGET_EFAULT;
10579 }
10580 }
10581 return ret;
10582#endif
bellard31e31b82003-02-18 22:55:36 +000010583 case TARGET_NR_getpgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010584 return get_errno(getpgid(arg1));
bellard31e31b82003-02-18 22:55:36 +000010585 case TARGET_NR_fchdir:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010586 return get_errno(fchdir(arg1));
bellard31e31b82003-02-18 22:55:36 +000010587 case TARGET_NR_personality:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010588 return get_errno(personality(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +000010589#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +000010590 case TARGET_NR__llseek:
10591 {
10592 int64_t res;
Peter Maydell0c1592d2011-02-22 13:02:26 +000010593#if !defined(__NR_llseek)
Peter Maydell9fea2732016-08-11 18:59:39 +010010594 res = lseek(arg1, ((uint64_t)arg2 << 32) | (abi_ulong)arg3, arg5);
Peter Maydell0c1592d2011-02-22 13:02:26 +000010595 if (res == -1) {
10596 ret = get_errno(res);
10597 } else {
10598 ret = 0;
10599 }
10600#else
bellard31e31b82003-02-18 22:55:36 +000010601 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard4f2ac232004-04-26 19:44:02 +000010602#endif
Peter Maydell0c1592d2011-02-22 13:02:26 +000010603 if ((ret == 0) && put_user_s64(res, arg4)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010604 return -TARGET_EFAULT;
Peter Maydell0c1592d2011-02-22 13:02:26 +000010605 }
bellard31e31b82003-02-18 22:55:36 +000010606 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010607 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +000010608#endif
Chen Gang704eff62015-08-21 05:37:33 +080010609#ifdef TARGET_NR_getdents
bellard31e31b82003-02-18 22:55:36 +000010610 case TARGET_NR_getdents:
Richard Hendersonfd08ddb2021-11-14 11:35:36 +010010611 return do_getdents(arg1, arg2, arg3);
Chen Gang704eff62015-08-21 05:37:33 +080010612#endif /* TARGET_NR_getdents */
ths3ae43202007-09-16 21:39:48 +000010613#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +000010614 case TARGET_NR_getdents64:
Richard Hendersonfd08ddb2021-11-14 11:35:36 +010010615 return do_getdents64(arg1, arg2, arg3);
bellarda541f292004-04-12 20:39:29 +000010616#endif /* TARGET_NR_getdents64 */
Laurent Vivier9468a5d2013-01-10 22:30:50 +010010617#if defined(TARGET_NR__newselect)
bellard31e31b82003-02-18 22:55:36 +000010618 case TARGET_NR__newselect:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010619 return do_select(arg1, arg2, arg3, arg4, arg5);
thse5febef2007-04-01 18:31:35 +000010620#endif
Filip Bozutae5ce9682020-08-25 00:30:49 +020010621#ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +000010622 case TARGET_NR_poll:
Filip Bozutae5ce9682020-08-25 00:30:49 +020010623 return do_ppoll(arg1, arg2, arg3, arg4, arg5, false, false);
10624#endif
10625#ifdef TARGET_NR_ppoll
Mike Frysingerd8035d42011-02-07 01:05:51 -050010626 case TARGET_NR_ppoll:
Filip Bozutae5ce9682020-08-25 00:30:49 +020010627 return do_ppoll(arg1, arg2, arg3, arg4, arg5, true, false);
10628#endif
10629#ifdef TARGET_NR_ppoll_time64
10630 case TARGET_NR_ppoll_time64:
10631 return do_ppoll(arg1, arg2, arg3, arg4, arg5, true, true);
thse5febef2007-04-01 18:31:35 +000010632#endif
bellard31e31b82003-02-18 22:55:36 +000010633 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +000010634 /* NOTE: the flock constant seems to be the same for every
10635 Linux platform */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010636 return get_errno(safe_flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +000010637 case TARGET_NR_readv:
10638 {
Richard Hendersonf287b2c2012-09-15 13:20:25 -070010639 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
10640 if (vec != NULL) {
Peter Maydell918c03e2016-06-06 19:58:02 +010010641 ret = get_errno(safe_readv(arg1, vec, arg3));
Richard Hendersonf287b2c2012-09-15 13:20:25 -070010642 unlock_iovec(vec, arg2, arg3, 1);
10643 } else {
10644 ret = -host_to_target_errno(errno);
10645 }
bellard31e31b82003-02-18 22:55:36 +000010646 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010647 return ret;
bellard31e31b82003-02-18 22:55:36 +000010648 case TARGET_NR_writev:
10649 {
Richard Hendersonf287b2c2012-09-15 13:20:25 -070010650 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
10651 if (vec != NULL) {
Peter Maydell918c03e2016-06-06 19:58:02 +010010652 ret = get_errno(safe_writev(arg1, vec, arg3));
Richard Hendersonf287b2c2012-09-15 13:20:25 -070010653 unlock_iovec(vec, arg2, arg3, 0);
10654 } else {
10655 ret = -host_to_target_errno(errno);
10656 }
bellard31e31b82003-02-18 22:55:36 +000010657 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010658 return ret;
Dejan Jovicevic0f263862016-10-11 11:52:46 +020010659#if defined(TARGET_NR_preadv)
10660 case TARGET_NR_preadv:
10661 {
10662 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
10663 if (vec != NULL) {
Max Filippov9ac22512018-04-04 17:30:41 -070010664 unsigned long low, high;
10665
10666 target_to_host_low_high(arg4, arg5, &low, &high);
10667 ret = get_errno(safe_preadv(arg1, vec, arg3, low, high));
Dejan Jovicevic0f263862016-10-11 11:52:46 +020010668 unlock_iovec(vec, arg2, arg3, 1);
10669 } else {
10670 ret = -host_to_target_errno(errno);
10671 }
10672 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010673 return ret;
Dejan Jovicevic0f263862016-10-11 11:52:46 +020010674#endif
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +020010675#if defined(TARGET_NR_pwritev)
10676 case TARGET_NR_pwritev:
10677 {
10678 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
10679 if (vec != NULL) {
Max Filippov9ac22512018-04-04 17:30:41 -070010680 unsigned long low, high;
10681
10682 target_to_host_low_high(arg4, arg5, &low, &high);
10683 ret = get_errno(safe_pwritev(arg1, vec, arg3, low, high));
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +020010684 unlock_iovec(vec, arg2, arg3, 0);
10685 } else {
10686 ret = -host_to_target_errno(errno);
10687 }
10688 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010689 return ret;
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +020010690#endif
bellard31e31b82003-02-18 22:55:36 +000010691 case TARGET_NR_getsid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010692 return get_errno(getsid(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +000010693#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +000010694 case TARGET_NR_fdatasync:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010695 return get_errno(fdatasync(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +000010696#endif
Mike Frysinger737de1d2011-02-07 01:05:55 -050010697 case TARGET_NR_sched_getaffinity:
10698 {
10699 unsigned int mask_size;
10700 unsigned long *mask;
10701
10702 /*
10703 * sched_getaffinity needs multiples of ulong, so need to take
10704 * care of mismatches between target ulong and host ulong sizes.
10705 */
10706 if (arg2 & (sizeof(abi_ulong) - 1)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010707 return -TARGET_EINVAL;
Mike Frysinger737de1d2011-02-07 01:05:55 -050010708 }
10709 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
10710
10711 mask = alloca(mask_size);
Samuel Thibault2e0a8712018-01-09 21:16:43 +010010712 memset(mask, 0, mask_size);
Mike Frysinger737de1d2011-02-07 01:05:55 -050010713 ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
10714
10715 if (!is_error(ret)) {
Peter Maydellbe3bd282014-05-15 14:40:23 +010010716 if (ret > arg2) {
10717 /* More data returned than the caller's buffer will fit.
10718 * This only happens if sizeof(abi_long) < sizeof(long)
10719 * and the caller passed us a buffer holding an odd number
10720 * of abi_longs. If the host kernel is actually using the
10721 * extra 4 bytes then fail EINVAL; otherwise we can just
10722 * ignore them and only copy the interesting part.
10723 */
10724 int numcpus = sysconf(_SC_NPROCESSORS_CONF);
10725 if (numcpus > arg2 * 8) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010726 return -TARGET_EINVAL;
Peter Maydellbe3bd282014-05-15 14:40:23 +010010727 }
10728 ret = arg2;
10729 }
10730
Samuel Thibault5fdefcf2018-02-11 18:47:04 +010010731 if (host_to_target_cpu_mask(mask, mask_size, arg3, ret)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010732 return -TARGET_EFAULT;
Samuel Thibault5fdefcf2018-02-11 18:47:04 +010010733 }
Mike Frysinger737de1d2011-02-07 01:05:55 -050010734 }
10735 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010736 return ret;
Mike Frysinger737de1d2011-02-07 01:05:55 -050010737 case TARGET_NR_sched_setaffinity:
10738 {
10739 unsigned int mask_size;
10740 unsigned long *mask;
10741
10742 /*
10743 * sched_setaffinity needs multiples of ulong, so need to take
10744 * care of mismatches between target ulong and host ulong sizes.
10745 */
10746 if (arg2 & (sizeof(abi_ulong) - 1)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010747 return -TARGET_EINVAL;
Mike Frysinger737de1d2011-02-07 01:05:55 -050010748 }
10749 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
Mike Frysinger737de1d2011-02-07 01:05:55 -050010750 mask = alloca(mask_size);
Samuel Thibault2e0a8712018-01-09 21:16:43 +010010751
10752 ret = target_to_host_cpu_mask(mask, mask_size, arg3, arg2);
10753 if (ret) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010754 return ret;
Mike Frysinger737de1d2011-02-07 01:05:55 -050010755 }
Mike Frysinger737de1d2011-02-07 01:05:55 -050010756
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010757 return get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
Mike Frysinger737de1d2011-02-07 01:05:55 -050010758 }
Samuel Thibaultb827c3e2018-01-12 09:14:35 +010010759 case TARGET_NR_getcpu:
10760 {
10761 unsigned cpu, node;
10762 ret = get_errno(sys_getcpu(arg1 ? &cpu : NULL,
10763 arg2 ? &node : NULL,
10764 NULL));
10765 if (is_error(ret)) {
Richard Henderson259841c2018-08-18 12:01:09 -070010766 return ret;
Samuel Thibaultb827c3e2018-01-12 09:14:35 +010010767 }
10768 if (arg1 && put_user_u32(cpu, arg1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010769 return -TARGET_EFAULT;
Samuel Thibaultb827c3e2018-01-12 09:14:35 +010010770 }
10771 if (arg2 && put_user_u32(node, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010772 return -TARGET_EFAULT;
Samuel Thibaultb827c3e2018-01-12 09:14:35 +010010773 }
10774 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010775 return ret;
bellard31e31b82003-02-18 22:55:36 +000010776 case TARGET_NR_sched_setparam:
bellard5cd43932003-03-29 16:54:36 +000010777 {
Tonis Tiigi407a1192022-01-04 20:18:19 -080010778 struct target_sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +000010779 struct sched_param schp;
pbrook53a59602006-03-25 19:31:22 +000010780
Tom Mustaa1d5c5b2014-08-12 13:53:38 -050010781 if (arg2 == 0) {
10782 return -TARGET_EINVAL;
10783 }
Tonis Tiigi407a1192022-01-04 20:18:19 -080010784 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010785 return -TARGET_EFAULT;
Tonis Tiigi407a1192022-01-04 20:18:19 -080010786 }
bellard5cd43932003-03-29 16:54:36 +000010787 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +000010788 unlock_user_struct(target_schp, arg2, 0);
Tonis Tiigi407a1192022-01-04 20:18:19 -080010789 return get_errno(sys_sched_setparam(arg1, &schp));
bellard5cd43932003-03-29 16:54:36 +000010790 }
bellard31e31b82003-02-18 22:55:36 +000010791 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +000010792 {
Tonis Tiigi407a1192022-01-04 20:18:19 -080010793 struct target_sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +000010794 struct sched_param schp;
Tom Mustaa1d5c5b2014-08-12 13:53:38 -050010795
10796 if (arg2 == 0) {
10797 return -TARGET_EINVAL;
10798 }
Tonis Tiigi407a1192022-01-04 20:18:19 -080010799 ret = get_errno(sys_sched_getparam(arg1, &schp));
bellard5cd43932003-03-29 16:54:36 +000010800 if (!is_error(ret)) {
Tonis Tiigi407a1192022-01-04 20:18:19 -080010801 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010802 return -TARGET_EFAULT;
Tonis Tiigi407a1192022-01-04 20:18:19 -080010803 }
bellard5cd43932003-03-29 16:54:36 +000010804 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +000010805 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +000010806 }
10807 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010808 return ret;
bellard31e31b82003-02-18 22:55:36 +000010809 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +000010810 {
Tonis Tiigi407a1192022-01-04 20:18:19 -080010811 struct target_sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +000010812 struct sched_param schp;
Tom Mustaa1d5c5b2014-08-12 13:53:38 -050010813 if (arg3 == 0) {
10814 return -TARGET_EINVAL;
10815 }
Tonis Tiigi407a1192022-01-04 20:18:19 -080010816 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010817 return -TARGET_EFAULT;
Tonis Tiigi407a1192022-01-04 20:18:19 -080010818 }
bellard5cd43932003-03-29 16:54:36 +000010819 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +000010820 unlock_user_struct(target_schp, arg3, 0);
Tonis Tiigi407a1192022-01-04 20:18:19 -080010821 return get_errno(sys_sched_setscheduler(arg1, arg2, &schp));
bellard5cd43932003-03-29 16:54:36 +000010822 }
bellard31e31b82003-02-18 22:55:36 +000010823 case TARGET_NR_sched_getscheduler:
Tonis Tiigi407a1192022-01-04 20:18:19 -080010824 return get_errno(sys_sched_getscheduler(arg1));
Tonis Tiigi45ad7612022-01-04 20:18:18 -080010825 case TARGET_NR_sched_getattr:
10826 {
10827 struct target_sched_attr *target_scha;
10828 struct sched_attr scha;
10829 if (arg2 == 0) {
10830 return -TARGET_EINVAL;
10831 }
10832 if (arg3 > sizeof(scha)) {
10833 arg3 = sizeof(scha);
10834 }
10835 ret = get_errno(sys_sched_getattr(arg1, &scha, arg3, arg4));
10836 if (!is_error(ret)) {
10837 target_scha = lock_user(VERIFY_WRITE, arg2, arg3, 0);
10838 if (!target_scha) {
10839 return -TARGET_EFAULT;
10840 }
10841 target_scha->size = tswap32(scha.size);
10842 target_scha->sched_policy = tswap32(scha.sched_policy);
10843 target_scha->sched_flags = tswap64(scha.sched_flags);
10844 target_scha->sched_nice = tswap32(scha.sched_nice);
10845 target_scha->sched_priority = tswap32(scha.sched_priority);
10846 target_scha->sched_runtime = tswap64(scha.sched_runtime);
10847 target_scha->sched_deadline = tswap64(scha.sched_deadline);
10848 target_scha->sched_period = tswap64(scha.sched_period);
10849 if (scha.size > offsetof(struct sched_attr, sched_util_min)) {
10850 target_scha->sched_util_min = tswap32(scha.sched_util_min);
10851 target_scha->sched_util_max = tswap32(scha.sched_util_max);
10852 }
10853 unlock_user(target_scha, arg2, arg3);
10854 }
10855 return ret;
10856 }
10857 case TARGET_NR_sched_setattr:
10858 {
10859 struct target_sched_attr *target_scha;
10860 struct sched_attr scha;
10861 uint32_t size;
10862 int zeroed;
10863 if (arg2 == 0) {
10864 return -TARGET_EINVAL;
10865 }
10866 if (get_user_u32(size, arg2)) {
10867 return -TARGET_EFAULT;
10868 }
10869 if (!size) {
10870 size = offsetof(struct target_sched_attr, sched_util_min);
10871 }
10872 if (size < offsetof(struct target_sched_attr, sched_util_min)) {
10873 if (put_user_u32(sizeof(struct target_sched_attr), arg2)) {
10874 return -TARGET_EFAULT;
10875 }
10876 return -TARGET_E2BIG;
10877 }
10878
10879 zeroed = check_zeroed_user(arg2, sizeof(struct target_sched_attr), size);
10880 if (zeroed < 0) {
10881 return zeroed;
10882 } else if (zeroed == 0) {
10883 if (put_user_u32(sizeof(struct target_sched_attr), arg2)) {
10884 return -TARGET_EFAULT;
10885 }
10886 return -TARGET_E2BIG;
10887 }
10888 if (size > sizeof(struct target_sched_attr)) {
10889 size = sizeof(struct target_sched_attr);
10890 }
10891
10892 target_scha = lock_user(VERIFY_READ, arg2, size, 1);
10893 if (!target_scha) {
10894 return -TARGET_EFAULT;
10895 }
10896 scha.size = size;
10897 scha.sched_policy = tswap32(target_scha->sched_policy);
10898 scha.sched_flags = tswap64(target_scha->sched_flags);
10899 scha.sched_nice = tswap32(target_scha->sched_nice);
10900 scha.sched_priority = tswap32(target_scha->sched_priority);
10901 scha.sched_runtime = tswap64(target_scha->sched_runtime);
10902 scha.sched_deadline = tswap64(target_scha->sched_deadline);
10903 scha.sched_period = tswap64(target_scha->sched_period);
10904 if (size > offsetof(struct target_sched_attr, sched_util_min)) {
10905 scha.sched_util_min = tswap32(target_scha->sched_util_min);
10906 scha.sched_util_max = tswap32(target_scha->sched_util_max);
10907 }
10908 unlock_user(target_scha, arg2, 0);
10909 return get_errno(sys_sched_setattr(arg1, &scha, arg3));
10910 }
bellard31e31b82003-02-18 22:55:36 +000010911 case TARGET_NR_sched_yield:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010912 return get_errno(sched_yield());
bellard31e31b82003-02-18 22:55:36 +000010913 case TARGET_NR_sched_get_priority_max:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010914 return get_errno(sched_get_priority_max(arg1));
bellard31e31b82003-02-18 22:55:36 +000010915 case TARGET_NR_sched_get_priority_min:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010916 return get_errno(sched_get_priority_min(arg1));
Alistair Francis859e8a82020-03-12 15:13:49 -070010917#ifdef TARGET_NR_sched_rr_get_interval
bellard31e31b82003-02-18 22:55:36 +000010918 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +000010919 {
bellard5cd43932003-03-29 16:54:36 +000010920 struct timespec ts;
10921 ret = get_errno(sched_rr_get_interval(arg1, &ts));
10922 if (!is_error(ret)) {
Tom Mustad4290c42014-08-12 13:53:39 -050010923 ret = host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +000010924 }
10925 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010926 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070010927#endif
Filip Bozutaddcbde12020-08-24 21:21:16 +020010928#ifdef TARGET_NR_sched_rr_get_interval_time64
10929 case TARGET_NR_sched_rr_get_interval_time64:
10930 {
10931 struct timespec ts;
10932 ret = get_errno(sched_rr_get_interval(arg1, &ts));
10933 if (!is_error(ret)) {
10934 ret = host_to_target_timespec64(arg2, &ts);
10935 }
10936 }
10937 return ret;
10938#endif
Alistair Francis859e8a82020-03-12 15:13:49 -070010939#if defined(TARGET_NR_nanosleep)
bellard31e31b82003-02-18 22:55:36 +000010940 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +000010941 {
bellard1b6b0292003-03-22 17:31:38 +000010942 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +000010943 target_to_host_timespec(&req, arg1);
Peter Maydell9e518222016-06-06 19:58:09 +010010944 ret = get_errno(safe_nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +000010945 if (is_error(ret) && arg2) {
10946 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +000010947 }
10948 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010949 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070010950#endif
bellard31e31b82003-02-18 22:55:36 +000010951 case TARGET_NR_prctl:
Richard Henderson87e9bf22021-12-27 07:01:22 -080010952 return do_prctl(cpu_env, arg1, arg2, arg3, arg4, arg5);
ths39b9aae2007-02-11 18:36:44 +000010953 break;
bellardd2fd1af2007-11-14 18:08:56 +000010954#ifdef TARGET_NR_arch_prctl
10955 case TARGET_NR_arch_prctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010956 return do_arch_prctl(cpu_env, arg1, arg2);
bellardd2fd1af2007-11-14 18:08:56 +000010957#endif
aurel32f2c7ba12008-03-28 22:32:06 +000010958#ifdef TARGET_NR_pread64
10959 case TARGET_NR_pread64:
James Clarke8bf8e9d2017-09-15 20:33:13 +010010960 if (regpairs_aligned(cpu_env, num)) {
Alexander Grafae017a52012-09-29 15:32:39 +000010961 arg4 = arg5;
10962 arg5 = arg6;
10963 }
Peter Maydell2bd3f892019-01-08 18:49:00 +000010964 if (arg2 == 0 && arg3 == 0) {
10965 /* Special-case NULL buffer and zero length, which should succeed */
10966 p = 0;
10967 } else {
10968 p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
10969 if (!p) {
10970 return -TARGET_EFAULT;
10971 }
10972 }
aurel32f2c7ba12008-03-28 22:32:06 +000010973 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
10974 unlock_user(p, arg2, ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010975 return ret;
aurel32f2c7ba12008-03-28 22:32:06 +000010976 case TARGET_NR_pwrite64:
James Clarke8bf8e9d2017-09-15 20:33:13 +010010977 if (regpairs_aligned(cpu_env, num)) {
Alexander Grafae017a52012-09-29 15:32:39 +000010978 arg4 = arg5;
10979 arg5 = arg6;
10980 }
Peter Maydell2bd3f892019-01-08 18:49:00 +000010981 if (arg2 == 0 && arg3 == 0) {
10982 /* Special-case NULL buffer and zero length, which should succeed */
10983 p = 0;
10984 } else {
10985 p = lock_user(VERIFY_READ, arg2, arg3, 1);
10986 if (!p) {
10987 return -TARGET_EFAULT;
10988 }
10989 }
aurel32f2c7ba12008-03-28 22:32:06 +000010990 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
10991 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010992 return ret;
aurel32f2c7ba12008-03-28 22:32:06 +000010993#endif
bellard31e31b82003-02-18 22:55:36 +000010994 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +000010995 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010996 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010997 ret = get_errno(sys_getcwd1(p, arg2));
10998 unlock_user(p, arg1, ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010999 return ret;
bellard31e31b82003-02-18 22:55:36 +000011000 case TARGET_NR_capget:
11001 case TARGET_NR_capset:
Peter Maydelle0eb2102014-03-17 12:15:35 +000011002 {
11003 struct target_user_cap_header *target_header;
11004 struct target_user_cap_data *target_data = NULL;
11005 struct __user_cap_header_struct header;
11006 struct __user_cap_data_struct data[2];
11007 struct __user_cap_data_struct *dataptr = NULL;
11008 int i, target_datalen;
11009 int data_items = 1;
11010
11011 if (!lock_user_struct(VERIFY_WRITE, target_header, arg1, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011012 return -TARGET_EFAULT;
Peter Maydelle0eb2102014-03-17 12:15:35 +000011013 }
11014 header.version = tswap32(target_header->version);
11015 header.pid = tswap32(target_header->pid);
11016
Peter Maydellec864872014-03-19 16:07:30 +000011017 if (header.version != _LINUX_CAPABILITY_VERSION) {
Peter Maydelle0eb2102014-03-17 12:15:35 +000011018 /* Version 2 and up takes pointer to two user_data structs */
11019 data_items = 2;
11020 }
11021
11022 target_datalen = sizeof(*target_data) * data_items;
11023
11024 if (arg2) {
11025 if (num == TARGET_NR_capget) {
11026 target_data = lock_user(VERIFY_WRITE, arg2, target_datalen, 0);
11027 } else {
11028 target_data = lock_user(VERIFY_READ, arg2, target_datalen, 1);
11029 }
11030 if (!target_data) {
11031 unlock_user_struct(target_header, arg1, 0);
Richard Henderson2852aaf2018-08-18 12:01:06 -070011032 return -TARGET_EFAULT;
Peter Maydelle0eb2102014-03-17 12:15:35 +000011033 }
11034
11035 if (num == TARGET_NR_capset) {
11036 for (i = 0; i < data_items; i++) {
11037 data[i].effective = tswap32(target_data[i].effective);
11038 data[i].permitted = tswap32(target_data[i].permitted);
11039 data[i].inheritable = tswap32(target_data[i].inheritable);
11040 }
11041 }
11042
11043 dataptr = data;
11044 }
11045
11046 if (num == TARGET_NR_capget) {
11047 ret = get_errno(capget(&header, dataptr));
11048 } else {
11049 ret = get_errno(capset(&header, dataptr));
11050 }
11051
11052 /* The kernel always updates version for both capget and capset */
11053 target_header->version = tswap32(header.version);
11054 unlock_user_struct(target_header, arg1, 1);
11055
11056 if (arg2) {
11057 if (num == TARGET_NR_capget) {
11058 for (i = 0; i < data_items; i++) {
11059 target_data[i].effective = tswap32(data[i].effective);
11060 target_data[i].permitted = tswap32(data[i].permitted);
11061 target_data[i].inheritable = tswap32(data[i].inheritable);
11062 }
11063 unlock_user(target_data, arg2, target_datalen);
11064 } else {
11065 unlock_user(target_data, arg2, 0);
11066 }
11067 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011068 return ret;
Peter Maydelle0eb2102014-03-17 12:15:35 +000011069 }
bellard31e31b82003-02-18 22:55:36 +000011070 case TARGET_NR_sigaltstack:
Richard Henderson6b208752021-04-25 19:53:12 -070011071 return do_sigaltstack(arg1, arg2, cpu_env);
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011072
11073#ifdef CONFIG_SENDFILE
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020011074#ifdef TARGET_NR_sendfile
bellard31e31b82003-02-18 22:55:36 +000011075 case TARGET_NR_sendfile:
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011076 {
11077 off_t *offp = NULL;
11078 off_t off;
11079 if (arg3) {
11080 ret = get_user_sal(off, arg3);
11081 if (is_error(ret)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011082 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011083 }
11084 offp = &off;
11085 }
11086 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
11087 if (!is_error(ret) && arg3) {
11088 abi_long ret2 = put_user_sal(off, arg3);
11089 if (is_error(ret2)) {
11090 ret = ret2;
11091 }
11092 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011093 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011094 }
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020011095#endif
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011096#ifdef TARGET_NR_sendfile64
11097 case TARGET_NR_sendfile64:
11098 {
11099 off_t *offp = NULL;
11100 off_t off;
11101 if (arg3) {
11102 ret = get_user_s64(off, arg3);
11103 if (is_error(ret)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011104 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011105 }
11106 offp = &off;
11107 }
11108 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
11109 if (!is_error(ret) && arg3) {
11110 abi_long ret2 = put_user_s64(off, arg3);
11111 if (is_error(ret2)) {
11112 ret = ret2;
11113 }
11114 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011115 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011116 }
11117#endif
bellardebc05482003-09-30 21:08:41 +000011118#endif
bellard048f6b42005-11-26 18:47:20 +000011119#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +000011120 case TARGET_NR_vfork:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011121 return get_errno(do_fork(cpu_env,
11122 CLONE_VFORK | CLONE_VM | TARGET_SIGCHLD,
11123 0, 0, 0, 0));
bellard048f6b42005-11-26 18:47:20 +000011124#endif
bellardebc05482003-09-30 21:08:41 +000011125#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +000011126 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +000011127 {
11128 struct rlimit rlim;
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +030011129 int resource = target_to_host_resource(arg1);
11130 ret = get_errno(getrlimit(resource, &rlim));
bellard728584b2003-04-29 20:43:36 +000011131 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +000011132 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +000011133 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011134 return -TARGET_EFAULT;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +090011135 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
11136 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +000011137 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +000011138 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011139 return ret;
bellard728584b2003-04-29 20:43:36 +000011140 }
bellardebc05482003-09-30 21:08:41 +000011141#endif
bellarda315a142005-01-30 22:59:18 +000011142#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +000011143 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +000011144 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011145 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011146 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
11147 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011148 return ret;
bellarda315a142005-01-30 22:59:18 +000011149#endif
11150#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +000011151 case TARGET_NR_ftruncate64:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011152 return target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellarda315a142005-01-30 22:59:18 +000011153#endif
11154#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +000011155 case TARGET_NR_stat64:
Richard Henderson2852aaf2018-08-18 12:01:06 -070011156 if (!(p = lock_user_string(arg1))) {
11157 return -TARGET_EFAULT;
11158 }
pbrook53a59602006-03-25 19:31:22 +000011159 ret = get_errno(stat(path(p), &st));
11160 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +000011161 if (!is_error(ret))
11162 ret = host_to_target_stat64(cpu_env, arg2, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011163 return ret;
bellarda315a142005-01-30 22:59:18 +000011164#endif
11165#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +000011166 case TARGET_NR_lstat64:
Richard Henderson2852aaf2018-08-18 12:01:06 -070011167 if (!(p = lock_user_string(arg1))) {
11168 return -TARGET_EFAULT;
11169 }
pbrook53a59602006-03-25 19:31:22 +000011170 ret = get_errno(lstat(path(p), &st));
11171 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +000011172 if (!is_error(ret))
11173 ret = host_to_target_stat64(cpu_env, arg2, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011174 return ret;
bellarda315a142005-01-30 22:59:18 +000011175#endif
11176#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +000011177 case TARGET_NR_fstat64:
balrog6a24a772008-09-20 02:23:36 +000011178 ret = get_errno(fstat(arg1, &st));
11179 if (!is_error(ret))
11180 ret = host_to_target_stat64(cpu_env, arg2, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011181 return ret;
bellardec86b0f2003-04-11 00:15:04 +000011182#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +010011183#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat))
aurel329d33b762009-04-08 23:07:05 +000011184#ifdef TARGET_NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +000011185 case TARGET_NR_fstatat64:
aurel329d33b762009-04-08 23:07:05 +000011186#endif
11187#ifdef TARGET_NR_newfstatat
11188 case TARGET_NR_newfstatat:
11189#endif
Richard Henderson2852aaf2018-08-18 12:01:06 -070011190 if (!(p = lock_user_string(arg2))) {
11191 return -TARGET_EFAULT;
11192 }
Peter Maydellc0d472b2013-06-12 16:20:21 +010011193 ret = get_errno(fstatat(arg1, path(p), &st, arg4));
Richard Henderson2852aaf2018-08-18 12:01:06 -070011194 unlock_user(p, arg2, 0);
balrog6a24a772008-09-20 02:23:36 +000011195 if (!is_error(ret))
11196 ret = host_to_target_stat64(cpu_env, arg3, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011197 return ret;
bellarda315a142005-01-30 22:59:18 +000011198#endif
Aleksandar Rikaloefa92182019-06-28 12:43:34 +020011199#if defined(TARGET_NR_statx)
11200 case TARGET_NR_statx:
11201 {
11202 struct target_statx *target_stx;
11203 int dirfd = arg1;
11204 int flags = arg3;
11205
11206 p = lock_user_string(arg2);
11207 if (p == NULL) {
11208 return -TARGET_EFAULT;
11209 }
11210#if defined(__NR_statx)
11211 {
11212 /*
11213 * It is assumed that struct statx is architecture independent.
11214 */
11215 struct target_statx host_stx;
11216 int mask = arg4;
11217
11218 ret = get_errno(sys_statx(dirfd, p, flags, mask, &host_stx));
11219 if (!is_error(ret)) {
11220 if (host_to_target_statx(&host_stx, arg5) != 0) {
11221 unlock_user(p, arg2, 0);
11222 return -TARGET_EFAULT;
11223 }
11224 }
11225
11226 if (ret != -TARGET_ENOSYS) {
11227 unlock_user(p, arg2, 0);
11228 return ret;
11229 }
11230 }
11231#endif
11232 ret = get_errno(fstatat(dirfd, path(p), &st, flags));
11233 unlock_user(p, arg2, 0);
11234
11235 if (!is_error(ret)) {
11236 if (!lock_user_struct(VERIFY_WRITE, target_stx, arg5, 0)) {
11237 return -TARGET_EFAULT;
11238 }
11239 memset(target_stx, 0, sizeof(*target_stx));
11240 __put_user(major(st.st_dev), &target_stx->stx_dev_major);
11241 __put_user(minor(st.st_dev), &target_stx->stx_dev_minor);
11242 __put_user(st.st_ino, &target_stx->stx_ino);
11243 __put_user(st.st_mode, &target_stx->stx_mode);
11244 __put_user(st.st_uid, &target_stx->stx_uid);
11245 __put_user(st.st_gid, &target_stx->stx_gid);
11246 __put_user(st.st_nlink, &target_stx->stx_nlink);
11247 __put_user(major(st.st_rdev), &target_stx->stx_rdev_major);
11248 __put_user(minor(st.st_rdev), &target_stx->stx_rdev_minor);
11249 __put_user(st.st_size, &target_stx->stx_size);
11250 __put_user(st.st_blksize, &target_stx->stx_blksize);
11251 __put_user(st.st_blocks, &target_stx->stx_blocks);
11252 __put_user(st.st_atime, &target_stx->stx_atime.tv_sec);
11253 __put_user(st.st_mtime, &target_stx->stx_mtime.tv_sec);
11254 __put_user(st.st_ctime, &target_stx->stx_ctime.tv_sec);
11255 unlock_user_struct(target_stx, arg5, 1);
11256 }
11257 }
11258 return ret;
11259#endif
Chen Gang704eff62015-08-21 05:37:33 +080011260#ifdef TARGET_NR_lchown
bellard67867302003-11-23 17:05:30 +000011261 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +000011262 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011263 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011264 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
11265 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011266 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080011267#endif
Riku Voipio0c866a72011-04-18 15:23:06 +030011268#ifdef TARGET_NR_getuid
bellard67867302003-11-23 17:05:30 +000011269 case TARGET_NR_getuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011270 return get_errno(high2lowuid(getuid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030011271#endif
11272#ifdef TARGET_NR_getgid
bellard67867302003-11-23 17:05:30 +000011273 case TARGET_NR_getgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011274 return get_errno(high2lowgid(getgid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030011275#endif
11276#ifdef TARGET_NR_geteuid
bellard67867302003-11-23 17:05:30 +000011277 case TARGET_NR_geteuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011278 return get_errno(high2lowuid(geteuid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030011279#endif
11280#ifdef TARGET_NR_getegid
bellard67867302003-11-23 17:05:30 +000011281 case TARGET_NR_getegid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011282 return get_errno(high2lowgid(getegid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030011283#endif
bellard67867302003-11-23 17:05:30 +000011284 case TARGET_NR_setreuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011285 return get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
bellard67867302003-11-23 17:05:30 +000011286 case TARGET_NR_setregid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011287 return get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
bellard67867302003-11-23 17:05:30 +000011288 case TARGET_NR_getgroups:
11289 {
11290 int gidsetsize = arg1;
Riku Voipio0c866a72011-04-18 15:23:06 +030011291 target_id *target_grouplist;
bellard67867302003-11-23 17:05:30 +000011292 gid_t *grouplist;
11293 int i;
11294
11295 grouplist = alloca(gidsetsize * sizeof(gid_t));
11296 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +000011297 if (gidsetsize == 0)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011298 return ret;
bellard67867302003-11-23 17:05:30 +000011299 if (!is_error(ret)) {
Andreas Schwab03903ff2013-04-09 05:41:33 +000011300 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * sizeof(target_id), 0);
bellard579a97f2007-11-11 14:26:47 +000011301 if (!target_grouplist)
Richard Henderson2852aaf2018-08-18 12:01:06 -070011302 return -TARGET_EFAULT;
balroga2155fc2008-09-20 02:12:08 +000011303 for(i = 0;i < ret; i++)
Riku Voipio0c866a72011-04-18 15:23:06 +030011304 target_grouplist[i] = tswapid(high2lowgid(grouplist[i]));
Andreas Schwab03903ff2013-04-09 05:41:33 +000011305 unlock_user(target_grouplist, arg2, gidsetsize * sizeof(target_id));
bellard67867302003-11-23 17:05:30 +000011306 }
11307 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011308 return ret;
bellard67867302003-11-23 17:05:30 +000011309 case TARGET_NR_setgroups:
11310 {
11311 int gidsetsize = arg1;
Riku Voipio0c866a72011-04-18 15:23:06 +030011312 target_id *target_grouplist;
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050011313 gid_t *grouplist = NULL;
bellard67867302003-11-23 17:05:30 +000011314 int i;
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050011315 if (gidsetsize) {
11316 grouplist = alloca(gidsetsize * sizeof(gid_t));
Andreas Schwab03903ff2013-04-09 05:41:33 +000011317 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * sizeof(target_id), 1);
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050011318 if (!target_grouplist) {
Richard Henderson259841c2018-08-18 12:01:09 -070011319 return -TARGET_EFAULT;
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050011320 }
11321 for (i = 0; i < gidsetsize; i++) {
11322 grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
11323 }
11324 unlock_user(target_grouplist, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +000011325 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011326 return get_errno(setgroups(gidsetsize, grouplist));
bellard67867302003-11-23 17:05:30 +000011327 }
bellard67867302003-11-23 17:05:30 +000011328 case TARGET_NR_fchown:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011329 return get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
Peter Maydellc0d472b2013-06-12 16:20:21 +010011330#if defined(TARGET_NR_fchownat)
thsccfa72b2007-09-24 09:23:34 +000011331 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +000011332 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011333 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +010011334 ret = get_errno(fchownat(arg1, p, low2highuid(arg3),
11335 low2highgid(arg4), arg5));
bellard579a97f2007-11-11 14:26:47 +000011336 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011337 return ret;
thsccfa72b2007-09-24 09:23:34 +000011338#endif
bellard67867302003-11-23 17:05:30 +000011339#ifdef TARGET_NR_setresuid
11340 case TARGET_NR_setresuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011341 return get_errno(sys_setresuid(low2highuid(arg1),
11342 low2highuid(arg2),
11343 low2highuid(arg3)));
bellard67867302003-11-23 17:05:30 +000011344#endif
11345#ifdef TARGET_NR_getresuid
11346 case TARGET_NR_getresuid:
11347 {
pbrook53a59602006-03-25 19:31:22 +000011348 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +000011349 ret = get_errno(getresuid(&ruid, &euid, &suid));
11350 if (!is_error(ret)) {
Peter Maydell76ca3102014-03-02 19:36:41 +000011351 if (put_user_id(high2lowuid(ruid), arg1)
11352 || put_user_id(high2lowuid(euid), arg2)
11353 || put_user_id(high2lowuid(suid), arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011354 return -TARGET_EFAULT;
bellard67867302003-11-23 17:05:30 +000011355 }
11356 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011357 return ret;
bellard67867302003-11-23 17:05:30 +000011358#endif
11359#ifdef TARGET_NR_getresgid
11360 case TARGET_NR_setresgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011361 return get_errno(sys_setresgid(low2highgid(arg1),
11362 low2highgid(arg2),
11363 low2highgid(arg3)));
bellard67867302003-11-23 17:05:30 +000011364#endif
11365#ifdef TARGET_NR_getresgid
11366 case TARGET_NR_getresgid:
11367 {
pbrook53a59602006-03-25 19:31:22 +000011368 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +000011369 ret = get_errno(getresgid(&rgid, &egid, &sgid));
11370 if (!is_error(ret)) {
Peter Maydell76ca3102014-03-02 19:36:41 +000011371 if (put_user_id(high2lowgid(rgid), arg1)
11372 || put_user_id(high2lowgid(egid), arg2)
11373 || put_user_id(high2lowgid(sgid), arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011374 return -TARGET_EFAULT;
bellard67867302003-11-23 17:05:30 +000011375 }
11376 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011377 return ret;
bellard67867302003-11-23 17:05:30 +000011378#endif
Chen Gang704eff62015-08-21 05:37:33 +080011379#ifdef TARGET_NR_chown
bellard67867302003-11-23 17:05:30 +000011380 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +000011381 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011382 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011383 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
11384 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011385 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080011386#endif
bellard67867302003-11-23 17:05:30 +000011387 case TARGET_NR_setuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011388 return get_errno(sys_setuid(low2highuid(arg1)));
bellard67867302003-11-23 17:05:30 +000011389 case TARGET_NR_setgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011390 return get_errno(sys_setgid(low2highgid(arg1)));
bellard67867302003-11-23 17:05:30 +000011391 case TARGET_NR_setfsuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011392 return get_errno(setfsuid(arg1));
bellard67867302003-11-23 17:05:30 +000011393 case TARGET_NR_setfsgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011394 return get_errno(setfsgid(arg1));
bellard67867302003-11-23 17:05:30 +000011395
bellarda315a142005-01-30 22:59:18 +000011396#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +000011397 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +000011398 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011399 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011400 ret = get_errno(lchown(p, arg2, arg3));
11401 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011402 return ret;
bellarda315a142005-01-30 22:59:18 +000011403#endif
11404#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +000011405 case TARGET_NR_getuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011406 return get_errno(getuid());
bellarda315a142005-01-30 22:59:18 +000011407#endif
aurel3264b4d282008-11-14 17:20:15 +000011408
11409#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
11410 /* Alpha specific */
11411 case TARGET_NR_getxuid:
Richard Hendersonba0e2762009-12-09 15:56:29 -080011412 {
11413 uid_t euid;
11414 euid=geteuid();
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020011415 cpu_env->ir[IR_A4]=euid;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011416 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011417 return get_errno(getuid());
aurel3264b4d282008-11-14 17:20:15 +000011418#endif
11419#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
11420 /* Alpha specific */
11421 case TARGET_NR_getxgid:
Richard Hendersonba0e2762009-12-09 15:56:29 -080011422 {
11423 uid_t egid;
11424 egid=getegid();
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020011425 cpu_env->ir[IR_A4]=egid;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011426 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011427 return get_errno(getgid());
aurel3264b4d282008-11-14 17:20:15 +000011428#endif
Richard Hendersonba0e2762009-12-09 15:56:29 -080011429#if defined(TARGET_NR_osf_getsysinfo) && defined(TARGET_ALPHA)
11430 /* Alpha specific */
11431 case TARGET_NR_osf_getsysinfo:
11432 ret = -TARGET_EOPNOTSUPP;
11433 switch (arg1) {
11434 case TARGET_GSI_IEEE_FP_CONTROL:
11435 {
Richard Henderson21ba8562019-04-26 15:20:51 -070011436 uint64_t fpcr = cpu_alpha_load_fpcr(cpu_env);
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020011437 uint64_t swcr = cpu_env->swcr;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011438
Richard Henderson21ba8562019-04-26 15:20:51 -070011439 swcr &= ~SWCR_STATUS_MASK;
11440 swcr |= (fpcr >> 35) & SWCR_STATUS_MASK;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011441
11442 if (put_user_u64 (swcr, arg2))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011443 return -TARGET_EFAULT;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011444 ret = 0;
11445 }
11446 break;
11447
11448 /* case GSI_IEEE_STATE_AT_SIGNAL:
11449 -- Not implemented in linux kernel.
11450 case GSI_UACPROC:
11451 -- Retrieves current unaligned access state; not much used.
11452 case GSI_PROC_TYPE:
11453 -- Retrieves implver information; surely not used.
11454 case GSI_GET_HWRPB:
11455 -- Grabs a copy of the HWRPB; surely not used.
11456 */
11457 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011458 return ret;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011459#endif
11460#if defined(TARGET_NR_osf_setsysinfo) && defined(TARGET_ALPHA)
11461 /* Alpha specific */
11462 case TARGET_NR_osf_setsysinfo:
11463 ret = -TARGET_EOPNOTSUPP;
11464 switch (arg1) {
11465 case TARGET_SSI_IEEE_FP_CONTROL:
Richard Hendersonba0e2762009-12-09 15:56:29 -080011466 {
Richard Henderson21ba8562019-04-26 15:20:51 -070011467 uint64_t swcr, fpcr;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011468
Richard Henderson6e06d512012-06-01 09:08:21 -070011469 if (get_user_u64 (swcr, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011470 return -TARGET_EFAULT;
Richard Henderson6e06d512012-06-01 09:08:21 -070011471 }
Richard Hendersonba0e2762009-12-09 15:56:29 -080011472
Richard Henderson21ba8562019-04-26 15:20:51 -070011473 /*
11474 * The kernel calls swcr_update_status to update the
11475 * status bits from the fpcr at every point that it
11476 * could be queried. Therefore, we store the status
11477 * bits only in FPCR.
11478 */
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020011479 cpu_env->swcr = swcr & (SWCR_TRAP_ENABLE_MASK | SWCR_MAP_MASK);
Richard Hendersonba0e2762009-12-09 15:56:29 -080011480
Richard Henderson21ba8562019-04-26 15:20:51 -070011481 fpcr = cpu_alpha_load_fpcr(cpu_env);
11482 fpcr &= ((uint64_t)FPCR_DYN_MASK << 32);
11483 fpcr |= alpha_ieee_swcr_to_fpcr(swcr);
Richard Henderson6e06d512012-06-01 09:08:21 -070011484 cpu_alpha_store_fpcr(cpu_env, fpcr);
11485 ret = 0;
11486 }
11487 break;
11488
11489 case TARGET_SSI_IEEE_RAISE_EXCEPTION:
11490 {
Richard Henderson21ba8562019-04-26 15:20:51 -070011491 uint64_t exc, fpcr, fex;
Richard Henderson6e06d512012-06-01 09:08:21 -070011492
11493 if (get_user_u64(exc, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011494 return -TARGET_EFAULT;
Richard Henderson6e06d512012-06-01 09:08:21 -070011495 }
Richard Henderson21ba8562019-04-26 15:20:51 -070011496 exc &= SWCR_STATUS_MASK;
11497 fpcr = cpu_alpha_load_fpcr(cpu_env);
Richard Hendersonba0e2762009-12-09 15:56:29 -080011498
Richard Henderson6e06d512012-06-01 09:08:21 -070011499 /* Old exceptions are not signaled. */
Richard Henderson21ba8562019-04-26 15:20:51 -070011500 fex = alpha_ieee_fpcr_to_swcr(fpcr);
11501 fex = exc & ~fex;
11502 fex >>= SWCR_STATUS_TO_EXCSUM_SHIFT;
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020011503 fex &= (cpu_env)->swcr;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011504
Richard Henderson21ba8562019-04-26 15:20:51 -070011505 /* Update the hardware fpcr. */
11506 fpcr |= alpha_ieee_swcr_to_fpcr(exc);
11507 cpu_alpha_store_fpcr(cpu_env, fpcr);
11508
11509 if (fex) {
11510 int si_code = TARGET_FPE_FLTUNK;
Richard Henderson6e06d512012-06-01 09:08:21 -070011511 target_siginfo_t info;
Richard Henderson21ba8562019-04-26 15:20:51 -070011512
11513 if (fex & SWCR_TRAP_ENABLE_DNO) {
11514 si_code = TARGET_FPE_FLTUND;
11515 }
11516 if (fex & SWCR_TRAP_ENABLE_INE) {
11517 si_code = TARGET_FPE_FLTRES;
11518 }
11519 if (fex & SWCR_TRAP_ENABLE_UNF) {
11520 si_code = TARGET_FPE_FLTUND;
11521 }
11522 if (fex & SWCR_TRAP_ENABLE_OVF) {
11523 si_code = TARGET_FPE_FLTOVF;
11524 }
11525 if (fex & SWCR_TRAP_ENABLE_DZE) {
11526 si_code = TARGET_FPE_FLTDIV;
11527 }
11528 if (fex & SWCR_TRAP_ENABLE_INV) {
11529 si_code = TARGET_FPE_FLTINV;
11530 }
11531
Richard Henderson6e06d512012-06-01 09:08:21 -070011532 info.si_signo = SIGFPE;
11533 info.si_errno = 0;
11534 info.si_code = si_code;
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020011535 info._sifields._sigfault._addr = (cpu_env)->pc;
11536 queue_signal(cpu_env, info.si_signo,
Peter Maydell9d2803f2016-07-28 16:44:46 +010011537 QEMU_SI_FAULT, &info);
Richard Hendersonba0e2762009-12-09 15:56:29 -080011538 }
Richard Henderson21ba8562019-04-26 15:20:51 -070011539 ret = 0;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011540 }
11541 break;
11542
11543 /* case SSI_NVPAIRS:
11544 -- Used with SSIN_UACPROC to enable unaligned accesses.
11545 case SSI_IEEE_STATE_AT_SIGNAL:
11546 case SSI_IEEE_IGNORE_STATE_AT_SIGNAL:
11547 -- Not implemented in linux kernel
11548 */
11549 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011550 return ret;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011551#endif
11552#ifdef TARGET_NR_osf_sigprocmask
11553 /* Alpha specific. */
11554 case TARGET_NR_osf_sigprocmask:
11555 {
11556 abi_ulong mask;
Juan Quintelabc088ba2011-06-16 17:37:10 +010011557 int how;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011558 sigset_t set, oldset;
11559
11560 switch(arg1) {
11561 case TARGET_SIG_BLOCK:
11562 how = SIG_BLOCK;
11563 break;
11564 case TARGET_SIG_UNBLOCK:
11565 how = SIG_UNBLOCK;
11566 break;
11567 case TARGET_SIG_SETMASK:
11568 how = SIG_SETMASK;
11569 break;
11570 default:
Richard Henderson259841c2018-08-18 12:01:09 -070011571 return -TARGET_EINVAL;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011572 }
11573 mask = arg2;
11574 target_to_host_old_sigset(&set, &mask);
Peter Maydell3d3efba2016-05-27 15:51:49 +010011575 ret = do_sigprocmask(how, &set, &oldset);
11576 if (!ret) {
11577 host_to_target_old_sigset(&mask, &oldset);
11578 ret = mask;
11579 }
Richard Hendersonba0e2762009-12-09 15:56:29 -080011580 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011581 return ret;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011582#endif
aurel3264b4d282008-11-14 17:20:15 +000011583
bellarda315a142005-01-30 22:59:18 +000011584#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +000011585 case TARGET_NR_getgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011586 return get_errno(getgid());
bellarda315a142005-01-30 22:59:18 +000011587#endif
11588#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +000011589 case TARGET_NR_geteuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011590 return get_errno(geteuid());
bellarda315a142005-01-30 22:59:18 +000011591#endif
11592#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +000011593 case TARGET_NR_getegid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011594 return get_errno(getegid());
bellarda315a142005-01-30 22:59:18 +000011595#endif
11596#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +000011597 case TARGET_NR_setreuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011598 return get_errno(setreuid(arg1, arg2));
bellarda315a142005-01-30 22:59:18 +000011599#endif
11600#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +000011601 case TARGET_NR_setregid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011602 return get_errno(setregid(arg1, arg2));
bellarda315a142005-01-30 22:59:18 +000011603#endif
11604#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +000011605 case TARGET_NR_getgroups32:
bellard99c475a2005-01-31 20:45:13 +000011606 {
11607 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +000011608 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +000011609 gid_t *grouplist;
11610 int i;
11611
11612 grouplist = alloca(gidsetsize * sizeof(gid_t));
11613 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +000011614 if (gidsetsize == 0)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011615 return ret;
bellard99c475a2005-01-31 20:45:13 +000011616 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +000011617 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
11618 if (!target_grouplist) {
Richard Henderson259841c2018-08-18 12:01:09 -070011619 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000011620 }
balroga2155fc2008-09-20 02:12:08 +000011621 for(i = 0;i < ret; i++)
pbrook53a59602006-03-25 19:31:22 +000011622 target_grouplist[i] = tswap32(grouplist[i]);
11623 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +000011624 }
11625 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011626 return ret;
bellarda315a142005-01-30 22:59:18 +000011627#endif
11628#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +000011629 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +000011630 {
11631 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +000011632 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +000011633 gid_t *grouplist;
11634 int i;
ths3b46e622007-09-17 08:09:54 +000011635
bellard99c475a2005-01-31 20:45:13 +000011636 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +000011637 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
11638 if (!target_grouplist) {
Richard Henderson259841c2018-08-18 12:01:09 -070011639 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000011640 }
bellard99c475a2005-01-31 20:45:13 +000011641 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +000011642 grouplist[i] = tswap32(target_grouplist[i]);
11643 unlock_user(target_grouplist, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011644 return get_errno(setgroups(gidsetsize, grouplist));
bellard99c475a2005-01-31 20:45:13 +000011645 }
bellarda315a142005-01-30 22:59:18 +000011646#endif
11647#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +000011648 case TARGET_NR_fchown32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011649 return get_errno(fchown(arg1, arg2, arg3));
bellarda315a142005-01-30 22:59:18 +000011650#endif
11651#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +000011652 case TARGET_NR_setresuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011653 return get_errno(sys_setresuid(arg1, arg2, arg3));
bellarda315a142005-01-30 22:59:18 +000011654#endif
11655#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +000011656 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +000011657 {
pbrook53a59602006-03-25 19:31:22 +000011658 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +000011659 ret = get_errno(getresuid(&ruid, &euid, &suid));
11660 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +000011661 if (put_user_u32(ruid, arg1)
11662 || put_user_u32(euid, arg2)
11663 || put_user_u32(suid, arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011664 return -TARGET_EFAULT;
bellardb03c60f2003-03-23 17:19:56 +000011665 }
11666 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011667 return ret;
bellarda315a142005-01-30 22:59:18 +000011668#endif
11669#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +000011670 case TARGET_NR_setresgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011671 return get_errno(sys_setresgid(arg1, arg2, arg3));
bellarda315a142005-01-30 22:59:18 +000011672#endif
11673#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +000011674 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +000011675 {
pbrook53a59602006-03-25 19:31:22 +000011676 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +000011677 ret = get_errno(getresgid(&rgid, &egid, &sgid));
11678 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +000011679 if (put_user_u32(rgid, arg1)
11680 || put_user_u32(egid, arg2)
11681 || put_user_u32(sgid, arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011682 return -TARGET_EFAULT;
bellardb03c60f2003-03-23 17:19:56 +000011683 }
11684 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011685 return ret;
bellarda315a142005-01-30 22:59:18 +000011686#endif
11687#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +000011688 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +000011689 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011690 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011691 ret = get_errno(chown(p, arg2, arg3));
11692 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011693 return ret;
bellarda315a142005-01-30 22:59:18 +000011694#endif
11695#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +000011696 case TARGET_NR_setuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011697 return get_errno(sys_setuid(arg1));
bellarda315a142005-01-30 22:59:18 +000011698#endif
11699#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +000011700 case TARGET_NR_setgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011701 return get_errno(sys_setgid(arg1));
bellarda315a142005-01-30 22:59:18 +000011702#endif
11703#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +000011704 case TARGET_NR_setfsuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011705 return get_errno(setfsuid(arg1));
bellarda315a142005-01-30 22:59:18 +000011706#endif
11707#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +000011708 case TARGET_NR_setfsgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011709 return get_errno(setfsgid(arg1));
bellarda315a142005-01-30 22:59:18 +000011710#endif
bellardffa65c32004-01-04 23:57:22 +000011711#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +000011712 case TARGET_NR_mincore:
aurel3204bb9ac2008-10-01 21:46:41 +000011713 {
Richard Henderson259841c2018-08-18 12:01:09 -070011714 void *a = lock_user(VERIFY_READ, arg1, arg2, 0);
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000011715 if (!a) {
Richard Henderson259841c2018-08-18 12:01:09 -070011716 return -TARGET_ENOMEM;
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000011717 }
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000011718 p = lock_user_string(arg3);
11719 if (!p) {
Richard Henderson259841c2018-08-18 12:01:09 -070011720 ret = -TARGET_EFAULT;
11721 } else {
11722 ret = get_errno(mincore(a, arg2, p));
11723 unlock_user(p, arg3, ret);
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000011724 }
aurel3204bb9ac2008-10-01 21:46:41 +000011725 unlock_user(a, arg1, 0);
11726 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011727 return ret;
bellardffa65c32004-01-04 23:57:22 +000011728#endif
aurel32408321b2008-10-01 21:46:32 +000011729#ifdef TARGET_NR_arm_fadvise64_64
11730 case TARGET_NR_arm_fadvise64_64:
Peter Maydelle0156a92016-05-31 15:45:09 +010011731 /* arm_fadvise64_64 looks like fadvise64_64 but
11732 * with different argument order: fd, advice, offset, len
11733 * rather than the usual fd, offset, len, advice.
11734 * Note that offset and len are both 64-bit so appear as
11735 * pairs of 32-bit registers.
11736 */
11737 ret = posix_fadvise(arg1, target_offset64(arg3, arg4),
11738 target_offset64(arg5, arg6), arg2);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011739 return -host_to_target_errno(ret);
aurel32408321b2008-10-01 21:46:32 +000011740#endif
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011741
11742#if TARGET_ABI_BITS == 32
11743
11744#ifdef TARGET_NR_fadvise64_64
11745 case TARGET_NR_fadvise64_64:
Max Filippov64a563d2018-04-01 15:02:34 -070011746#if defined(TARGET_PPC) || defined(TARGET_XTENSA)
Laurent Vivier43046b52017-03-02 01:11:45 +010011747 /* 6 args: fd, advice, offset (high, low), len (high, low) */
11748 ret = arg2;
11749 arg2 = arg3;
11750 arg3 = arg4;
11751 arg4 = arg5;
11752 arg5 = arg6;
11753 arg6 = ret;
11754#else
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011755 /* 6 args: fd, offset (high, low), len (high, low), advice */
James Clarke8bf8e9d2017-09-15 20:33:13 +010011756 if (regpairs_aligned(cpu_env, num)) {
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011757 /* offset is in (3,4), len in (5,6) and advice in 7 */
11758 arg2 = arg3;
11759 arg3 = arg4;
11760 arg4 = arg5;
11761 arg5 = arg6;
11762 arg6 = arg7;
11763 }
Laurent Vivier43046b52017-03-02 01:11:45 +010011764#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011765 ret = posix_fadvise(arg1, target_offset64(arg2, arg3),
11766 target_offset64(arg4, arg5), arg6);
11767 return -host_to_target_errno(ret);
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011768#endif
11769
11770#ifdef TARGET_NR_fadvise64
11771 case TARGET_NR_fadvise64:
11772 /* 5 args: fd, offset (high, low), len, advice */
James Clarke8bf8e9d2017-09-15 20:33:13 +010011773 if (regpairs_aligned(cpu_env, num)) {
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011774 /* offset is in (3,4), len in 5 and advice in 6 */
11775 arg2 = arg3;
11776 arg3 = arg4;
11777 arg4 = arg5;
11778 arg5 = arg6;
11779 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011780 ret = posix_fadvise(arg1, target_offset64(arg2, arg3), arg4, arg5);
11781 return -host_to_target_errno(ret);
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011782#endif
11783
11784#else /* not a 32-bit ABI */
Peter Maydelle0156a92016-05-31 15:45:09 +010011785#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_fadvise64)
aurel32408321b2008-10-01 21:46:32 +000011786#ifdef TARGET_NR_fadvise64_64
11787 case TARGET_NR_fadvise64_64:
11788#endif
Ulrich Hechte72d2cc2009-07-24 19:10:31 +020011789#ifdef TARGET_NR_fadvise64
11790 case TARGET_NR_fadvise64:
11791#endif
11792#ifdef TARGET_S390X
11793 switch (arg4) {
11794 case 4: arg4 = POSIX_FADV_NOREUSE + 1; break; /* make sure it's an invalid value */
11795 case 5: arg4 = POSIX_FADV_NOREUSE + 2; break; /* ditto */
11796 case 6: arg4 = POSIX_FADV_DONTNEED; break;
11797 case 7: arg4 = POSIX_FADV_NOREUSE; break;
11798 default: break;
11799 }
11800#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011801 return -host_to_target_errno(posix_fadvise(arg1, arg2, arg3, arg4));
aurel32408321b2008-10-01 21:46:32 +000011802#endif
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011803#endif /* end of 64-bit ABI fadvise handling */
11804
bellardffa65c32004-01-04 23:57:22 +000011805#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +000011806 case TARGET_NR_madvise:
Ilya Leoshkevich892a4f62022-06-21 16:42:05 +020011807 return target_madvise(arg1, arg2, arg3);
bellardffa65c32004-01-04 23:57:22 +000011808#endif
Alex Bennéebbf5f2a2020-04-03 20:11:40 +010011809#ifdef TARGET_NR_fcntl64
bellard31e31b82003-02-18 22:55:36 +000011810 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +000011811 {
Alex Bennéebbf5f2a2020-04-03 20:11:40 +010011812 int cmd;
11813 struct flock64 fl;
Peter Maydell213d3e92016-06-13 11:22:05 +010011814 from_flock64_fn *copyfrom = copy_from_user_flock64;
11815 to_flock64_fn *copyto = copy_to_user_flock64;
11816
pbrookce4defa2006-02-09 16:49:55 +000011817#ifdef TARGET_ARM
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020011818 if (!cpu_env->eabi) {
Laurent Vivier7f254c52018-05-02 23:57:30 +020011819 copyfrom = copy_from_user_oabi_flock64;
11820 copyto = copy_to_user_oabi_flock64;
Peter Maydell213d3e92016-06-13 11:22:05 +010011821 }
pbrookce4defa2006-02-09 16:49:55 +000011822#endif
bellard77e46722003-04-29 20:39:06 +000011823
Alex Bennéebbf5f2a2020-04-03 20:11:40 +010011824 cmd = target_to_host_fcntl_cmd(arg2);
Peter Maydell31b63192011-12-05 23:11:50 +000011825 if (cmd == -TARGET_EINVAL) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011826 return cmd;
Peter Maydell31b63192011-12-05 23:11:50 +000011827 }
thsb1e341e2007-03-20 21:50:52 +000011828
bellard60cd49d2003-03-16 22:53:56 +000011829 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +000011830 case TARGET_F_GETLK64:
Peter Maydell213d3e92016-06-13 11:22:05 +010011831 ret = copyfrom(&fl, arg3);
11832 if (ret) {
11833 break;
ths58134272007-03-31 18:59:32 +000011834 }
Laurent Vivieraf8ab2b2018-07-13 14:58:05 +020011835 ret = get_errno(safe_fcntl(arg1, cmd, &fl));
Peter Maydell213d3e92016-06-13 11:22:05 +010011836 if (ret == 0) {
11837 ret = copyto(arg3, &fl);
11838 }
bellard77e46722003-04-29 20:39:06 +000011839 break;
11840
thsb1e341e2007-03-20 21:50:52 +000011841 case TARGET_F_SETLK64:
11842 case TARGET_F_SETLKW64:
Peter Maydell213d3e92016-06-13 11:22:05 +010011843 ret = copyfrom(&fl, arg3);
11844 if (ret) {
11845 break;
pbrookce4defa2006-02-09 16:49:55 +000011846 }
Peter Maydell435da5e2016-06-13 11:22:05 +010011847 ret = get_errno(safe_fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +000011848 break;
bellard60cd49d2003-03-16 22:53:56 +000011849 default:
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +020011850 ret = do_fcntl(arg1, arg2, arg3);
bellard60cd49d2003-03-16 22:53:56 +000011851 break;
11852 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011853 return ret;
bellard77e46722003-04-29 20:39:06 +000011854 }
bellard60cd49d2003-03-16 22:53:56 +000011855#endif
ths7d600c82006-12-08 01:32:58 +000011856#ifdef TARGET_NR_cacheflush
11857 case TARGET_NR_cacheflush:
11858 /* self-modifying code is handled automatically, so nothing needed */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011859 return 0;
ths7d600c82006-12-08 01:32:58 +000011860#endif
bellardc573ff62004-01-04 15:51:36 +000011861#ifdef TARGET_NR_getpagesize
11862 case TARGET_NR_getpagesize:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011863 return TARGET_PAGE_SIZE;
bellardc573ff62004-01-04 15:51:36 +000011864#endif
bellard31e31b82003-02-18 22:55:36 +000011865 case TARGET_NR_gettid:
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +000011866 return get_errno(sys_gettid());
thse5febef2007-04-01 18:31:35 +000011867#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +000011868 case TARGET_NR_readahead:
aurel322054ac92008-10-13 21:08:07 +000011869#if TARGET_ABI_BITS == 32
James Clarke8bf8e9d2017-09-15 20:33:13 +010011870 if (regpairs_aligned(cpu_env, num)) {
aurel322054ac92008-10-13 21:08:07 +000011871 arg2 = arg3;
11872 arg3 = arg4;
11873 arg4 = arg5;
11874 }
Lena Djokic77c68502016-11-24 17:08:56 +010011875 ret = get_errno(readahead(arg1, target_offset64(arg2, arg3) , arg4));
aurel322054ac92008-10-13 21:08:07 +000011876#else
11877 ret = get_errno(readahead(arg1, arg2, arg3));
11878#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011879 return ret;
thse5febef2007-04-01 18:31:35 +000011880#endif
An-Cheng Huanga790ae32011-08-09 12:34:06 -070011881#ifdef CONFIG_ATTR
bellardebc05482003-09-30 21:08:41 +000011882#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +000011883 case TARGET_NR_listxattr:
11884 case TARGET_NR_llistxattr:
Peter Maydellfb5590f2011-12-14 15:37:19 +000011885 {
11886 void *p, *b = 0;
11887 if (arg2) {
11888 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
11889 if (!b) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011890 return -TARGET_EFAULT;
Peter Maydellfb5590f2011-12-14 15:37:19 +000011891 }
11892 }
11893 p = lock_user_string(arg1);
11894 if (p) {
11895 if (num == TARGET_NR_listxattr) {
11896 ret = get_errno(listxattr(p, b, arg3));
11897 } else {
11898 ret = get_errno(llistxattr(p, b, arg3));
11899 }
11900 } else {
11901 ret = -TARGET_EFAULT;
11902 }
11903 unlock_user(p, arg1, 0);
11904 unlock_user(b, arg2, arg3);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011905 return ret;
Peter Maydellfb5590f2011-12-14 15:37:19 +000011906 }
11907 case TARGET_NR_flistxattr:
11908 {
11909 void *b = 0;
11910 if (arg2) {
11911 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
11912 if (!b) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011913 return -TARGET_EFAULT;
Peter Maydellfb5590f2011-12-14 15:37:19 +000011914 }
11915 }
11916 ret = get_errno(flistxattr(arg1, b, arg3));
11917 unlock_user(b, arg2, arg3);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011918 return ret;
Peter Maydellfb5590f2011-12-14 15:37:19 +000011919 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070011920 case TARGET_NR_setxattr:
Peter Maydell30297b52011-12-14 15:37:18 +000011921 case TARGET_NR_lsetxattr:
An-Cheng Huanga790ae32011-08-09 12:34:06 -070011922 {
Peter Maydelle3c33ec2011-12-14 15:37:17 +000011923 void *p, *n, *v = 0;
11924 if (arg3) {
11925 v = lock_user(VERIFY_READ, arg3, arg4, 1);
11926 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011927 return -TARGET_EFAULT;
Peter Maydelle3c33ec2011-12-14 15:37:17 +000011928 }
11929 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070011930 p = lock_user_string(arg1);
11931 n = lock_user_string(arg2);
Peter Maydelle3c33ec2011-12-14 15:37:17 +000011932 if (p && n) {
Peter Maydell30297b52011-12-14 15:37:18 +000011933 if (num == TARGET_NR_setxattr) {
11934 ret = get_errno(setxattr(p, n, v, arg4, arg5));
11935 } else {
11936 ret = get_errno(lsetxattr(p, n, v, arg4, arg5));
11937 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070011938 } else {
11939 ret = -TARGET_EFAULT;
11940 }
11941 unlock_user(p, arg1, 0);
11942 unlock_user(n, arg2, 0);
11943 unlock_user(v, arg3, 0);
11944 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011945 return ret;
Peter Maydell30297b52011-12-14 15:37:18 +000011946 case TARGET_NR_fsetxattr:
11947 {
11948 void *n, *v = 0;
11949 if (arg3) {
11950 v = lock_user(VERIFY_READ, arg3, arg4, 1);
11951 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011952 return -TARGET_EFAULT;
Peter Maydell30297b52011-12-14 15:37:18 +000011953 }
11954 }
11955 n = lock_user_string(arg2);
11956 if (n) {
11957 ret = get_errno(fsetxattr(arg1, n, v, arg4, arg5));
11958 } else {
11959 ret = -TARGET_EFAULT;
11960 }
11961 unlock_user(n, arg2, 0);
11962 unlock_user(v, arg3, 0);
11963 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011964 return ret;
An-Cheng Huanga790ae32011-08-09 12:34:06 -070011965 case TARGET_NR_getxattr:
Peter Maydell30297b52011-12-14 15:37:18 +000011966 case TARGET_NR_lgetxattr:
An-Cheng Huanga790ae32011-08-09 12:34:06 -070011967 {
Peter Maydelle3c33ec2011-12-14 15:37:17 +000011968 void *p, *n, *v = 0;
11969 if (arg3) {
11970 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
11971 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011972 return -TARGET_EFAULT;
Peter Maydelle3c33ec2011-12-14 15:37:17 +000011973 }
11974 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070011975 p = lock_user_string(arg1);
11976 n = lock_user_string(arg2);
Peter Maydelle3c33ec2011-12-14 15:37:17 +000011977 if (p && n) {
Peter Maydell30297b52011-12-14 15:37:18 +000011978 if (num == TARGET_NR_getxattr) {
11979 ret = get_errno(getxattr(p, n, v, arg4));
11980 } else {
11981 ret = get_errno(lgetxattr(p, n, v, arg4));
11982 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070011983 } else {
11984 ret = -TARGET_EFAULT;
11985 }
11986 unlock_user(p, arg1, 0);
11987 unlock_user(n, arg2, 0);
11988 unlock_user(v, arg3, arg4);
11989 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011990 return ret;
Peter Maydell30297b52011-12-14 15:37:18 +000011991 case TARGET_NR_fgetxattr:
11992 {
11993 void *n, *v = 0;
11994 if (arg3) {
11995 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
11996 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011997 return -TARGET_EFAULT;
Peter Maydell30297b52011-12-14 15:37:18 +000011998 }
11999 }
12000 n = lock_user_string(arg2);
12001 if (n) {
12002 ret = get_errno(fgetxattr(arg1, n, v, arg4));
12003 } else {
12004 ret = -TARGET_EFAULT;
12005 }
12006 unlock_user(n, arg2, 0);
12007 unlock_user(v, arg3, arg4);
12008 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012009 return ret;
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012010 case TARGET_NR_removexattr:
Peter Maydell30297b52011-12-14 15:37:18 +000012011 case TARGET_NR_lremovexattr:
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012012 {
12013 void *p, *n;
12014 p = lock_user_string(arg1);
12015 n = lock_user_string(arg2);
12016 if (p && n) {
Peter Maydell30297b52011-12-14 15:37:18 +000012017 if (num == TARGET_NR_removexattr) {
12018 ret = get_errno(removexattr(p, n));
12019 } else {
12020 ret = get_errno(lremovexattr(p, n));
12021 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012022 } else {
12023 ret = -TARGET_EFAULT;
12024 }
12025 unlock_user(p, arg1, 0);
12026 unlock_user(n, arg2, 0);
12027 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012028 return ret;
Peter Maydell30297b52011-12-14 15:37:18 +000012029 case TARGET_NR_fremovexattr:
12030 {
12031 void *n;
12032 n = lock_user_string(arg2);
12033 if (n) {
12034 ret = get_errno(fremovexattr(arg1, n));
12035 } else {
12036 ret = -TARGET_EFAULT;
12037 }
12038 unlock_user(n, arg2, 0);
12039 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012040 return ret;
bellardebc05482003-09-30 21:08:41 +000012041#endif
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012042#endif /* CONFIG_ATTR */
bellardebc05482003-09-30 21:08:41 +000012043#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +000012044 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +000012045#if defined(TARGET_MIPS)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020012046 cpu_env->active_tc.CP0_UserLocal = arg1;
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012047 return 0;
edgar_iglef967792009-01-07 14:19:38 +000012048#elif defined(TARGET_CRIS)
12049 if (arg1 & 0xff)
12050 ret = -TARGET_EINVAL;
12051 else {
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020012052 cpu_env->pregs[PR_PID] = arg1;
edgar_iglef967792009-01-07 14:19:38 +000012053 ret = 0;
12054 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012055 return ret;
bellard8d18e892007-11-14 15:18:40 +000012056#elif defined(TARGET_I386) && defined(TARGET_ABI32)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012057 return do_set_thread_area(cpu_env, arg1);
Peter Maydell1ccd9372013-07-16 18:44:55 +010012058#elif defined(TARGET_M68K)
12059 {
Andreas Färber0429a972013-08-26 18:14:44 +020012060 TaskState *ts = cpu->opaque;
Peter Maydell1ccd9372013-07-16 18:44:55 +010012061 ts->tp_value = arg1;
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012062 return 0;
Peter Maydell1ccd9372013-07-16 18:44:55 +010012063 }
ths6f5b89a2007-03-02 20:48:00 +000012064#else
Richard Henderson10f45d92018-08-18 12:01:07 -070012065 return -TARGET_ENOSYS;
ths6f5b89a2007-03-02 20:48:00 +000012066#endif
12067#endif
12068#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +000012069 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +000012070#if defined(TARGET_I386) && defined(TARGET_ABI32)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012071 return do_get_thread_area(cpu_env, arg1);
Peter Maydell1ccd9372013-07-16 18:44:55 +010012072#elif defined(TARGET_M68K)
12073 {
Andreas Färber0429a972013-08-26 18:14:44 +020012074 TaskState *ts = cpu->opaque;
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012075 return ts->tp_value;
Peter Maydell1ccd9372013-07-16 18:44:55 +010012076 }
bellard8d18e892007-11-14 15:18:40 +000012077#else
Richard Henderson10f45d92018-08-18 12:01:07 -070012078 return -TARGET_ENOSYS;
bellardebc05482003-09-30 21:08:41 +000012079#endif
bellard8d18e892007-11-14 15:18:40 +000012080#endif
bellard48dc41e2006-06-21 18:15:50 +000012081#ifdef TARGET_NR_getdomainname
12082 case TARGET_NR_getdomainname:
Richard Henderson10f45d92018-08-18 12:01:07 -070012083 return -TARGET_ENOSYS;
bellard48dc41e2006-06-21 18:15:50 +000012084#endif
ths6f5b89a2007-03-02 20:48:00 +000012085
Max Filippov12e33402018-04-01 13:13:49 -070012086#ifdef TARGET_NR_clock_settime
12087 case TARGET_NR_clock_settime:
12088 {
12089 struct timespec ts;
12090
12091 ret = target_to_host_timespec(&ts, arg2);
12092 if (!is_error(ret)) {
12093 ret = get_errno(clock_settime(arg1, &ts));
12094 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012095 return ret;
Max Filippov12e33402018-04-01 13:13:49 -070012096 }
12097#endif
Alistair Francisc6c8d102020-03-12 15:13:53 -070012098#ifdef TARGET_NR_clock_settime64
12099 case TARGET_NR_clock_settime64:
12100 {
12101 struct timespec ts;
12102
12103 ret = target_to_host_timespec64(&ts, arg2);
12104 if (!is_error(ret)) {
12105 ret = get_errno(clock_settime(arg1, &ts));
12106 }
12107 return ret;
12108 }
12109#endif
thsb5906f92007-03-19 13:32:45 +000012110#ifdef TARGET_NR_clock_gettime
12111 case TARGET_NR_clock_gettime:
12112 {
12113 struct timespec ts;
12114 ret = get_errno(clock_gettime(arg1, &ts));
12115 if (!is_error(ret)) {
Max Filippovb9f99082018-04-01 13:14:04 -070012116 ret = host_to_target_timespec(arg2, &ts);
thsb5906f92007-03-19 13:32:45 +000012117 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012118 return ret;
thsb5906f92007-03-19 13:32:45 +000012119 }
12120#endif
Alistair Francisc6c8d102020-03-12 15:13:53 -070012121#ifdef TARGET_NR_clock_gettime64
12122 case TARGET_NR_clock_gettime64:
12123 {
12124 struct timespec ts;
12125 ret = get_errno(clock_gettime(arg1, &ts));
12126 if (!is_error(ret)) {
12127 ret = host_to_target_timespec64(arg2, &ts);
12128 }
12129 return ret;
12130 }
12131#endif
thsb5906f92007-03-19 13:32:45 +000012132#ifdef TARGET_NR_clock_getres
12133 case TARGET_NR_clock_getres:
12134 {
12135 struct timespec ts;
12136 ret = get_errno(clock_getres(arg1, &ts));
12137 if (!is_error(ret)) {
12138 host_to_target_timespec(arg2, &ts);
12139 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012140 return ret;
thsb5906f92007-03-19 13:32:45 +000012141 }
12142#endif
Filip Bozuta828cb3a2020-07-22 17:34:21 +020012143#ifdef TARGET_NR_clock_getres_time64
12144 case TARGET_NR_clock_getres_time64:
12145 {
12146 struct timespec ts;
12147 ret = get_errno(clock_getres(arg1, &ts));
12148 if (!is_error(ret)) {
12149 host_to_target_timespec64(arg2, &ts);
12150 }
12151 return ret;
12152 }
12153#endif
pbrook63d76512008-05-29 13:43:29 +000012154#ifdef TARGET_NR_clock_nanosleep
12155 case TARGET_NR_clock_nanosleep:
12156 {
12157 struct timespec ts;
Filip Bozutab09d6402020-07-27 22:13:26 +020012158 if (target_to_host_timespec(&ts, arg3)) {
12159 return -TARGET_EFAULT;
12160 }
Peter Maydell9e518222016-06-06 19:58:09 +010012161 ret = get_errno(safe_clock_nanosleep(arg1, arg2,
12162 &ts, arg4 ? &ts : NULL));
Laurent Vivier8ec68a02020-07-24 07:45:05 +010012163 /*
12164 * if the call is interrupted by a signal handler, it fails
12165 * with error -TARGET_EINTR and if arg4 is not NULL and arg2 is not
12166 * TIMER_ABSTIME, it returns the remaining unslept time in arg4.
12167 */
Filip Bozutab09d6402020-07-27 22:13:26 +020012168 if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME &&
12169 host_to_target_timespec(arg4, &ts)) {
12170 return -TARGET_EFAULT;
Laurent Vivier8ec68a02020-07-24 07:45:05 +010012171 }
Tom Musta8fbe8fd2014-08-12 13:53:41 -050012172
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012173 return ret;
pbrook63d76512008-05-29 13:43:29 +000012174 }
12175#endif
Filip Bozuta6ac03b22020-08-24 21:21:15 +020012176#ifdef TARGET_NR_clock_nanosleep_time64
12177 case TARGET_NR_clock_nanosleep_time64:
12178 {
12179 struct timespec ts;
12180
12181 if (target_to_host_timespec64(&ts, arg3)) {
12182 return -TARGET_EFAULT;
12183 }
12184
12185 ret = get_errno(safe_clock_nanosleep(arg1, arg2,
12186 &ts, arg4 ? &ts : NULL));
12187
12188 if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME &&
12189 host_to_target_timespec64(arg4, &ts)) {
12190 return -TARGET_EFAULT;
12191 }
12192 return ret;
12193 }
12194#endif
thsb5906f92007-03-19 13:32:45 +000012195
Helge Deller9a7f6822022-05-28 12:52:10 +020012196#if defined(TARGET_NR_set_tid_address)
ths6f5b89a2007-03-02 20:48:00 +000012197 case TARGET_NR_set_tid_address:
Helge Deller9a7f6822022-05-28 12:52:10 +020012198 {
12199 TaskState *ts = cpu->opaque;
12200 ts->child_tidptr = arg1;
12201 /* do not call host set_tid_address() syscall, instead return tid() */
12202 return get_errno(sys_gettid());
12203 }
ths6f5b89a2007-03-02 20:48:00 +000012204#endif
12205
ths4cae1d12007-07-12 11:06:53 +000012206 case TARGET_NR_tkill:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012207 return get_errno(safe_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +000012208
ths71455572007-06-21 21:45:30 +000012209 case TARGET_NR_tgkill:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012210 return get_errno(safe_tgkill((int)arg1, (int)arg2,
12211 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +000012212
ths4f2b1fe2007-06-21 21:57:12 +000012213#ifdef TARGET_NR_set_robust_list
12214 case TARGET_NR_set_robust_list:
Peter Maydelle9a970a2013-02-08 04:34:54 +000012215 case TARGET_NR_get_robust_list:
12216 /* The ABI for supporting robust futexes has userspace pass
12217 * the kernel a pointer to a linked list which is updated by
12218 * userspace after the syscall; the list is walked by the kernel
12219 * when the thread exits. Since the linked list in QEMU guest
12220 * memory isn't a valid linked list for the host and we have
12221 * no way to reliably intercept the thread-death event, we can't
12222 * support these. Silently return ENOSYS so that guest userspace
12223 * falls back to a non-robust futex implementation (which should
12224 * be OK except in the corner case of the guest crashing while
12225 * holding a mutex that is shared with another process via
12226 * shared memory).
12227 */
Richard Henderson10f45d92018-08-18 12:01:07 -070012228 return -TARGET_ENOSYS;
ths4f2b1fe2007-06-21 21:57:12 +000012229#endif
12230
Peter Maydell1acae9f2013-07-02 14:04:12 +010012231#if defined(TARGET_NR_utimensat)
ths9007f0e2007-09-25 17:50:37 +000012232 case TARGET_NR_utimensat:
12233 {
Riku Voipioebc996f2009-04-21 15:01:51 +030012234 struct timespec *tsp, ts[2];
12235 if (!arg3) {
12236 tsp = NULL;
12237 } else {
Filip Bozutab3a3af72020-08-11 13:31:01 +020012238 if (target_to_host_timespec(ts, arg3)) {
12239 return -TARGET_EFAULT;
12240 }
12241 if (target_to_host_timespec(ts + 1, arg3 +
12242 sizeof(struct target_timespec))) {
12243 return -TARGET_EFAULT;
12244 }
Riku Voipioebc996f2009-04-21 15:01:51 +030012245 tsp = ts;
12246 }
ths9007f0e2007-09-25 17:50:37 +000012247 if (!arg2)
Riku Voipioebc996f2009-04-21 15:01:51 +030012248 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
ths9007f0e2007-09-25 17:50:37 +000012249 else {
bellard579a97f2007-11-11 14:26:47 +000012250 if (!(p = lock_user_string(arg2))) {
Richard Henderson259841c2018-08-18 12:01:09 -070012251 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000012252 }
Riku Voipioebc996f2009-04-21 15:01:51 +030012253 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
bellard579a97f2007-11-11 14:26:47 +000012254 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +000012255 }
12256 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012257 return ret;
ths9007f0e2007-09-25 17:50:37 +000012258#endif
Filip Bozutacac46eb2020-08-25 00:30:50 +020012259#ifdef TARGET_NR_utimensat_time64
12260 case TARGET_NR_utimensat_time64:
12261 {
12262 struct timespec *tsp, ts[2];
12263 if (!arg3) {
12264 tsp = NULL;
12265 } else {
12266 if (target_to_host_timespec64(ts, arg3)) {
12267 return -TARGET_EFAULT;
12268 }
12269 if (target_to_host_timespec64(ts + 1, arg3 +
12270 sizeof(struct target__kernel_timespec))) {
12271 return -TARGET_EFAULT;
12272 }
12273 tsp = ts;
12274 }
12275 if (!arg2)
12276 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
12277 else {
12278 p = lock_user_string(arg2);
12279 if (!p) {
12280 return -TARGET_EFAULT;
12281 }
12282 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
12283 unlock_user(p, arg2, 0);
12284 }
12285 }
12286 return ret;
12287#endif
Alistair Francis859e8a82020-03-12 15:13:49 -070012288#ifdef TARGET_NR_futex
pbrookbd0c5662008-05-29 14:34:11 +000012289 case TARGET_NR_futex:
Richard Henderson3e8f1622021-02-12 10:48:43 -080012290 return do_futex(cpu, arg1, arg2, arg3, arg4, arg5, arg6);
Alistair Francis859e8a82020-03-12 15:13:49 -070012291#endif
Alistair Francis14690292020-03-18 15:47:01 -070012292#ifdef TARGET_NR_futex_time64
12293 case TARGET_NR_futex_time64:
Richard Henderson3e8f1622021-02-12 10:48:43 -080012294 return do_futex_time64(cpu, arg1, arg2, arg3, arg4, arg5, arg6);
Alistair Francis14690292020-03-18 15:47:01 -070012295#endif
Paul Brook33f53ac2022-01-26 20:26:36 +000012296#ifdef CONFIG_INOTIFY
12297#if defined(TARGET_NR_inotify_init)
aurel3239b59762008-10-01 21:46:50 +000012298 case TARGET_NR_inotify_init:
Paul Brook33f53ac2022-01-26 20:26:36 +000012299 ret = get_errno(inotify_init());
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030012300 if (ret >= 0) {
12301 fd_trans_register(ret, &target_inotify_trans);
12302 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012303 return ret;
aurel3239b59762008-10-01 21:46:50 +000012304#endif
Paul Brook33f53ac2022-01-26 20:26:36 +000012305#if defined(TARGET_NR_inotify_init1) && defined(CONFIG_INOTIFY1)
Riku Voipioc05c7a72010-03-26 15:25:11 +000012306 case TARGET_NR_inotify_init1:
Paul Brook33f53ac2022-01-26 20:26:36 +000012307 ret = get_errno(inotify_init1(target_to_host_bitmask(arg1,
Lena Djokicfea243e2016-11-24 17:08:53 +010012308 fcntl_flags_tbl)));
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030012309 if (ret >= 0) {
12310 fd_trans_register(ret, &target_inotify_trans);
12311 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012312 return ret;
Riku Voipioc05c7a72010-03-26 15:25:11 +000012313#endif
Paul Brook33f53ac2022-01-26 20:26:36 +000012314#if defined(TARGET_NR_inotify_add_watch)
aurel3239b59762008-10-01 21:46:50 +000012315 case TARGET_NR_inotify_add_watch:
12316 p = lock_user_string(arg2);
Paul Brook33f53ac2022-01-26 20:26:36 +000012317 ret = get_errno(inotify_add_watch(arg1, path(p), arg3));
aurel3239b59762008-10-01 21:46:50 +000012318 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012319 return ret;
aurel3239b59762008-10-01 21:46:50 +000012320#endif
Paul Brook33f53ac2022-01-26 20:26:36 +000012321#if defined(TARGET_NR_inotify_rm_watch)
aurel3239b59762008-10-01 21:46:50 +000012322 case TARGET_NR_inotify_rm_watch:
Paul Brook33f53ac2022-01-26 20:26:36 +000012323 return get_errno(inotify_rm_watch(arg1, arg2));
12324#endif
aurel3239b59762008-10-01 21:46:50 +000012325#endif
ths9007f0e2007-09-25 17:50:37 +000012326
Nathan Froyd8ec9cf82009-07-22 09:14:36 -070012327#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
aurel3224e10032009-04-15 16:11:43 +000012328 case TARGET_NR_mq_open:
12329 {
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020012330 struct mq_attr posix_mq_attr;
Lena Djokic26400772016-11-24 17:08:58 +010012331 struct mq_attr *pposix_mq_attr;
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020012332 int host_flags;
aurel3224e10032009-04-15 16:11:43 +000012333
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020012334 host_flags = target_to_host_bitmask(arg2, fcntl_flags_tbl);
Lena Djokic26400772016-11-24 17:08:58 +010012335 pposix_mq_attr = NULL;
12336 if (arg4) {
12337 if (copy_from_user_mq_attr(&posix_mq_attr, arg4) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012338 return -TARGET_EFAULT;
Lena Djokic26400772016-11-24 17:08:58 +010012339 }
12340 pposix_mq_attr = &posix_mq_attr;
Tom Mustab6ce1f62014-08-12 13:53:36 -050012341 }
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020012342 p = lock_user_string(arg1 - 1);
12343 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012344 return -TARGET_EFAULT;
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020012345 }
Lena Djokic26400772016-11-24 17:08:58 +010012346 ret = get_errno(mq_open(p, host_flags, arg3, pposix_mq_attr));
aurel3224e10032009-04-15 16:11:43 +000012347 unlock_user (p, arg1, 0);
12348 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012349 return ret;
aurel3224e10032009-04-15 16:11:43 +000012350
12351 case TARGET_NR_mq_unlink:
12352 p = lock_user_string(arg1 - 1);
Peter Maydell32112152016-07-12 13:02:13 +010012353 if (!p) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012354 return -TARGET_EFAULT;
Peter Maydell32112152016-07-12 13:02:13 +010012355 }
aurel3224e10032009-04-15 16:11:43 +000012356 ret = get_errno(mq_unlink(p));
12357 unlock_user (p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012358 return ret;
aurel3224e10032009-04-15 16:11:43 +000012359
Alistair Francis859e8a82020-03-12 15:13:49 -070012360#ifdef TARGET_NR_mq_timedsend
aurel3224e10032009-04-15 16:11:43 +000012361 case TARGET_NR_mq_timedsend:
12362 {
12363 struct timespec ts;
12364
12365 p = lock_user (VERIFY_READ, arg2, arg3, 1);
12366 if (arg5 != 0) {
Filip Bozutadcbcf5c2020-08-24 21:37:51 +020012367 if (target_to_host_timespec(&ts, arg5)) {
12368 return -TARGET_EFAULT;
12369 }
Peter Maydelld40ecd62016-06-06 19:58:06 +010012370 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts));
Filip Bozutadcbcf5c2020-08-24 21:37:51 +020012371 if (!is_error(ret) && host_to_target_timespec(arg5, &ts)) {
12372 return -TARGET_EFAULT;
12373 }
Peter Maydelld40ecd62016-06-06 19:58:06 +010012374 } else {
12375 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL));
aurel3224e10032009-04-15 16:11:43 +000012376 }
aurel3224e10032009-04-15 16:11:43 +000012377 unlock_user (p, arg2, arg3);
12378 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012379 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070012380#endif
Filip Bozutad107e372020-08-24 21:37:52 +020012381#ifdef TARGET_NR_mq_timedsend_time64
12382 case TARGET_NR_mq_timedsend_time64:
12383 {
12384 struct timespec ts;
12385
12386 p = lock_user(VERIFY_READ, arg2, arg3, 1);
12387 if (arg5 != 0) {
12388 if (target_to_host_timespec64(&ts, arg5)) {
12389 return -TARGET_EFAULT;
12390 }
12391 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts));
12392 if (!is_error(ret) && host_to_target_timespec64(arg5, &ts)) {
12393 return -TARGET_EFAULT;
12394 }
12395 } else {
12396 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL));
12397 }
12398 unlock_user(p, arg2, arg3);
12399 }
12400 return ret;
12401#endif
aurel3224e10032009-04-15 16:11:43 +000012402
Alistair Francis859e8a82020-03-12 15:13:49 -070012403#ifdef TARGET_NR_mq_timedreceive
aurel3224e10032009-04-15 16:11:43 +000012404 case TARGET_NR_mq_timedreceive:
12405 {
12406 struct timespec ts;
12407 unsigned int prio;
12408
12409 p = lock_user (VERIFY_READ, arg2, arg3, 1);
12410 if (arg5 != 0) {
Filip Bozutadcbcf5c2020-08-24 21:37:51 +020012411 if (target_to_host_timespec(&ts, arg5)) {
12412 return -TARGET_EFAULT;
12413 }
Peter Maydelld40ecd62016-06-06 19:58:06 +010012414 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12415 &prio, &ts));
Filip Bozutadcbcf5c2020-08-24 21:37:51 +020012416 if (!is_error(ret) && host_to_target_timespec(arg5, &ts)) {
12417 return -TARGET_EFAULT;
12418 }
Peter Maydelld40ecd62016-06-06 19:58:06 +010012419 } else {
12420 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12421 &prio, NULL));
aurel3224e10032009-04-15 16:11:43 +000012422 }
aurel3224e10032009-04-15 16:11:43 +000012423 unlock_user (p, arg2, arg3);
12424 if (arg4 != 0)
12425 put_user_u32(prio, arg4);
12426 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012427 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070012428#endif
Filip Bozutad107e372020-08-24 21:37:52 +020012429#ifdef TARGET_NR_mq_timedreceive_time64
12430 case TARGET_NR_mq_timedreceive_time64:
12431 {
12432 struct timespec ts;
12433 unsigned int prio;
12434
12435 p = lock_user(VERIFY_READ, arg2, arg3, 1);
12436 if (arg5 != 0) {
12437 if (target_to_host_timespec64(&ts, arg5)) {
12438 return -TARGET_EFAULT;
12439 }
12440 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12441 &prio, &ts));
12442 if (!is_error(ret) && host_to_target_timespec64(arg5, &ts)) {
12443 return -TARGET_EFAULT;
12444 }
12445 } else {
12446 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12447 &prio, NULL));
12448 }
12449 unlock_user(p, arg2, arg3);
12450 if (arg4 != 0) {
12451 put_user_u32(prio, arg4);
12452 }
12453 }
12454 return ret;
12455#endif
aurel3224e10032009-04-15 16:11:43 +000012456
12457 /* Not implemented for now... */
12458/* case TARGET_NR_mq_notify: */
12459/* break; */
12460
12461 case TARGET_NR_mq_getsetattr:
12462 {
12463 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
12464 ret = 0;
aurel3224e10032009-04-15 16:11:43 +000012465 if (arg2 != 0) {
12466 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
Max Filippova23ea402018-03-31 08:20:15 -070012467 ret = get_errno(mq_setattr(arg1, &posix_mq_attr_in,
12468 &posix_mq_attr_out));
12469 } else if (arg3 != 0) {
12470 ret = get_errno(mq_getattr(arg1, &posix_mq_attr_out));
aurel3224e10032009-04-15 16:11:43 +000012471 }
Max Filippova23ea402018-03-31 08:20:15 -070012472 if (ret == 0 && arg3 != 0) {
12473 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
12474 }
aurel3224e10032009-04-15 16:11:43 +000012475 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012476 return ret;
aurel3224e10032009-04-15 16:11:43 +000012477#endif
12478
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012479#ifdef CONFIG_SPLICE
12480#ifdef TARGET_NR_tee
12481 case TARGET_NR_tee:
12482 {
12483 ret = get_errno(tee(arg1,arg2,arg3,arg4));
12484 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012485 return ret;
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012486#endif
12487#ifdef TARGET_NR_splice
12488 case TARGET_NR_splice:
12489 {
12490 loff_t loff_in, loff_out;
12491 loff_t *ploff_in = NULL, *ploff_out = NULL;
Andreas Schwab17644b32015-03-10 17:11:35 +010012492 if (arg2) {
12493 if (get_user_u64(loff_in, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012494 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010012495 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012496 ploff_in = &loff_in;
12497 }
Andreas Schwab17644b32015-03-10 17:11:35 +010012498 if (arg4) {
12499 if (get_user_u64(loff_out, arg4)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012500 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010012501 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012502 ploff_out = &loff_out;
12503 }
12504 ret = get_errno(splice(arg1, ploff_in, arg3, ploff_out, arg5, arg6));
Andreas Schwab17644b32015-03-10 17:11:35 +010012505 if (arg2) {
12506 if (put_user_u64(loff_in, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012507 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010012508 }
12509 }
12510 if (arg4) {
12511 if (put_user_u64(loff_out, arg4)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012512 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010012513 }
12514 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012515 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012516 return ret;
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012517#endif
12518#ifdef TARGET_NR_vmsplice
12519 case TARGET_NR_vmsplice:
12520 {
Richard Hendersonf287b2c2012-09-15 13:20:25 -070012521 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
12522 if (vec != NULL) {
12523 ret = get_errno(vmsplice(arg1, vec, arg3, arg4));
12524 unlock_iovec(vec, arg2, arg3, 0);
12525 } else {
12526 ret = -host_to_target_errno(errno);
12527 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012528 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012529 return ret;
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012530#endif
12531#endif /* CONFIG_SPLICE */
Riku Voipioc2882b92009-08-12 15:08:24 +030012532#ifdef CONFIG_EVENTFD
12533#if defined(TARGET_NR_eventfd)
12534 case TARGET_NR_eventfd:
12535 ret = get_errno(eventfd(arg1, 0));
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030012536 if (ret >= 0) {
12537 fd_trans_register(ret, &target_eventfd_trans);
12538 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012539 return ret;
Riku Voipioc2882b92009-08-12 15:08:24 +030012540#endif
12541#if defined(TARGET_NR_eventfd2)
12542 case TARGET_NR_eventfd2:
Petar Jovanovic5947c692013-04-08 20:26:10 +020012543 {
Helge Deller78721302021-02-10 07:12:14 +010012544 int host_flags = arg2 & (~(TARGET_O_NONBLOCK_MASK | TARGET_O_CLOEXEC));
Petar Jovanovic5947c692013-04-08 20:26:10 +020012545 if (arg2 & TARGET_O_NONBLOCK) {
12546 host_flags |= O_NONBLOCK;
12547 }
12548 if (arg2 & TARGET_O_CLOEXEC) {
12549 host_flags |= O_CLOEXEC;
12550 }
12551 ret = get_errno(eventfd(arg1, host_flags));
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030012552 if (ret >= 0) {
12553 fd_trans_register(ret, &target_eventfd_trans);
12554 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012555 return ret;
Petar Jovanovic5947c692013-04-08 20:26:10 +020012556 }
Riku Voipioc2882b92009-08-12 15:08:24 +030012557#endif
12558#endif /* CONFIG_EVENTFD */
Ulrich Hechtd0927932009-09-17 20:22:14 +030012559#if defined(CONFIG_FALLOCATE) && defined(TARGET_NR_fallocate)
12560 case TARGET_NR_fallocate:
Alexander Graf20249ae2012-02-06 21:37:07 +010012561#if TARGET_ABI_BITS == 32
12562 ret = get_errno(fallocate(arg1, arg2, target_offset64(arg3, arg4),
12563 target_offset64(arg5, arg6)));
12564#else
Ulrich Hechtd0927932009-09-17 20:22:14 +030012565 ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
Alexander Graf20249ae2012-02-06 21:37:07 +010012566#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012567 return ret;
Ulrich Hechtd0927932009-09-17 20:22:14 +030012568#endif
Peter Maydellc727f472011-01-06 11:05:10 +000012569#if defined(CONFIG_SYNC_FILE_RANGE)
12570#if defined(TARGET_NR_sync_file_range)
12571 case TARGET_NR_sync_file_range:
12572#if TARGET_ABI_BITS == 32
Riku Voipiobfcedc52011-06-20 16:24:39 +030012573#if defined(TARGET_MIPS)
12574 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
12575 target_offset64(arg5, arg6), arg7));
12576#else
Peter Maydellc727f472011-01-06 11:05:10 +000012577 ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3),
12578 target_offset64(arg4, arg5), arg6));
Riku Voipiobfcedc52011-06-20 16:24:39 +030012579#endif /* !TARGET_MIPS */
Peter Maydellc727f472011-01-06 11:05:10 +000012580#else
12581 ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4));
12582#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012583 return ret;
Peter Maydellc727f472011-01-06 11:05:10 +000012584#endif
Laurent Vivier5bcb4982020-03-10 11:33:50 +010012585#if defined(TARGET_NR_sync_file_range2) || \
12586 defined(TARGET_NR_arm_sync_file_range)
Peter Maydellc727f472011-01-06 11:05:10 +000012587#if defined(TARGET_NR_sync_file_range2)
12588 case TARGET_NR_sync_file_range2:
Laurent Vivier5bcb4982020-03-10 11:33:50 +010012589#endif
12590#if defined(TARGET_NR_arm_sync_file_range)
12591 case TARGET_NR_arm_sync_file_range:
12592#endif
Peter Maydellc727f472011-01-06 11:05:10 +000012593 /* This is like sync_file_range but the arguments are reordered */
12594#if TARGET_ABI_BITS == 32
12595 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
12596 target_offset64(arg5, arg6), arg2));
12597#else
12598 ret = get_errno(sync_file_range(arg1, arg3, arg4, arg2));
12599#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012600 return ret;
Peter Maydellc727f472011-01-06 11:05:10 +000012601#endif
12602#endif
Laurent Viviere36800c2015-10-02 14:48:09 +020012603#if defined(TARGET_NR_signalfd4)
12604 case TARGET_NR_signalfd4:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012605 return do_signalfd4(arg1, arg2, arg4);
Laurent Viviere36800c2015-10-02 14:48:09 +020012606#endif
12607#if defined(TARGET_NR_signalfd)
12608 case TARGET_NR_signalfd:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012609 return do_signalfd4(arg1, arg2, 0);
Laurent Viviere36800c2015-10-02 14:48:09 +020012610#endif
Peter Maydell3b6edd12011-02-15 18:35:05 +000012611#if defined(CONFIG_EPOLL)
12612#if defined(TARGET_NR_epoll_create)
12613 case TARGET_NR_epoll_create:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012614 return get_errno(epoll_create(arg1));
Peter Maydell3b6edd12011-02-15 18:35:05 +000012615#endif
12616#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1)
12617 case TARGET_NR_epoll_create1:
Sergei Trofimovich386d3862020-04-15 23:05:08 +010012618 return get_errno(epoll_create1(target_to_host_bitmask(arg1, fcntl_flags_tbl)));
Peter Maydell3b6edd12011-02-15 18:35:05 +000012619#endif
12620#if defined(TARGET_NR_epoll_ctl)
12621 case TARGET_NR_epoll_ctl:
12622 {
12623 struct epoll_event ep;
12624 struct epoll_event *epp = 0;
12625 if (arg4) {
LemonBoyc7811022020-04-17 17:34:54 +020012626 if (arg2 != EPOLL_CTL_DEL) {
12627 struct target_epoll_event *target_ep;
12628 if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) {
12629 return -TARGET_EFAULT;
12630 }
12631 ep.events = tswap32(target_ep->events);
12632 /*
12633 * The epoll_data_t union is just opaque data to the kernel,
12634 * so we transfer all 64 bits across and need not worry what
12635 * actual data type it is.
12636 */
12637 ep.data.u64 = tswap64(target_ep->data.u64);
12638 unlock_user_struct(target_ep, arg4, 0);
Peter Maydell3b6edd12011-02-15 18:35:05 +000012639 }
LemonBoyc7811022020-04-17 17:34:54 +020012640 /*
12641 * before kernel 2.6.9, EPOLL_CTL_DEL operation required a
12642 * non-null pointer, even though this argument is ignored.
12643 *
Peter Maydell3b6edd12011-02-15 18:35:05 +000012644 */
Peter Maydell3b6edd12011-02-15 18:35:05 +000012645 epp = &ep;
12646 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012647 return get_errno(epoll_ctl(arg1, arg2, arg3, epp));
Peter Maydell3b6edd12011-02-15 18:35:05 +000012648 }
12649#endif
12650
Peter Maydell227f0212016-06-06 19:58:11 +010012651#if defined(TARGET_NR_epoll_wait) || defined(TARGET_NR_epoll_pwait)
Peter Maydell3b6edd12011-02-15 18:35:05 +000012652#if defined(TARGET_NR_epoll_wait)
12653 case TARGET_NR_epoll_wait:
12654#endif
Peter Maydell227f0212016-06-06 19:58:11 +010012655#if defined(TARGET_NR_epoll_pwait)
Peter Maydell3b6edd12011-02-15 18:35:05 +000012656 case TARGET_NR_epoll_pwait:
12657#endif
12658 {
12659 struct target_epoll_event *target_ep;
12660 struct epoll_event *ep;
12661 int epfd = arg1;
12662 int maxevents = arg3;
12663 int timeout = arg4;
12664
Peter Maydell2ba7fae32016-07-18 15:35:59 +010012665 if (maxevents <= 0 || maxevents > TARGET_EP_MAX_EVENTS) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012666 return -TARGET_EINVAL;
Peter Maydell2ba7fae32016-07-18 15:35:59 +010012667 }
12668
Peter Maydell3b6edd12011-02-15 18:35:05 +000012669 target_ep = lock_user(VERIFY_WRITE, arg2,
12670 maxevents * sizeof(struct target_epoll_event), 1);
12671 if (!target_ep) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012672 return -TARGET_EFAULT;
Peter Maydell3b6edd12011-02-15 18:35:05 +000012673 }
12674
Peter Maydell04c95f42016-07-18 15:36:00 +010012675 ep = g_try_new(struct epoll_event, maxevents);
12676 if (!ep) {
12677 unlock_user(target_ep, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012678 return -TARGET_ENOMEM;
Peter Maydell04c95f42016-07-18 15:36:00 +010012679 }
Peter Maydell3b6edd12011-02-15 18:35:05 +000012680
12681 switch (num) {
Peter Maydell227f0212016-06-06 19:58:11 +010012682#if defined(TARGET_NR_epoll_pwait)
Peter Maydell3b6edd12011-02-15 18:35:05 +000012683 case TARGET_NR_epoll_pwait:
12684 {
Richard Hendersoncd0e31a2022-03-15 01:43:07 -070012685 sigset_t *set = NULL;
Peter Maydell3b6edd12011-02-15 18:35:05 +000012686
12687 if (arg5) {
Richard Hendersoncd0e31a2022-03-15 01:43:07 -070012688 ret = process_sigsuspend_mask(&set, arg5, arg6);
12689 if (ret != 0) {
Peter Maydellc8157012016-06-30 14:23:24 +010012690 break;
12691 }
Peter Maydell3b6edd12011-02-15 18:35:05 +000012692 }
12693
Peter Maydell227f0212016-06-06 19:58:11 +010012694 ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
12695 set, SIGSET_T_SIZE));
Richard Hendersoncd0e31a2022-03-15 01:43:07 -070012696
12697 if (set) {
12698 finish_sigsuspend_mask(ret);
12699 }
Peter Maydell3b6edd12011-02-15 18:35:05 +000012700 break;
12701 }
12702#endif
12703#if defined(TARGET_NR_epoll_wait)
12704 case TARGET_NR_epoll_wait:
Peter Maydell227f0212016-06-06 19:58:11 +010012705 ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
12706 NULL, 0));
Peter Maydell3b6edd12011-02-15 18:35:05 +000012707 break;
12708#endif
12709 default:
12710 ret = -TARGET_ENOSYS;
12711 }
12712 if (!is_error(ret)) {
12713 int i;
12714 for (i = 0; i < ret; i++) {
12715 target_ep[i].events = tswap32(ep[i].events);
12716 target_ep[i].data.u64 = tswap64(ep[i].data.u64);
12717 }
Peter Maydell04c95f42016-07-18 15:36:00 +010012718 unlock_user(target_ep, arg2,
12719 ret * sizeof(struct target_epoll_event));
12720 } else {
12721 unlock_user(target_ep, arg2, 0);
Peter Maydell3b6edd12011-02-15 18:35:05 +000012722 }
Peter Maydell04c95f42016-07-18 15:36:00 +010012723 g_free(ep);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012724 return ret;
Peter Maydell3b6edd12011-02-15 18:35:05 +000012725 }
12726#endif
12727#endif
Peter Maydell163a05a2011-06-27 17:44:52 +010012728#ifdef TARGET_NR_prlimit64
12729 case TARGET_NR_prlimit64:
12730 {
12731 /* args: pid, resource number, ptr to new rlimit, ptr to old rlimit */
12732 struct target_rlimit64 *target_rnew, *target_rold;
12733 struct host_rlimit64 rnew, rold, *rnewp = 0;
Felix Janda95018012014-12-02 22:11:17 +010012734 int resource = target_to_host_resource(arg2);
Tobias Koch055d92f2020-03-05 21:24:00 +010012735
12736 if (arg3 && (resource != RLIMIT_AS &&
12737 resource != RLIMIT_DATA &&
12738 resource != RLIMIT_STACK)) {
Peter Maydell163a05a2011-06-27 17:44:52 +010012739 if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012740 return -TARGET_EFAULT;
Peter Maydell163a05a2011-06-27 17:44:52 +010012741 }
12742 rnew.rlim_cur = tswap64(target_rnew->rlim_cur);
12743 rnew.rlim_max = tswap64(target_rnew->rlim_max);
12744 unlock_user_struct(target_rnew, arg3, 0);
12745 rnewp = &rnew;
12746 }
12747
Felix Janda95018012014-12-02 22:11:17 +010012748 ret = get_errno(sys_prlimit64(arg1, resource, rnewp, arg4 ? &rold : 0));
Peter Maydell163a05a2011-06-27 17:44:52 +010012749 if (!is_error(ret) && arg4) {
12750 if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012751 return -TARGET_EFAULT;
Peter Maydell163a05a2011-06-27 17:44:52 +010012752 }
12753 target_rold->rlim_cur = tswap64(rold.rlim_cur);
12754 target_rold->rlim_max = tswap64(rold.rlim_max);
12755 unlock_user_struct(target_rold, arg4, 1);
12756 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012757 return ret;
Peter Maydell163a05a2011-06-27 17:44:52 +010012758 }
12759#endif
Richard Henderson3d21d292012-09-15 13:20:46 -070012760#ifdef TARGET_NR_gethostname
12761 case TARGET_NR_gethostname:
12762 {
12763 char *name = lock_user(VERIFY_WRITE, arg1, arg2, 0);
12764 if (name) {
12765 ret = get_errno(gethostname(name, arg2));
12766 unlock_user(name, arg1, arg2);
12767 } else {
12768 ret = -TARGET_EFAULT;
12769 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012770 return ret;
Richard Henderson3d21d292012-09-15 13:20:46 -070012771 }
12772#endif
Riku Voipio89aaf1a2013-07-24 09:44:26 +030012773#ifdef TARGET_NR_atomic_cmpxchg_32
12774 case TARGET_NR_atomic_cmpxchg_32:
12775 {
12776 /* should use start_exclusive from main.c */
12777 abi_ulong mem_value;
12778 if (get_user_u32(mem_value, arg6)) {
12779 target_siginfo_t info;
12780 info.si_signo = SIGSEGV;
12781 info.si_errno = 0;
12782 info.si_code = TARGET_SEGV_MAPERR;
12783 info._sifields._sigfault._addr = arg6;
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020012784 queue_signal(cpu_env, info.si_signo, QEMU_SI_FAULT, &info);
Riku Voipio89aaf1a2013-07-24 09:44:26 +030012785 ret = 0xdeadbeef;
12786
12787 }
12788 if (mem_value == arg2)
12789 put_user_u32(arg1, arg6);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012790 return mem_value;
Riku Voipio89aaf1a2013-07-24 09:44:26 +030012791 }
12792#endif
12793#ifdef TARGET_NR_atomic_barrier
12794 case TARGET_NR_atomic_barrier:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012795 /* Like the kernel implementation and the
12796 qemu arm barrier, no-op this? */
12797 return 0;
Riku Voipio89aaf1a2013-07-24 09:44:26 +030012798#endif
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012799
12800#ifdef TARGET_NR_timer_create
12801 case TARGET_NR_timer_create:
12802 {
12803 /* args: clockid_t clockid, struct sigevent *sevp, timer_t *timerid */
12804
12805 struct sigevent host_sevp = { {0}, }, *phost_sevp = NULL;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012806
12807 int clkid = arg1;
12808 int timer_index = next_free_host_timer();
12809
12810 if (timer_index < 0) {
12811 ret = -TARGET_EAGAIN;
12812 } else {
12813 timer_t *phtimer = g_posix_timers + timer_index;
12814
12815 if (arg2) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012816 phost_sevp = &host_sevp;
Peter Maydellc0659762014-08-09 15:42:32 +010012817 ret = target_to_host_sigevent(phost_sevp, arg2);
12818 if (ret != 0) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012819 return ret;
Peter Maydellc0659762014-08-09 15:42:32 +010012820 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012821 }
12822
12823 ret = get_errno(timer_create(clkid, phost_sevp, phtimer));
12824 if (ret) {
12825 phtimer = NULL;
12826 } else {
Alexander Grafaecc8862014-11-10 21:33:03 +010012827 if (put_user(TIMER_MAGIC | timer_index, arg3, target_timer_t)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012828 return -TARGET_EFAULT;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012829 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012830 }
12831 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012832 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012833 }
12834#endif
12835
12836#ifdef TARGET_NR_timer_settime
12837 case TARGET_NR_timer_settime:
12838 {
12839 /* args: timer_t timerid, int flags, const struct itimerspec *new_value,
12840 * struct itimerspec * old_value */
Alexander Grafaecc8862014-11-10 21:33:03 +010012841 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020012842
Alexander Grafaecc8862014-11-10 21:33:03 +010012843 if (timerid < 0) {
12844 ret = timerid;
12845 } else if (arg3 == 0) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012846 ret = -TARGET_EINVAL;
12847 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020012848 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012849 struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
12850
Marc-André Lureau40c80b52017-01-19 10:15:32 -050012851 if (target_to_host_itimerspec(&hspec_new, arg3)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012852 return -TARGET_EFAULT;
Marc-André Lureau40c80b52017-01-19 10:15:32 -050012853 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012854 ret = get_errno(
12855 timer_settime(htimer, arg2, &hspec_new, &hspec_old));
Marc-André Lureau40c80b52017-01-19 10:15:32 -050012856 if (arg4 && host_to_target_itimerspec(arg4, &hspec_old)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012857 return -TARGET_EFAULT;
Marc-André Lureau40c80b52017-01-19 10:15:32 -050012858 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012859 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012860 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012861 }
12862#endif
12863
Filip Bozuta828cb3a2020-07-22 17:34:21 +020012864#ifdef TARGET_NR_timer_settime64
12865 case TARGET_NR_timer_settime64:
12866 {
12867 target_timer_t timerid = get_timer_id(arg1);
12868
12869 if (timerid < 0) {
12870 ret = timerid;
12871 } else if (arg3 == 0) {
12872 ret = -TARGET_EINVAL;
12873 } else {
12874 timer_t htimer = g_posix_timers[timerid];
12875 struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
12876
12877 if (target_to_host_itimerspec64(&hspec_new, arg3)) {
12878 return -TARGET_EFAULT;
12879 }
12880 ret = get_errno(
12881 timer_settime(htimer, arg2, &hspec_new, &hspec_old));
12882 if (arg4 && host_to_target_itimerspec64(arg4, &hspec_old)) {
12883 return -TARGET_EFAULT;
12884 }
12885 }
12886 return ret;
12887 }
12888#endif
12889
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012890#ifdef TARGET_NR_timer_gettime
12891 case TARGET_NR_timer_gettime:
12892 {
12893 /* args: timer_t timerid, struct itimerspec *curr_value */
Alexander Grafaecc8862014-11-10 21:33:03 +010012894 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020012895
Alexander Grafaecc8862014-11-10 21:33:03 +010012896 if (timerid < 0) {
12897 ret = timerid;
12898 } else if (!arg2) {
12899 ret = -TARGET_EFAULT;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012900 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020012901 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012902 struct itimerspec hspec;
12903 ret = get_errno(timer_gettime(htimer, &hspec));
12904
12905 if (host_to_target_itimerspec(arg2, &hspec)) {
12906 ret = -TARGET_EFAULT;
12907 }
12908 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012909 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012910 }
12911#endif
12912
Filip Bozuta828cb3a2020-07-22 17:34:21 +020012913#ifdef TARGET_NR_timer_gettime64
12914 case TARGET_NR_timer_gettime64:
12915 {
12916 /* args: timer_t timerid, struct itimerspec64 *curr_value */
12917 target_timer_t timerid = get_timer_id(arg1);
12918
12919 if (timerid < 0) {
12920 ret = timerid;
12921 } else if (!arg2) {
12922 ret = -TARGET_EFAULT;
12923 } else {
12924 timer_t htimer = g_posix_timers[timerid];
12925 struct itimerspec hspec;
12926 ret = get_errno(timer_gettime(htimer, &hspec));
12927
12928 if (host_to_target_itimerspec64(arg2, &hspec)) {
12929 ret = -TARGET_EFAULT;
12930 }
12931 }
12932 return ret;
12933 }
12934#endif
12935
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012936#ifdef TARGET_NR_timer_getoverrun
12937 case TARGET_NR_timer_getoverrun:
12938 {
12939 /* args: timer_t timerid */
Alexander Grafaecc8862014-11-10 21:33:03 +010012940 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020012941
Alexander Grafaecc8862014-11-10 21:33:03 +010012942 if (timerid < 0) {
12943 ret = timerid;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012944 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020012945 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012946 ret = get_errno(timer_getoverrun(htimer));
12947 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012948 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012949 }
12950#endif
12951
12952#ifdef TARGET_NR_timer_delete
12953 case TARGET_NR_timer_delete:
12954 {
12955 /* args: timer_t timerid */
Alexander Grafaecc8862014-11-10 21:33:03 +010012956 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020012957
Alexander Grafaecc8862014-11-10 21:33:03 +010012958 if (timerid < 0) {
12959 ret = timerid;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012960 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020012961 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012962 ret = get_errno(timer_delete(htimer));
Alexander Grafe52a99f2014-08-22 13:56:18 +020012963 g_posix_timers[timerid] = 0;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012964 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012965 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012966 }
12967#endif
12968
Riku Voipio51834342014-06-22 11:25:42 +010012969#if defined(TARGET_NR_timerfd_create) && defined(CONFIG_TIMERFD)
12970 case TARGET_NR_timerfd_create:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012971 return get_errno(timerfd_create(arg1,
12972 target_to_host_bitmask(arg2, fcntl_flags_tbl)));
Riku Voipio51834342014-06-22 11:25:42 +010012973#endif
12974
12975#if defined(TARGET_NR_timerfd_gettime) && defined(CONFIG_TIMERFD)
12976 case TARGET_NR_timerfd_gettime:
12977 {
12978 struct itimerspec its_curr;
12979
12980 ret = get_errno(timerfd_gettime(arg1, &its_curr));
12981
12982 if (arg2 && host_to_target_itimerspec(arg2, &its_curr)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012983 return -TARGET_EFAULT;
Riku Voipio51834342014-06-22 11:25:42 +010012984 }
12985 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012986 return ret;
Riku Voipio51834342014-06-22 11:25:42 +010012987#endif
12988
Filip Bozuta828cb3a2020-07-22 17:34:21 +020012989#if defined(TARGET_NR_timerfd_gettime64) && defined(CONFIG_TIMERFD)
12990 case TARGET_NR_timerfd_gettime64:
12991 {
12992 struct itimerspec its_curr;
12993
12994 ret = get_errno(timerfd_gettime(arg1, &its_curr));
12995
12996 if (arg2 && host_to_target_itimerspec64(arg2, &its_curr)) {
12997 return -TARGET_EFAULT;
12998 }
12999 }
13000 return ret;
13001#endif
13002
Riku Voipio51834342014-06-22 11:25:42 +010013003#if defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD)
13004 case TARGET_NR_timerfd_settime:
13005 {
13006 struct itimerspec its_new, its_old, *p_new;
13007
13008 if (arg3) {
13009 if (target_to_host_itimerspec(&its_new, arg3)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013010 return -TARGET_EFAULT;
Riku Voipio51834342014-06-22 11:25:42 +010013011 }
13012 p_new = &its_new;
13013 } else {
13014 p_new = NULL;
13015 }
13016
13017 ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
13018
13019 if (arg4 && host_to_target_itimerspec(arg4, &its_old)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013020 return -TARGET_EFAULT;
Riku Voipio51834342014-06-22 11:25:42 +010013021 }
13022 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013023 return ret;
Riku Voipio51834342014-06-22 11:25:42 +010013024#endif
13025
Filip Bozuta828cb3a2020-07-22 17:34:21 +020013026#if defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)
13027 case TARGET_NR_timerfd_settime64:
13028 {
13029 struct itimerspec its_new, its_old, *p_new;
13030
13031 if (arg3) {
13032 if (target_to_host_itimerspec64(&its_new, arg3)) {
13033 return -TARGET_EFAULT;
13034 }
13035 p_new = &its_new;
13036 } else {
13037 p_new = NULL;
13038 }
13039
13040 ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
13041
13042 if (arg4 && host_to_target_itimerspec64(arg4, &its_old)) {
13043 return -TARGET_EFAULT;
13044 }
13045 }
13046 return ret;
13047#endif
13048
Paul Burtonab31cda2014-06-22 11:25:43 +010013049#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
13050 case TARGET_NR_ioprio_get:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013051 return get_errno(ioprio_get(arg1, arg2));
Paul Burtonab31cda2014-06-22 11:25:43 +010013052#endif
13053
13054#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
13055 case TARGET_NR_ioprio_set:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013056 return get_errno(ioprio_set(arg1, arg2, arg3));
Paul Burtonab31cda2014-06-22 11:25:43 +010013057#endif
13058
Riku Voipio9af5c902014-08-12 15:58:57 +030013059#if defined(TARGET_NR_setns) && defined(CONFIG_SETNS)
13060 case TARGET_NR_setns:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013061 return get_errno(setns(arg1, arg2));
Riku Voipio9af5c902014-08-12 15:58:57 +030013062#endif
13063#if defined(TARGET_NR_unshare) && defined(CONFIG_SETNS)
13064 case TARGET_NR_unshare:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013065 return get_errno(unshare(arg1));
Riku Voipio9af5c902014-08-12 15:58:57 +030013066#endif
Laurent Vivier2f147882016-09-25 22:20:20 +020013067#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
13068 case TARGET_NR_kcmp:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013069 return get_errno(kcmp(arg1, arg2, arg3, arg4, arg5));
Laurent Vivier2f147882016-09-25 22:20:20 +020013070#endif
Richard Hendersonfa97e382018-07-18 13:06:48 -070013071#ifdef TARGET_NR_swapcontext
13072 case TARGET_NR_swapcontext:
13073 /* PowerPC specific. */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013074 return do_swapcontext(cpu_env, arg1, arg2, arg3);
Richard Hendersonfa97e382018-07-18 13:06:48 -070013075#endif
Shu-Chun Weng9bdfa4d2019-08-19 11:09:47 -070013076#ifdef TARGET_NR_memfd_create
13077 case TARGET_NR_memfd_create:
13078 p = lock_user_string(arg1);
13079 if (!p) {
13080 return -TARGET_EFAULT;
13081 }
13082 ret = get_errno(memfd_create(p, arg2));
13083 fd_trans_unregister(ret);
13084 unlock_user(p, arg1, 0);
13085 return ret;
13086#endif
Andreas Schwab85004762019-05-13 11:02:53 +020013087#if defined TARGET_NR_membarrier && defined __NR_membarrier
13088 case TARGET_NR_membarrier:
13089 return get_errno(membarrier(arg1, arg2));
13090#endif
Riku Voipio9af5c902014-08-12 15:58:57 +030013091
Andreas Schwab84946452020-11-12 12:45:16 +010013092#if defined(TARGET_NR_copy_file_range) && defined(__NR_copy_file_range)
13093 case TARGET_NR_copy_file_range:
13094 {
13095 loff_t inoff, outoff;
13096 loff_t *pinoff = NULL, *poutoff = NULL;
13097
13098 if (arg2) {
13099 if (get_user_u64(inoff, arg2)) {
13100 return -TARGET_EFAULT;
13101 }
13102 pinoff = &inoff;
13103 }
13104 if (arg4) {
13105 if (get_user_u64(outoff, arg4)) {
13106 return -TARGET_EFAULT;
13107 }
13108 poutoff = &outoff;
13109 }
Giuseppe Musacchio0fa259d2021-05-03 19:41:59 +020013110 /* Do not sign-extend the count parameter. */
Andreas Schwab84946452020-11-12 12:45:16 +010013111 ret = get_errno(safe_copy_file_range(arg1, pinoff, arg3, poutoff,
Giuseppe Musacchio0fa259d2021-05-03 19:41:59 +020013112 (abi_ulong)arg5, arg6));
Andreas Schwab84946452020-11-12 12:45:16 +010013113 if (!is_error(ret) && ret > 0) {
13114 if (arg2) {
13115 if (put_user_u64(inoff, arg2)) {
13116 return -TARGET_EFAULT;
13117 }
13118 }
13119 if (arg4) {
13120 if (put_user_u64(outoff, arg4)) {
13121 return -TARGET_EFAULT;
13122 }
13123 }
13124 }
13125 }
13126 return ret;
13127#endif
13128
YAMAMOTO Takashie10fbe82021-05-31 14:50:12 +090013129#if defined(TARGET_NR_pivot_root)
13130 case TARGET_NR_pivot_root:
13131 {
13132 void *p2;
13133 p = lock_user_string(arg1); /* new_root */
13134 p2 = lock_user_string(arg2); /* put_old */
13135 if (!p || !p2) {
13136 ret = -TARGET_EFAULT;
13137 } else {
13138 ret = get_errno(pivot_root(p, p2));
13139 }
13140 unlock_user(p2, arg2, 0);
13141 unlock_user(p, arg1, 0);
13142 }
13143 return ret;
13144#endif
13145
bellard31e31b82003-02-18 22:55:36 +000013146 default:
Philippe Mathieu-Daudé122f9c82018-07-06 12:51:25 -030013147 qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013148 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +000013149 }
bellard31e31b82003-02-18 22:55:36 +000013150 return ret;
13151}
Richard Hendersondc1ce182018-08-18 12:01:04 -070013152
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +020013153abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1,
Richard Hendersondc1ce182018-08-18 12:01:04 -070013154 abi_long arg2, abi_long arg3, abi_long arg4,
13155 abi_long arg5, abi_long arg6, abi_long arg7,
13156 abi_long arg8)
13157{
Richard Henderson29a0af62019-03-22 16:07:18 -070013158 CPUState *cpu = env_cpu(cpu_env);
Richard Hendersondc1ce182018-08-18 12:01:04 -070013159 abi_long ret;
13160
13161#ifdef DEBUG_ERESTARTSYS
13162 /* Debug-only code for exercising the syscall-restart code paths
13163 * in the per-architecture cpu main loops: restart every syscall
13164 * the guest makes once before letting it through.
13165 */
13166 {
13167 static bool flag;
13168 flag = !flag;
13169 if (flag) {
Richard Hendersonaf254a22021-11-22 19:47:33 +010013170 return -QEMU_ERESTARTSYS;
Richard Hendersondc1ce182018-08-18 12:01:04 -070013171 }
13172 }
13173#endif
13174
Emilio G. Cotac36f7a62018-10-21 13:27:44 -040013175 record_syscall_start(cpu, num, arg1,
13176 arg2, arg3, arg4, arg5, arg6, arg7, arg8);
Richard Hendersondc1ce182018-08-18 12:01:04 -070013177
Josh Kunz4b25a502020-02-03 18:54:14 -080013178 if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
Filip Bozutae400e112020-08-11 18:45:49 +020013179 print_syscall(cpu_env, num, arg1, arg2, arg3, arg4, arg5, arg6);
Josh Kunz4b25a502020-02-03 18:54:14 -080013180 }
13181
13182 ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4,
13183 arg5, arg6, arg7, arg8);
13184
13185 if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
Filip Bozutae400e112020-08-11 18:45:49 +020013186 print_syscall_ret(cpu_env, num, ret, arg1, arg2,
13187 arg3, arg4, arg5, arg6);
Richard Hendersondc1ce182018-08-18 12:01:04 -070013188 }
13189
Emilio G. Cotac36f7a62018-10-21 13:27:44 -040013190 record_syscall_return(cpu, num, ret);
Richard Hendersondc1ce182018-08-18 12:01:04 -070013191 return ret;
13192}