blob: 389ec09764734b2dc71d111181caf9d6fb68337e [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"
Richard Henderson5ebdd772019-03-14 13:10:53 -0700130#include "qemu/guest-random.h"
Alex Bennée01ef6b92020-04-03 20:11:46 +0100131#include "qemu/selfmap.h"
Emilio G. Cotac36f7a62018-10-21 13:27:44 -0400132#include "user/syscall-trace.h"
Richard Henderson51977e22019-03-12 19:22:20 -0700133#include "qapi/error.h"
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200134#include "fd-trans.h"
Philippe Mathieu-Daudédcb32f12020-01-01 12:23:00 +0100135#include "tcg/tcg.h"
bellard31e31b82003-02-18 22:55:36 +0000136
Peter Maydell5ea2fc82016-08-02 18:41:27 +0100137#ifndef CLONE_IO
138#define CLONE_IO 0x80000000 /* Clone io context */
139#endif
140
141/* We can't directly call the host clone syscall, because this will
142 * badly confuse libc (breaking mutexes, for example). So we must
143 * divide clone flags into:
144 * * flag combinations that look like pthread_create()
145 * * flag combinations that look like fork()
146 * * flags we can implement within QEMU itself
147 * * flags we can't support and will return an error for
148 */
149/* For thread creation, all these flags must be present; for
150 * fork, none must be present.
151 */
152#define CLONE_THREAD_FLAGS \
153 (CLONE_VM | CLONE_FS | CLONE_FILES | \
154 CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM)
155
156/* These flags are ignored:
157 * CLONE_DETACHED is now ignored by the kernel;
158 * CLONE_IO is just an optimisation hint to the I/O scheduler
159 */
160#define CLONE_IGNORED_FLAGS \
161 (CLONE_DETACHED | CLONE_IO)
162
163/* Flags for fork which we can implement within QEMU itself */
164#define CLONE_OPTIONAL_FORK_FLAGS \
165 (CLONE_SETTLS | CLONE_PARENT_SETTID | \
166 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID)
167
168/* Flags for thread creation which we can implement within QEMU itself */
169#define CLONE_OPTIONAL_THREAD_FLAGS \
170 (CLONE_SETTLS | CLONE_PARENT_SETTID | \
171 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | CLONE_PARENT)
172
173#define CLONE_INVALID_FORK_FLAGS \
174 (~(CSIGNAL | CLONE_OPTIONAL_FORK_FLAGS | CLONE_IGNORED_FLAGS))
175
176#define CLONE_INVALID_THREAD_FLAGS \
177 (~(CSIGNAL | CLONE_THREAD_FLAGS | CLONE_OPTIONAL_THREAD_FLAGS | \
178 CLONE_IGNORED_FLAGS))
179
180/* CLONE_VFORK is special cased early in do_fork(). The other flag bits
181 * have almost all been allocated. We cannot support any of
182 * CLONE_NEWNS, CLONE_NEWCGROUP, CLONE_NEWUTS, CLONE_NEWIPC,
183 * CLONE_NEWUSER, CLONE_NEWPID, CLONE_NEWNET, CLONE_PTRACE, CLONE_UNTRACED.
184 * The checks against the invalid thread masks above will catch these.
185 * (The one remaining unallocated bit is 0x1000 which used to be CLONE_PID.)
186 */
pbrook30813ce2008-06-02 15:45:44 +0000187
Timothy E Baldwin71a8f7f2016-05-12 18:47:45 +0100188/* Define DEBUG_ERESTARTSYS to force every syscall to be restarted
189 * once. This exercises the codepaths for restart.
190 */
191//#define DEBUG_ERESTARTSYS
bellard31e31b82003-02-18 22:55:36 +0000192
bellard1a9353d2003-03-16 20:28:50 +0000193//#include <linux/msdos_fs.h>
aurel326556a832008-10-13 21:08:17 +0000194#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2])
195#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct linux_dirent [2])
bellard1a9353d2003-03-16 20:28:50 +0000196
bellard70a194b2003-08-11 22:20:16 +0000197#undef _syscall0
198#undef _syscall1
199#undef _syscall2
200#undef _syscall3
201#undef _syscall4
202#undef _syscall5
bellard83fcb512006-06-14 13:37:16 +0000203#undef _syscall6
bellard70a194b2003-08-11 22:20:16 +0000204
bellard83fcb512006-06-14 13:37:16 +0000205#define _syscall0(type,name) \
blueswir18fcd3692008-08-17 20:26:25 +0000206static type name (void) \
bellard83fcb512006-06-14 13:37:16 +0000207{ \
208 return syscall(__NR_##name); \
bellard70a194b2003-08-11 22:20:16 +0000209}
210
bellard83fcb512006-06-14 13:37:16 +0000211#define _syscall1(type,name,type1,arg1) \
blueswir18fcd3692008-08-17 20:26:25 +0000212static type name (type1 arg1) \
bellard83fcb512006-06-14 13:37:16 +0000213{ \
214 return syscall(__NR_##name, arg1); \
bellard70a194b2003-08-11 22:20:16 +0000215}
216
bellard83fcb512006-06-14 13:37:16 +0000217#define _syscall2(type,name,type1,arg1,type2,arg2) \
blueswir18fcd3692008-08-17 20:26:25 +0000218static type name (type1 arg1,type2 arg2) \
bellard83fcb512006-06-14 13:37:16 +0000219{ \
220 return syscall(__NR_##name, arg1, arg2); \
bellard70a194b2003-08-11 22:20:16 +0000221}
222
bellard83fcb512006-06-14 13:37:16 +0000223#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
blueswir18fcd3692008-08-17 20:26:25 +0000224static type name (type1 arg1,type2 arg2,type3 arg3) \
bellard83fcb512006-06-14 13:37:16 +0000225{ \
226 return syscall(__NR_##name, arg1, arg2, arg3); \
bellard70a194b2003-08-11 22:20:16 +0000227}
228
bellard83fcb512006-06-14 13:37:16 +0000229#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
blueswir18fcd3692008-08-17 20:26:25 +0000230static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
bellard83fcb512006-06-14 13:37:16 +0000231{ \
232 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
bellard70a194b2003-08-11 22:20:16 +0000233}
234
bellard83fcb512006-06-14 13:37:16 +0000235#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
236 type5,arg5) \
blueswir18fcd3692008-08-17 20:26:25 +0000237static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
bellard83fcb512006-06-14 13:37:16 +0000238{ \
239 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
bellard70a194b2003-08-11 22:20:16 +0000240}
bellard83fcb512006-06-14 13:37:16 +0000241
242
243#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
244 type5,arg5,type6,arg6) \
blueswir18fcd3692008-08-17 20:26:25 +0000245static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
246 type6 arg6) \
bellard83fcb512006-06-14 13:37:16 +0000247{ \
248 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
249}
250
bellard70a194b2003-08-11 22:20:16 +0000251
bellard31e31b82003-02-18 22:55:36 +0000252#define __NR_sys_uname __NR_uname
bellard72f03902003-02-18 23:33:18 +0000253#define __NR_sys_getcwd1 __NR_getcwd
bellard72f03902003-02-18 23:33:18 +0000254#define __NR_sys_getdents __NR_getdents
bellarddab2ed92003-03-22 15:23:14 +0000255#define __NR_sys_getdents64 __NR_getdents64
thsc6cda172007-10-09 03:42:34 +0000256#define __NR_sys_getpriority __NR_getpriority
bellard66fb9762003-03-23 01:06:05 +0000257#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +0200258#define __NR_sys_rt_tgsigqueueinfo __NR_rt_tgsigqueueinfo
ths7494b0f2007-02-11 18:26:53 +0000259#define __NR_sys_syslog __NR_syslog
Alistair Francis14690292020-03-18 15:47:01 -0700260#if defined(__NR_futex)
261# define __NR_sys_futex __NR_futex
262#endif
263#if defined(__NR_futex_time64)
264# define __NR_sys_futex_time64 __NR_futex_time64
265#endif
aurel3239b59762008-10-01 21:46:50 +0000266#define __NR_sys_inotify_init __NR_inotify_init
267#define __NR_sys_inotify_add_watch __NR_inotify_add_watch
268#define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch
Aleksandar Rikaloefa92182019-06-28 12:43:34 +0200269#define __NR_sys_statx __NR_statx
bellard31e31b82003-02-18 22:55:36 +0000270
Peter Maydellb1cef6d2018-01-25 16:19:49 +0000271#if defined(__alpha__) || defined(__x86_64__) || defined(__s390x__)
bellard9af9eaa2003-04-07 21:34:41 +0000272#define __NR__llseek __NR_lseek
273#endif
274
James Hogana29e5ba2014-03-25 21:51:08 +0000275/* Newer kernel ports have llseek() instead of _llseek() */
276#if defined(TARGET_NR_llseek) && !defined(TARGET_NR__llseek)
277#define TARGET_NR__llseek TARGET_NR_llseek
278#endif
279
Helge Deller78721302021-02-10 07:12:14 +0100280/* some platforms need to mask more bits than just TARGET_O_NONBLOCK */
281#ifndef TARGET_O_NONBLOCK_MASK
282#define TARGET_O_NONBLOCK_MASK TARGET_O_NONBLOCK
283#endif
284
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +0000285#define __NR_sys_gettid __NR_gettid
286_syscall0(int, sys_gettid)
Peter Maydell2b3f64c2018-04-19 13:57:40 +0100287
288/* For the 64-bit guest on 32-bit host case we must emulate
289 * getdents using getdents64, because otherwise the host
290 * might hand us back more dirent records than we can fit
291 * into the guest buffer after structure format conversion.
292 * Otherwise we emulate getdents with getdents if the host has it.
293 */
294#if defined(__NR_getdents) && HOST_LONG_BITS >= TARGET_ABI_BITS
295#define EMULATE_GETDENTS_WITH_GETDENTS
296#endif
297
298#if defined(TARGET_NR_getdents) && defined(EMULATE_GETDENTS_WITH_GETDENTS)
aurel323b3f24a2009-04-15 16:12:13 +0000299_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
Peter Maydell3307e232013-06-12 16:20:21 +0100300#endif
Peter Maydell2b3f64c2018-04-19 13:57:40 +0100301#if (defined(TARGET_NR_getdents) && \
302 !defined(EMULATE_GETDENTS_WITH_GETDENTS)) || \
Peter Maydell3307e232013-06-12 16:20:21 +0100303 (defined(TARGET_NR_getdents64) && defined(__NR_getdents64))
aurel323b3f24a2009-04-15 16:12:13 +0000304_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
305#endif
Richard Hendersond35b2612010-06-04 12:14:10 -0700306#if defined(TARGET_NR__llseek) && defined(__NR_llseek)
aurel323b3f24a2009-04-15 16:12:13 +0000307_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
308 loff_t *, res, uint, wh);
309#endif
Miloš Stojanovićc1a402a2017-05-15 16:59:45 +0200310_syscall3(int, sys_rt_sigqueueinfo, pid_t, pid, int, sig, siginfo_t *, uinfo)
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +0200311_syscall4(int, sys_rt_tgsigqueueinfo, pid_t, pid, pid_t, tid, int, sig,
312 siginfo_t *, uinfo)
aurel323b3f24a2009-04-15 16:12:13 +0000313_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
aurel323b3f24a2009-04-15 16:12:13 +0000314#ifdef __NR_exit_group
315_syscall1(int,exit_group,int,error_code)
316#endif
317#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
318_syscall1(int,set_tid_address,int *,tidptr)
319#endif
Alistair Francis14690292020-03-18 15:47:01 -0700320#if defined(__NR_futex)
aurel323b3f24a2009-04-15 16:12:13 +0000321_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
322 const struct timespec *,timeout,int *,uaddr2,int,val3)
323#endif
Alistair Francis14690292020-03-18 15:47:01 -0700324#if defined(__NR_futex_time64)
325_syscall6(int,sys_futex_time64,int *,uaddr,int,op,int,val,
326 const struct timespec *,timeout,int *,uaddr2,int,val3)
327#endif
Mike Frysinger737de1d2011-02-07 01:05:55 -0500328#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
329_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
330 unsigned long *, user_mask_ptr);
331#define __NR_sys_sched_setaffinity __NR_sched_setaffinity
332_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
333 unsigned long *, user_mask_ptr);
Samuel Thibaultb827c3e2018-01-12 09:14:35 +0100334#define __NR_sys_getcpu __NR_getcpu
335_syscall3(int, sys_getcpu, unsigned *, cpu, unsigned *, node, void *, tcache);
Alexander Graf0f6b4d22011-09-27 14:39:42 +0200336_syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd,
337 void *, arg);
Peter Maydelle0eb2102014-03-17 12:15:35 +0000338_syscall2(int, capget, struct __user_cap_header_struct *, header,
339 struct __user_cap_data_struct *, data);
340_syscall2(int, capset, struct __user_cap_header_struct *, header,
341 struct __user_cap_data_struct *, data);
Paul Burtonab31cda2014-06-22 11:25:43 +0100342#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
343_syscall2(int, ioprio_get, int, which, int, who)
344#endif
345#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
346_syscall3(int, ioprio_set, int, which, int, who, int, ioprio)
347#endif
Laurent Vivierf894efd2016-02-21 10:56:23 +0100348#if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
349_syscall3(int, getrandom, void *, buf, size_t, buflen, unsigned int, flags)
350#endif
aurel323b3f24a2009-04-15 16:12:13 +0000351
Laurent Vivier2f147882016-09-25 22:20:20 +0200352#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
353_syscall5(int, kcmp, pid_t, pid1, pid_t, pid2, int, type,
354 unsigned long, idx1, unsigned long, idx2)
355#endif
356
Aleksandar Rikaloefa92182019-06-28 12:43:34 +0200357/*
358 * It is assumed that struct statx is architecture independent.
359 */
360#if defined(TARGET_NR_statx) && defined(__NR_statx)
361_syscall5(int, sys_statx, int, dirfd, const char *, pathname, int, flags,
362 unsigned int, mask, struct target_statx *, statxbuf)
363#endif
Andreas Schwab85004762019-05-13 11:02:53 +0200364#if defined(TARGET_NR_membarrier) && defined(__NR_membarrier)
365_syscall2(int, membarrier, int, cmd, int, flags)
366#endif
Aleksandar Rikaloefa92182019-06-28 12:43:34 +0200367
aurel323b3f24a2009-04-15 16:12:13 +0000368static bitmask_transtbl fcntl_flags_tbl[] = {
369 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
370 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
371 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
372 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
373 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
374 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
375 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
376 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
Richard Hendersonafc87632012-07-25 14:30:34 -0700377 { TARGET_O_SYNC, TARGET_O_DSYNC, O_SYNC, O_DSYNC, },
aurel323b3f24a2009-04-15 16:12:13 +0000378 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
379 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
380 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
381 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
aurel323b3f24a2009-04-15 16:12:13 +0000382#if defined(O_DIRECT)
383 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
384#endif
Richard Hendersonafc87632012-07-25 14:30:34 -0700385#if defined(O_NOATIME)
386 { TARGET_O_NOATIME, TARGET_O_NOATIME, O_NOATIME, O_NOATIME },
387#endif
388#if defined(O_CLOEXEC)
389 { TARGET_O_CLOEXEC, TARGET_O_CLOEXEC, O_CLOEXEC, O_CLOEXEC },
390#endif
391#if defined(O_PATH)
392 { TARGET_O_PATH, TARGET_O_PATH, O_PATH, O_PATH },
393#endif
Riku Voipio5f9cee42017-08-08 16:01:19 +0300394#if defined(O_TMPFILE)
395 { TARGET_O_TMPFILE, TARGET_O_TMPFILE, O_TMPFILE, O_TMPFILE },
396#endif
Richard Hendersonafc87632012-07-25 14:30:34 -0700397 /* Don't terminate the list prematurely on 64-bit host+guest. */
398#if TARGET_O_LARGEFILE != 0 || O_LARGEFILE != 0
399 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
400#endif
aurel323b3f24a2009-04-15 16:12:13 +0000401 { 0, 0, 0, 0 }
402};
403
Andreas Schwab0f6bb192020-07-23 12:27:13 +0200404_syscall2(int, sys_getcwd1, char *, buf, size_t, size)
aurel323b3f24a2009-04-15 16:12:13 +0000405
Filip Bozutacac46eb2020-08-25 00:30:50 +0200406#if defined(TARGET_NR_utimensat) || defined(TARGET_NR_utimensat_time64)
Peter Maydell700fa582016-07-18 11:47:55 +0100407#if defined(__NR_utimensat)
Peter Maydell1acae9f2013-07-02 14:04:12 +0100408#define __NR_sys_utimensat __NR_utimensat
ths9007f0e2007-09-25 17:50:37 +0000409_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
410 const struct timespec *,tsp,int,flags)
Peter Maydell1acae9f2013-07-02 14:04:12 +0100411#else
412static int sys_utimensat(int dirfd, const char *pathname,
413 const struct timespec times[2], int flags)
414{
415 errno = ENOSYS;
416 return -1;
417}
ths9007f0e2007-09-25 17:50:37 +0000418#endif
Peter Maydell1acae9f2013-07-02 14:04:12 +0100419#endif /* TARGET_NR_utimensat */
aurel323b3f24a2009-04-15 16:12:13 +0000420
Andreas Schwab95d03072018-01-23 11:53:31 +0100421#ifdef TARGET_NR_renameat2
422#if defined(__NR_renameat2)
423#define __NR_sys_renameat2 __NR_renameat2
424_syscall5(int, sys_renameat2, int, oldfd, const char *, old, int, newfd,
425 const char *, new, unsigned int, flags)
426#else
427static int sys_renameat2(int oldfd, const char *old,
428 int newfd, const char *new, int flags)
429{
430 if (flags == 0) {
431 return renameat(oldfd, old, newfd, new);
432 }
433 errno = ENOSYS;
434 return -1;
435}
436#endif
437#endif /* TARGET_NR_renameat2 */
438
aurel323b3f24a2009-04-15 16:12:13 +0000439#ifdef CONFIG_INOTIFY
aurel328690e422009-04-17 13:50:32 +0000440#include <sys/inotify.h>
aurel323b3f24a2009-04-15 16:12:13 +0000441
aurel3239b59762008-10-01 21:46:50 +0000442#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
aurel323b3f24a2009-04-15 16:12:13 +0000443static int sys_inotify_init(void)
444{
445 return (inotify_init());
446}
aurel3239b59762008-10-01 21:46:50 +0000447#endif
448#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
aurel323b3f24a2009-04-15 16:12:13 +0000449static int sys_inotify_add_watch(int fd,const char *pathname, int32_t mask)
450{
451 return (inotify_add_watch(fd, pathname, mask));
452}
aurel3239b59762008-10-01 21:46:50 +0000453#endif
454#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
aurel323b3f24a2009-04-15 16:12:13 +0000455static int sys_inotify_rm_watch(int fd, int32_t wd)
456{
aurel328690e422009-04-17 13:50:32 +0000457 return (inotify_rm_watch(fd, wd));
aurel323b3f24a2009-04-15 16:12:13 +0000458}
aurel3239b59762008-10-01 21:46:50 +0000459#endif
Riku Voipioc05c7a72010-03-26 15:25:11 +0000460#ifdef CONFIG_INOTIFY1
461#if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1)
462static int sys_inotify_init1(int flags)
463{
464 return (inotify_init1(flags));
465}
466#endif
467#endif
aurel323b3f24a2009-04-15 16:12:13 +0000468#else
469/* Userspace can usually survive runtime without inotify */
470#undef TARGET_NR_inotify_init
Riku Voipioc05c7a72010-03-26 15:25:11 +0000471#undef TARGET_NR_inotify_init1
aurel323b3f24a2009-04-15 16:12:13 +0000472#undef TARGET_NR_inotify_add_watch
473#undef TARGET_NR_inotify_rm_watch
474#endif /* CONFIG_INOTIFY */
475
Peter Maydell163a05a2011-06-27 17:44:52 +0100476#if defined(TARGET_NR_prlimit64)
477#ifndef __NR_prlimit64
478# define __NR_prlimit64 -1
479#endif
480#define __NR_sys_prlimit64 __NR_prlimit64
481/* The glibc rlimit structure may not be that used by the underlying syscall */
482struct host_rlimit64 {
483 uint64_t rlim_cur;
484 uint64_t rlim_max;
485};
486_syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
487 const struct host_rlimit64 *, new_limit,
488 struct host_rlimit64 *, old_limit)
489#endif
490
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +1100491
492#if defined(TARGET_NR_timer_create)
zhaolichang6f9ff552020-09-17 15:50:25 +0800493/* Maximum of 32 active POSIX timers allowed at any one time. */
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +1100494static timer_t g_posix_timers[32] = { 0, } ;
495
496static inline int next_free_host_timer(void)
497{
498 int k ;
499 /* FIXME: Does finding the next free slot require a lock? */
500 for (k = 0; k < ARRAY_SIZE(g_posix_timers); k++) {
501 if (g_posix_timers[k] == 0) {
502 g_posix_timers[k] = (timer_t) 1;
503 return k;
504 }
505 }
506 return -1;
507}
508#endif
509
thsb92c47c2007-11-01 00:07:38 +0000510#define ERRNO_TABLE_SIZE 1200
511
512/* target_to_host_errno_table[] is initialized from
513 * host_to_target_errno_table[] in syscall_init(). */
514static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
515};
516
ths637947f2007-06-01 12:09:19 +0000517/*
thsfe8f0962007-07-12 10:59:21 +0000518 * This list is the union of errno values overridden in asm-<arch>/errno.h
ths637947f2007-06-01 12:09:19 +0000519 * minus the errnos that are not actually generic to all archs.
520 */
thsb92c47c2007-11-01 00:07:38 +0000521static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
Chen Gang08703b92015-09-07 10:35:06 +0800522 [EAGAIN] = TARGET_EAGAIN,
ths637947f2007-06-01 12:09:19 +0000523 [EIDRM] = TARGET_EIDRM,
524 [ECHRNG] = TARGET_ECHRNG,
525 [EL2NSYNC] = TARGET_EL2NSYNC,
526 [EL3HLT] = TARGET_EL3HLT,
527 [EL3RST] = TARGET_EL3RST,
528 [ELNRNG] = TARGET_ELNRNG,
529 [EUNATCH] = TARGET_EUNATCH,
530 [ENOCSI] = TARGET_ENOCSI,
531 [EL2HLT] = TARGET_EL2HLT,
532 [EDEADLK] = TARGET_EDEADLK,
533 [ENOLCK] = TARGET_ENOLCK,
534 [EBADE] = TARGET_EBADE,
535 [EBADR] = TARGET_EBADR,
536 [EXFULL] = TARGET_EXFULL,
537 [ENOANO] = TARGET_ENOANO,
538 [EBADRQC] = TARGET_EBADRQC,
539 [EBADSLT] = TARGET_EBADSLT,
540 [EBFONT] = TARGET_EBFONT,
541 [ENOSTR] = TARGET_ENOSTR,
542 [ENODATA] = TARGET_ENODATA,
543 [ETIME] = TARGET_ETIME,
544 [ENOSR] = TARGET_ENOSR,
545 [ENONET] = TARGET_ENONET,
546 [ENOPKG] = TARGET_ENOPKG,
547 [EREMOTE] = TARGET_EREMOTE,
548 [ENOLINK] = TARGET_ENOLINK,
549 [EADV] = TARGET_EADV,
550 [ESRMNT] = TARGET_ESRMNT,
551 [ECOMM] = TARGET_ECOMM,
552 [EPROTO] = TARGET_EPROTO,
553 [EDOTDOT] = TARGET_EDOTDOT,
554 [EMULTIHOP] = TARGET_EMULTIHOP,
555 [EBADMSG] = TARGET_EBADMSG,
556 [ENAMETOOLONG] = TARGET_ENAMETOOLONG,
557 [EOVERFLOW] = TARGET_EOVERFLOW,
558 [ENOTUNIQ] = TARGET_ENOTUNIQ,
559 [EBADFD] = TARGET_EBADFD,
560 [EREMCHG] = TARGET_EREMCHG,
561 [ELIBACC] = TARGET_ELIBACC,
562 [ELIBBAD] = TARGET_ELIBBAD,
563 [ELIBSCN] = TARGET_ELIBSCN,
564 [ELIBMAX] = TARGET_ELIBMAX,
565 [ELIBEXEC] = TARGET_ELIBEXEC,
566 [EILSEQ] = TARGET_EILSEQ,
567 [ENOSYS] = TARGET_ENOSYS,
568 [ELOOP] = TARGET_ELOOP,
569 [ERESTART] = TARGET_ERESTART,
570 [ESTRPIPE] = TARGET_ESTRPIPE,
571 [ENOTEMPTY] = TARGET_ENOTEMPTY,
572 [EUSERS] = TARGET_EUSERS,
573 [ENOTSOCK] = TARGET_ENOTSOCK,
574 [EDESTADDRREQ] = TARGET_EDESTADDRREQ,
575 [EMSGSIZE] = TARGET_EMSGSIZE,
576 [EPROTOTYPE] = TARGET_EPROTOTYPE,
577 [ENOPROTOOPT] = TARGET_ENOPROTOOPT,
578 [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT,
579 [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT,
580 [EOPNOTSUPP] = TARGET_EOPNOTSUPP,
581 [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT,
582 [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT,
583 [EADDRINUSE] = TARGET_EADDRINUSE,
584 [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL,
585 [ENETDOWN] = TARGET_ENETDOWN,
586 [ENETUNREACH] = TARGET_ENETUNREACH,
587 [ENETRESET] = TARGET_ENETRESET,
588 [ECONNABORTED] = TARGET_ECONNABORTED,
589 [ECONNRESET] = TARGET_ECONNRESET,
590 [ENOBUFS] = TARGET_ENOBUFS,
591 [EISCONN] = TARGET_EISCONN,
592 [ENOTCONN] = TARGET_ENOTCONN,
593 [EUCLEAN] = TARGET_EUCLEAN,
594 [ENOTNAM] = TARGET_ENOTNAM,
595 [ENAVAIL] = TARGET_ENAVAIL,
596 [EISNAM] = TARGET_EISNAM,
597 [EREMOTEIO] = TARGET_EREMOTEIO,
Aleksandar Markovic0444a3b2016-09-19 13:44:43 +0200598 [EDQUOT] = TARGET_EDQUOT,
ths637947f2007-06-01 12:09:19 +0000599 [ESHUTDOWN] = TARGET_ESHUTDOWN,
600 [ETOOMANYREFS] = TARGET_ETOOMANYREFS,
601 [ETIMEDOUT] = TARGET_ETIMEDOUT,
602 [ECONNREFUSED] = TARGET_ECONNREFUSED,
603 [EHOSTDOWN] = TARGET_EHOSTDOWN,
604 [EHOSTUNREACH] = TARGET_EHOSTUNREACH,
605 [EALREADY] = TARGET_EALREADY,
606 [EINPROGRESS] = TARGET_EINPROGRESS,
607 [ESTALE] = TARGET_ESTALE,
608 [ECANCELED] = TARGET_ECANCELED,
609 [ENOMEDIUM] = TARGET_ENOMEDIUM,
610 [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE,
thsb7fe5db2007-07-23 15:37:46 +0000611#ifdef ENOKEY
ths637947f2007-06-01 12:09:19 +0000612 [ENOKEY] = TARGET_ENOKEY,
thsb7fe5db2007-07-23 15:37:46 +0000613#endif
614#ifdef EKEYEXPIRED
ths637947f2007-06-01 12:09:19 +0000615 [EKEYEXPIRED] = TARGET_EKEYEXPIRED,
thsb7fe5db2007-07-23 15:37:46 +0000616#endif
617#ifdef EKEYREVOKED
ths637947f2007-06-01 12:09:19 +0000618 [EKEYREVOKED] = TARGET_EKEYREVOKED,
thsb7fe5db2007-07-23 15:37:46 +0000619#endif
620#ifdef EKEYREJECTED
ths637947f2007-06-01 12:09:19 +0000621 [EKEYREJECTED] = TARGET_EKEYREJECTED,
thsb7fe5db2007-07-23 15:37:46 +0000622#endif
623#ifdef EOWNERDEAD
ths637947f2007-06-01 12:09:19 +0000624 [EOWNERDEAD] = TARGET_EOWNERDEAD,
thsb7fe5db2007-07-23 15:37:46 +0000625#endif
626#ifdef ENOTRECOVERABLE
ths637947f2007-06-01 12:09:19 +0000627 [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
thsb7fe5db2007-07-23 15:37:46 +0000628#endif
Aleksandar Markovicda39db62016-09-22 18:56:56 +0200629#ifdef ENOMSG
630 [ENOMSG] = TARGET_ENOMSG,
631#endif
Richard Hendersonfe8ed7d2016-12-05 13:08:12 -0800632#ifdef ERKFILL
633 [ERFKILL] = TARGET_ERFKILL,
634#endif
635#ifdef EHWPOISON
636 [EHWPOISON] = TARGET_EHWPOISON,
637#endif
thsb92c47c2007-11-01 00:07:38 +0000638};
ths637947f2007-06-01 12:09:19 +0000639
640static inline int host_to_target_errno(int err)
641{
Timothy E Baldwin24661192016-05-12 18:47:25 +0100642 if (err >= 0 && err < ERRNO_TABLE_SIZE &&
643 host_to_target_errno_table[err]) {
ths637947f2007-06-01 12:09:19 +0000644 return host_to_target_errno_table[err];
Timothy E Baldwin24661192016-05-12 18:47:25 +0100645 }
ths637947f2007-06-01 12:09:19 +0000646 return err;
647}
648
thsb92c47c2007-11-01 00:07:38 +0000649static inline int target_to_host_errno(int err)
650{
Timothy E Baldwin24661192016-05-12 18:47:25 +0100651 if (err >= 0 && err < ERRNO_TABLE_SIZE &&
652 target_to_host_errno_table[err]) {
thsb92c47c2007-11-01 00:07:38 +0000653 return target_to_host_errno_table[err];
Timothy E Baldwin24661192016-05-12 18:47:25 +0100654 }
thsb92c47c2007-11-01 00:07:38 +0000655 return err;
656}
657
blueswir1992f48a2007-10-14 16:27:31 +0000658static inline abi_long get_errno(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000659{
660 if (ret == -1)
ths637947f2007-06-01 12:09:19 +0000661 return -host_to_target_errno(errno);
bellard31e31b82003-02-18 22:55:36 +0000662 else
663 return ret;
664}
665
Peter Maydell7dcdaea2016-06-06 19:58:18 +0100666const char *target_strerror(int err)
thsb92c47c2007-11-01 00:07:38 +0000667{
Peter Maydellda2a34f2016-06-06 19:58:19 +0100668 if (err == TARGET_ERESTARTSYS) {
669 return "To be restarted";
670 }
671 if (err == TARGET_QEMU_ESIGRETURN) {
672 return "Successful exit from sigreturn";
673 }
674
Alexander Graf962b2892011-11-21 12:04:07 +0100675 if ((err >= ERRNO_TABLE_SIZE) || (err < 0)) {
676 return NULL;
677 }
thsb92c47c2007-11-01 00:07:38 +0000678 return strerror(target_to_host_errno(err));
679}
680
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100681#define safe_syscall0(type, name) \
682static type safe_##name(void) \
683{ \
684 return safe_syscall(__NR_##name); \
685}
686
687#define safe_syscall1(type, name, type1, arg1) \
688static type safe_##name(type1 arg1) \
689{ \
690 return safe_syscall(__NR_##name, arg1); \
691}
692
693#define safe_syscall2(type, name, type1, arg1, type2, arg2) \
694static type safe_##name(type1 arg1, type2 arg2) \
695{ \
696 return safe_syscall(__NR_##name, arg1, arg2); \
697}
698
699#define safe_syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
700static type safe_##name(type1 arg1, type2 arg2, type3 arg3) \
701{ \
702 return safe_syscall(__NR_##name, arg1, arg2, arg3); \
703}
704
705#define safe_syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
706 type4, arg4) \
707static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
708{ \
709 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4); \
710}
711
712#define safe_syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \
713 type4, arg4, type5, arg5) \
714static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
715 type5 arg5) \
716{ \
717 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
718}
719
720#define safe_syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \
721 type4, arg4, type5, arg5, type6, arg6) \
722static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
723 type5 arg5, type6 arg6) \
724{ \
725 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
726}
727
Timothy E Baldwin50afd022016-05-12 18:47:47 +0100728safe_syscall3(ssize_t, read, int, fd, void *, buff, size_t, count)
729safe_syscall3(ssize_t, write, int, fd, const void *, buff, size_t, count)
Timothy E Baldwinc10a0732016-05-12 18:47:48 +0100730safe_syscall4(int, openat, int, dirfd, const char *, pathname, \
731 int, flags, mode_t, mode)
Alistair Francis859e8a82020-03-12 15:13:49 -0700732#if defined(TARGET_NR_wait4) || defined(TARGET_NR_waitpid)
Timothy E Baldwin4af80a32016-05-12 18:47:49 +0100733safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \
734 struct rusage *, rusage)
Alistair Francis859e8a82020-03-12 15:13:49 -0700735#endif
Timothy E Baldwin4af80a32016-05-12 18:47:49 +0100736safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \
737 int, options, struct rusage *, rusage)
Timothy E Baldwinffdcbe22016-05-12 18:47:50 +0100738safe_syscall3(int, execve, const char *, filename, char **, argv, char **, envp)
Alistair Francis859e8a82020-03-12 15:13:49 -0700739#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \
Filip Bozutae5ce9682020-08-25 00:30:49 +0200740 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
Peter Maydell6df9d382016-05-12 18:47:51 +0100741safe_syscall6(int, pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, \
742 fd_set *, exceptfds, struct timespec *, timeout, void *, sig)
Alistair Francis859e8a82020-03-12 15:13:49 -0700743#endif
Filip Bozutae5ce9682020-08-25 00:30:49 +0200744#if defined(TARGET_NR_ppoll) || defined(TARGET_NR_ppoll_time64)
Peter Maydella6130232016-06-06 19:58:10 +0100745safe_syscall5(int, ppoll, struct pollfd *, ufds, unsigned int, nfds,
746 struct timespec *, tsp, const sigset_t *, sigmask,
747 size_t, sigsetsize)
Alistair Francis859e8a82020-03-12 15:13:49 -0700748#endif
Peter Maydell227f0212016-06-06 19:58:11 +0100749safe_syscall6(int, epoll_pwait, int, epfd, struct epoll_event *, events,
750 int, maxevents, int, timeout, const sigset_t *, sigmask,
751 size_t, sigsetsize)
Alistair Francis14690292020-03-18 15:47:01 -0700752#if defined(__NR_futex)
Peter Maydelld509eeb2016-05-12 18:47:52 +0100753safe_syscall6(int,futex,int *,uaddr,int,op,int,val, \
754 const struct timespec *,timeout,int *,uaddr2,int,val3)
Alistair Francis859e8a82020-03-12 15:13:49 -0700755#endif
Alistair Francis14690292020-03-18 15:47:01 -0700756#if defined(__NR_futex_time64)
757safe_syscall6(int,futex_time64,int *,uaddr,int,op,int,val, \
758 const struct timespec *,timeout,int *,uaddr2,int,val3)
759#endif
Peter Maydell2fe4fba2016-05-27 15:51:48 +0100760safe_syscall2(int, rt_sigsuspend, sigset_t *, newset, size_t, sigsetsize)
Peter Maydellbef653d2016-05-27 15:51:57 +0100761safe_syscall2(int, kill, pid_t, pid, int, sig)
762safe_syscall2(int, tkill, int, tid, int, sig)
763safe_syscall3(int, tgkill, int, tgid, int, pid, int, sig)
Peter Maydell918c03e2016-06-06 19:58:02 +0100764safe_syscall3(ssize_t, readv, int, fd, const struct iovec *, iov, int, iovcnt)
765safe_syscall3(ssize_t, writev, int, fd, const struct iovec *, iov, int, iovcnt)
Dejan Jovicevic0f263862016-10-11 11:52:46 +0200766safe_syscall5(ssize_t, preadv, int, fd, const struct iovec *, iov, int, iovcnt,
767 unsigned long, pos_l, unsigned long, pos_h)
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +0200768safe_syscall5(ssize_t, pwritev, int, fd, const struct iovec *, iov, int, iovcnt,
769 unsigned long, pos_l, unsigned long, pos_h)
Peter Maydell2a3c7612016-06-06 19:58:03 +0100770safe_syscall3(int, connect, int, fd, const struct sockaddr *, addr,
771 socklen_t, addrlen)
Peter Maydell66687532016-06-06 19:58:04 +0100772safe_syscall6(ssize_t, sendto, int, fd, const void *, buf, size_t, len,
773 int, flags, const struct sockaddr *, addr, socklen_t, addrlen)
774safe_syscall6(ssize_t, recvfrom, int, fd, void *, buf, size_t, len,
775 int, flags, struct sockaddr *, addr, socklen_t *, addrlen)
776safe_syscall3(ssize_t, sendmsg, int, fd, const struct msghdr *, msg, int, flags)
777safe_syscall3(ssize_t, recvmsg, int, fd, struct msghdr *, msg, int, flags)
Peter Maydell2a845982016-06-06 19:58:07 +0100778safe_syscall2(int, flock, int, fd, int, operation)
Filip Bozutaddcbde12020-08-24 21:21:16 +0200779#if defined(TARGET_NR_rt_sigtimedwait) || defined(TARGET_NR_rt_sigtimedwait_time64)
Peter Maydellb3f82332016-06-06 19:58:08 +0100780safe_syscall4(int, rt_sigtimedwait, const sigset_t *, these, siginfo_t *, uinfo,
781 const struct timespec *, uts, size_t, sigsetsize)
Alistair Francis859e8a82020-03-12 15:13:49 -0700782#endif
Peter Maydellff6dc132016-06-06 19:58:13 +0100783safe_syscall4(int, accept4, int, fd, struct sockaddr *, addr, socklen_t *, len,
784 int, flags)
Alistair Francis859e8a82020-03-12 15:13:49 -0700785#if defined(TARGET_NR_nanosleep)
Peter Maydell9e518222016-06-06 19:58:09 +0100786safe_syscall2(int, nanosleep, const struct timespec *, req,
787 struct timespec *, rem)
Alistair Francis859e8a82020-03-12 15:13:49 -0700788#endif
Filip Bozuta6ac03b22020-08-24 21:21:15 +0200789#if defined(TARGET_NR_clock_nanosleep) || \
790 defined(TARGET_NR_clock_nanosleep_time64)
Peter Maydell9e518222016-06-06 19:58:09 +0100791safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags,
792 const struct timespec *, req, struct timespec *, rem)
793#endif
Laurent Vivier524fa342019-05-29 10:48:04 +0200794#ifdef __NR_ipc
Matus Kyseld8c08b12020-06-26 14:46:11 +0200795#ifdef __s390x__
796safe_syscall5(int, ipc, int, call, long, first, long, second, long, third,
797 void *, ptr)
798#else
Peter Maydell89f9fe42016-06-06 19:58:05 +0100799safe_syscall6(int, ipc, int, call, long, first, long, second, long, third,
800 void *, ptr, long, fifth)
Laurent Vivier86e63692019-05-23 19:54:13 +0200801#endif
Matus Kyseld8c08b12020-06-26 14:46:11 +0200802#endif
Laurent Vivier86e63692019-05-23 19:54:13 +0200803#ifdef __NR_msgsnd
804safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz,
805 int, flags)
Laurent Vivier86e63692019-05-23 19:54:13 +0200806#endif
807#ifdef __NR_msgrcv
808safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz,
809 long, msgtype, int, flags)
Laurent Vivier86e63692019-05-23 19:54:13 +0200810#endif
811#ifdef __NR_semtimedop
812safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops,
813 unsigned, nsops, const struct timespec *, timeout)
Peter Maydell89f9fe42016-06-06 19:58:05 +0100814#endif
Filip Bozutad107e372020-08-24 21:37:52 +0200815#if defined(TARGET_NR_mq_timedsend) || \
816 defined(TARGET_NR_mq_timedsend_time64)
Peter Maydelld40ecd62016-06-06 19:58:06 +0100817safe_syscall5(int, mq_timedsend, int, mqdes, const char *, msg_ptr,
818 size_t, len, unsigned, prio, const struct timespec *, timeout)
Alistair Francis859e8a82020-03-12 15:13:49 -0700819#endif
Filip Bozutad107e372020-08-24 21:37:52 +0200820#if defined(TARGET_NR_mq_timedreceive) || \
821 defined(TARGET_NR_mq_timedreceive_time64)
Peter Maydelld40ecd62016-06-06 19:58:06 +0100822safe_syscall5(int, mq_timedreceive, int, mqdes, char *, msg_ptr,
823 size_t, len, unsigned *, prio, const struct timespec *, timeout)
824#endif
Andreas Schwab84946452020-11-12 12:45:16 +0100825#if defined(TARGET_NR_copy_file_range) && defined(__NR_copy_file_range)
826safe_syscall6(ssize_t, copy_file_range, int, infd, loff_t *, pinoff,
827 int, outfd, loff_t *, poutoff, size_t, length,
828 unsigned int, flags)
829#endif
830
Peter Maydell49ca6f32016-06-06 19:58:14 +0100831/* We do ioctl like this rather than via safe_syscall3 to preserve the
832 * "third argument might be integer or pointer or not present" behaviour of
833 * the libc function.
834 */
835#define safe_ioctl(...) safe_syscall(__NR_ioctl, __VA_ARGS__)
Peter Maydell435da5e2016-06-13 11:22:05 +0100836/* Similarly for fcntl. Note that callers must always:
837 * pass the F_GETLK64 etc constants rather than the unsuffixed F_GETLK
838 * use the flock64 struct rather than unsuffixed flock
839 * This will then work and use a 64-bit offset for both 32-bit and 64-bit hosts.
840 */
841#ifdef __NR_fcntl64
842#define safe_fcntl(...) safe_syscall(__NR_fcntl64, __VA_ARGS__)
843#else
844#define safe_fcntl(...) safe_syscall(__NR_fcntl, __VA_ARGS__)
845#endif
Timothy E Baldwin50afd022016-05-12 18:47:47 +0100846
Paul Burton8289d112014-06-22 11:25:33 +0100847static inline int host_to_target_sock_type(int host_type)
848{
849 int target_type;
850
851 switch (host_type & 0xf /* SOCK_TYPE_MASK */) {
852 case SOCK_DGRAM:
853 target_type = TARGET_SOCK_DGRAM;
854 break;
855 case SOCK_STREAM:
856 target_type = TARGET_SOCK_STREAM;
857 break;
858 default:
859 target_type = host_type & 0xf /* SOCK_TYPE_MASK */;
860 break;
861 }
862
863#if defined(SOCK_CLOEXEC)
864 if (host_type & SOCK_CLOEXEC) {
865 target_type |= TARGET_SOCK_CLOEXEC;
866 }
867#endif
868
869#if defined(SOCK_NONBLOCK)
870 if (host_type & SOCK_NONBLOCK) {
871 target_type |= TARGET_SOCK_NONBLOCK;
872 }
873#endif
874
875 return target_type;
876}
877
blueswir1992f48a2007-10-14 16:27:31 +0000878static abi_ulong target_brk;
879static abi_ulong target_original_brk;
vincent4d1de872011-06-14 21:56:33 +0000880static abi_ulong brk_page;
bellard31e31b82003-02-18 22:55:36 +0000881
blueswir1992f48a2007-10-14 16:27:31 +0000882void target_set_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000883{
blueswir14c1de732007-07-07 20:45:44 +0000884 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
vincent4d1de872011-06-14 21:56:33 +0000885 brk_page = HOST_PAGE_ALIGN(target_brk);
bellard31e31b82003-02-18 22:55:36 +0000886}
887
vincent4d1de872011-06-14 21:56:33 +0000888//#define DEBUGF_BRK(message, args...) do { fprintf(stderr, (message), ## args); } while (0)
889#define DEBUGF_BRK(message, args...)
890
ths0da46a62007-10-20 20:23:07 +0000891/* do_brk() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000892abi_long do_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000893{
blueswir1992f48a2007-10-14 16:27:31 +0000894 abi_long mapped_addr;
Peter Maydellef4330c2016-07-22 13:41:52 +0100895 abi_ulong new_alloc_size;
bellard31e31b82003-02-18 22:55:36 +0000896
Richard Hendersonee1bf832021-02-12 10:48:44 -0800897 /* brk pointers are always untagged */
898
Paul Brook3a0c6c42012-02-09 19:04:27 +0000899 DEBUGF_BRK("do_brk(" TARGET_ABI_FMT_lx ") -> ", new_brk);
ths3b46e622007-09-17 08:09:54 +0000900
vincent4d1de872011-06-14 21:56:33 +0000901 if (!new_brk) {
Paul Brook3a0c6c42012-02-09 19:04:27 +0000902 DEBUGF_BRK(TARGET_ABI_FMT_lx " (!new_brk)\n", target_brk);
vincent4d1de872011-06-14 21:56:33 +0000903 return target_brk;
904 }
905 if (new_brk < target_original_brk) {
Paul Brook3a0c6c42012-02-09 19:04:27 +0000906 DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk < target_original_brk)\n",
907 target_brk);
vincent4d1de872011-06-14 21:56:33 +0000908 return target_brk;
909 }
bellard31e31b82003-02-18 22:55:36 +0000910
vincent4d1de872011-06-14 21:56:33 +0000911 /* If the new brk is less than the highest page reserved to the
912 * target heap allocation, set it and we're almost done... */
913 if (new_brk <= brk_page) {
914 /* Heap contents are initialized to zero, as for anonymous
915 * mapped pages. */
916 if (new_brk > target_brk) {
Richard Henderson3e8f1622021-02-12 10:48:43 -0800917 memset(g2h_untagged(target_brk), 0, new_brk - target_brk);
vincent4d1de872011-06-14 21:56:33 +0000918 }
bellard31e31b82003-02-18 22:55:36 +0000919 target_brk = new_brk;
Paul Brook3a0c6c42012-02-09 19:04:27 +0000920 DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk <= brk_page)\n", target_brk);
Paolo Bonzini72e21db2018-12-13 23:37:36 +0100921 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000922 }
923
Peter Maydell00faf082011-04-18 16:34:24 +0100924 /* We need to allocate more memory after the brk... Note that
925 * we don't use MAP_FIXED because that will map over the top of
926 * any existing mapping (like the one with the host libc or qemu
927 * itself); instead we treat "mapped but at wrong address" as
928 * a failure and unmap again.
929 */
vincent4d1de872011-06-14 21:56:33 +0000930 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page);
ths5fafdf22007-09-16 21:08:06 +0000931 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
bellard54936002003-05-13 00:25:15 +0000932 PROT_READ|PROT_WRITE,
Peter Maydell00faf082011-04-18 16:34:24 +0100933 MAP_ANON|MAP_PRIVATE, 0, 0));
934
935 if (mapped_addr == brk_page) {
Cédric VINCENT70afc342011-08-26 10:56:50 +0200936 /* Heap contents are initialized to zero, as for anonymous
937 * mapped pages. Technically the new pages are already
938 * initialized to zero since they *are* anonymous mapped
939 * pages, however we have to take care with the contents that
940 * come from the remaining part of the previous page: it may
941 * contains garbage data due to a previous heap usage (grown
942 * then shrunken). */
Richard Henderson3e8f1622021-02-12 10:48:43 -0800943 memset(g2h_untagged(target_brk), 0, brk_page - target_brk);
Cédric VINCENT70afc342011-08-26 10:56:50 +0200944
Peter Maydell00faf082011-04-18 16:34:24 +0100945 target_brk = new_brk;
vincent4d1de872011-06-14 21:56:33 +0000946 brk_page = HOST_PAGE_ALIGN(target_brk);
Paul Brook3a0c6c42012-02-09 19:04:27 +0000947 DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr == brk_page)\n",
948 target_brk);
Peter Maydell00faf082011-04-18 16:34:24 +0100949 return target_brk;
950 } else if (mapped_addr != -1) {
951 /* Mapped but at wrong address, meaning there wasn't actually
952 * enough space for this brk.
953 */
954 target_munmap(mapped_addr, new_alloc_size);
955 mapped_addr = -1;
Paul Brook3a0c6c42012-02-09 19:04:27 +0000956 DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr != -1)\n", target_brk);
vincent4d1de872011-06-14 21:56:33 +0000957 }
958 else {
Paul Brook3a0c6c42012-02-09 19:04:27 +0000959 DEBUGF_BRK(TARGET_ABI_FMT_lx " (otherwise)\n", target_brk);
Peter Maydell00faf082011-04-18 16:34:24 +0100960 }
balrog7ab240a2008-04-26 12:17:34 +0000961
Richard Henderson7dd46c02010-05-03 10:07:49 -0700962#if defined(TARGET_ALPHA)
963 /* We (partially) emulate OSF/1 on Alpha, which requires we
964 return a proper errno, not an unchanged brk value. */
Peter Maydell00faf082011-04-18 16:34:24 +0100965 return -TARGET_ENOMEM;
Richard Henderson7dd46c02010-05-03 10:07:49 -0700966#endif
Peter Maydell00faf082011-04-18 16:34:24 +0100967 /* For everything else, return the previous break. */
balrog7ab240a2008-04-26 12:17:34 +0000968 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000969}
970
Alistair Francis859e8a82020-03-12 15:13:49 -0700971#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \
Filip Bozutae5ce9682020-08-25 00:30:49 +0200972 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
ths26edcf42007-12-09 02:25:24 +0000973static inline abi_long copy_from_user_fdset(fd_set *fds,
974 abi_ulong target_fds_addr,
975 int n)
bellard31e31b82003-02-18 22:55:36 +0000976{
ths26edcf42007-12-09 02:25:24 +0000977 int i, nw, j, k;
978 abi_ulong b, *target_fds;
979
Laurent Vivierb1b2db22016-05-31 18:36:02 +0200980 nw = DIV_ROUND_UP(n, TARGET_ABI_BITS);
ths26edcf42007-12-09 02:25:24 +0000981 if (!(target_fds = lock_user(VERIFY_READ,
982 target_fds_addr,
983 sizeof(abi_ulong) * nw,
984 1)))
985 return -TARGET_EFAULT;
986
987 FD_ZERO(fds);
988 k = 0;
989 for (i = 0; i < nw; i++) {
990 /* grab the abi_ulong */
991 __get_user(b, &target_fds[i]);
992 for (j = 0; j < TARGET_ABI_BITS; j++) {
993 /* check the bit inside the abi_ulong */
994 if ((b >> j) & 1)
995 FD_SET(k, fds);
996 k++;
bellard31e31b82003-02-18 22:55:36 +0000997 }
bellard31e31b82003-02-18 22:55:36 +0000998 }
ths26edcf42007-12-09 02:25:24 +0000999
1000 unlock_user(target_fds, target_fds_addr, 0);
1001
1002 return 0;
bellard31e31b82003-02-18 22:55:36 +00001003}
1004
Mike Frysinger055e0902011-06-03 17:01:49 -04001005static inline abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr,
1006 abi_ulong target_fds_addr,
1007 int n)
1008{
1009 if (target_fds_addr) {
1010 if (copy_from_user_fdset(fds, target_fds_addr, n))
1011 return -TARGET_EFAULT;
1012 *fds_ptr = fds;
1013 } else {
1014 *fds_ptr = NULL;
1015 }
1016 return 0;
1017}
1018
ths26edcf42007-12-09 02:25:24 +00001019static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
1020 const fd_set *fds,
1021 int n)
bellard31e31b82003-02-18 22:55:36 +00001022{
bellard31e31b82003-02-18 22:55:36 +00001023 int i, nw, j, k;
blueswir1992f48a2007-10-14 16:27:31 +00001024 abi_long v;
ths26edcf42007-12-09 02:25:24 +00001025 abi_ulong *target_fds;
bellard31e31b82003-02-18 22:55:36 +00001026
Laurent Vivierb1b2db22016-05-31 18:36:02 +02001027 nw = DIV_ROUND_UP(n, TARGET_ABI_BITS);
ths26edcf42007-12-09 02:25:24 +00001028 if (!(target_fds = lock_user(VERIFY_WRITE,
1029 target_fds_addr,
1030 sizeof(abi_ulong) * nw,
1031 0)))
1032 return -TARGET_EFAULT;
1033
1034 k = 0;
1035 for (i = 0; i < nw; i++) {
1036 v = 0;
1037 for (j = 0; j < TARGET_ABI_BITS; j++) {
Andreas Schwab9ab709b2013-04-09 01:02:34 +00001038 v |= ((abi_ulong)(FD_ISSET(k, fds) != 0) << j);
ths26edcf42007-12-09 02:25:24 +00001039 k++;
bellard31e31b82003-02-18 22:55:36 +00001040 }
ths26edcf42007-12-09 02:25:24 +00001041 __put_user(v, &target_fds[i]);
bellard31e31b82003-02-18 22:55:36 +00001042 }
ths26edcf42007-12-09 02:25:24 +00001043
1044 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
1045
1046 return 0;
bellard31e31b82003-02-18 22:55:36 +00001047}
Alistair Francis859e8a82020-03-12 15:13:49 -07001048#endif
bellard31e31b82003-02-18 22:55:36 +00001049
bellardc596ed12003-07-13 17:32:31 +00001050#if defined(__alpha__)
1051#define HOST_HZ 1024
1052#else
1053#define HOST_HZ 100
1054#endif
1055
blueswir1992f48a2007-10-14 16:27:31 +00001056static inline abi_long host_to_target_clock_t(long ticks)
bellardc596ed12003-07-13 17:32:31 +00001057{
1058#if HOST_HZ == TARGET_HZ
1059 return ticks;
1060#else
1061 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
1062#endif
1063}
1064
bellard579a97f2007-11-11 14:26:47 +00001065static inline abi_long host_to_target_rusage(abi_ulong target_addr,
1066 const struct rusage *rusage)
bellardb4091862003-05-16 15:39:34 +00001067{
pbrook53a59602006-03-25 19:31:22 +00001068 struct target_rusage *target_rusage;
1069
bellard579a97f2007-11-11 14:26:47 +00001070 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
1071 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001072 target_rusage->ru_utime.tv_sec = tswapal(rusage->ru_utime.tv_sec);
1073 target_rusage->ru_utime.tv_usec = tswapal(rusage->ru_utime.tv_usec);
1074 target_rusage->ru_stime.tv_sec = tswapal(rusage->ru_stime.tv_sec);
1075 target_rusage->ru_stime.tv_usec = tswapal(rusage->ru_stime.tv_usec);
1076 target_rusage->ru_maxrss = tswapal(rusage->ru_maxrss);
1077 target_rusage->ru_ixrss = tswapal(rusage->ru_ixrss);
1078 target_rusage->ru_idrss = tswapal(rusage->ru_idrss);
1079 target_rusage->ru_isrss = tswapal(rusage->ru_isrss);
1080 target_rusage->ru_minflt = tswapal(rusage->ru_minflt);
1081 target_rusage->ru_majflt = tswapal(rusage->ru_majflt);
1082 target_rusage->ru_nswap = tswapal(rusage->ru_nswap);
1083 target_rusage->ru_inblock = tswapal(rusage->ru_inblock);
1084 target_rusage->ru_oublock = tswapal(rusage->ru_oublock);
1085 target_rusage->ru_msgsnd = tswapal(rusage->ru_msgsnd);
1086 target_rusage->ru_msgrcv = tswapal(rusage->ru_msgrcv);
1087 target_rusage->ru_nsignals = tswapal(rusage->ru_nsignals);
1088 target_rusage->ru_nvcsw = tswapal(rusage->ru_nvcsw);
1089 target_rusage->ru_nivcsw = tswapal(rusage->ru_nivcsw);
pbrook53a59602006-03-25 19:31:22 +00001090 unlock_user_struct(target_rusage, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001091
1092 return 0;
bellardb4091862003-05-16 15:39:34 +00001093}
1094
Alistair Francis859e8a82020-03-12 15:13:49 -07001095#ifdef TARGET_NR_setrlimit
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001096static inline rlim_t target_to_host_rlim(abi_ulong target_rlim)
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001097{
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001098 abi_ulong target_rlim_swap;
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001099 rlim_t result;
1100
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001101 target_rlim_swap = tswapal(target_rlim);
1102 if (target_rlim_swap == TARGET_RLIM_INFINITY)
1103 return RLIM_INFINITY;
1104
1105 result = target_rlim_swap;
1106 if (target_rlim_swap != (rlim_t)result)
1107 return RLIM_INFINITY;
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001108
1109 return result;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001110}
Alistair Francis859e8a82020-03-12 15:13:49 -07001111#endif
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001112
Alistair Francis859e8a82020-03-12 15:13:49 -07001113#if defined(TARGET_NR_getrlimit) || defined(TARGET_NR_ugetrlimit)
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001114static inline abi_ulong host_to_target_rlim(rlim_t rlim)
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001115{
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001116 abi_ulong target_rlim_swap;
1117 abi_ulong result;
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001118
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001119 if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim)
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001120 target_rlim_swap = TARGET_RLIM_INFINITY;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001121 else
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001122 target_rlim_swap = rlim;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001123 result = tswapal(target_rlim_swap);
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001124
1125 return result;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001126}
Alistair Francis859e8a82020-03-12 15:13:49 -07001127#endif
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001128
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03001129static inline int target_to_host_resource(int code)
1130{
1131 switch (code) {
1132 case TARGET_RLIMIT_AS:
1133 return RLIMIT_AS;
1134 case TARGET_RLIMIT_CORE:
1135 return RLIMIT_CORE;
1136 case TARGET_RLIMIT_CPU:
1137 return RLIMIT_CPU;
1138 case TARGET_RLIMIT_DATA:
1139 return RLIMIT_DATA;
1140 case TARGET_RLIMIT_FSIZE:
1141 return RLIMIT_FSIZE;
1142 case TARGET_RLIMIT_LOCKS:
1143 return RLIMIT_LOCKS;
1144 case TARGET_RLIMIT_MEMLOCK:
1145 return RLIMIT_MEMLOCK;
1146 case TARGET_RLIMIT_MSGQUEUE:
1147 return RLIMIT_MSGQUEUE;
1148 case TARGET_RLIMIT_NICE:
1149 return RLIMIT_NICE;
1150 case TARGET_RLIMIT_NOFILE:
1151 return RLIMIT_NOFILE;
1152 case TARGET_RLIMIT_NPROC:
1153 return RLIMIT_NPROC;
1154 case TARGET_RLIMIT_RSS:
1155 return RLIMIT_RSS;
1156 case TARGET_RLIMIT_RTPRIO:
1157 return RLIMIT_RTPRIO;
1158 case TARGET_RLIMIT_SIGPENDING:
1159 return RLIMIT_SIGPENDING;
1160 case TARGET_RLIMIT_STACK:
1161 return RLIMIT_STACK;
1162 default:
1163 return code;
1164 }
1165}
1166
ths788f5ec2007-12-09 02:37:05 +00001167static inline abi_long copy_from_user_timeval(struct timeval *tv,
1168 abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +00001169{
pbrook53a59602006-03-25 19:31:22 +00001170 struct target_timeval *target_tv;
1171
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001172 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) {
bellard579a97f2007-11-11 14:26:47 +00001173 return -TARGET_EFAULT;
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001174 }
ths788f5ec2007-12-09 02:37:05 +00001175
1176 __get_user(tv->tv_sec, &target_tv->tv_sec);
1177 __get_user(tv->tv_usec, &target_tv->tv_usec);
1178
1179 unlock_user_struct(target_tv, target_tv_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001180
1181 return 0;
bellard31e31b82003-02-18 22:55:36 +00001182}
1183
ths788f5ec2007-12-09 02:37:05 +00001184static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
1185 const struct timeval *tv)
bellard31e31b82003-02-18 22:55:36 +00001186{
pbrook53a59602006-03-25 19:31:22 +00001187 struct target_timeval *target_tv;
1188
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001189 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
bellard579a97f2007-11-11 14:26:47 +00001190 return -TARGET_EFAULT;
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001191 }
ths788f5ec2007-12-09 02:37:05 +00001192
1193 __put_user(tv->tv_sec, &target_tv->tv_sec);
1194 __put_user(tv->tv_usec, &target_tv->tv_usec);
1195
1196 unlock_user_struct(target_tv, target_tv_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001197
1198 return 0;
bellard31e31b82003-02-18 22:55:36 +00001199}
1200
Filip Bozuta6ac03b22020-08-24 21:21:15 +02001201#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
1202static inline abi_long copy_from_user_timeval64(struct timeval *tv,
1203 abi_ulong target_tv_addr)
1204{
1205 struct target__kernel_sock_timeval *target_tv;
1206
1207 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) {
1208 return -TARGET_EFAULT;
1209 }
1210
1211 __get_user(tv->tv_sec, &target_tv->tv_sec);
1212 __get_user(tv->tv_usec, &target_tv->tv_usec);
1213
1214 unlock_user_struct(target_tv, target_tv_addr, 0);
1215
1216 return 0;
1217}
1218#endif
1219
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001220static inline abi_long copy_to_user_timeval64(abi_ulong target_tv_addr,
Filip Bozuta6ac03b22020-08-24 21:21:15 +02001221 const struct timeval *tv)
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001222{
1223 struct target__kernel_sock_timeval *target_tv;
1224
1225 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
1226 return -TARGET_EFAULT;
1227 }
1228
1229 __put_user(tv->tv_sec, &target_tv->tv_sec);
1230 __put_user(tv->tv_usec, &target_tv->tv_usec);
1231
1232 unlock_user_struct(target_tv, target_tv_addr, 1);
1233
1234 return 0;
1235}
1236
Alistair Francis859e8a82020-03-12 15:13:49 -07001237#if defined(TARGET_NR_futex) || \
1238 defined(TARGET_NR_rt_sigtimedwait) || \
1239 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6) || \
1240 defined(TARGET_NR_nanosleep) || defined(TARGET_NR_clock_settime) || \
1241 defined(TARGET_NR_utimensat) || defined(TARGET_NR_mq_timedsend) || \
Matus Kyseld8c08b12020-06-26 14:46:11 +02001242 defined(TARGET_NR_mq_timedreceive) || defined(TARGET_NR_ipc) || \
Filip Bozuta2c86c902020-07-22 17:34:20 +02001243 defined(TARGET_NR_semop) || defined(TARGET_NR_semtimedop) || \
1244 defined(TARGET_NR_timer_settime) || \
1245 (defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD))
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001246static inline abi_long target_to_host_timespec(struct timespec *host_ts,
1247 abi_ulong target_addr)
1248{
1249 struct target_timespec *target_ts;
1250
1251 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) {
1252 return -TARGET_EFAULT;
1253 }
1254 __get_user(host_ts->tv_sec, &target_ts->tv_sec);
1255 __get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1256 unlock_user_struct(target_ts, target_addr, 0);
1257 return 0;
1258}
Alistair Francis859e8a82020-03-12 15:13:49 -07001259#endif
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001260
Filip Bozuta828cb3a2020-07-22 17:34:21 +02001261#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) || \
1262 defined(TARGET_NR_timer_settime64) || \
Filip Bozutad107e372020-08-24 21:37:52 +02001263 defined(TARGET_NR_mq_timedsend_time64) || \
1264 defined(TARGET_NR_mq_timedreceive_time64) || \
Filip Bozuta6ac03b22020-08-24 21:21:15 +02001265 (defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)) || \
Filip Bozutaddcbde12020-08-24 21:21:16 +02001266 defined(TARGET_NR_clock_nanosleep_time64) || \
Filip Bozutacac46eb2020-08-25 00:30:50 +02001267 defined(TARGET_NR_rt_sigtimedwait_time64) || \
1268 defined(TARGET_NR_utimensat) || \
1269 defined(TARGET_NR_utimensat_time64) || \
Filip Bozutae5ce9682020-08-25 00:30:49 +02001270 defined(TARGET_NR_semtimedop_time64) || \
1271 defined(TARGET_NR_pselect6_time64) || defined(TARGET_NR_ppoll_time64)
Alistair Francisc6c8d102020-03-12 15:13:53 -07001272static inline abi_long target_to_host_timespec64(struct timespec *host_ts,
1273 abi_ulong target_addr)
1274{
1275 struct target__kernel_timespec *target_ts;
1276
1277 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) {
1278 return -TARGET_EFAULT;
1279 }
1280 __get_user(host_ts->tv_sec, &target_ts->tv_sec);
1281 __get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
Laurent Vivier00576752020-08-27 09:04:49 +02001282 /* in 32bit mode, this drops the padding */
1283 host_ts->tv_nsec = (long)(abi_long)host_ts->tv_nsec;
Alistair Francisc6c8d102020-03-12 15:13:53 -07001284 unlock_user_struct(target_ts, target_addr, 0);
1285 return 0;
1286}
1287#endif
1288
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001289static inline abi_long host_to_target_timespec(abi_ulong target_addr,
1290 struct timespec *host_ts)
1291{
1292 struct target_timespec *target_ts;
1293
1294 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) {
1295 return -TARGET_EFAULT;
1296 }
1297 __put_user(host_ts->tv_sec, &target_ts->tv_sec);
1298 __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1299 unlock_user_struct(target_ts, target_addr, 1);
1300 return 0;
1301}
1302
1303static inline abi_long host_to_target_timespec64(abi_ulong target_addr,
1304 struct timespec *host_ts)
1305{
1306 struct target__kernel_timespec *target_ts;
1307
1308 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) {
1309 return -TARGET_EFAULT;
1310 }
1311 __put_user(host_ts->tv_sec, &target_ts->tv_sec);
1312 __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1313 unlock_user_struct(target_ts, target_addr, 1);
1314 return 0;
1315}
1316
Richard Hendersona52f5f82020-02-12 19:22:23 -08001317#if defined(TARGET_NR_gettimeofday)
1318static inline abi_long copy_to_user_timezone(abi_ulong target_tz_addr,
1319 struct timezone *tz)
1320{
1321 struct target_timezone *target_tz;
1322
1323 if (!lock_user_struct(VERIFY_WRITE, target_tz, target_tz_addr, 1)) {
1324 return -TARGET_EFAULT;
1325 }
1326
1327 __put_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
1328 __put_user(tz->tz_dsttime, &target_tz->tz_dsttime);
1329
1330 unlock_user_struct(target_tz, target_tz_addr, 1);
1331
1332 return 0;
1333}
1334#endif
1335
Alistair Francis859e8a82020-03-12 15:13:49 -07001336#if defined(TARGET_NR_settimeofday)
Paul Burtonef4467e2014-06-22 11:25:40 +01001337static inline abi_long copy_from_user_timezone(struct timezone *tz,
1338 abi_ulong target_tz_addr)
1339{
1340 struct target_timezone *target_tz;
1341
1342 if (!lock_user_struct(VERIFY_READ, target_tz, target_tz_addr, 1)) {
1343 return -TARGET_EFAULT;
1344 }
1345
1346 __get_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
1347 __get_user(tz->tz_dsttime, &target_tz->tz_dsttime);
1348
1349 unlock_user_struct(target_tz, target_tz_addr, 0);
1350
1351 return 0;
1352}
Alistair Francis859e8a82020-03-12 15:13:49 -07001353#endif
Paul Burtonef4467e2014-06-22 11:25:40 +01001354
Nathan Froyd8ec9cf82009-07-22 09:14:36 -07001355#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
1356#include <mqueue.h>
1357
aurel3224e10032009-04-15 16:11:43 +00001358static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr,
1359 abi_ulong target_mq_attr_addr)
1360{
1361 struct target_mq_attr *target_mq_attr;
1362
1363 if (!lock_user_struct(VERIFY_READ, target_mq_attr,
1364 target_mq_attr_addr, 1))
1365 return -TARGET_EFAULT;
1366
1367 __get_user(attr->mq_flags, &target_mq_attr->mq_flags);
1368 __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
1369 __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
1370 __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
1371
1372 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0);
1373
1374 return 0;
1375}
1376
1377static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
1378 const struct mq_attr *attr)
1379{
1380 struct target_mq_attr *target_mq_attr;
1381
1382 if (!lock_user_struct(VERIFY_WRITE, target_mq_attr,
1383 target_mq_attr_addr, 0))
1384 return -TARGET_EFAULT;
1385
1386 __put_user(attr->mq_flags, &target_mq_attr->mq_flags);
1387 __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
1388 __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
1389 __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
1390
1391 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1);
1392
1393 return 0;
1394}
Nathan Froyd8ec9cf82009-07-22 09:14:36 -07001395#endif
bellard31e31b82003-02-18 22:55:36 +00001396
Mike Frysinger055e0902011-06-03 17:01:49 -04001397#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect)
ths0da46a62007-10-20 20:23:07 +00001398/* do_select() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001399static abi_long do_select(int n,
ths26edcf42007-12-09 02:25:24 +00001400 abi_ulong rfd_addr, abi_ulong wfd_addr,
1401 abi_ulong efd_addr, abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +00001402{
1403 fd_set rfds, wfds, efds;
1404 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
Peter Maydell6df9d382016-05-12 18:47:51 +01001405 struct timeval tv;
1406 struct timespec ts, *ts_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00001407 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00001408
Mike Frysinger055e0902011-06-03 17:01:49 -04001409 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
1410 if (ret) {
1411 return ret;
pbrook53a59602006-03-25 19:31:22 +00001412 }
Mike Frysinger055e0902011-06-03 17:01:49 -04001413 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
1414 if (ret) {
1415 return ret;
pbrook53a59602006-03-25 19:31:22 +00001416 }
Mike Frysinger055e0902011-06-03 17:01:49 -04001417 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
1418 if (ret) {
1419 return ret;
pbrook53a59602006-03-25 19:31:22 +00001420 }
ths3b46e622007-09-17 08:09:54 +00001421
ths26edcf42007-12-09 02:25:24 +00001422 if (target_tv_addr) {
ths788f5ec2007-12-09 02:37:05 +00001423 if (copy_from_user_timeval(&tv, target_tv_addr))
1424 return -TARGET_EFAULT;
Peter Maydell6df9d382016-05-12 18:47:51 +01001425 ts.tv_sec = tv.tv_sec;
1426 ts.tv_nsec = tv.tv_usec * 1000;
1427 ts_ptr = &ts;
bellard31e31b82003-02-18 22:55:36 +00001428 } else {
Peter Maydell6df9d382016-05-12 18:47:51 +01001429 ts_ptr = NULL;
bellard31e31b82003-02-18 22:55:36 +00001430 }
ths26edcf42007-12-09 02:25:24 +00001431
Peter Maydell6df9d382016-05-12 18:47:51 +01001432 ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
1433 ts_ptr, NULL));
pbrook53a59602006-03-25 19:31:22 +00001434
ths26edcf42007-12-09 02:25:24 +00001435 if (!is_error(ret)) {
1436 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
1437 return -TARGET_EFAULT;
1438 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
1439 return -TARGET_EFAULT;
1440 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
1441 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00001442
Peter Maydell6df9d382016-05-12 18:47:51 +01001443 if (target_tv_addr) {
1444 tv.tv_sec = ts.tv_sec;
1445 tv.tv_usec = ts.tv_nsec / 1000;
1446 if (copy_to_user_timeval(target_tv_addr, &tv)) {
1447 return -TARGET_EFAULT;
1448 }
1449 }
bellard31e31b82003-02-18 22:55:36 +00001450 }
bellard579a97f2007-11-11 14:26:47 +00001451
bellard31e31b82003-02-18 22:55:36 +00001452 return ret;
1453}
Laurent Vivier5457dc92016-07-08 01:17:27 +02001454
1455#if defined(TARGET_WANT_OLD_SYS_SELECT)
1456static abi_long do_old_select(abi_ulong arg1)
1457{
1458 struct target_sel_arg_struct *sel;
1459 abi_ulong inp, outp, exp, tvp;
1460 long nsel;
1461
1462 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1)) {
1463 return -TARGET_EFAULT;
1464 }
1465
1466 nsel = tswapal(sel->n);
1467 inp = tswapal(sel->inp);
1468 outp = tswapal(sel->outp);
1469 exp = tswapal(sel->exp);
1470 tvp = tswapal(sel->tvp);
1471
1472 unlock_user_struct(sel, arg1, 0);
1473
1474 return do_select(nsel, inp, outp, exp, tvp);
1475}
1476#endif
Mike Frysinger055e0902011-06-03 17:01:49 -04001477#endif
bellard31e31b82003-02-18 22:55:36 +00001478
Filip Bozutae5ce9682020-08-25 00:30:49 +02001479#if defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
1480static abi_long do_pselect6(abi_long arg1, abi_long arg2, abi_long arg3,
1481 abi_long arg4, abi_long arg5, abi_long arg6,
1482 bool time64)
1483{
1484 abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr;
1485 fd_set rfds, wfds, efds;
1486 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
1487 struct timespec ts, *ts_ptr;
1488 abi_long ret;
1489
1490 /*
1491 * The 6th arg is actually two args smashed together,
1492 * so we cannot use the C library.
1493 */
1494 sigset_t set;
1495 struct {
1496 sigset_t *set;
1497 size_t size;
1498 } sig, *sig_ptr;
1499
1500 abi_ulong arg_sigset, arg_sigsize, *arg7;
1501 target_sigset_t *target_sigset;
1502
1503 n = arg1;
1504 rfd_addr = arg2;
1505 wfd_addr = arg3;
1506 efd_addr = arg4;
1507 ts_addr = arg5;
1508
1509 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
1510 if (ret) {
1511 return ret;
1512 }
1513 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
1514 if (ret) {
1515 return ret;
1516 }
1517 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
1518 if (ret) {
1519 return ret;
1520 }
1521
1522 /*
1523 * This takes a timespec, and not a timeval, so we cannot
1524 * use the do_select() helper ...
1525 */
1526 if (ts_addr) {
1527 if (time64) {
1528 if (target_to_host_timespec64(&ts, ts_addr)) {
1529 return -TARGET_EFAULT;
1530 }
1531 } else {
1532 if (target_to_host_timespec(&ts, ts_addr)) {
1533 return -TARGET_EFAULT;
1534 }
1535 }
1536 ts_ptr = &ts;
1537 } else {
1538 ts_ptr = NULL;
1539 }
1540
1541 /* Extract the two packed args for the sigset */
1542 if (arg6) {
1543 sig_ptr = &sig;
1544 sig.size = SIGSET_T_SIZE;
1545
1546 arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1);
1547 if (!arg7) {
1548 return -TARGET_EFAULT;
1549 }
1550 arg_sigset = tswapal(arg7[0]);
1551 arg_sigsize = tswapal(arg7[1]);
1552 unlock_user(arg7, arg6, 0);
1553
1554 if (arg_sigset) {
1555 sig.set = &set;
1556 if (arg_sigsize != sizeof(*target_sigset)) {
1557 /* Like the kernel, we enforce correct size sigsets */
1558 return -TARGET_EINVAL;
1559 }
1560 target_sigset = lock_user(VERIFY_READ, arg_sigset,
1561 sizeof(*target_sigset), 1);
1562 if (!target_sigset) {
1563 return -TARGET_EFAULT;
1564 }
1565 target_to_host_sigset(&set, target_sigset);
1566 unlock_user(target_sigset, arg_sigset, 0);
1567 } else {
1568 sig.set = NULL;
1569 }
1570 } else {
1571 sig_ptr = NULL;
1572 }
1573
1574 ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
1575 ts_ptr, sig_ptr));
1576
1577 if (!is_error(ret)) {
1578 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n)) {
1579 return -TARGET_EFAULT;
1580 }
1581 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n)) {
1582 return -TARGET_EFAULT;
1583 }
1584 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n)) {
1585 return -TARGET_EFAULT;
1586 }
1587 if (time64) {
1588 if (ts_addr && host_to_target_timespec64(ts_addr, &ts)) {
1589 return -TARGET_EFAULT;
1590 }
1591 } else {
1592 if (ts_addr && host_to_target_timespec(ts_addr, &ts)) {
1593 return -TARGET_EFAULT;
1594 }
1595 }
1596 }
1597 return ret;
1598}
1599#endif
1600
1601#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll) || \
1602 defined(TARGET_NR_ppoll_time64)
1603static abi_long do_ppoll(abi_long arg1, abi_long arg2, abi_long arg3,
1604 abi_long arg4, abi_long arg5, bool ppoll, bool time64)
1605{
1606 struct target_pollfd *target_pfd;
1607 unsigned int nfds = arg2;
1608 struct pollfd *pfd;
1609 unsigned int i;
1610 abi_long ret;
1611
1612 pfd = NULL;
1613 target_pfd = NULL;
1614 if (nfds) {
1615 if (nfds > (INT_MAX / sizeof(struct target_pollfd))) {
1616 return -TARGET_EINVAL;
1617 }
1618 target_pfd = lock_user(VERIFY_WRITE, arg1,
1619 sizeof(struct target_pollfd) * nfds, 1);
1620 if (!target_pfd) {
1621 return -TARGET_EFAULT;
1622 }
1623
1624 pfd = alloca(sizeof(struct pollfd) * nfds);
1625 for (i = 0; i < nfds; i++) {
1626 pfd[i].fd = tswap32(target_pfd[i].fd);
1627 pfd[i].events = tswap16(target_pfd[i].events);
1628 }
1629 }
1630 if (ppoll) {
1631 struct timespec _timeout_ts, *timeout_ts = &_timeout_ts;
1632 target_sigset_t *target_set;
1633 sigset_t _set, *set = &_set;
1634
1635 if (arg3) {
1636 if (time64) {
1637 if (target_to_host_timespec64(timeout_ts, arg3)) {
1638 unlock_user(target_pfd, arg1, 0);
1639 return -TARGET_EFAULT;
1640 }
1641 } else {
1642 if (target_to_host_timespec(timeout_ts, arg3)) {
1643 unlock_user(target_pfd, arg1, 0);
1644 return -TARGET_EFAULT;
1645 }
1646 }
1647 } else {
1648 timeout_ts = NULL;
1649 }
1650
1651 if (arg4) {
1652 if (arg5 != sizeof(target_sigset_t)) {
1653 unlock_user(target_pfd, arg1, 0);
1654 return -TARGET_EINVAL;
1655 }
1656
1657 target_set = lock_user(VERIFY_READ, arg4,
1658 sizeof(target_sigset_t), 1);
1659 if (!target_set) {
1660 unlock_user(target_pfd, arg1, 0);
1661 return -TARGET_EFAULT;
1662 }
1663 target_to_host_sigset(set, target_set);
1664 } else {
1665 set = NULL;
1666 }
1667
1668 ret = get_errno(safe_ppoll(pfd, nfds, timeout_ts,
1669 set, SIGSET_T_SIZE));
1670
1671 if (!is_error(ret) && arg3) {
1672 if (time64) {
1673 if (host_to_target_timespec64(arg3, timeout_ts)) {
1674 return -TARGET_EFAULT;
1675 }
1676 } else {
1677 if (host_to_target_timespec(arg3, timeout_ts)) {
1678 return -TARGET_EFAULT;
1679 }
1680 }
1681 }
1682 if (arg4) {
1683 unlock_user(target_set, arg4, 0);
1684 }
1685 } else {
1686 struct timespec ts, *pts;
1687
1688 if (arg3 >= 0) {
1689 /* Convert ms to secs, ns */
1690 ts.tv_sec = arg3 / 1000;
1691 ts.tv_nsec = (arg3 % 1000) * 1000000LL;
1692 pts = &ts;
1693 } else {
1694 /* -ve poll() timeout means "infinite" */
1695 pts = NULL;
1696 }
1697 ret = get_errno(safe_ppoll(pfd, nfds, pts, NULL, 0));
1698 }
1699
1700 if (!is_error(ret)) {
1701 for (i = 0; i < nfds; i++) {
1702 target_pfd[i].revents = tswap16(pfd[i].revents);
1703 }
1704 }
1705 unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds);
1706 return ret;
1707}
1708#endif
1709
Riku Voipio099d6b02009-05-05 12:10:04 +03001710static abi_long do_pipe2(int host_pipe[], int flags)
1711{
1712#ifdef CONFIG_PIPE2
1713 return pipe2(host_pipe, flags);
1714#else
1715 return -ENOSYS;
1716#endif
1717}
1718
Richard Hendersonfb41a662010-05-03 10:07:52 -07001719static abi_long do_pipe(void *cpu_env, abi_ulong pipedes,
1720 int flags, int is_pipe2)
Riku Voipio099d6b02009-05-05 12:10:04 +03001721{
1722 int host_pipe[2];
1723 abi_long ret;
1724 ret = flags ? do_pipe2(host_pipe, flags) : pipe(host_pipe);
1725
1726 if (is_error(ret))
1727 return get_errno(ret);
Richard Hendersonfb41a662010-05-03 10:07:52 -07001728
1729 /* Several targets have special calling conventions for the original
1730 pipe syscall, but didn't replicate this into the pipe2 syscall. */
1731 if (!is_pipe2) {
1732#if defined(TARGET_ALPHA)
1733 ((CPUAlphaState *)cpu_env)->ir[IR_A4] = host_pipe[1];
1734 return host_pipe[0];
1735#elif defined(TARGET_MIPS)
1736 ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1];
1737 return host_pipe[0];
1738#elif defined(TARGET_SH4)
takasi-y@ops.dti.ne.jp597c0212010-02-18 00:35:03 +09001739 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
Richard Hendersonfb41a662010-05-03 10:07:52 -07001740 return host_pipe[0];
Peter Maydell82f05b62013-07-06 17:39:48 +01001741#elif defined(TARGET_SPARC)
1742 ((CPUSPARCState*)cpu_env)->regwptr[1] = host_pipe[1];
1743 return host_pipe[0];
takasi-y@ops.dti.ne.jp597c0212010-02-18 00:35:03 +09001744#endif
Richard Hendersonfb41a662010-05-03 10:07:52 -07001745 }
1746
Riku Voipio099d6b02009-05-05 12:10:04 +03001747 if (put_user_s32(host_pipe[0], pipedes)
1748 || put_user_s32(host_pipe[1], pipedes + sizeof(host_pipe[0])))
1749 return -TARGET_EFAULT;
Riku Voipio099d6b02009-05-05 12:10:04 +03001750 return get_errno(ret);
1751}
1752
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001753static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
1754 abi_ulong target_addr,
1755 socklen_t len)
1756{
1757 struct target_ip_mreqn *target_smreqn;
1758
1759 target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
1760 if (!target_smreqn)
1761 return -TARGET_EFAULT;
1762 mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
1763 mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
1764 if (len == sizeof(struct target_ip_mreqn))
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001765 mreqn->imr_ifindex = tswapal(target_smreqn->imr_ifindex);
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001766 unlock_user(target_smreqn, target_addr, 0);
1767
1768 return 0;
1769}
1770
Laurent Vivier7b36f782015-10-28 21:40:44 +01001771static inline abi_long target_to_host_sockaddr(int fd, struct sockaddr *addr,
bellard579a97f2007-11-11 14:26:47 +00001772 abi_ulong target_addr,
1773 socklen_t len)
bellard7854b052003-03-29 17:22:23 +00001774{
aurel32607175e2009-04-15 16:11:59 +00001775 const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
1776 sa_family_t sa_family;
pbrook53a59602006-03-25 19:31:22 +00001777 struct target_sockaddr *target_saddr;
1778
Laurent Vivier7b36f782015-10-28 21:40:44 +01001779 if (fd_trans_target_to_host_addr(fd)) {
1780 return fd_trans_target_to_host_addr(fd)(addr, target_addr, len);
1781 }
1782
bellard579a97f2007-11-11 14:26:47 +00001783 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
1784 if (!target_saddr)
1785 return -TARGET_EFAULT;
aurel32607175e2009-04-15 16:11:59 +00001786
1787 sa_family = tswap16(target_saddr->sa_family);
1788
1789 /* Oops. The caller might send a incomplete sun_path; sun_path
1790 * must be terminated by \0 (see the manual page), but
1791 * unfortunately it is quite common to specify sockaddr_un
1792 * length as "strlen(x->sun_path)" while it should be
1793 * "strlen(...) + 1". We'll fix that here if needed.
1794 * Linux kernel has a similar feature.
1795 */
1796
1797 if (sa_family == AF_UNIX) {
1798 if (len < unix_maxlen && len > 0) {
1799 char *cp = (char*)target_saddr;
1800
1801 if ( cp[len-1] && !cp[len] )
1802 len++;
1803 }
1804 if (len > unix_maxlen)
1805 len = unix_maxlen;
1806 }
1807
pbrook53a59602006-03-25 19:31:22 +00001808 memcpy(addr, target_saddr, len);
aurel32607175e2009-04-15 16:11:59 +00001809 addr->sa_family = sa_family;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02001810 if (sa_family == AF_NETLINK) {
1811 struct sockaddr_nl *nladdr;
1812
1813 nladdr = (struct sockaddr_nl *)addr;
1814 nladdr->nl_pid = tswap32(nladdr->nl_pid);
1815 nladdr->nl_groups = tswap32(nladdr->nl_groups);
1816 } else if (sa_family == AF_PACKET) {
Joakim Tjernlund33a29b52014-07-12 15:47:07 +02001817 struct target_sockaddr_ll *lladdr;
1818
1819 lladdr = (struct target_sockaddr_ll *)addr;
1820 lladdr->sll_ifindex = tswap32(lladdr->sll_ifindex);
1821 lladdr->sll_hatype = tswap16(lladdr->sll_hatype);
1822 }
pbrook53a59602006-03-25 19:31:22 +00001823 unlock_user(target_saddr, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001824
1825 return 0;
bellard7854b052003-03-29 17:22:23 +00001826}
1827
bellard579a97f2007-11-11 14:26:47 +00001828static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
1829 struct sockaddr *addr,
1830 socklen_t len)
bellard7854b052003-03-29 17:22:23 +00001831{
pbrook53a59602006-03-25 19:31:22 +00001832 struct target_sockaddr *target_saddr;
1833
Peter Maydella1e22192016-07-07 15:44:43 +01001834 if (len == 0) {
1835 return 0;
1836 }
Philippe Mathieu-Daudé68607102017-07-26 23:42:18 -03001837 assert(addr);
Peter Maydella1e22192016-07-07 15:44:43 +01001838
bellard579a97f2007-11-11 14:26:47 +00001839 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
1840 if (!target_saddr)
1841 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001842 memcpy(target_saddr, addr, len);
Peter Maydella1e22192016-07-07 15:44:43 +01001843 if (len >= offsetof(struct target_sockaddr, sa_family) +
1844 sizeof(target_saddr->sa_family)) {
1845 target_saddr->sa_family = tswap16(addr->sa_family);
1846 }
Philippe Mathieu-Daudéa47401b2019-10-21 13:48:52 +02001847 if (addr->sa_family == AF_NETLINK &&
1848 len >= sizeof(struct target_sockaddr_nl)) {
1849 struct target_sockaddr_nl *target_nl =
1850 (struct target_sockaddr_nl *)target_saddr;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02001851 target_nl->nl_pid = tswap32(target_nl->nl_pid);
1852 target_nl->nl_groups = tswap32(target_nl->nl_groups);
Laurent Viviera82ea932016-06-27 00:18:22 +02001853 } else if (addr->sa_family == AF_PACKET) {
1854 struct sockaddr_ll *target_ll = (struct sockaddr_ll *)target_saddr;
1855 target_ll->sll_ifindex = tswap32(target_ll->sll_ifindex);
1856 target_ll->sll_hatype = tswap16(target_ll->sll_hatype);
Helge Delleree1ac3a2017-02-18 23:31:30 +01001857 } else if (addr->sa_family == AF_INET6 &&
1858 len >= sizeof(struct target_sockaddr_in6)) {
1859 struct target_sockaddr_in6 *target_in6 =
1860 (struct target_sockaddr_in6 *)target_saddr;
1861 target_in6->sin6_scope_id = tswap16(target_in6->sin6_scope_id);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02001862 }
pbrook53a59602006-03-25 19:31:22 +00001863 unlock_user(target_saddr, target_addr, len);
bellard579a97f2007-11-11 14:26:47 +00001864
1865 return 0;
bellard7854b052003-03-29 17:22:23 +00001866}
1867
bellard5a4a8982007-11-11 17:39:18 +00001868static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
1869 struct target_msghdr *target_msgh)
bellard7854b052003-03-29 17:22:23 +00001870{
1871 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001872 abi_long msg_controllen;
1873 abi_ulong target_cmsg_addr;
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001874 struct target_cmsghdr *target_cmsg, *target_cmsg_start;
bellard7854b052003-03-29 17:22:23 +00001875 socklen_t space = 0;
bellard5a4a8982007-11-11 17:39:18 +00001876
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001877 msg_controllen = tswapal(target_msgh->msg_controllen);
bellard5a4a8982007-11-11 17:39:18 +00001878 if (msg_controllen < sizeof (struct target_cmsghdr))
1879 goto the_end;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001880 target_cmsg_addr = tswapal(target_msgh->msg_control);
bellard5a4a8982007-11-11 17:39:18 +00001881 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001882 target_cmsg_start = target_cmsg;
bellard5a4a8982007-11-11 17:39:18 +00001883 if (!target_cmsg)
1884 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001885
1886 while (cmsg && target_cmsg) {
1887 void *data = CMSG_DATA(cmsg);
1888 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1889
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001890 int len = tswapal(target_cmsg->cmsg_len)
Peter Maydellad762b92017-12-15 13:52:56 +00001891 - sizeof(struct target_cmsghdr);
bellard7854b052003-03-29 17:22:23 +00001892
1893 space += CMSG_SPACE(len);
1894 if (space > msgh->msg_controllen) {
1895 space -= CMSG_SPACE(len);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001896 /* This is a QEMU bug, since we allocated the payload
1897 * area ourselves (unlike overflow in host-to-target
1898 * conversion, which is just the guest giving us a buffer
1899 * that's too small). It can't happen for the payload types
1900 * we currently support; if it becomes an issue in future
1901 * we would need to improve our allocation strategy to
1902 * something more intelligent than "twice the size of the
1903 * target buffer we're reading from".
1904 */
Josh Kunz39be5352020-02-03 18:54:13 -08001905 qemu_log_mask(LOG_UNIMP,
1906 ("Unsupported ancillary data %d/%d: "
1907 "unhandled msg size\n"),
1908 tswap32(target_cmsg->cmsg_level),
1909 tswap32(target_cmsg->cmsg_type));
bellard7854b052003-03-29 17:22:23 +00001910 break;
1911 }
1912
Petar Jovanovicdbf4f792013-09-13 19:27:29 +02001913 if (tswap32(target_cmsg->cmsg_level) == TARGET_SOL_SOCKET) {
1914 cmsg->cmsg_level = SOL_SOCKET;
1915 } else {
1916 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
1917 }
bellard7854b052003-03-29 17:22:23 +00001918 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
1919 cmsg->cmsg_len = CMSG_LEN(len);
1920
Alex Suykov30b8b682014-12-23 07:52:58 +02001921 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +00001922 int *fd = (int *)data;
1923 int *target_fd = (int *)target_data;
1924 int i, numfds = len / sizeof(int);
1925
Peter Maydell876e23c2015-05-26 19:46:32 +01001926 for (i = 0; i < numfds; i++) {
1927 __get_user(fd[i], target_fd + i);
1928 }
Alex Suykov30b8b682014-12-23 07:52:58 +02001929 } else if (cmsg->cmsg_level == SOL_SOCKET
1930 && cmsg->cmsg_type == SCM_CREDENTIALS) {
1931 struct ucred *cred = (struct ucred *)data;
1932 struct target_ucred *target_cred =
1933 (struct target_ucred *)target_data;
1934
Peter Maydell876e23c2015-05-26 19:46:32 +01001935 __get_user(cred->pid, &target_cred->pid);
1936 __get_user(cred->uid, &target_cred->uid);
1937 __get_user(cred->gid, &target_cred->gid);
Alex Suykov30b8b682014-12-23 07:52:58 +02001938 } else {
Josh Kunz39be5352020-02-03 18:54:13 -08001939 qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n",
1940 cmsg->cmsg_level, cmsg->cmsg_type);
Alex Suykov30b8b682014-12-23 07:52:58 +02001941 memcpy(data, target_data, len);
bellard7854b052003-03-29 17:22:23 +00001942 }
1943
1944 cmsg = CMSG_NXTHDR(msgh, cmsg);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001945 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg,
1946 target_cmsg_start);
bellard7854b052003-03-29 17:22:23 +00001947 }
bellard5a4a8982007-11-11 17:39:18 +00001948 unlock_user(target_cmsg, target_cmsg_addr, 0);
1949 the_end:
bellard7854b052003-03-29 17:22:23 +00001950 msgh->msg_controllen = space;
bellard5a4a8982007-11-11 17:39:18 +00001951 return 0;
bellard7854b052003-03-29 17:22:23 +00001952}
1953
bellard5a4a8982007-11-11 17:39:18 +00001954static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
1955 struct msghdr *msgh)
bellard7854b052003-03-29 17:22:23 +00001956{
1957 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001958 abi_long msg_controllen;
1959 abi_ulong target_cmsg_addr;
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001960 struct target_cmsghdr *target_cmsg, *target_cmsg_start;
bellard7854b052003-03-29 17:22:23 +00001961 socklen_t space = 0;
1962
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001963 msg_controllen = tswapal(target_msgh->msg_controllen);
bellard5a4a8982007-11-11 17:39:18 +00001964 if (msg_controllen < sizeof (struct target_cmsghdr))
1965 goto the_end;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001966 target_cmsg_addr = tswapal(target_msgh->msg_control);
bellard5a4a8982007-11-11 17:39:18 +00001967 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001968 target_cmsg_start = target_cmsg;
bellard5a4a8982007-11-11 17:39:18 +00001969 if (!target_cmsg)
1970 return -TARGET_EFAULT;
1971
bellard7854b052003-03-29 17:22:23 +00001972 while (cmsg && target_cmsg) {
1973 void *data = CMSG_DATA(cmsg);
1974 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1975
Peter Maydellad762b92017-12-15 13:52:56 +00001976 int len = cmsg->cmsg_len - sizeof(struct cmsghdr);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001977 int tgt_len, tgt_space;
bellard7854b052003-03-29 17:22:23 +00001978
Peter Maydellc2aeb252015-05-26 19:46:31 +01001979 /* We never copy a half-header but may copy half-data;
1980 * this is Linux's behaviour in put_cmsg(). Note that
1981 * truncation here is a guest problem (which we report
1982 * to the guest via the CTRUNC bit), unlike truncation
1983 * in target_to_host_cmsg, which is a QEMU bug.
1984 */
Peter Maydell71749702017-12-15 13:52:55 +00001985 if (msg_controllen < sizeof(struct target_cmsghdr)) {
Peter Maydellc2aeb252015-05-26 19:46:31 +01001986 target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
bellard7854b052003-03-29 17:22:23 +00001987 break;
1988 }
1989
Petar Jovanovicdbf4f792013-09-13 19:27:29 +02001990 if (cmsg->cmsg_level == SOL_SOCKET) {
1991 target_cmsg->cmsg_level = tswap32(TARGET_SOL_SOCKET);
1992 } else {
1993 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
1994 }
bellard7854b052003-03-29 17:22:23 +00001995 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
bellard7854b052003-03-29 17:22:23 +00001996
Peter Maydellc2aeb252015-05-26 19:46:31 +01001997 /* Payload types which need a different size of payload on
1998 * the target must adjust tgt_len here.
1999 */
Peter Maydell309786c2018-05-18 19:47:15 +01002000 tgt_len = len;
Peter Maydellc2aeb252015-05-26 19:46:31 +01002001 switch (cmsg->cmsg_level) {
2002 case SOL_SOCKET:
2003 switch (cmsg->cmsg_type) {
2004 case SO_TIMESTAMP:
2005 tgt_len = sizeof(struct target_timeval);
2006 break;
2007 default:
2008 break;
2009 }
Peter Maydell309786c2018-05-18 19:47:15 +01002010 break;
Peter Maydellc2aeb252015-05-26 19:46:31 +01002011 default:
2012 break;
2013 }
2014
Peter Maydell71749702017-12-15 13:52:55 +00002015 if (msg_controllen < TARGET_CMSG_LEN(tgt_len)) {
Peter Maydellc2aeb252015-05-26 19:46:31 +01002016 target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
Peter Maydell71749702017-12-15 13:52:55 +00002017 tgt_len = msg_controllen - sizeof(struct target_cmsghdr);
Peter Maydellc2aeb252015-05-26 19:46:31 +01002018 }
2019
2020 /* We must now copy-and-convert len bytes of payload
2021 * into tgt_len bytes of destination space. Bear in mind
2022 * that in both source and destination we may be dealing
2023 * with a truncated value!
2024 */
Huw Davies52b65492014-04-17 14:02:47 +01002025 switch (cmsg->cmsg_level) {
2026 case SOL_SOCKET:
2027 switch (cmsg->cmsg_type) {
2028 case SCM_RIGHTS:
2029 {
2030 int *fd = (int *)data;
2031 int *target_fd = (int *)target_data;
Peter Maydellc2aeb252015-05-26 19:46:31 +01002032 int i, numfds = tgt_len / sizeof(int);
bellard7854b052003-03-29 17:22:23 +00002033
Peter Maydell876e23c2015-05-26 19:46:32 +01002034 for (i = 0; i < numfds; i++) {
2035 __put_user(fd[i], target_fd + i);
2036 }
Huw Davies52b65492014-04-17 14:02:47 +01002037 break;
2038 }
2039 case SO_TIMESTAMP:
2040 {
2041 struct timeval *tv = (struct timeval *)data;
2042 struct target_timeval *target_tv =
2043 (struct target_timeval *)target_data;
Jing Huangaebf5bc2012-07-24 14:01:42 +00002044
Peter Maydellc2aeb252015-05-26 19:46:31 +01002045 if (len != sizeof(struct timeval) ||
2046 tgt_len != sizeof(struct target_timeval)) {
Huw Davies52b65492014-04-17 14:02:47 +01002047 goto unimplemented;
Peter Maydellc2aeb252015-05-26 19:46:31 +01002048 }
Huw Davies52b65492014-04-17 14:02:47 +01002049
2050 /* copy struct timeval to target */
Peter Maydell876e23c2015-05-26 19:46:32 +01002051 __put_user(tv->tv_sec, &target_tv->tv_sec);
2052 __put_user(tv->tv_usec, &target_tv->tv_usec);
Huw Davies52b65492014-04-17 14:02:47 +01002053 break;
2054 }
Huw Davies4bc29752014-04-17 14:02:48 +01002055 case SCM_CREDENTIALS:
2056 {
2057 struct ucred *cred = (struct ucred *)data;
2058 struct target_ucred *target_cred =
2059 (struct target_ucred *)target_data;
2060
2061 __put_user(cred->pid, &target_cred->pid);
2062 __put_user(cred->uid, &target_cred->uid);
2063 __put_user(cred->gid, &target_cred->gid);
2064 break;
2065 }
Huw Davies52b65492014-04-17 14:02:47 +01002066 default:
2067 goto unimplemented;
2068 }
2069 break;
2070
Helge Delleree1ac3a2017-02-18 23:31:30 +01002071 case SOL_IP:
2072 switch (cmsg->cmsg_type) {
2073 case IP_TTL:
2074 {
2075 uint32_t *v = (uint32_t *)data;
2076 uint32_t *t_int = (uint32_t *)target_data;
2077
Peter Maydell71749702017-12-15 13:52:55 +00002078 if (len != sizeof(uint32_t) ||
2079 tgt_len != sizeof(uint32_t)) {
2080 goto unimplemented;
2081 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01002082 __put_user(*v, t_int);
2083 break;
2084 }
2085 case IP_RECVERR:
2086 {
2087 struct errhdr_t {
2088 struct sock_extended_err ee;
2089 struct sockaddr_in offender;
2090 };
2091 struct errhdr_t *errh = (struct errhdr_t *)data;
2092 struct errhdr_t *target_errh =
2093 (struct errhdr_t *)target_data;
2094
Peter Maydell71749702017-12-15 13:52:55 +00002095 if (len != sizeof(struct errhdr_t) ||
2096 tgt_len != sizeof(struct errhdr_t)) {
2097 goto unimplemented;
2098 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01002099 __put_user(errh->ee.ee_errno, &target_errh->ee.ee_errno);
2100 __put_user(errh->ee.ee_origin, &target_errh->ee.ee_origin);
2101 __put_user(errh->ee.ee_type, &target_errh->ee.ee_type);
2102 __put_user(errh->ee.ee_code, &target_errh->ee.ee_code);
2103 __put_user(errh->ee.ee_pad, &target_errh->ee.ee_pad);
2104 __put_user(errh->ee.ee_info, &target_errh->ee.ee_info);
2105 __put_user(errh->ee.ee_data, &target_errh->ee.ee_data);
2106 host_to_target_sockaddr((unsigned long) &target_errh->offender,
2107 (void *) &errh->offender, sizeof(errh->offender));
2108 break;
2109 }
2110 default:
2111 goto unimplemented;
2112 }
2113 break;
2114
2115 case SOL_IPV6:
2116 switch (cmsg->cmsg_type) {
2117 case IPV6_HOPLIMIT:
2118 {
2119 uint32_t *v = (uint32_t *)data;
2120 uint32_t *t_int = (uint32_t *)target_data;
2121
Peter Maydell71749702017-12-15 13:52:55 +00002122 if (len != sizeof(uint32_t) ||
2123 tgt_len != sizeof(uint32_t)) {
2124 goto unimplemented;
2125 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01002126 __put_user(*v, t_int);
2127 break;
2128 }
2129 case IPV6_RECVERR:
2130 {
2131 struct errhdr6_t {
2132 struct sock_extended_err ee;
2133 struct sockaddr_in6 offender;
2134 };
2135 struct errhdr6_t *errh = (struct errhdr6_t *)data;
2136 struct errhdr6_t *target_errh =
2137 (struct errhdr6_t *)target_data;
2138
Peter Maydell71749702017-12-15 13:52:55 +00002139 if (len != sizeof(struct errhdr6_t) ||
2140 tgt_len != sizeof(struct errhdr6_t)) {
2141 goto unimplemented;
2142 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01002143 __put_user(errh->ee.ee_errno, &target_errh->ee.ee_errno);
2144 __put_user(errh->ee.ee_origin, &target_errh->ee.ee_origin);
2145 __put_user(errh->ee.ee_type, &target_errh->ee.ee_type);
2146 __put_user(errh->ee.ee_code, &target_errh->ee.ee_code);
2147 __put_user(errh->ee.ee_pad, &target_errh->ee.ee_pad);
2148 __put_user(errh->ee.ee_info, &target_errh->ee.ee_info);
2149 __put_user(errh->ee.ee_data, &target_errh->ee.ee_data);
2150 host_to_target_sockaddr((unsigned long) &target_errh->offender,
2151 (void *) &errh->offender, sizeof(errh->offender));
2152 break;
2153 }
2154 default:
2155 goto unimplemented;
2156 }
2157 break;
2158
Huw Davies52b65492014-04-17 14:02:47 +01002159 default:
2160 unimplemented:
Josh Kunz39be5352020-02-03 18:54:13 -08002161 qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n",
2162 cmsg->cmsg_level, cmsg->cmsg_type);
Peter Maydellc2aeb252015-05-26 19:46:31 +01002163 memcpy(target_data, data, MIN(len, tgt_len));
2164 if (tgt_len > len) {
2165 memset(target_data + len, 0, tgt_len - len);
2166 }
bellard7854b052003-03-29 17:22:23 +00002167 }
2168
Peter Maydell71749702017-12-15 13:52:55 +00002169 target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(tgt_len));
2170 tgt_space = TARGET_CMSG_SPACE(tgt_len);
Peter Maydellc2aeb252015-05-26 19:46:31 +01002171 if (msg_controllen < tgt_space) {
2172 tgt_space = msg_controllen;
2173 }
2174 msg_controllen -= tgt_space;
2175 space += tgt_space;
bellard7854b052003-03-29 17:22:23 +00002176 cmsg = CMSG_NXTHDR(msgh, cmsg);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02002177 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg,
2178 target_cmsg_start);
bellard7854b052003-03-29 17:22:23 +00002179 }
bellard5a4a8982007-11-11 17:39:18 +00002180 unlock_user(target_cmsg, target_cmsg_addr, space);
2181 the_end:
Matthias Brauncbb21ee2011-08-12 19:57:41 +02002182 target_msgh->msg_controllen = tswapal(space);
bellard5a4a8982007-11-11 17:39:18 +00002183 return 0;
bellard7854b052003-03-29 17:22:23 +00002184}
2185
ths0da46a62007-10-20 20:23:07 +00002186/* do_setsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002187static abi_long do_setsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00002188 abi_ulong optval_addr, socklen_t optlen)
bellard7854b052003-03-29 17:22:23 +00002189{
blueswir1992f48a2007-10-14 16:27:31 +00002190 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +00002191 int val;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02002192 struct ip_mreqn *ip_mreq;
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02002193 struct ip_mreq_source *ip_mreq_source;
ths3b46e622007-09-17 08:09:54 +00002194
bellard8853f862004-02-22 14:57:26 +00002195 switch(level) {
2196 case SOL_TCP:
Shu-Chun Wengfe51b0a2020-12-18 11:32:11 -08002197 case SOL_UDP:
2198 /* TCP and UDP options all take an 'int' value. */
bellard7854b052003-03-29 17:22:23 +00002199 if (optlen < sizeof(uint32_t))
ths0da46a62007-10-20 20:23:07 +00002200 return -TARGET_EINVAL;
ths3b46e622007-09-17 08:09:54 +00002201
bellard2f619692007-11-16 10:46:05 +00002202 if (get_user_u32(val, optval_addr))
2203 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00002204 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
2205 break;
2206 case SOL_IP:
2207 switch(optname) {
bellard2efbe912005-07-23 15:10:20 +00002208 case IP_TOS:
2209 case IP_TTL:
bellard8853f862004-02-22 14:57:26 +00002210 case IP_HDRINCL:
bellard2efbe912005-07-23 15:10:20 +00002211 case IP_ROUTER_ALERT:
2212 case IP_RECVOPTS:
2213 case IP_RETOPTS:
2214 case IP_PKTINFO:
2215 case IP_MTU_DISCOVER:
2216 case IP_RECVERR:
Helge Delleree1ac3a2017-02-18 23:31:30 +01002217 case IP_RECVTTL:
bellard2efbe912005-07-23 15:10:20 +00002218 case IP_RECVTOS:
2219#ifdef IP_FREEBIND
2220 case IP_FREEBIND:
2221#endif
2222 case IP_MULTICAST_TTL:
2223 case IP_MULTICAST_LOOP:
bellard8853f862004-02-22 14:57:26 +00002224 val = 0;
2225 if (optlen >= sizeof(uint32_t)) {
bellard2f619692007-11-16 10:46:05 +00002226 if (get_user_u32(val, optval_addr))
2227 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00002228 } else if (optlen >= 1) {
bellard2f619692007-11-16 10:46:05 +00002229 if (get_user_u8(val, optval_addr))
2230 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00002231 }
2232 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
2233 break;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02002234 case IP_ADD_MEMBERSHIP:
2235 case IP_DROP_MEMBERSHIP:
2236 if (optlen < sizeof (struct target_ip_mreq) ||
2237 optlen > sizeof (struct target_ip_mreqn))
2238 return -TARGET_EINVAL;
2239
2240 ip_mreq = (struct ip_mreqn *) alloca(optlen);
2241 target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
2242 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen));
2243 break;
2244
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02002245 case IP_BLOCK_SOURCE:
2246 case IP_UNBLOCK_SOURCE:
2247 case IP_ADD_SOURCE_MEMBERSHIP:
2248 case IP_DROP_SOURCE_MEMBERSHIP:
2249 if (optlen != sizeof (struct target_ip_mreq_source))
2250 return -TARGET_EINVAL;
2251
2252 ip_mreq_source = lock_user(VERIFY_READ, optval_addr, optlen, 1);
2253 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen));
2254 unlock_user (ip_mreq_source, optval_addr, 0);
2255 break;
2256
bellard8853f862004-02-22 14:57:26 +00002257 default:
2258 goto unimplemented;
2259 }
2260 break;
Laurent Vivier0d78b3b2013-08-30 01:46:43 +02002261 case SOL_IPV6:
2262 switch (optname) {
2263 case IPV6_MTU_DISCOVER:
2264 case IPV6_MTU:
2265 case IPV6_V6ONLY:
2266 case IPV6_RECVPKTINFO:
Helge Delleree1ac3a2017-02-18 23:31:30 +01002267 case IPV6_UNICAST_HOPS:
Laurent Vivier21749c42018-06-27 23:21:52 +02002268 case IPV6_MULTICAST_HOPS:
2269 case IPV6_MULTICAST_LOOP:
Helge Delleree1ac3a2017-02-18 23:31:30 +01002270 case IPV6_RECVERR:
2271 case IPV6_RECVHOPLIMIT:
2272 case IPV6_2292HOPLIMIT:
2273 case IPV6_CHECKSUM:
Helge Dellerb9cce6d2019-03-10 12:12:16 +01002274 case IPV6_ADDRFORM:
2275 case IPV6_2292PKTINFO:
2276 case IPV6_RECVTCLASS:
2277 case IPV6_RECVRTHDR:
2278 case IPV6_2292RTHDR:
2279 case IPV6_RECVHOPOPTS:
2280 case IPV6_2292HOPOPTS:
2281 case IPV6_RECVDSTOPTS:
2282 case IPV6_2292DSTOPTS:
2283 case IPV6_TCLASS:
Shu-Chun Weng22db1212020-12-18 11:32:12 -08002284 case IPV6_ADDR_PREFERENCES:
Helge Dellerb9cce6d2019-03-10 12:12:16 +01002285#ifdef IPV6_RECVPATHMTU
2286 case IPV6_RECVPATHMTU:
2287#endif
2288#ifdef IPV6_TRANSPARENT
2289 case IPV6_TRANSPARENT:
2290#endif
2291#ifdef IPV6_FREEBIND
2292 case IPV6_FREEBIND:
2293#endif
2294#ifdef IPV6_RECVORIGDSTADDR
2295 case IPV6_RECVORIGDSTADDR:
2296#endif
Laurent Vivier0d78b3b2013-08-30 01:46:43 +02002297 val = 0;
2298 if (optlen < sizeof(uint32_t)) {
2299 return -TARGET_EINVAL;
2300 }
2301 if (get_user_u32(val, optval_addr)) {
2302 return -TARGET_EFAULT;
2303 }
2304 ret = get_errno(setsockopt(sockfd, level, optname,
2305 &val, sizeof(val)));
2306 break;
Helge Delleree1ac3a2017-02-18 23:31:30 +01002307 case IPV6_PKTINFO:
2308 {
2309 struct in6_pktinfo pki;
2310
2311 if (optlen < sizeof(pki)) {
2312 return -TARGET_EINVAL;
2313 }
2314
2315 if (copy_from_user(&pki, optval_addr, sizeof(pki))) {
2316 return -TARGET_EFAULT;
2317 }
2318
2319 pki.ipi6_ifindex = tswap32(pki.ipi6_ifindex);
2320
2321 ret = get_errno(setsockopt(sockfd, level, optname,
2322 &pki, sizeof(pki)));
2323 break;
2324 }
Neng Chen22bf4ee2019-06-19 16:17:10 +02002325 case IPV6_ADD_MEMBERSHIP:
2326 case IPV6_DROP_MEMBERSHIP:
2327 {
2328 struct ipv6_mreq ipv6mreq;
2329
2330 if (optlen < sizeof(ipv6mreq)) {
2331 return -TARGET_EINVAL;
2332 }
2333
2334 if (copy_from_user(&ipv6mreq, optval_addr, sizeof(ipv6mreq))) {
2335 return -TARGET_EFAULT;
2336 }
2337
2338 ipv6mreq.ipv6mr_interface = tswap32(ipv6mreq.ipv6mr_interface);
2339
2340 ret = get_errno(setsockopt(sockfd, level, optname,
2341 &ipv6mreq, sizeof(ipv6mreq)));
2342 break;
2343 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01002344 default:
2345 goto unimplemented;
2346 }
2347 break;
2348 case SOL_ICMPV6:
2349 switch (optname) {
2350 case ICMPV6_FILTER:
2351 {
2352 struct icmp6_filter icmp6f;
2353
2354 if (optlen > sizeof(icmp6f)) {
2355 optlen = sizeof(icmp6f);
2356 }
2357
2358 if (copy_from_user(&icmp6f, optval_addr, optlen)) {
2359 return -TARGET_EFAULT;
2360 }
2361
2362 for (val = 0; val < 8; val++) {
2363 icmp6f.data[val] = tswap32(icmp6f.data[val]);
2364 }
2365
2366 ret = get_errno(setsockopt(sockfd, level, optname,
2367 &icmp6f, optlen));
2368 break;
2369 }
Laurent Vivier0d78b3b2013-08-30 01:46:43 +02002370 default:
2371 goto unimplemented;
2372 }
2373 break;
Jing Huang920394d2012-07-24 13:59:23 +00002374 case SOL_RAW:
2375 switch (optname) {
2376 case ICMP_FILTER:
Helge Delleree1ac3a2017-02-18 23:31:30 +01002377 case IPV6_CHECKSUM:
2378 /* those take an u32 value */
Jing Huang920394d2012-07-24 13:59:23 +00002379 if (optlen < sizeof(uint32_t)) {
2380 return -TARGET_EINVAL;
2381 }
2382
2383 if (get_user_u32(val, optval_addr)) {
2384 return -TARGET_EFAULT;
2385 }
2386 ret = get_errno(setsockopt(sockfd, level, optname,
2387 &val, sizeof(val)));
2388 break;
2389
2390 default:
2391 goto unimplemented;
2392 }
2393 break;
Yunqiang Suf31dddd2019-06-19 16:17:11 +02002394#if defined(SOL_ALG) && defined(ALG_SET_KEY) && defined(ALG_SET_AEAD_AUTHSIZE)
2395 case SOL_ALG:
2396 switch (optname) {
2397 case ALG_SET_KEY:
2398 {
2399 char *alg_key = g_malloc(optlen);
2400
2401 if (!alg_key) {
2402 return -TARGET_ENOMEM;
2403 }
2404 if (copy_from_user(alg_key, optval_addr, optlen)) {
2405 g_free(alg_key);
2406 return -TARGET_EFAULT;
2407 }
2408 ret = get_errno(setsockopt(sockfd, level, optname,
2409 alg_key, optlen));
2410 g_free(alg_key);
2411 break;
2412 }
2413 case ALG_SET_AEAD_AUTHSIZE:
2414 {
2415 ret = get_errno(setsockopt(sockfd, level, optname,
2416 NULL, optlen));
2417 break;
2418 }
2419 default:
2420 goto unimplemented;
2421 }
2422 break;
2423#endif
bellard3532fa72006-06-24 15:06:03 +00002424 case TARGET_SOL_SOCKET:
bellard8853f862004-02-22 14:57:26 +00002425 switch (optname) {
Laurent Vivier1b09aeb2013-01-01 08:24:11 +00002426 case TARGET_SO_RCVTIMEO:
2427 {
2428 struct timeval tv;
2429
2430 optname = SO_RCVTIMEO;
2431
2432set_timeout:
2433 if (optlen != sizeof(struct target_timeval)) {
2434 return -TARGET_EINVAL;
2435 }
2436
2437 if (copy_from_user_timeval(&tv, optval_addr)) {
2438 return -TARGET_EFAULT;
2439 }
2440
2441 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
2442 &tv, sizeof(tv)));
2443 return ret;
2444 }
2445 case TARGET_SO_SNDTIMEO:
2446 optname = SO_SNDTIMEO;
2447 goto set_timeout;
Laurent Vivierf57d4192013-08-30 01:46:41 +02002448 case TARGET_SO_ATTACH_FILTER:
2449 {
2450 struct target_sock_fprog *tfprog;
2451 struct target_sock_filter *tfilter;
2452 struct sock_fprog fprog;
2453 struct sock_filter *filter;
2454 int i;
2455
2456 if (optlen != sizeof(*tfprog)) {
2457 return -TARGET_EINVAL;
2458 }
2459 if (!lock_user_struct(VERIFY_READ, tfprog, optval_addr, 0)) {
2460 return -TARGET_EFAULT;
2461 }
2462 if (!lock_user_struct(VERIFY_READ, tfilter,
2463 tswapal(tfprog->filter), 0)) {
2464 unlock_user_struct(tfprog, optval_addr, 1);
2465 return -TARGET_EFAULT;
2466 }
2467
2468 fprog.len = tswap16(tfprog->len);
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05302469 filter = g_try_new(struct sock_filter, fprog.len);
Laurent Vivierf57d4192013-08-30 01:46:41 +02002470 if (filter == NULL) {
2471 unlock_user_struct(tfilter, tfprog->filter, 1);
2472 unlock_user_struct(tfprog, optval_addr, 1);
2473 return -TARGET_ENOMEM;
2474 }
2475 for (i = 0; i < fprog.len; i++) {
2476 filter[i].code = tswap16(tfilter[i].code);
2477 filter[i].jt = tfilter[i].jt;
2478 filter[i].jf = tfilter[i].jf;
2479 filter[i].k = tswap32(tfilter[i].k);
2480 }
2481 fprog.filter = filter;
2482
2483 ret = get_errno(setsockopt(sockfd, SOL_SOCKET,
2484 SO_ATTACH_FILTER, &fprog, sizeof(fprog)));
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05302485 g_free(filter);
Laurent Vivierf57d4192013-08-30 01:46:41 +02002486
2487 unlock_user_struct(tfilter, tfprog->filter, 1);
2488 unlock_user_struct(tfprog, optval_addr, 1);
2489 return ret;
2490 }
Joakim Tjernlund451aaf62014-07-12 15:47:06 +02002491 case TARGET_SO_BINDTODEVICE:
2492 {
2493 char *dev_ifname, *addr_ifname;
2494
2495 if (optlen > IFNAMSIZ - 1) {
2496 optlen = IFNAMSIZ - 1;
2497 }
2498 dev_ifname = lock_user(VERIFY_READ, optval_addr, optlen, 1);
2499 if (!dev_ifname) {
2500 return -TARGET_EFAULT;
2501 }
2502 optname = SO_BINDTODEVICE;
2503 addr_ifname = alloca(IFNAMSIZ);
2504 memcpy(addr_ifname, dev_ifname, optlen);
2505 addr_ifname[optlen] = 0;
Chen Gangfad6c582016-01-11 13:58:50 +08002506 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
2507 addr_ifname, optlen));
Joakim Tjernlund451aaf62014-07-12 15:47:06 +02002508 unlock_user (dev_ifname, optval_addr, 0);
2509 return ret;
2510 }
Carlo Marcelo Arenas BelĂłn83eb6e52018-08-24 01:56:01 -07002511 case TARGET_SO_LINGER:
2512 {
2513 struct linger lg;
2514 struct target_linger *tlg;
2515
2516 if (optlen != sizeof(struct target_linger)) {
2517 return -TARGET_EINVAL;
2518 }
2519 if (!lock_user_struct(VERIFY_READ, tlg, optval_addr, 1)) {
2520 return -TARGET_EFAULT;
2521 }
2522 __get_user(lg.l_onoff, &tlg->l_onoff);
2523 __get_user(lg.l_linger, &tlg->l_linger);
2524 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, SO_LINGER,
2525 &lg, sizeof(lg)));
2526 unlock_user_struct(tlg, optval_addr, 0);
2527 return ret;
2528 }
bellard8853f862004-02-22 14:57:26 +00002529 /* Options with 'int' argument. */
bellard3532fa72006-06-24 15:06:03 +00002530 case TARGET_SO_DEBUG:
2531 optname = SO_DEBUG;
2532 break;
2533 case TARGET_SO_REUSEADDR:
2534 optname = SO_REUSEADDR;
2535 break;
Yunqiang Su113a9dd2018-10-30 13:55:08 +01002536#ifdef SO_REUSEPORT
2537 case TARGET_SO_REUSEPORT:
2538 optname = SO_REUSEPORT;
2539 break;
2540#endif
bellard3532fa72006-06-24 15:06:03 +00002541 case TARGET_SO_TYPE:
2542 optname = SO_TYPE;
2543 break;
2544 case TARGET_SO_ERROR:
2545 optname = SO_ERROR;
2546 break;
2547 case TARGET_SO_DONTROUTE:
2548 optname = SO_DONTROUTE;
2549 break;
2550 case TARGET_SO_BROADCAST:
2551 optname = SO_BROADCAST;
2552 break;
2553 case TARGET_SO_SNDBUF:
2554 optname = SO_SNDBUF;
2555 break;
Paul Burtond79b6cc2014-06-22 11:25:35 +01002556 case TARGET_SO_SNDBUFFORCE:
2557 optname = SO_SNDBUFFORCE;
2558 break;
bellard3532fa72006-06-24 15:06:03 +00002559 case TARGET_SO_RCVBUF:
2560 optname = SO_RCVBUF;
2561 break;
Paul Burtond79b6cc2014-06-22 11:25:35 +01002562 case TARGET_SO_RCVBUFFORCE:
2563 optname = SO_RCVBUFFORCE;
2564 break;
bellard3532fa72006-06-24 15:06:03 +00002565 case TARGET_SO_KEEPALIVE:
2566 optname = SO_KEEPALIVE;
2567 break;
2568 case TARGET_SO_OOBINLINE:
2569 optname = SO_OOBINLINE;
2570 break;
2571 case TARGET_SO_NO_CHECK:
2572 optname = SO_NO_CHECK;
2573 break;
2574 case TARGET_SO_PRIORITY:
2575 optname = SO_PRIORITY;
2576 break;
bellard5e83e8e2005-03-01 22:32:06 +00002577#ifdef SO_BSDCOMPAT
bellard3532fa72006-06-24 15:06:03 +00002578 case TARGET_SO_BSDCOMPAT:
2579 optname = SO_BSDCOMPAT;
2580 break;
bellard5e83e8e2005-03-01 22:32:06 +00002581#endif
bellard3532fa72006-06-24 15:06:03 +00002582 case TARGET_SO_PASSCRED:
2583 optname = SO_PASSCRED;
2584 break;
Paul Burton82d0fe62014-06-22 11:25:36 +01002585 case TARGET_SO_PASSSEC:
2586 optname = SO_PASSSEC;
2587 break;
bellard3532fa72006-06-24 15:06:03 +00002588 case TARGET_SO_TIMESTAMP:
2589 optname = SO_TIMESTAMP;
2590 break;
2591 case TARGET_SO_RCVLOWAT:
2592 optname = SO_RCVLOWAT;
2593 break;
bellard8853f862004-02-22 14:57:26 +00002594 default:
2595 goto unimplemented;
2596 }
bellard3532fa72006-06-24 15:06:03 +00002597 if (optlen < sizeof(uint32_t))
bellard2f619692007-11-16 10:46:05 +00002598 return -TARGET_EINVAL;
bellard3532fa72006-06-24 15:06:03 +00002599
bellard2f619692007-11-16 10:46:05 +00002600 if (get_user_u32(val, optval_addr))
2601 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00002602 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
bellard8853f862004-02-22 14:57:26 +00002603 break;
Josh Kunza2d86682019-10-29 15:43:10 -07002604#ifdef SOL_NETLINK
2605 case SOL_NETLINK:
2606 switch (optname) {
2607 case NETLINK_PKTINFO:
2608 case NETLINK_ADD_MEMBERSHIP:
2609 case NETLINK_DROP_MEMBERSHIP:
2610 case NETLINK_BROADCAST_ERROR:
2611 case NETLINK_NO_ENOBUFS:
2612#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2613 case NETLINK_LISTEN_ALL_NSID:
2614 case NETLINK_CAP_ACK:
2615#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2616#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
2617 case NETLINK_EXT_ACK:
2618#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2619#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
2620 case NETLINK_GET_STRICT_CHK:
2621#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2622 break;
2623 default:
2624 goto unimplemented;
2625 }
2626 val = 0;
2627 if (optlen < sizeof(uint32_t)) {
2628 return -TARGET_EINVAL;
2629 }
2630 if (get_user_u32(val, optval_addr)) {
2631 return -TARGET_EFAULT;
2632 }
2633 ret = get_errno(setsockopt(sockfd, SOL_NETLINK, optname, &val,
2634 sizeof(val)));
2635 break;
2636#endif /* SOL_NETLINK */
bellard7854b052003-03-29 17:22:23 +00002637 default:
bellard8853f862004-02-22 14:57:26 +00002638 unimplemented:
Josh Kunz39be5352020-02-03 18:54:13 -08002639 qemu_log_mask(LOG_UNIMP, "Unsupported setsockopt level=%d optname=%d\n",
2640 level, optname);
ths6fa13c12007-12-18 02:41:04 +00002641 ret = -TARGET_ENOPROTOOPT;
bellard7854b052003-03-29 17:22:23 +00002642 }
bellard8853f862004-02-22 14:57:26 +00002643 return ret;
bellard7854b052003-03-29 17:22:23 +00002644}
2645
ths0da46a62007-10-20 20:23:07 +00002646/* do_getsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002647static abi_long do_getsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00002648 abi_ulong optval_addr, abi_ulong optlen)
bellard7854b052003-03-29 17:22:23 +00002649{
blueswir1992f48a2007-10-14 16:27:31 +00002650 abi_long ret;
blueswir1b55266b2008-09-20 08:07:15 +00002651 int len, val;
2652 socklen_t lv;
bellard8853f862004-02-22 14:57:26 +00002653
2654 switch(level) {
bellard3532fa72006-06-24 15:06:03 +00002655 case TARGET_SOL_SOCKET:
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002656 level = SOL_SOCKET;
2657 switch (optname) {
2658 /* These don't just return a single integer */
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002659 case TARGET_SO_PEERNAME:
2660 goto unimplemented;
Andreas Schwab405dc4c2019-05-13 11:06:26 +02002661 case TARGET_SO_RCVTIMEO: {
2662 struct timeval tv;
2663 socklen_t tvlen;
2664
2665 optname = SO_RCVTIMEO;
2666
2667get_timeout:
2668 if (get_user_u32(len, optlen)) {
2669 return -TARGET_EFAULT;
2670 }
2671 if (len < 0) {
2672 return -TARGET_EINVAL;
2673 }
2674
2675 tvlen = sizeof(tv);
2676 ret = get_errno(getsockopt(sockfd, level, optname,
2677 &tv, &tvlen));
2678 if (ret < 0) {
2679 return ret;
2680 }
2681 if (len > sizeof(struct target_timeval)) {
2682 len = sizeof(struct target_timeval);
2683 }
2684 if (copy_to_user_timeval(optval_addr, &tv)) {
2685 return -TARGET_EFAULT;
2686 }
2687 if (put_user_u32(len, optlen)) {
2688 return -TARGET_EFAULT;
2689 }
2690 break;
2691 }
2692 case TARGET_SO_SNDTIMEO:
2693 optname = SO_SNDTIMEO;
2694 goto get_timeout;
Akos PASZTORY583359a2011-11-14 15:09:49 +02002695 case TARGET_SO_PEERCRED: {
2696 struct ucred cr;
2697 socklen_t crlen;
2698 struct target_ucred *tcr;
2699
2700 if (get_user_u32(len, optlen)) {
2701 return -TARGET_EFAULT;
2702 }
2703 if (len < 0) {
2704 return -TARGET_EINVAL;
2705 }
2706
2707 crlen = sizeof(cr);
2708 ret = get_errno(getsockopt(sockfd, level, SO_PEERCRED,
2709 &cr, &crlen));
2710 if (ret < 0) {
2711 return ret;
2712 }
2713 if (len > crlen) {
2714 len = crlen;
2715 }
2716 if (!lock_user_struct(VERIFY_WRITE, tcr, optval_addr, 0)) {
2717 return -TARGET_EFAULT;
2718 }
2719 __put_user(cr.pid, &tcr->pid);
2720 __put_user(cr.uid, &tcr->uid);
2721 __put_user(cr.gid, &tcr->gid);
2722 unlock_user_struct(tcr, optval_addr, 1);
2723 if (put_user_u32(len, optlen)) {
2724 return -TARGET_EFAULT;
2725 }
2726 break;
2727 }
Laurent Vivier6d485a52020-02-04 22:19:01 +01002728 case TARGET_SO_PEERSEC: {
2729 char *name;
2730
2731 if (get_user_u32(len, optlen)) {
2732 return -TARGET_EFAULT;
2733 }
2734 if (len < 0) {
2735 return -TARGET_EINVAL;
2736 }
2737 name = lock_user(VERIFY_WRITE, optval_addr, len, 0);
2738 if (!name) {
2739 return -TARGET_EFAULT;
2740 }
2741 lv = len;
2742 ret = get_errno(getsockopt(sockfd, level, SO_PEERSEC,
2743 name, &lv));
2744 if (put_user_u32(lv, optlen)) {
2745 ret = -TARGET_EFAULT;
2746 }
2747 unlock_user(name, optval_addr, lv);
2748 break;
2749 }
Carlo Marcelo Arenas BelĂłn83eb6e52018-08-24 01:56:01 -07002750 case TARGET_SO_LINGER:
2751 {
2752 struct linger lg;
2753 socklen_t lglen;
2754 struct target_linger *tlg;
2755
2756 if (get_user_u32(len, optlen)) {
2757 return -TARGET_EFAULT;
2758 }
2759 if (len < 0) {
2760 return -TARGET_EINVAL;
2761 }
2762
2763 lglen = sizeof(lg);
2764 ret = get_errno(getsockopt(sockfd, level, SO_LINGER,
2765 &lg, &lglen));
2766 if (ret < 0) {
2767 return ret;
2768 }
2769 if (len > lglen) {
2770 len = lglen;
2771 }
2772 if (!lock_user_struct(VERIFY_WRITE, tlg, optval_addr, 0)) {
2773 return -TARGET_EFAULT;
2774 }
2775 __put_user(lg.l_onoff, &tlg->l_onoff);
2776 __put_user(lg.l_linger, &tlg->l_linger);
2777 unlock_user_struct(tlg, optval_addr, 1);
2778 if (put_user_u32(len, optlen)) {
2779 return -TARGET_EFAULT;
2780 }
2781 break;
2782 }
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002783 /* Options with 'int' argument. */
2784 case TARGET_SO_DEBUG:
2785 optname = SO_DEBUG;
2786 goto int_case;
2787 case TARGET_SO_REUSEADDR:
2788 optname = SO_REUSEADDR;
2789 goto int_case;
Yunqiang Su113a9dd2018-10-30 13:55:08 +01002790#ifdef SO_REUSEPORT
2791 case TARGET_SO_REUSEPORT:
2792 optname = SO_REUSEPORT;
2793 goto int_case;
2794#endif
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002795 case TARGET_SO_TYPE:
2796 optname = SO_TYPE;
2797 goto int_case;
2798 case TARGET_SO_ERROR:
2799 optname = SO_ERROR;
2800 goto int_case;
2801 case TARGET_SO_DONTROUTE:
2802 optname = SO_DONTROUTE;
2803 goto int_case;
2804 case TARGET_SO_BROADCAST:
2805 optname = SO_BROADCAST;
2806 goto int_case;
2807 case TARGET_SO_SNDBUF:
2808 optname = SO_SNDBUF;
2809 goto int_case;
2810 case TARGET_SO_RCVBUF:
2811 optname = SO_RCVBUF;
2812 goto int_case;
2813 case TARGET_SO_KEEPALIVE:
2814 optname = SO_KEEPALIVE;
2815 goto int_case;
2816 case TARGET_SO_OOBINLINE:
2817 optname = SO_OOBINLINE;
2818 goto int_case;
2819 case TARGET_SO_NO_CHECK:
2820 optname = SO_NO_CHECK;
2821 goto int_case;
2822 case TARGET_SO_PRIORITY:
2823 optname = SO_PRIORITY;
2824 goto int_case;
2825#ifdef SO_BSDCOMPAT
2826 case TARGET_SO_BSDCOMPAT:
2827 optname = SO_BSDCOMPAT;
2828 goto int_case;
2829#endif
2830 case TARGET_SO_PASSCRED:
2831 optname = SO_PASSCRED;
2832 goto int_case;
2833 case TARGET_SO_TIMESTAMP:
2834 optname = SO_TIMESTAMP;
2835 goto int_case;
2836 case TARGET_SO_RCVLOWAT:
2837 optname = SO_RCVLOWAT;
2838 goto int_case;
Paul Burtonaec1ca42014-06-22 11:25:34 +01002839 case TARGET_SO_ACCEPTCONN:
2840 optname = SO_ACCEPTCONN;
2841 goto int_case;
Jason A. Donenfeldec63e062021-02-04 16:39:25 +01002842 case TARGET_SO_PROTOCOL:
2843 optname = SO_PROTOCOL;
2844 goto int_case;
2845 case TARGET_SO_DOMAIN:
2846 optname = SO_DOMAIN;
2847 goto int_case;
bellard8853f862004-02-22 14:57:26 +00002848 default:
bellard2efbe912005-07-23 15:10:20 +00002849 goto int_case;
2850 }
2851 break;
2852 case SOL_TCP:
Shu-Chun Wengfe51b0a2020-12-18 11:32:11 -08002853 case SOL_UDP:
2854 /* TCP and UDP options all take an 'int' value. */
bellard2efbe912005-07-23 15:10:20 +00002855 int_case:
bellard2f619692007-11-16 10:46:05 +00002856 if (get_user_u32(len, optlen))
2857 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002858 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00002859 return -TARGET_EINVAL;
Mike Frysinger73160d92011-02-07 01:05:49 -05002860 lv = sizeof(lv);
bellard2efbe912005-07-23 15:10:20 +00002861 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2862 if (ret < 0)
2863 return ret;
Paul Burton8289d112014-06-22 11:25:33 +01002864 if (optname == SO_TYPE) {
2865 val = host_to_target_sock_type(val);
2866 }
bellard2efbe912005-07-23 15:10:20 +00002867 if (len > lv)
2868 len = lv;
bellard2f619692007-11-16 10:46:05 +00002869 if (len == 4) {
2870 if (put_user_u32(val, optval_addr))
2871 return -TARGET_EFAULT;
2872 } else {
2873 if (put_user_u8(val, optval_addr))
2874 return -TARGET_EFAULT;
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002875 }
bellard2f619692007-11-16 10:46:05 +00002876 if (put_user_u32(len, optlen))
2877 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002878 break;
2879 case SOL_IP:
2880 switch(optname) {
2881 case IP_TOS:
2882 case IP_TTL:
2883 case IP_HDRINCL:
2884 case IP_ROUTER_ALERT:
2885 case IP_RECVOPTS:
2886 case IP_RETOPTS:
2887 case IP_PKTINFO:
2888 case IP_MTU_DISCOVER:
2889 case IP_RECVERR:
2890 case IP_RECVTOS:
2891#ifdef IP_FREEBIND
2892 case IP_FREEBIND:
2893#endif
2894 case IP_MULTICAST_TTL:
2895 case IP_MULTICAST_LOOP:
bellard2f619692007-11-16 10:46:05 +00002896 if (get_user_u32(len, optlen))
2897 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00002898 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00002899 return -TARGET_EINVAL;
Mike Frysinger73160d92011-02-07 01:05:49 -05002900 lv = sizeof(lv);
bellard8853f862004-02-22 14:57:26 +00002901 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2902 if (ret < 0)
2903 return ret;
bellard2efbe912005-07-23 15:10:20 +00002904 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
bellard2efbe912005-07-23 15:10:20 +00002905 len = 1;
bellard2f619692007-11-16 10:46:05 +00002906 if (put_user_u32(len, optlen)
2907 || put_user_u8(val, optval_addr))
2908 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002909 } else {
bellard2efbe912005-07-23 15:10:20 +00002910 if (len > sizeof(int))
2911 len = sizeof(int);
bellard2f619692007-11-16 10:46:05 +00002912 if (put_user_u32(len, optlen)
2913 || put_user_u32(val, optval_addr))
2914 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002915 }
bellard8853f862004-02-22 14:57:26 +00002916 break;
bellard2efbe912005-07-23 15:10:20 +00002917 default:
thsc02f4992007-12-18 02:39:59 +00002918 ret = -TARGET_ENOPROTOOPT;
2919 break;
bellard8853f862004-02-22 14:57:26 +00002920 }
2921 break;
Tom Deseynbd8ed482018-12-13 14:06:11 +01002922 case SOL_IPV6:
2923 switch (optname) {
2924 case IPV6_MTU_DISCOVER:
2925 case IPV6_MTU:
2926 case IPV6_V6ONLY:
2927 case IPV6_RECVPKTINFO:
2928 case IPV6_UNICAST_HOPS:
2929 case IPV6_MULTICAST_HOPS:
2930 case IPV6_MULTICAST_LOOP:
2931 case IPV6_RECVERR:
2932 case IPV6_RECVHOPLIMIT:
2933 case IPV6_2292HOPLIMIT:
2934 case IPV6_CHECKSUM:
Helge Dellerb9cce6d2019-03-10 12:12:16 +01002935 case IPV6_ADDRFORM:
2936 case IPV6_2292PKTINFO:
2937 case IPV6_RECVTCLASS:
2938 case IPV6_RECVRTHDR:
2939 case IPV6_2292RTHDR:
2940 case IPV6_RECVHOPOPTS:
2941 case IPV6_2292HOPOPTS:
2942 case IPV6_RECVDSTOPTS:
2943 case IPV6_2292DSTOPTS:
2944 case IPV6_TCLASS:
Shu-Chun Weng22db1212020-12-18 11:32:12 -08002945 case IPV6_ADDR_PREFERENCES:
Helge Dellerb9cce6d2019-03-10 12:12:16 +01002946#ifdef IPV6_RECVPATHMTU
2947 case IPV6_RECVPATHMTU:
2948#endif
2949#ifdef IPV6_TRANSPARENT
2950 case IPV6_TRANSPARENT:
2951#endif
2952#ifdef IPV6_FREEBIND
2953 case IPV6_FREEBIND:
2954#endif
2955#ifdef IPV6_RECVORIGDSTADDR
2956 case IPV6_RECVORIGDSTADDR:
2957#endif
Tom Deseynbd8ed482018-12-13 14:06:11 +01002958 if (get_user_u32(len, optlen))
2959 return -TARGET_EFAULT;
2960 if (len < 0)
2961 return -TARGET_EINVAL;
2962 lv = sizeof(lv);
2963 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2964 if (ret < 0)
2965 return ret;
2966 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
2967 len = 1;
2968 if (put_user_u32(len, optlen)
2969 || put_user_u8(val, optval_addr))
2970 return -TARGET_EFAULT;
2971 } else {
2972 if (len > sizeof(int))
2973 len = sizeof(int);
2974 if (put_user_u32(len, optlen)
2975 || put_user_u32(val, optval_addr))
2976 return -TARGET_EFAULT;
2977 }
2978 break;
2979 default:
2980 ret = -TARGET_ENOPROTOOPT;
2981 break;
2982 }
2983 break;
Josh Kunza2d86682019-10-29 15:43:10 -07002984#ifdef SOL_NETLINK
2985 case SOL_NETLINK:
2986 switch (optname) {
2987 case NETLINK_PKTINFO:
2988 case NETLINK_BROADCAST_ERROR:
2989 case NETLINK_NO_ENOBUFS:
2990#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2991 case NETLINK_LISTEN_ALL_NSID:
2992 case NETLINK_CAP_ACK:
2993#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2994#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
2995 case NETLINK_EXT_ACK:
2996#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2997#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
2998 case NETLINK_GET_STRICT_CHK:
2999#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
3000 if (get_user_u32(len, optlen)) {
3001 return -TARGET_EFAULT;
3002 }
3003 if (len != sizeof(val)) {
3004 return -TARGET_EINVAL;
3005 }
3006 lv = len;
3007 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
3008 if (ret < 0) {
3009 return ret;
3010 }
3011 if (put_user_u32(lv, optlen)
3012 || put_user_u32(val, optval_addr)) {
3013 return -TARGET_EFAULT;
3014 }
3015 break;
3016#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
3017 case NETLINK_LIST_MEMBERSHIPS:
3018 {
3019 uint32_t *results;
3020 int i;
3021 if (get_user_u32(len, optlen)) {
3022 return -TARGET_EFAULT;
3023 }
3024 if (len < 0) {
3025 return -TARGET_EINVAL;
3026 }
3027 results = lock_user(VERIFY_WRITE, optval_addr, len, 1);
3028 if (!results) {
3029 return -TARGET_EFAULT;
3030 }
3031 lv = len;
3032 ret = get_errno(getsockopt(sockfd, level, optname, results, &lv));
3033 if (ret < 0) {
3034 unlock_user(results, optval_addr, 0);
3035 return ret;
3036 }
3037 /* swap host endianess to target endianess. */
3038 for (i = 0; i < (len / sizeof(uint32_t)); i++) {
3039 results[i] = tswap32(results[i]);
3040 }
3041 if (put_user_u32(lv, optlen)) {
3042 return -TARGET_EFAULT;
3043 }
3044 unlock_user(results, optval_addr, 0);
3045 break;
3046 }
3047#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
3048 default:
3049 goto unimplemented;
3050 }
Laurent Vivierc0cb8802019-11-12 11:50:55 +01003051 break;
Josh Kunza2d86682019-10-29 15:43:10 -07003052#endif /* SOL_NETLINK */
bellard8853f862004-02-22 14:57:26 +00003053 default:
3054 unimplemented:
Josh Kunz39be5352020-02-03 18:54:13 -08003055 qemu_log_mask(LOG_UNIMP,
3056 "getsockopt level=%d optname=%d not yet supported\n",
3057 level, optname);
thsc02f4992007-12-18 02:39:59 +00003058 ret = -TARGET_EOPNOTSUPP;
bellard8853f862004-02-22 14:57:26 +00003059 break;
3060 }
3061 return ret;
bellard7854b052003-03-29 17:22:23 +00003062}
3063
Max Filippov9ac22512018-04-04 17:30:41 -07003064/* Convert target low/high pair representing file offset into the host
3065 * low/high pair. This function doesn't handle offsets bigger than 64 bits
3066 * as the kernel doesn't handle them either.
3067 */
3068static void target_to_host_low_high(abi_ulong tlow,
3069 abi_ulong thigh,
3070 unsigned long *hlow,
3071 unsigned long *hhigh)
3072{
3073 uint64_t off = tlow |
3074 ((unsigned long long)thigh << TARGET_LONG_BITS / 2) <<
3075 TARGET_LONG_BITS / 2;
3076
3077 *hlow = off;
3078 *hhigh = (off >> HOST_LONG_BITS / 2) >> HOST_LONG_BITS / 2;
3079}
3080
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003081static struct iovec *lock_iovec(int type, abi_ulong target_addr,
Peter Maydelldab32b32016-07-15 14:57:26 +01003082 abi_ulong count, int copy)
pbrook53a59602006-03-25 19:31:22 +00003083{
3084 struct target_iovec *target_vec;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003085 struct iovec *vec;
3086 abi_ulong total_len, max_len;
balrogd732dcb2008-10-28 10:21:03 +00003087 int i;
Peter Maydell501bb4b2014-02-17 18:55:33 +00003088 int err = 0;
Tom Musta29560a62014-08-12 13:53:43 -05003089 bool bad_address = false;
pbrook53a59602006-03-25 19:31:22 +00003090
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003091 if (count == 0) {
3092 errno = 0;
3093 return NULL;
pbrook53a59602006-03-25 19:31:22 +00003094 }
Peter Maydelldab32b32016-07-15 14:57:26 +01003095 if (count > IOV_MAX) {
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003096 errno = EINVAL;
3097 return NULL;
3098 }
3099
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303100 vec = g_try_new0(struct iovec, count);
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003101 if (vec == NULL) {
3102 errno = ENOMEM;
3103 return NULL;
3104 }
3105
3106 target_vec = lock_user(VERIFY_READ, target_addr,
3107 count * sizeof(struct target_iovec), 1);
3108 if (target_vec == NULL) {
Peter Maydell501bb4b2014-02-17 18:55:33 +00003109 err = EFAULT;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003110 goto fail2;
3111 }
3112
3113 /* ??? If host page size > target page size, this will result in a
3114 value larger than what we can actually support. */
3115 max_len = 0x7fffffff & TARGET_PAGE_MASK;
3116 total_len = 0;
3117
3118 for (i = 0; i < count; i++) {
3119 abi_ulong base = tswapal(target_vec[i].iov_base);
3120 abi_long len = tswapal(target_vec[i].iov_len);
3121
3122 if (len < 0) {
Peter Maydell501bb4b2014-02-17 18:55:33 +00003123 err = EINVAL;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003124 goto fail;
3125 } else if (len == 0) {
3126 /* Zero length pointer is ignored. */
3127 vec[i].iov_base = 0;
3128 } else {
3129 vec[i].iov_base = lock_user(type, base, len, copy);
Tom Musta29560a62014-08-12 13:53:43 -05003130 /* If the first buffer pointer is bad, this is a fault. But
3131 * subsequent bad buffers will result in a partial write; this
3132 * is realized by filling the vector with null pointers and
3133 * zero lengths. */
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003134 if (!vec[i].iov_base) {
Tom Musta29560a62014-08-12 13:53:43 -05003135 if (i == 0) {
3136 err = EFAULT;
3137 goto fail;
3138 } else {
3139 bad_address = true;
3140 }
3141 }
3142 if (bad_address) {
3143 len = 0;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003144 }
3145 if (len > max_len - total_len) {
3146 len = max_len - total_len;
3147 }
3148 }
3149 vec[i].iov_len = len;
3150 total_len += len;
3151 }
3152
3153 unlock_user(target_vec, target_addr, 0);
3154 return vec;
3155
3156 fail:
Chen Gang S7eff5182015-01-23 18:01:09 +08003157 while (--i >= 0) {
3158 if (tswapal(target_vec[i].iov_len) > 0) {
3159 unlock_user(vec[i].iov_base, tswapal(target_vec[i].iov_base), 0);
3160 }
3161 }
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003162 unlock_user(target_vec, target_addr, 0);
Peter Maydell501bb4b2014-02-17 18:55:33 +00003163 fail2:
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303164 g_free(vec);
Peter Maydell501bb4b2014-02-17 18:55:33 +00003165 errno = err;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003166 return NULL;
pbrook53a59602006-03-25 19:31:22 +00003167}
3168
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003169static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
Peter Maydelldab32b32016-07-15 14:57:26 +01003170 abi_ulong count, int copy)
pbrook53a59602006-03-25 19:31:22 +00003171{
3172 struct target_iovec *target_vec;
pbrook53a59602006-03-25 19:31:22 +00003173 int i;
3174
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003175 target_vec = lock_user(VERIFY_READ, target_addr,
3176 count * sizeof(struct target_iovec), 1);
3177 if (target_vec) {
3178 for (i = 0; i < count; i++) {
3179 abi_ulong base = tswapal(target_vec[i].iov_base);
Chen Gang S71ec7ce2015-01-23 18:07:50 +08003180 abi_long len = tswapal(target_vec[i].iov_len);
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003181 if (len < 0) {
3182 break;
3183 }
balrogd732dcb2008-10-28 10:21:03 +00003184 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
3185 }
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003186 unlock_user(target_vec, target_addr, 0);
pbrook53a59602006-03-25 19:31:22 +00003187 }
bellard579a97f2007-11-11 14:26:47 +00003188
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303189 g_free(vec);
pbrook53a59602006-03-25 19:31:22 +00003190}
3191
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003192static inline int target_to_host_sock_type(int *type)
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003193{
3194 int host_type = 0;
3195 int target_type = *type;
3196
3197 switch (target_type & TARGET_SOCK_TYPE_MASK) {
3198 case TARGET_SOCK_DGRAM:
3199 host_type = SOCK_DGRAM;
3200 break;
3201 case TARGET_SOCK_STREAM:
3202 host_type = SOCK_STREAM;
3203 break;
3204 default:
3205 host_type = target_type & TARGET_SOCK_TYPE_MASK;
3206 break;
3207 }
3208 if (target_type & TARGET_SOCK_CLOEXEC) {
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003209#if defined(SOCK_CLOEXEC)
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003210 host_type |= SOCK_CLOEXEC;
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003211#else
3212 return -TARGET_EINVAL;
3213#endif
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003214 }
3215 if (target_type & TARGET_SOCK_NONBLOCK) {
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003216#if defined(SOCK_NONBLOCK)
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003217 host_type |= SOCK_NONBLOCK;
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003218#elif !defined(O_NONBLOCK)
3219 return -TARGET_EINVAL;
3220#endif
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003221 }
3222 *type = host_type;
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003223 return 0;
3224}
3225
3226/* Try to emulate socket type flags after socket creation. */
3227static int sock_flags_fixup(int fd, int target_type)
3228{
3229#if !defined(SOCK_NONBLOCK) && defined(O_NONBLOCK)
3230 if (target_type & TARGET_SOCK_NONBLOCK) {
3231 int flags = fcntl(fd, F_GETFL);
3232 if (fcntl(fd, F_SETFL, O_NONBLOCK | flags) == -1) {
3233 close(fd);
3234 return -TARGET_EINVAL;
3235 }
3236 }
3237#endif
3238 return fd;
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003239}
3240
ths0da46a62007-10-20 20:23:07 +00003241/* do_socket() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003242static abi_long do_socket(int domain, int type, int protocol)
bellard3532fa72006-06-24 15:06:03 +00003243{
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003244 int target_type = type;
3245 int ret;
3246
3247 ret = target_to_host_sock_type(&type);
3248 if (ret) {
3249 return ret;
3250 }
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003251
Laurent Vivier575b22b2016-06-02 22:14:15 +02003252 if (domain == PF_NETLINK && !(
3253#ifdef CONFIG_RTNETLINK
3254 protocol == NETLINK_ROUTE ||
3255#endif
3256 protocol == NETLINK_KOBJECT_UEVENT ||
3257 protocol == NETLINK_AUDIT)) {
Josh Kunz71e24432020-07-06 17:10:36 -07003258 return -TARGET_EPROTONOSUPPORT;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003259 }
Laurent Vivierff626f22015-10-28 21:40:42 +01003260
3261 if (domain == AF_PACKET ||
3262 (domain == AF_INET && type == SOCK_PACKET)) {
3263 protocol = tswap16(protocol);
3264 }
3265
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003266 ret = get_errno(socket(domain, type, protocol));
3267 if (ret >= 0) {
3268 ret = sock_flags_fixup(ret, target_type);
Laurent Vivier0cf22722015-10-28 21:40:45 +01003269 if (type == SOCK_PACKET) {
3270 /* Manage an obsolete case :
3271 * if socket type is SOCK_PACKET, bind by name
3272 */
3273 fd_trans_register(ret, &target_packet_trans);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003274 } else if (domain == PF_NETLINK) {
3275 switch (protocol) {
Laurent Vivier575b22b2016-06-02 22:14:15 +02003276#ifdef CONFIG_RTNETLINK
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003277 case NETLINK_ROUTE:
3278 fd_trans_register(ret, &target_netlink_route_trans);
3279 break;
Laurent Vivier575b22b2016-06-02 22:14:15 +02003280#endif
Laurent Vivierb2656202016-05-22 18:56:20 +02003281 case NETLINK_KOBJECT_UEVENT:
3282 /* nothing to do: messages are strings */
3283 break;
Laurent Vivier5ce9bb52016-05-22 18:56:21 +02003284 case NETLINK_AUDIT:
3285 fd_trans_register(ret, &target_netlink_audit_trans);
3286 break;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003287 default:
3288 g_assert_not_reached();
3289 }
Laurent Vivier0cf22722015-10-28 21:40:45 +01003290 }
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003291 }
3292 return ret;
bellard3532fa72006-06-24 15:06:03 +00003293}
3294
ths0da46a62007-10-20 20:23:07 +00003295/* do_bind() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003296static abi_long do_bind(int sockfd, abi_ulong target_addr,
3297 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00003298{
aurel328f7aeaf2009-01-30 19:47:57 +00003299 void *addr;
Arnaud Patard917507b2009-06-19 10:44:45 +03003300 abi_long ret;
aurel328f7aeaf2009-01-30 19:47:57 +00003301
Blue Swirl38724252010-09-18 05:53:14 +00003302 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003303 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003304 }
aurel328f7aeaf2009-01-30 19:47:57 +00003305
aurel32607175e2009-04-15 16:11:59 +00003306 addr = alloca(addrlen+1);
ths3b46e622007-09-17 08:09:54 +00003307
Laurent Vivier7b36f782015-10-28 21:40:44 +01003308 ret = target_to_host_sockaddr(sockfd, addr, target_addr, addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03003309 if (ret)
3310 return ret;
3311
bellard3532fa72006-06-24 15:06:03 +00003312 return get_errno(bind(sockfd, addr, addrlen));
3313}
3314
ths0da46a62007-10-20 20:23:07 +00003315/* do_connect() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003316static abi_long do_connect(int sockfd, abi_ulong target_addr,
3317 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00003318{
aurel328f7aeaf2009-01-30 19:47:57 +00003319 void *addr;
Arnaud Patard917507b2009-06-19 10:44:45 +03003320 abi_long ret;
aurel328f7aeaf2009-01-30 19:47:57 +00003321
Blue Swirl38724252010-09-18 05:53:14 +00003322 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003323 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003324 }
aurel328f7aeaf2009-01-30 19:47:57 +00003325
Joakim Tjernlund2dd08df2014-07-11 17:18:03 +02003326 addr = alloca(addrlen+1);
ths3b46e622007-09-17 08:09:54 +00003327
Laurent Vivier7b36f782015-10-28 21:40:44 +01003328 ret = target_to_host_sockaddr(sockfd, addr, target_addr, addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03003329 if (ret)
3330 return ret;
3331
Peter Maydell2a3c7612016-06-06 19:58:03 +01003332 return get_errno(safe_connect(sockfd, addr, addrlen));
bellard3532fa72006-06-24 15:06:03 +00003333}
3334
Alexander Graff19e00d2014-03-02 19:36:42 +00003335/* do_sendrecvmsg_locked() Must return target values and target errnos. */
3336static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
3337 int flags, int send)
bellard3532fa72006-06-24 15:06:03 +00003338{
balrog6de645c2008-10-28 10:26:29 +00003339 abi_long ret, len;
bellard3532fa72006-06-24 15:06:03 +00003340 struct msghdr msg;
Peter Maydelldab32b32016-07-15 14:57:26 +01003341 abi_ulong count;
bellard3532fa72006-06-24 15:06:03 +00003342 struct iovec *vec;
blueswir1992f48a2007-10-14 16:27:31 +00003343 abi_ulong target_vec;
bellard3532fa72006-06-24 15:06:03 +00003344
bellard3532fa72006-06-24 15:06:03 +00003345 if (msgp->msg_name) {
3346 msg.msg_namelen = tswap32(msgp->msg_namelen);
Joakim Tjernlund2dd08df2014-07-11 17:18:03 +02003347 msg.msg_name = alloca(msg.msg_namelen+1);
Laurent Vivier7b36f782015-10-28 21:40:44 +01003348 ret = target_to_host_sockaddr(fd, msg.msg_name,
3349 tswapal(msgp->msg_name),
3350 msg.msg_namelen);
Peter Maydell26a6fc92016-07-15 14:57:28 +01003351 if (ret == -TARGET_EFAULT) {
3352 /* For connected sockets msg_name and msg_namelen must
3353 * be ignored, so returning EFAULT immediately is wrong.
3354 * Instead, pass a bad msg_name to the host kernel, and
3355 * let it decide whether to return EFAULT or not.
3356 */
3357 msg.msg_name = (void *)-1;
3358 } else if (ret) {
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003359 goto out2;
Arnaud Patard917507b2009-06-19 10:44:45 +03003360 }
bellard3532fa72006-06-24 15:06:03 +00003361 } else {
3362 msg.msg_name = NULL;
3363 msg.msg_namelen = 0;
3364 }
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003365 msg.msg_controllen = 2 * tswapal(msgp->msg_controllen);
bellard3532fa72006-06-24 15:06:03 +00003366 msg.msg_control = alloca(msg.msg_controllen);
Jonas Schievink1d3d1b22018-07-12 00:12:44 +02003367 memset(msg.msg_control, 0, msg.msg_controllen);
3368
bellard3532fa72006-06-24 15:06:03 +00003369 msg.msg_flags = tswap32(msgp->msg_flags);
ths3b46e622007-09-17 08:09:54 +00003370
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003371 count = tswapal(msgp->msg_iovlen);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003372 target_vec = tswapal(msgp->msg_iov);
Peter Maydell97b07972016-07-15 14:57:27 +01003373
3374 if (count > IOV_MAX) {
3375 /* sendrcvmsg returns a different errno for this condition than
3376 * readv/writev, so we must catch it here before lock_iovec() does.
3377 */
3378 ret = -TARGET_EMSGSIZE;
3379 goto out2;
3380 }
3381
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003382 vec = lock_iovec(send ? VERIFY_READ : VERIFY_WRITE,
3383 target_vec, count, send);
3384 if (vec == NULL) {
3385 ret = -host_to_target_errno(errno);
3386 goto out2;
3387 }
bellard3532fa72006-06-24 15:06:03 +00003388 msg.msg_iovlen = count;
3389 msg.msg_iov = vec;
ths3b46e622007-09-17 08:09:54 +00003390
bellard3532fa72006-06-24 15:06:03 +00003391 if (send) {
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003392 if (fd_trans_target_to_host_data(fd)) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003393 void *host_msg;
3394
3395 host_msg = g_malloc(msg.msg_iov->iov_len);
3396 memcpy(host_msg, msg.msg_iov->iov_base, msg.msg_iov->iov_len);
3397 ret = fd_trans_target_to_host_data(fd)(host_msg,
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003398 msg.msg_iov->iov_len);
Laurent Vivier7d61d892016-06-21 19:51:14 +02003399 if (ret >= 0) {
3400 msg.msg_iov->iov_base = host_msg;
3401 ret = get_errno(safe_sendmsg(fd, &msg, flags));
3402 }
3403 g_free(host_msg);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003404 } else {
3405 ret = target_to_host_cmsg(&msg, msgp);
Laurent Vivier7d61d892016-06-21 19:51:14 +02003406 if (ret == 0) {
3407 ret = get_errno(safe_sendmsg(fd, &msg, flags));
3408 }
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003409 }
bellard3532fa72006-06-24 15:06:03 +00003410 } else {
Peter Maydell66687532016-06-06 19:58:04 +01003411 ret = get_errno(safe_recvmsg(fd, &msg, flags));
balrog6de645c2008-10-28 10:26:29 +00003412 if (!is_error(ret)) {
3413 len = ret;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003414 if (fd_trans_host_to_target_data(fd)) {
3415 ret = fd_trans_host_to_target_data(fd)(msg.msg_iov->iov_base,
Laurent Vivier2a03d3e2018-08-20 19:15:54 +02003416 MIN(msg.msg_iov->iov_len, len));
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003417 } else {
3418 ret = host_to_target_cmsg(msgp, &msg);
3419 }
Jing Huangca619062012-07-24 13:58:02 +00003420 if (!is_error(ret)) {
3421 msgp->msg_namelen = tswap32(msg.msg_namelen);
Andreas Schwab24894f32019-02-12 17:34:35 +01003422 msgp->msg_flags = tswap32(msg.msg_flags);
Peter Maydell26a6fc92016-07-15 14:57:28 +01003423 if (msg.msg_name != NULL && msg.msg_name != (void *)-1) {
Jing Huangca619062012-07-24 13:58:02 +00003424 ret = host_to_target_sockaddr(tswapal(msgp->msg_name),
3425 msg.msg_name, msg.msg_namelen);
3426 if (ret) {
3427 goto out;
3428 }
3429 }
3430
balrog6de645c2008-10-28 10:26:29 +00003431 ret = len;
Jing Huangca619062012-07-24 13:58:02 +00003432 }
balrog6de645c2008-10-28 10:26:29 +00003433 }
bellard3532fa72006-06-24 15:06:03 +00003434 }
Jing Huangca619062012-07-24 13:58:02 +00003435
3436out:
bellard3532fa72006-06-24 15:06:03 +00003437 unlock_iovec(vec, target_vec, count, !send);
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003438out2:
Alexander Graff19e00d2014-03-02 19:36:42 +00003439 return ret;
3440}
3441
3442static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
3443 int flags, int send)
3444{
3445 abi_long ret;
3446 struct target_msghdr *msgp;
3447
3448 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
3449 msgp,
3450 target_msg,
3451 send ? 1 : 0)) {
3452 return -TARGET_EFAULT;
3453 }
3454 ret = do_sendrecvmsg_locked(fd, msgp, flags, send);
bellard579a97f2007-11-11 14:26:47 +00003455 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
bellard3532fa72006-06-24 15:06:03 +00003456 return ret;
3457}
3458
Alexander Graff19e00d2014-03-02 19:36:42 +00003459/* We don't rely on the C library to have sendmmsg/recvmmsg support,
3460 * so it might not have this *mmsg-specific flag either.
3461 */
3462#ifndef MSG_WAITFORONE
3463#define MSG_WAITFORONE 0x10000
3464#endif
3465
3466static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec,
3467 unsigned int vlen, unsigned int flags,
3468 int send)
3469{
3470 struct target_mmsghdr *mmsgp;
3471 abi_long ret = 0;
3472 int i;
3473
3474 if (vlen > UIO_MAXIOV) {
3475 vlen = UIO_MAXIOV;
3476 }
3477
3478 mmsgp = lock_user(VERIFY_WRITE, target_msgvec, sizeof(*mmsgp) * vlen, 1);
3479 if (!mmsgp) {
3480 return -TARGET_EFAULT;
3481 }
3482
3483 for (i = 0; i < vlen; i++) {
3484 ret = do_sendrecvmsg_locked(fd, &mmsgp[i].msg_hdr, flags, send);
3485 if (is_error(ret)) {
3486 break;
3487 }
3488 mmsgp[i].msg_len = tswap32(ret);
3489 /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
3490 if (flags & MSG_WAITFORONE) {
3491 flags |= MSG_DONTWAIT;
3492 }
3493 }
3494
3495 unlock_user(mmsgp, target_msgvec, sizeof(*mmsgp) * i);
3496
3497 /* Return number of datagrams sent if we sent any at all;
3498 * otherwise return the error.
3499 */
3500 if (i) {
3501 return i;
3502 }
3503 return ret;
3504}
Alexander Graff19e00d2014-03-02 19:36:42 +00003505
Peter Maydella94b4982013-02-08 04:35:04 +00003506/* do_accept4() Must return target values and target errnos. */
3507static abi_long do_accept4(int fd, abi_ulong target_addr,
3508 abi_ulong target_addrlen_addr, int flags)
pbrook1be9e1d2006-11-19 15:26:04 +00003509{
Andreas Schwabcd813362019-02-14 12:43:40 +01003510 socklen_t addrlen, ret_addrlen;
bellard2f619692007-11-16 10:46:05 +00003511 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00003512 abi_long ret;
Petar Jovanovicd25295d2014-03-31 17:41:23 +02003513 int host_flags;
3514
3515 host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
pbrook1be9e1d2006-11-19 15:26:04 +00003516
Peter Maydella94b4982013-02-08 04:35:04 +00003517 if (target_addr == 0) {
Peter Maydellff6dc132016-06-06 19:58:13 +01003518 return get_errno(safe_accept4(fd, NULL, NULL, host_flags));
Peter Maydella94b4982013-02-08 04:35:04 +00003519 }
Arnaud Patard917507b2009-06-19 10:44:45 +03003520
Matus Kysele554eb42020-09-30 17:16:16 +02003521 /* linux returns EFAULT if addrlen pointer is invalid */
bellard2f619692007-11-16 10:46:05 +00003522 if (get_user_u32(addrlen, target_addrlen_addr))
Matus Kysele554eb42020-09-30 17:16:16 +02003523 return -TARGET_EFAULT;
bellard2f619692007-11-16 10:46:05 +00003524
Blue Swirl38724252010-09-18 05:53:14 +00003525 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003526 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003527 }
aurel328f7aeaf2009-01-30 19:47:57 +00003528
Richard Hendersonc7169b02021-02-12 10:48:47 -08003529 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
Matus Kysele554eb42020-09-30 17:16:16 +02003530 return -TARGET_EFAULT;
Richard Hendersonc7169b02021-02-12 10:48:47 -08003531 }
Arnaud Patard917507b2009-06-19 10:44:45 +03003532
bellard2f619692007-11-16 10:46:05 +00003533 addr = alloca(addrlen);
3534
Andreas Schwabcd813362019-02-14 12:43:40 +01003535 ret_addrlen = addrlen;
3536 ret = get_errno(safe_accept4(fd, addr, &ret_addrlen, host_flags));
pbrook1be9e1d2006-11-19 15:26:04 +00003537 if (!is_error(ret)) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003538 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3539 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
bellard2f619692007-11-16 10:46:05 +00003540 ret = -TARGET_EFAULT;
Andreas Schwabcd813362019-02-14 12:43:40 +01003541 }
pbrook1be9e1d2006-11-19 15:26:04 +00003542 }
3543 return ret;
3544}
3545
ths0da46a62007-10-20 20:23:07 +00003546/* do_getpeername() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003547static abi_long do_getpeername(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00003548 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00003549{
Andreas Schwabcd813362019-02-14 12:43:40 +01003550 socklen_t addrlen, ret_addrlen;
bellard2f619692007-11-16 10:46:05 +00003551 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00003552 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003553
bellard2f619692007-11-16 10:46:05 +00003554 if (get_user_u32(addrlen, target_addrlen_addr))
3555 return -TARGET_EFAULT;
3556
Blue Swirl38724252010-09-18 05:53:14 +00003557 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003558 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003559 }
aurel328f7aeaf2009-01-30 19:47:57 +00003560
Richard Hendersonc7169b02021-02-12 10:48:47 -08003561 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
Arnaud Patard917507b2009-06-19 10:44:45 +03003562 return -TARGET_EFAULT;
Richard Hendersonc7169b02021-02-12 10:48:47 -08003563 }
Arnaud Patard917507b2009-06-19 10:44:45 +03003564
bellard2f619692007-11-16 10:46:05 +00003565 addr = alloca(addrlen);
3566
Andreas Schwabcd813362019-02-14 12:43:40 +01003567 ret_addrlen = addrlen;
3568 ret = get_errno(getpeername(fd, addr, &ret_addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003569 if (!is_error(ret)) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003570 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3571 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
bellard2f619692007-11-16 10:46:05 +00003572 ret = -TARGET_EFAULT;
Andreas Schwabcd813362019-02-14 12:43:40 +01003573 }
pbrook1be9e1d2006-11-19 15:26:04 +00003574 }
3575 return ret;
3576}
3577
ths0da46a62007-10-20 20:23:07 +00003578/* do_getsockname() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003579static abi_long do_getsockname(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00003580 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00003581{
Andreas Schwabcd813362019-02-14 12:43:40 +01003582 socklen_t addrlen, ret_addrlen;
bellard2f619692007-11-16 10:46:05 +00003583 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00003584 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003585
bellard2f619692007-11-16 10:46:05 +00003586 if (get_user_u32(addrlen, target_addrlen_addr))
3587 return -TARGET_EFAULT;
3588
Blue Swirl38724252010-09-18 05:53:14 +00003589 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003590 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003591 }
aurel328f7aeaf2009-01-30 19:47:57 +00003592
Richard Hendersonc7169b02021-02-12 10:48:47 -08003593 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
Arnaud Patard917507b2009-06-19 10:44:45 +03003594 return -TARGET_EFAULT;
Richard Hendersonc7169b02021-02-12 10:48:47 -08003595 }
Arnaud Patard917507b2009-06-19 10:44:45 +03003596
bellard2f619692007-11-16 10:46:05 +00003597 addr = alloca(addrlen);
3598
Andreas Schwabcd813362019-02-14 12:43:40 +01003599 ret_addrlen = addrlen;
3600 ret = get_errno(getsockname(fd, addr, &ret_addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003601 if (!is_error(ret)) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003602 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3603 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
bellard2f619692007-11-16 10:46:05 +00003604 ret = -TARGET_EFAULT;
Andreas Schwabcd813362019-02-14 12:43:40 +01003605 }
pbrook1be9e1d2006-11-19 15:26:04 +00003606 }
3607 return ret;
3608}
3609
ths0da46a62007-10-20 20:23:07 +00003610/* do_socketpair() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003611static abi_long do_socketpair(int domain, int type, int protocol,
bellard2f619692007-11-16 10:46:05 +00003612 abi_ulong target_tab_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00003613{
3614 int tab[2];
blueswir1992f48a2007-10-14 16:27:31 +00003615 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003616
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003617 target_to_host_sock_type(&type);
3618
pbrook1be9e1d2006-11-19 15:26:04 +00003619 ret = get_errno(socketpair(domain, type, protocol, tab));
3620 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00003621 if (put_user_s32(tab[0], target_tab_addr)
3622 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
3623 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00003624 }
3625 return ret;
3626}
3627
ths0da46a62007-10-20 20:23:07 +00003628/* do_sendto() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003629static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
3630 abi_ulong target_addr, socklen_t addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00003631{
3632 void *addr;
3633 void *host_msg;
Laurent Vivier7d61d892016-06-21 19:51:14 +02003634 void *copy_msg = NULL;
blueswir1992f48a2007-10-14 16:27:31 +00003635 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003636
Blue Swirl38724252010-09-18 05:53:14 +00003637 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003638 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003639 }
aurel328f7aeaf2009-01-30 19:47:57 +00003640
bellard579a97f2007-11-11 14:26:47 +00003641 host_msg = lock_user(VERIFY_READ, msg, len, 1);
3642 if (!host_msg)
3643 return -TARGET_EFAULT;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003644 if (fd_trans_target_to_host_data(fd)) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003645 copy_msg = host_msg;
3646 host_msg = g_malloc(len);
3647 memcpy(host_msg, copy_msg, len);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003648 ret = fd_trans_target_to_host_data(fd)(host_msg, len);
3649 if (ret < 0) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003650 goto fail;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003651 }
3652 }
pbrook1be9e1d2006-11-19 15:26:04 +00003653 if (target_addr) {
Joakim Tjernlund2dd08df2014-07-11 17:18:03 +02003654 addr = alloca(addrlen+1);
Laurent Vivier7b36f782015-10-28 21:40:44 +01003655 ret = target_to_host_sockaddr(fd, addr, target_addr, addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03003656 if (ret) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003657 goto fail;
Arnaud Patard917507b2009-06-19 10:44:45 +03003658 }
Peter Maydell66687532016-06-06 19:58:04 +01003659 ret = get_errno(safe_sendto(fd, host_msg, len, flags, addr, addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003660 } else {
Peter Maydell66687532016-06-06 19:58:04 +01003661 ret = get_errno(safe_sendto(fd, host_msg, len, flags, NULL, 0));
pbrook1be9e1d2006-11-19 15:26:04 +00003662 }
Laurent Vivier7d61d892016-06-21 19:51:14 +02003663fail:
3664 if (copy_msg) {
3665 g_free(host_msg);
3666 host_msg = copy_msg;
3667 }
pbrook1be9e1d2006-11-19 15:26:04 +00003668 unlock_user(host_msg, msg, 0);
3669 return ret;
3670}
3671
ths0da46a62007-10-20 20:23:07 +00003672/* do_recvfrom() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003673static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
3674 abi_ulong target_addr,
3675 abi_ulong target_addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00003676{
Andreas Schwabcd813362019-02-14 12:43:40 +01003677 socklen_t addrlen, ret_addrlen;
pbrook1be9e1d2006-11-19 15:26:04 +00003678 void *addr;
3679 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00003680 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003681
bellard579a97f2007-11-11 14:26:47 +00003682 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
3683 if (!host_msg)
3684 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00003685 if (target_addr) {
bellard2f619692007-11-16 10:46:05 +00003686 if (get_user_u32(addrlen, target_addrlen)) {
3687 ret = -TARGET_EFAULT;
3688 goto fail;
3689 }
Blue Swirl38724252010-09-18 05:53:14 +00003690 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003691 ret = -TARGET_EINVAL;
3692 goto fail;
3693 }
pbrook1be9e1d2006-11-19 15:26:04 +00003694 addr = alloca(addrlen);
Andreas Schwabcd813362019-02-14 12:43:40 +01003695 ret_addrlen = addrlen;
Peter Maydell66687532016-06-06 19:58:04 +01003696 ret = get_errno(safe_recvfrom(fd, host_msg, len, flags,
Andreas Schwabcd813362019-02-14 12:43:40 +01003697 addr, &ret_addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003698 } else {
3699 addr = NULL; /* To keep compiler quiet. */
Andreas Schwabcd813362019-02-14 12:43:40 +01003700 addrlen = 0; /* To keep compiler quiet. */
Peter Maydell66687532016-06-06 19:58:04 +01003701 ret = get_errno(safe_recvfrom(fd, host_msg, len, flags, NULL, 0));
pbrook1be9e1d2006-11-19 15:26:04 +00003702 }
3703 if (!is_error(ret)) {
Laurent Vivierc35e1f92016-06-21 19:51:15 +02003704 if (fd_trans_host_to_target_data(fd)) {
Laurent Vivier2a03d3e2018-08-20 19:15:54 +02003705 abi_long trans;
3706 trans = fd_trans_host_to_target_data(fd)(host_msg, MIN(ret, len));
3707 if (is_error(trans)) {
3708 ret = trans;
3709 goto fail;
3710 }
Laurent Vivierc35e1f92016-06-21 19:51:15 +02003711 }
pbrook1be9e1d2006-11-19 15:26:04 +00003712 if (target_addr) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003713 host_to_target_sockaddr(target_addr, addr,
3714 MIN(addrlen, ret_addrlen));
3715 if (put_user_u32(ret_addrlen, target_addrlen)) {
bellard2f619692007-11-16 10:46:05 +00003716 ret = -TARGET_EFAULT;
3717 goto fail;
3718 }
pbrook1be9e1d2006-11-19 15:26:04 +00003719 }
3720 unlock_user(host_msg, msg, len);
3721 } else {
bellard2f619692007-11-16 10:46:05 +00003722fail:
pbrook1be9e1d2006-11-19 15:26:04 +00003723 unlock_user(host_msg, msg, 0);
3724 }
3725 return ret;
3726}
3727
j_mayer32407102007-09-26 23:01:49 +00003728#ifdef TARGET_NR_socketcall
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003729/* do_socketcall() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003730static abi_long do_socketcall(int num, abi_ulong vptr)
bellard31e31b82003-02-18 22:55:36 +00003731{
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003732 static const unsigned nargs[] = { /* number of arguments per operation */
3733 [TARGET_SYS_SOCKET] = 3, /* domain, type, protocol */
3734 [TARGET_SYS_BIND] = 3, /* fd, addr, addrlen */
3735 [TARGET_SYS_CONNECT] = 3, /* fd, addr, addrlen */
3736 [TARGET_SYS_LISTEN] = 2, /* fd, backlog */
3737 [TARGET_SYS_ACCEPT] = 3, /* fd, addr, addrlen */
3738 [TARGET_SYS_GETSOCKNAME] = 3, /* fd, addr, addrlen */
3739 [TARGET_SYS_GETPEERNAME] = 3, /* fd, addr, addrlen */
3740 [TARGET_SYS_SOCKETPAIR] = 4, /* domain, type, protocol, tab */
3741 [TARGET_SYS_SEND] = 4, /* fd, msg, len, flags */
3742 [TARGET_SYS_RECV] = 4, /* fd, msg, len, flags */
3743 [TARGET_SYS_SENDTO] = 6, /* fd, msg, len, flags, addr, addrlen */
3744 [TARGET_SYS_RECVFROM] = 6, /* fd, msg, len, flags, addr, addrlen */
3745 [TARGET_SYS_SHUTDOWN] = 2, /* fd, how */
3746 [TARGET_SYS_SETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
3747 [TARGET_SYS_GETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
3748 [TARGET_SYS_SENDMSG] = 3, /* fd, msg, flags */
3749 [TARGET_SYS_RECVMSG] = 3, /* fd, msg, flags */
3750 [TARGET_SYS_ACCEPT4] = 4, /* fd, addr, addrlen, flags */
3751 [TARGET_SYS_RECVMMSG] = 4, /* fd, msgvec, vlen, flags */
3752 [TARGET_SYS_SENDMMSG] = 4, /* fd, msgvec, vlen, flags */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003753 };
3754 abi_long a[6]; /* max 6 args */
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003755 unsigned i;
bellard31e31b82003-02-18 22:55:36 +00003756
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003757 /* check the range of the first argument num */
3758 /* (TARGET_SYS_SENDMMSG is the highest among TARGET_SYS_xxx) */
3759 if (num < 1 || num > TARGET_SYS_SENDMMSG) {
3760 return -TARGET_EINVAL;
3761 }
3762 /* ensure we have space for args */
3763 if (nargs[num] > ARRAY_SIZE(a)) {
3764 return -TARGET_EINVAL;
3765 }
3766 /* collect the arguments in a[] according to nargs[] */
3767 for (i = 0; i < nargs[num]; ++i) {
3768 if (get_user_ual(a[i], vptr + i * sizeof(abi_long)) != 0) {
3769 return -TARGET_EFAULT;
André Hentschelb9d36eb2014-01-06 20:18:52 +01003770 }
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003771 }
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003772 /* now when we have the args, invoke the appropriate underlying function */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003773 switch (num) {
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003774 case TARGET_SYS_SOCKET: /* domain, type, protocol */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003775 return do_socket(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003776 case TARGET_SYS_BIND: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003777 return do_bind(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003778 case TARGET_SYS_CONNECT: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003779 return do_connect(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003780 case TARGET_SYS_LISTEN: /* sockfd, backlog */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003781 return get_errno(listen(a[0], a[1]));
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003782 case TARGET_SYS_ACCEPT: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003783 return do_accept4(a[0], a[1], a[2], 0);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003784 case TARGET_SYS_GETSOCKNAME: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003785 return do_getsockname(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003786 case TARGET_SYS_GETPEERNAME: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003787 return do_getpeername(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003788 case TARGET_SYS_SOCKETPAIR: /* domain, type, protocol, tab */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003789 return do_socketpair(a[0], a[1], a[2], a[3]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003790 case TARGET_SYS_SEND: /* sockfd, msg, len, flags */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003791 return do_sendto(a[0], a[1], a[2], a[3], 0, 0);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003792 case TARGET_SYS_RECV: /* sockfd, msg, len, flags */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003793 return do_recvfrom(a[0], a[1], a[2], a[3], 0, 0);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003794 case TARGET_SYS_SENDTO: /* sockfd, msg, len, flags, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003795 return do_sendto(a[0], a[1], a[2], a[3], a[4], a[5]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003796 case TARGET_SYS_RECVFROM: /* sockfd, msg, len, flags, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003797 return do_recvfrom(a[0], a[1], a[2], a[3], a[4], a[5]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003798 case TARGET_SYS_SHUTDOWN: /* sockfd, how */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003799 return get_errno(shutdown(a[0], a[1]));
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003800 case TARGET_SYS_SETSOCKOPT: /* sockfd, level, optname, optval, optlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003801 return do_setsockopt(a[0], a[1], a[2], a[3], a[4]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003802 case TARGET_SYS_GETSOCKOPT: /* sockfd, level, optname, optval, optlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003803 return do_getsockopt(a[0], a[1], a[2], a[3], a[4]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003804 case TARGET_SYS_SENDMSG: /* sockfd, msg, flags */
3805 return do_sendrecvmsg(a[0], a[1], a[2], 1);
3806 case TARGET_SYS_RECVMSG: /* sockfd, msg, flags */
3807 return do_sendrecvmsg(a[0], a[1], a[2], 0);
3808 case TARGET_SYS_ACCEPT4: /* sockfd, addr, addrlen, flags */
3809 return do_accept4(a[0], a[1], a[2], a[3]);
3810 case TARGET_SYS_RECVMMSG: /* sockfd, msgvec, vlen, flags */
3811 return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0);
3812 case TARGET_SYS_SENDMMSG: /* sockfd, msgvec, vlen, flags */
3813 return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 1);
bellard31e31b82003-02-18 22:55:36 +00003814 default:
Josh Kunz39be5352020-02-03 18:54:13 -08003815 qemu_log_mask(LOG_UNIMP, "Unsupported socketcall: %d\n", num);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003816 return -TARGET_EINVAL;
bellard31e31b82003-02-18 22:55:36 +00003817 }
bellard31e31b82003-02-18 22:55:36 +00003818}
j_mayer32407102007-09-26 23:01:49 +00003819#endif
bellard31e31b82003-02-18 22:55:36 +00003820
bellard8853f862004-02-22 14:57:26 +00003821#define N_SHM_REGIONS 32
3822
3823static struct shm_region {
Peter Maydellb6e17872016-02-09 15:57:11 +00003824 abi_ulong start;
3825 abi_ulong size;
3826 bool in_use;
bellard8853f862004-02-22 14:57:26 +00003827} shm_regions[N_SHM_REGIONS];
3828
Peter Maydell005eb2a2016-07-15 16:50:47 +01003829#ifndef TARGET_SEMID64_DS
3830/* asm-generic version of this struct */
3831struct target_semid64_ds
ths3eb6b042007-06-03 14:26:27 +00003832{
3833 struct target_ipc_perm sem_perm;
blueswir1992f48a2007-10-14 16:27:31 +00003834 abi_ulong sem_otime;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003835#if TARGET_ABI_BITS == 32
blueswir1992f48a2007-10-14 16:27:31 +00003836 abi_ulong __unused1;
Tom Musta03527342014-08-12 13:53:32 -05003837#endif
blueswir1992f48a2007-10-14 16:27:31 +00003838 abi_ulong sem_ctime;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003839#if TARGET_ABI_BITS == 32
blueswir1992f48a2007-10-14 16:27:31 +00003840 abi_ulong __unused2;
Tom Musta03527342014-08-12 13:53:32 -05003841#endif
blueswir1992f48a2007-10-14 16:27:31 +00003842 abi_ulong sem_nsems;
3843 abi_ulong __unused3;
3844 abi_ulong __unused4;
ths3eb6b042007-06-03 14:26:27 +00003845};
Peter Maydell005eb2a2016-07-15 16:50:47 +01003846#endif
ths3eb6b042007-06-03 14:26:27 +00003847
bellard579a97f2007-11-11 14:26:47 +00003848static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
3849 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00003850{
3851 struct target_ipc_perm *target_ip;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003852 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003853
bellard579a97f2007-11-11 14:26:47 +00003854 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
3855 return -TARGET_EFAULT;
Michael S. Tsirkine8bbe362009-09-30 18:56:44 +00003856 target_ip = &(target_sd->sem_perm);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003857 host_ip->__key = tswap32(target_ip->__key);
3858 host_ip->uid = tswap32(target_ip->uid);
3859 host_ip->gid = tswap32(target_ip->gid);
3860 host_ip->cuid = tswap32(target_ip->cuid);
3861 host_ip->cgid = tswap32(target_ip->cgid);
3862#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
3863 host_ip->mode = tswap32(target_ip->mode);
3864#else
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003865 host_ip->mode = tswap16(target_ip->mode);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003866#endif
3867#if defined(TARGET_PPC)
3868 host_ip->__seq = tswap32(target_ip->__seq);
3869#else
3870 host_ip->__seq = tswap16(target_ip->__seq);
3871#endif
ths3eb6b042007-06-03 14:26:27 +00003872 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00003873 return 0;
ths3eb6b042007-06-03 14:26:27 +00003874}
3875
bellard579a97f2007-11-11 14:26:47 +00003876static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
3877 struct ipc_perm *host_ip)
ths3eb6b042007-06-03 14:26:27 +00003878{
3879 struct target_ipc_perm *target_ip;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003880 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003881
bellard579a97f2007-11-11 14:26:47 +00003882 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3883 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00003884 target_ip = &(target_sd->sem_perm);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003885 target_ip->__key = tswap32(host_ip->__key);
3886 target_ip->uid = tswap32(host_ip->uid);
3887 target_ip->gid = tswap32(host_ip->gid);
3888 target_ip->cuid = tswap32(host_ip->cuid);
3889 target_ip->cgid = tswap32(host_ip->cgid);
3890#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
3891 target_ip->mode = tswap32(host_ip->mode);
3892#else
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003893 target_ip->mode = tswap16(host_ip->mode);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003894#endif
3895#if defined(TARGET_PPC)
3896 target_ip->__seq = tswap32(host_ip->__seq);
3897#else
3898 target_ip->__seq = tswap16(host_ip->__seq);
3899#endif
ths3eb6b042007-06-03 14:26:27 +00003900 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00003901 return 0;
ths3eb6b042007-06-03 14:26:27 +00003902}
3903
bellard579a97f2007-11-11 14:26:47 +00003904static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
3905 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00003906{
Peter Maydell005eb2a2016-07-15 16:50:47 +01003907 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003908
bellard579a97f2007-11-11 14:26:47 +00003909 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
3910 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00003911 if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
3912 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003913 host_sd->sem_nsems = tswapal(target_sd->sem_nsems);
3914 host_sd->sem_otime = tswapal(target_sd->sem_otime);
3915 host_sd->sem_ctime = tswapal(target_sd->sem_ctime);
ths3eb6b042007-06-03 14:26:27 +00003916 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00003917 return 0;
ths3eb6b042007-06-03 14:26:27 +00003918}
3919
bellard579a97f2007-11-11 14:26:47 +00003920static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
3921 struct semid_ds *host_sd)
ths3eb6b042007-06-03 14:26:27 +00003922{
Peter Maydell005eb2a2016-07-15 16:50:47 +01003923 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003924
bellard579a97f2007-11-11 14:26:47 +00003925 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3926 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00003927 if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
Dong Xu Wang3a931132011-11-29 16:52:38 +08003928 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003929 target_sd->sem_nsems = tswapal(host_sd->sem_nsems);
3930 target_sd->sem_otime = tswapal(host_sd->sem_otime);
3931 target_sd->sem_ctime = tswapal(host_sd->sem_ctime);
ths3eb6b042007-06-03 14:26:27 +00003932 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00003933 return 0;
ths3eb6b042007-06-03 14:26:27 +00003934}
3935
aurel32e5289082009-04-18 16:16:12 +00003936struct target_seminfo {
3937 int semmap;
3938 int semmni;
3939 int semmns;
3940 int semmnu;
3941 int semmsl;
3942 int semopm;
3943 int semume;
3944 int semusz;
3945 int semvmx;
3946 int semaem;
3947};
3948
3949static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
3950 struct seminfo *host_seminfo)
3951{
3952 struct target_seminfo *target_seminfo;
3953 if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
3954 return -TARGET_EFAULT;
3955 __put_user(host_seminfo->semmap, &target_seminfo->semmap);
3956 __put_user(host_seminfo->semmni, &target_seminfo->semmni);
3957 __put_user(host_seminfo->semmns, &target_seminfo->semmns);
3958 __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
3959 __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
3960 __put_user(host_seminfo->semopm, &target_seminfo->semopm);
3961 __put_user(host_seminfo->semume, &target_seminfo->semume);
3962 __put_user(host_seminfo->semusz, &target_seminfo->semusz);
3963 __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
3964 __put_user(host_seminfo->semaem, &target_seminfo->semaem);
3965 unlock_user_struct(target_seminfo, target_addr, 1);
3966 return 0;
3967}
3968
thsfa294812007-02-02 22:05:00 +00003969union semun {
3970 int val;
ths3eb6b042007-06-03 14:26:27 +00003971 struct semid_ds *buf;
thsfa294812007-02-02 22:05:00 +00003972 unsigned short *array;
aurel32e5289082009-04-18 16:16:12 +00003973 struct seminfo *__buf;
thsfa294812007-02-02 22:05:00 +00003974};
3975
ths3eb6b042007-06-03 14:26:27 +00003976union target_semun {
3977 int val;
aurel32e5289082009-04-18 16:16:12 +00003978 abi_ulong buf;
3979 abi_ulong array;
3980 abi_ulong __buf;
ths3eb6b042007-06-03 14:26:27 +00003981};
3982
aurel32e5289082009-04-18 16:16:12 +00003983static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
3984 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00003985{
aurel32e5289082009-04-18 16:16:12 +00003986 int nsems;
3987 unsigned short *array;
3988 union semun semun;
3989 struct semid_ds semid_ds;
3990 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00003991
aurel32e5289082009-04-18 16:16:12 +00003992 semun.buf = &semid_ds;
3993
3994 ret = semctl(semid, 0, IPC_STAT, semun);
3995 if (ret == -1)
3996 return get_errno(ret);
3997
3998 nsems = semid_ds.sem_nsems;
3999
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304000 *host_array = g_try_new(unsigned short, nsems);
Peter Maydell69d4c702014-02-17 18:55:34 +00004001 if (!*host_array) {
4002 return -TARGET_ENOMEM;
4003 }
aurel32e5289082009-04-18 16:16:12 +00004004 array = lock_user(VERIFY_READ, target_addr,
4005 nsems*sizeof(unsigned short), 1);
Peter Maydell69d4c702014-02-17 18:55:34 +00004006 if (!array) {
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304007 g_free(*host_array);
aurel32e5289082009-04-18 16:16:12 +00004008 return -TARGET_EFAULT;
Peter Maydell69d4c702014-02-17 18:55:34 +00004009 }
aurel32e5289082009-04-18 16:16:12 +00004010
4011 for(i=0; i<nsems; i++) {
4012 __get_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00004013 }
aurel32e5289082009-04-18 16:16:12 +00004014 unlock_user(array, target_addr, 0);
4015
bellard579a97f2007-11-11 14:26:47 +00004016 return 0;
ths3eb6b042007-06-03 14:26:27 +00004017}
4018
aurel32e5289082009-04-18 16:16:12 +00004019static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
4020 unsigned short **host_array)
ths3eb6b042007-06-03 14:26:27 +00004021{
aurel32e5289082009-04-18 16:16:12 +00004022 int nsems;
4023 unsigned short *array;
4024 union semun semun;
4025 struct semid_ds semid_ds;
4026 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00004027
aurel32e5289082009-04-18 16:16:12 +00004028 semun.buf = &semid_ds;
4029
4030 ret = semctl(semid, 0, IPC_STAT, semun);
4031 if (ret == -1)
4032 return get_errno(ret);
4033
4034 nsems = semid_ds.sem_nsems;
4035
4036 array = lock_user(VERIFY_WRITE, target_addr,
4037 nsems*sizeof(unsigned short), 0);
4038 if (!array)
4039 return -TARGET_EFAULT;
4040
4041 for(i=0; i<nsems; i++) {
4042 __put_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00004043 }
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304044 g_free(*host_array);
aurel32e5289082009-04-18 16:16:12 +00004045 unlock_user(array, target_addr, 1);
4046
bellard579a97f2007-11-11 14:26:47 +00004047 return 0;
ths3eb6b042007-06-03 14:26:27 +00004048}
4049
aurel32e5289082009-04-18 16:16:12 +00004050static inline abi_long do_semctl(int semid, int semnum, int cmd,
Stefan Weild1c002b2015-02-08 15:40:58 +01004051 abi_ulong target_arg)
ths3eb6b042007-06-03 14:26:27 +00004052{
Stefan Weild1c002b2015-02-08 15:40:58 +01004053 union target_semun target_su = { .buf = target_arg };
ths3eb6b042007-06-03 14:26:27 +00004054 union semun arg;
4055 struct semid_ds dsarg;
vibi sreenivasan7b8118e2009-06-19 13:34:39 +05304056 unsigned short *array = NULL;
aurel32e5289082009-04-18 16:16:12 +00004057 struct seminfo seminfo;
4058 abi_long ret = -TARGET_EINVAL;
4059 abi_long err;
4060 cmd &= 0xff;
ths3eb6b042007-06-03 14:26:27 +00004061
4062 switch( cmd ) {
4063 case GETVAL:
ths3eb6b042007-06-03 14:26:27 +00004064 case SETVAL:
Tom Musta5464bae2014-08-12 13:53:34 -05004065 /* In 64 bit cross-endian situations, we will erroneously pick up
4066 * the wrong half of the union for the "val" element. To rectify
4067 * this, the entire 8-byte structure is byteswapped, followed by
4068 * a swap of the 4 byte val field. In other cases, the data is
4069 * already in proper host byte order. */
4070 if (sizeof(target_su.val) != (sizeof(target_su.buf))) {
4071 target_su.buf = tswapal(target_su.buf);
4072 arg.val = tswap32(target_su.val);
4073 } else {
4074 arg.val = target_su.val;
4075 }
aurel32e5289082009-04-18 16:16:12 +00004076 ret = get_errno(semctl(semid, semnum, cmd, arg));
ths3eb6b042007-06-03 14:26:27 +00004077 break;
4078 case GETALL:
ths3eb6b042007-06-03 14:26:27 +00004079 case SETALL:
aurel32e5289082009-04-18 16:16:12 +00004080 err = target_to_host_semarray(semid, &array, target_su.array);
4081 if (err)
4082 return err;
4083 arg.array = array;
4084 ret = get_errno(semctl(semid, semnum, cmd, arg));
4085 err = host_to_target_semarray(semid, target_su.array, &array);
4086 if (err)
4087 return err;
ths3eb6b042007-06-03 14:26:27 +00004088 break;
4089 case IPC_STAT:
ths3eb6b042007-06-03 14:26:27 +00004090 case IPC_SET:
aurel32e5289082009-04-18 16:16:12 +00004091 case SEM_STAT:
4092 err = target_to_host_semid_ds(&dsarg, target_su.buf);
4093 if (err)
4094 return err;
4095 arg.buf = &dsarg;
4096 ret = get_errno(semctl(semid, semnum, cmd, arg));
4097 err = host_to_target_semid_ds(target_su.buf, &dsarg);
4098 if (err)
4099 return err;
ths3eb6b042007-06-03 14:26:27 +00004100 break;
aurel32e5289082009-04-18 16:16:12 +00004101 case IPC_INFO:
4102 case SEM_INFO:
4103 arg.__buf = &seminfo;
4104 ret = get_errno(semctl(semid, semnum, cmd, arg));
4105 err = host_to_target_seminfo(target_su.__buf, &seminfo);
4106 if (err)
4107 return err;
4108 break;
4109 case IPC_RMID:
4110 case GETPID:
4111 case GETNCNT:
4112 case GETZCNT:
4113 ret = get_errno(semctl(semid, semnum, cmd, NULL));
4114 break;
ths3eb6b042007-06-03 14:26:27 +00004115 }
4116
4117 return ret;
4118}
4119
aurel32e5289082009-04-18 16:16:12 +00004120struct target_sembuf {
4121 unsigned short sem_num;
4122 short sem_op;
4123 short sem_flg;
4124};
4125
4126static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
4127 abi_ulong target_addr,
4128 unsigned nsops)
4129{
4130 struct target_sembuf *target_sembuf;
4131 int i;
4132
4133 target_sembuf = lock_user(VERIFY_READ, target_addr,
4134 nsops*sizeof(struct target_sembuf), 1);
4135 if (!target_sembuf)
4136 return -TARGET_EFAULT;
4137
4138 for(i=0; i<nsops; i++) {
4139 __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
4140 __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
4141 __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
4142 }
4143
4144 unlock_user(target_sembuf, target_addr, 0);
4145
4146 return 0;
4147}
4148
Matus Kyseld8c08b12020-06-26 14:46:11 +02004149#if defined(TARGET_NR_ipc) || defined(TARGET_NR_semop) || \
Filip Bozutacac46eb2020-08-25 00:30:50 +02004150 defined(TARGET_NR_semtimedop) || defined(TARGET_NR_semtimedop_time64)
Matus Kyseld8c08b12020-06-26 14:46:11 +02004151
4152/*
4153 * This macro is required to handle the s390 variants, which passes the
4154 * arguments in a different order than default.
4155 */
4156#ifdef __s390x__
4157#define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
4158 (__nsops), (__timeout), (__sops)
4159#else
4160#define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
4161 (__nsops), 0, (__sops), (__timeout)
4162#endif
4163
4164static inline abi_long do_semtimedop(int semid,
4165 abi_long ptr,
4166 unsigned nsops,
Filip Bozutacac46eb2020-08-25 00:30:50 +02004167 abi_long timeout, bool time64)
aurel32e5289082009-04-18 16:16:12 +00004168{
Filip Bozuta0a7ec842020-08-18 20:07:22 +02004169 struct sembuf *sops;
Matus Kyseld8c08b12020-06-26 14:46:11 +02004170 struct timespec ts, *pts = NULL;
Laurent Vivier524fa342019-05-29 10:48:04 +02004171 abi_long ret;
aurel32e5289082009-04-18 16:16:12 +00004172
Matus Kyseld8c08b12020-06-26 14:46:11 +02004173 if (timeout) {
4174 pts = &ts;
Filip Bozutacac46eb2020-08-25 00:30:50 +02004175 if (time64) {
4176 if (target_to_host_timespec64(pts, timeout)) {
4177 return -TARGET_EFAULT;
4178 }
4179 } else {
4180 if (target_to_host_timespec(pts, timeout)) {
4181 return -TARGET_EFAULT;
4182 }
Matus Kyseld8c08b12020-06-26 14:46:11 +02004183 }
4184 }
4185
Filip Bozuta0a7ec842020-08-18 20:07:22 +02004186 if (nsops > TARGET_SEMOPM) {
4187 return -TARGET_E2BIG;
4188 }
4189
4190 sops = g_new(struct sembuf, nsops);
4191
4192 if (target_to_host_sembuf(sops, ptr, nsops)) {
4193 g_free(sops);
aurel32e5289082009-04-18 16:16:12 +00004194 return -TARGET_EFAULT;
Filip Bozuta0a7ec842020-08-18 20:07:22 +02004195 }
aurel32e5289082009-04-18 16:16:12 +00004196
Laurent Vivier524fa342019-05-29 10:48:04 +02004197 ret = -TARGET_ENOSYS;
4198#ifdef __NR_semtimedop
Matus Kyseld8c08b12020-06-26 14:46:11 +02004199 ret = get_errno(safe_semtimedop(semid, sops, nsops, pts));
Laurent Vivier524fa342019-05-29 10:48:04 +02004200#endif
4201#ifdef __NR_ipc
4202 if (ret == -TARGET_ENOSYS) {
Matus Kyseld8c08b12020-06-26 14:46:11 +02004203 ret = get_errno(safe_ipc(IPCOP_semtimedop, semid,
4204 SEMTIMEDOP_IPC_ARGS(nsops, sops, (long)pts)));
Laurent Vivier524fa342019-05-29 10:48:04 +02004205 }
4206#endif
Filip Bozuta0a7ec842020-08-18 20:07:22 +02004207 g_free(sops);
Laurent Vivier524fa342019-05-29 10:48:04 +02004208 return ret;
aurel32e5289082009-04-18 16:16:12 +00004209}
Matus Kyseld8c08b12020-06-26 14:46:11 +02004210#endif
aurel32e5289082009-04-18 16:16:12 +00004211
ths1bc012f2007-06-03 14:27:49 +00004212struct target_msqid_ds
4213{
aurel321c54ff92008-10-13 21:08:44 +00004214 struct target_ipc_perm msg_perm;
4215 abi_ulong msg_stime;
4216#if TARGET_ABI_BITS == 32
4217 abi_ulong __unused1;
4218#endif
4219 abi_ulong msg_rtime;
4220#if TARGET_ABI_BITS == 32
4221 abi_ulong __unused2;
4222#endif
4223 abi_ulong msg_ctime;
4224#if TARGET_ABI_BITS == 32
4225 abi_ulong __unused3;
4226#endif
4227 abi_ulong __msg_cbytes;
4228 abi_ulong msg_qnum;
4229 abi_ulong msg_qbytes;
4230 abi_ulong msg_lspid;
4231 abi_ulong msg_lrpid;
4232 abi_ulong __unused4;
4233 abi_ulong __unused5;
ths1bc012f2007-06-03 14:27:49 +00004234};
4235
bellard579a97f2007-11-11 14:26:47 +00004236static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
4237 abi_ulong target_addr)
ths1bc012f2007-06-03 14:27:49 +00004238{
4239 struct target_msqid_ds *target_md;
4240
bellard579a97f2007-11-11 14:26:47 +00004241 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
4242 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00004243 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
4244 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02004245 host_md->msg_stime = tswapal(target_md->msg_stime);
4246 host_md->msg_rtime = tswapal(target_md->msg_rtime);
4247 host_md->msg_ctime = tswapal(target_md->msg_ctime);
4248 host_md->__msg_cbytes = tswapal(target_md->__msg_cbytes);
4249 host_md->msg_qnum = tswapal(target_md->msg_qnum);
4250 host_md->msg_qbytes = tswapal(target_md->msg_qbytes);
4251 host_md->msg_lspid = tswapal(target_md->msg_lspid);
4252 host_md->msg_lrpid = tswapal(target_md->msg_lrpid);
ths1bc012f2007-06-03 14:27:49 +00004253 unlock_user_struct(target_md, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00004254 return 0;
ths1bc012f2007-06-03 14:27:49 +00004255}
4256
bellard579a97f2007-11-11 14:26:47 +00004257static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
4258 struct msqid_ds *host_md)
ths1bc012f2007-06-03 14:27:49 +00004259{
4260 struct target_msqid_ds *target_md;
4261
bellard579a97f2007-11-11 14:26:47 +00004262 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
4263 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00004264 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
4265 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02004266 target_md->msg_stime = tswapal(host_md->msg_stime);
4267 target_md->msg_rtime = tswapal(host_md->msg_rtime);
4268 target_md->msg_ctime = tswapal(host_md->msg_ctime);
4269 target_md->__msg_cbytes = tswapal(host_md->__msg_cbytes);
4270 target_md->msg_qnum = tswapal(host_md->msg_qnum);
4271 target_md->msg_qbytes = tswapal(host_md->msg_qbytes);
4272 target_md->msg_lspid = tswapal(host_md->msg_lspid);
4273 target_md->msg_lrpid = tswapal(host_md->msg_lrpid);
ths1bc012f2007-06-03 14:27:49 +00004274 unlock_user_struct(target_md, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00004275 return 0;
ths1bc012f2007-06-03 14:27:49 +00004276}
4277
aurel321c54ff92008-10-13 21:08:44 +00004278struct target_msginfo {
4279 int msgpool;
4280 int msgmap;
4281 int msgmax;
4282 int msgmnb;
4283 int msgmni;
4284 int msgssz;
4285 int msgtql;
4286 unsigned short int msgseg;
4287};
4288
4289static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
4290 struct msginfo *host_msginfo)
4291{
4292 struct target_msginfo *target_msginfo;
4293 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
4294 return -TARGET_EFAULT;
4295 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
4296 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
4297 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
4298 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
4299 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
4300 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
4301 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
4302 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
4303 unlock_user_struct(target_msginfo, target_addr, 1);
aurel3200b229a2008-10-24 13:12:52 +00004304 return 0;
aurel321c54ff92008-10-13 21:08:44 +00004305}
4306
4307static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
ths1bc012f2007-06-03 14:27:49 +00004308{
4309 struct msqid_ds dsarg;
aurel321c54ff92008-10-13 21:08:44 +00004310 struct msginfo msginfo;
4311 abi_long ret = -TARGET_EINVAL;
4312
4313 cmd &= 0xff;
4314
4315 switch (cmd) {
ths1bc012f2007-06-03 14:27:49 +00004316 case IPC_STAT:
4317 case IPC_SET:
aurel321c54ff92008-10-13 21:08:44 +00004318 case MSG_STAT:
4319 if (target_to_host_msqid_ds(&dsarg,ptr))
4320 return -TARGET_EFAULT;
4321 ret = get_errno(msgctl(msgid, cmd, &dsarg));
4322 if (host_to_target_msqid_ds(ptr,&dsarg))
4323 return -TARGET_EFAULT;
4324 break;
4325 case IPC_RMID:
4326 ret = get_errno(msgctl(msgid, cmd, NULL));
4327 break;
4328 case IPC_INFO:
4329 case MSG_INFO:
4330 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
4331 if (host_to_target_msginfo(ptr, &msginfo))
4332 return -TARGET_EFAULT;
4333 break;
ths1bc012f2007-06-03 14:27:49 +00004334 }
aurel321c54ff92008-10-13 21:08:44 +00004335
ths1bc012f2007-06-03 14:27:49 +00004336 return ret;
4337}
4338
4339struct target_msgbuf {
aurel321c54ff92008-10-13 21:08:44 +00004340 abi_long mtype;
4341 char mtext[1];
ths1bc012f2007-06-03 14:27:49 +00004342};
4343
blueswir1992f48a2007-10-14 16:27:31 +00004344static inline abi_long do_msgsnd(int msqid, abi_long msgp,
Tom Mustaedcc5f92014-08-12 13:53:37 -05004345 ssize_t msgsz, int msgflg)
ths1bc012f2007-06-03 14:27:49 +00004346{
4347 struct target_msgbuf *target_mb;
4348 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00004349 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00004350
Tom Mustaedcc5f92014-08-12 13:53:37 -05004351 if (msgsz < 0) {
4352 return -TARGET_EINVAL;
4353 }
4354
bellard579a97f2007-11-11 14:26:47 +00004355 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
4356 return -TARGET_EFAULT;
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304357 host_mb = g_try_malloc(msgsz + sizeof(long));
zhanghailiang29e03fc2014-08-14 15:29:18 +08004358 if (!host_mb) {
4359 unlock_user_struct(target_mb, msgp, 0);
4360 return -TARGET_ENOMEM;
4361 }
Matthias Brauncbb21ee2011-08-12 19:57:41 +02004362 host_mb->mtype = (abi_long) tswapal(target_mb->mtype);
aurel321c54ff92008-10-13 21:08:44 +00004363 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
Laurent Vivier524fa342019-05-29 10:48:04 +02004364 ret = -TARGET_ENOSYS;
4365#ifdef __NR_msgsnd
Peter Maydell89f9fe42016-06-06 19:58:05 +01004366 ret = get_errno(safe_msgsnd(msqid, host_mb, msgsz, msgflg));
Laurent Vivier524fa342019-05-29 10:48:04 +02004367#endif
4368#ifdef __NR_ipc
4369 if (ret == -TARGET_ENOSYS) {
Matus Kyseld8c08b12020-06-26 14:46:11 +02004370#ifdef __s390x__
4371 ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg,
4372 host_mb));
4373#else
Laurent Vivier524fa342019-05-29 10:48:04 +02004374 ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg,
4375 host_mb, 0));
Matus Kyseld8c08b12020-06-26 14:46:11 +02004376#endif
Laurent Vivier524fa342019-05-29 10:48:04 +02004377 }
4378#endif
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304379 g_free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00004380 unlock_user_struct(target_mb, msgp, 0);
4381
4382 return ret;
4383}
4384
Matus Kyseld8c08b12020-06-26 14:46:11 +02004385#ifdef __NR_ipc
4386#if defined(__sparc__)
4387/* SPARC for msgrcv it does not use the kludge on final 2 arguments. */
4388#define MSGRCV_ARGS(__msgp, __msgtyp) __msgp, __msgtyp
4389#elif defined(__s390x__)
4390/* The s390 sys_ipc variant has only five parameters. */
4391#define MSGRCV_ARGS(__msgp, __msgtyp) \
4392 ((long int[]){(long int)__msgp, __msgtyp})
4393#else
4394#define MSGRCV_ARGS(__msgp, __msgtyp) \
4395 ((long int[]){(long int)__msgp, __msgtyp}), 0
4396#endif
4397#endif
4398
blueswir1992f48a2007-10-14 16:27:31 +00004399static inline abi_long do_msgrcv(int msqid, abi_long msgp,
Peter Maydell99874f62016-05-20 19:00:56 +01004400 ssize_t msgsz, abi_long msgtyp,
blueswir1992f48a2007-10-14 16:27:31 +00004401 int msgflg)
ths1bc012f2007-06-03 14:27:49 +00004402{
4403 struct target_msgbuf *target_mb;
bellard579a97f2007-11-11 14:26:47 +00004404 char *target_mtext;
ths1bc012f2007-06-03 14:27:49 +00004405 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00004406 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00004407
Peter Maydell99874f62016-05-20 19:00:56 +01004408 if (msgsz < 0) {
4409 return -TARGET_EINVAL;
4410 }
4411
bellard579a97f2007-11-11 14:26:47 +00004412 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
4413 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00004414
Peter Maydell415d8472016-05-20 19:00:57 +01004415 host_mb = g_try_malloc(msgsz + sizeof(long));
4416 if (!host_mb) {
4417 ret = -TARGET_ENOMEM;
4418 goto end;
4419 }
Laurent Vivier524fa342019-05-29 10:48:04 +02004420 ret = -TARGET_ENOSYS;
4421#ifdef __NR_msgrcv
Peter Maydell89f9fe42016-06-06 19:58:05 +01004422 ret = get_errno(safe_msgrcv(msqid, host_mb, msgsz, msgtyp, msgflg));
Laurent Vivier524fa342019-05-29 10:48:04 +02004423#endif
4424#ifdef __NR_ipc
4425 if (ret == -TARGET_ENOSYS) {
4426 ret = get_errno(safe_ipc(IPCOP_CALL(1, IPCOP_msgrcv), msqid, msgsz,
Matus Kyseld8c08b12020-06-26 14:46:11 +02004427 msgflg, MSGRCV_ARGS(host_mb, msgtyp)));
Laurent Vivier524fa342019-05-29 10:48:04 +02004428 }
4429#endif
aurel321c54ff92008-10-13 21:08:44 +00004430
bellard579a97f2007-11-11 14:26:47 +00004431 if (ret > 0) {
4432 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
4433 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
4434 if (!target_mtext) {
4435 ret = -TARGET_EFAULT;
4436 goto end;
4437 }
aurel321c54ff92008-10-13 21:08:44 +00004438 memcpy(target_mb->mtext, host_mb->mtext, ret);
bellard579a97f2007-11-11 14:26:47 +00004439 unlock_user(target_mtext, target_mtext_addr, ret);
4440 }
aurel321c54ff92008-10-13 21:08:44 +00004441
Matthias Brauncbb21ee2011-08-12 19:57:41 +02004442 target_mb->mtype = tswapal(host_mb->mtype);
ths1bc012f2007-06-03 14:27:49 +00004443
bellard579a97f2007-11-11 14:26:47 +00004444end:
4445 if (target_mb)
4446 unlock_user_struct(target_mb, msgp, 1);
Jim Meyering0d07fe42012-08-22 13:55:53 +02004447 g_free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00004448 return ret;
4449}
4450
Riku Voipio88a8c982009-04-03 10:42:00 +03004451static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
4452 abi_ulong target_addr)
4453{
4454 struct target_shmid_ds *target_sd;
4455
4456 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
4457 return -TARGET_EFAULT;
4458 if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
4459 return -TARGET_EFAULT;
4460 __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
4461 __get_user(host_sd->shm_atime, &target_sd->shm_atime);
4462 __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
4463 __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
4464 __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
4465 __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
4466 __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
4467 unlock_user_struct(target_sd, target_addr, 0);
4468 return 0;
4469}
4470
4471static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
4472 struct shmid_ds *host_sd)
4473{
4474 struct target_shmid_ds *target_sd;
4475
4476 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
4477 return -TARGET_EFAULT;
4478 if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
4479 return -TARGET_EFAULT;
4480 __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
4481 __put_user(host_sd->shm_atime, &target_sd->shm_atime);
4482 __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
4483 __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
4484 __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
4485 __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
4486 __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
4487 unlock_user_struct(target_sd, target_addr, 1);
4488 return 0;
4489}
4490
4491struct target_shminfo {
4492 abi_ulong shmmax;
4493 abi_ulong shmmin;
4494 abi_ulong shmmni;
4495 abi_ulong shmseg;
4496 abi_ulong shmall;
4497};
4498
4499static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
4500 struct shminfo *host_shminfo)
4501{
4502 struct target_shminfo *target_shminfo;
4503 if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
4504 return -TARGET_EFAULT;
4505 __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
4506 __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
4507 __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
4508 __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
4509 __put_user(host_shminfo->shmall, &target_shminfo->shmall);
4510 unlock_user_struct(target_shminfo, target_addr, 1);
4511 return 0;
4512}
4513
4514struct target_shm_info {
4515 int used_ids;
4516 abi_ulong shm_tot;
4517 abi_ulong shm_rss;
4518 abi_ulong shm_swp;
4519 abi_ulong swap_attempts;
4520 abi_ulong swap_successes;
4521};
4522
4523static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
4524 struct shm_info *host_shm_info)
4525{
4526 struct target_shm_info *target_shm_info;
4527 if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
4528 return -TARGET_EFAULT;
4529 __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
4530 __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
4531 __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
4532 __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
4533 __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
4534 __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
4535 unlock_user_struct(target_shm_info, target_addr, 1);
4536 return 0;
4537}
4538
4539static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
4540{
4541 struct shmid_ds dsarg;
4542 struct shminfo shminfo;
4543 struct shm_info shm_info;
4544 abi_long ret = -TARGET_EINVAL;
4545
4546 cmd &= 0xff;
4547
4548 switch(cmd) {
4549 case IPC_STAT:
4550 case IPC_SET:
4551 case SHM_STAT:
4552 if (target_to_host_shmid_ds(&dsarg, buf))
4553 return -TARGET_EFAULT;
4554 ret = get_errno(shmctl(shmid, cmd, &dsarg));
4555 if (host_to_target_shmid_ds(buf, &dsarg))
4556 return -TARGET_EFAULT;
4557 break;
4558 case IPC_INFO:
4559 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
4560 if (host_to_target_shminfo(buf, &shminfo))
4561 return -TARGET_EFAULT;
4562 break;
4563 case SHM_INFO:
4564 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
4565 if (host_to_target_shm_info(buf, &shm_info))
4566 return -TARGET_EFAULT;
4567 break;
4568 case IPC_RMID:
4569 case SHM_LOCK:
4570 case SHM_UNLOCK:
4571 ret = get_errno(shmctl(shmid, cmd, NULL));
4572 break;
4573 }
4574
4575 return ret;
4576}
4577
Peter Maydellee8e7612016-07-11 16:48:11 +01004578#ifndef TARGET_FORCE_SHMLBA
4579/* For most architectures, SHMLBA is the same as the page size;
4580 * some architectures have larger values, in which case they should
4581 * define TARGET_FORCE_SHMLBA and provide a target_shmlba() function.
4582 * This corresponds to the kernel arch code defining __ARCH_FORCE_SHMLBA
4583 * and defining its own value for SHMLBA.
4584 *
4585 * The kernel also permits SHMLBA to be set by the architecture to a
4586 * value larger than the page size without setting __ARCH_FORCE_SHMLBA;
4587 * this means that addresses are rounded to the large size if
4588 * SHM_RND is set but addresses not aligned to that size are not rejected
4589 * as long as they are at least page-aligned. Since the only architecture
4590 * which uses this is ia64 this code doesn't provide for that oddity.
4591 */
4592static inline abi_ulong target_shmlba(CPUArchState *cpu_env)
4593{
4594 return TARGET_PAGE_SIZE;
4595}
4596#endif
4597
4598static inline abi_ulong do_shmat(CPUArchState *cpu_env,
4599 int shmid, abi_ulong shmaddr, int shmflg)
Riku Voipio88a8c982009-04-03 10:42:00 +03004600{
4601 abi_long raddr;
4602 void *host_raddr;
4603 struct shmid_ds shm_info;
4604 int i,ret;
Peter Maydellee8e7612016-07-11 16:48:11 +01004605 abi_ulong shmlba;
Riku Voipio88a8c982009-04-03 10:42:00 +03004606
Richard Hendersonee1bf832021-02-12 10:48:44 -08004607 /* shmat pointers are always untagged */
4608
Riku Voipio88a8c982009-04-03 10:42:00 +03004609 /* find out the length of the shared memory segment */
4610 ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
4611 if (is_error(ret)) {
4612 /* can't get length, bail out */
4613 return ret;
4614 }
4615
Peter Maydellee8e7612016-07-11 16:48:11 +01004616 shmlba = target_shmlba(cpu_env);
4617
4618 if (shmaddr & (shmlba - 1)) {
4619 if (shmflg & SHM_RND) {
4620 shmaddr &= ~(shmlba - 1);
4621 } else {
4622 return -TARGET_EINVAL;
4623 }
4624 }
Richard Henderson46b12f42021-02-12 10:48:46 -08004625 if (!guest_range_valid_untagged(shmaddr, shm_info.shm_segsz)) {
Max Filippovebf9a362018-03-07 13:50:10 -08004626 return -TARGET_EINVAL;
4627 }
Peter Maydellee8e7612016-07-11 16:48:11 +01004628
Riku Voipio88a8c982009-04-03 10:42:00 +03004629 mmap_lock();
4630
4631 if (shmaddr)
Richard Henderson3e8f1622021-02-12 10:48:43 -08004632 host_raddr = shmat(shmid, (void *)g2h_untagged(shmaddr), shmflg);
Riku Voipio88a8c982009-04-03 10:42:00 +03004633 else {
4634 abi_ulong mmap_start;
4635
Richard Henderson30ab9ef2019-05-19 13:19:52 -07004636 /* In order to use the host shmat, we need to honor host SHMLBA. */
4637 mmap_start = mmap_find_vma(0, shm_info.shm_segsz, MAX(SHMLBA, shmlba));
Riku Voipio88a8c982009-04-03 10:42:00 +03004638
4639 if (mmap_start == -1) {
4640 errno = ENOMEM;
4641 host_raddr = (void *)-1;
4642 } else
Richard Henderson3e8f1622021-02-12 10:48:43 -08004643 host_raddr = shmat(shmid, g2h_untagged(mmap_start),
4644 shmflg | SHM_REMAP);
Riku Voipio88a8c982009-04-03 10:42:00 +03004645 }
4646
4647 if (host_raddr == (void *)-1) {
4648 mmap_unlock();
4649 return get_errno((long)host_raddr);
4650 }
4651 raddr=h2g((unsigned long)host_raddr);
4652
4653 page_set_flags(raddr, raddr + shm_info.shm_segsz,
Richard Hendersond9c58582021-02-12 10:48:32 -08004654 PAGE_VALID | PAGE_RESET | PAGE_READ |
4655 (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
Riku Voipio88a8c982009-04-03 10:42:00 +03004656
4657 for (i = 0; i < N_SHM_REGIONS; i++) {
Peter Maydellb6e17872016-02-09 15:57:11 +00004658 if (!shm_regions[i].in_use) {
4659 shm_regions[i].in_use = true;
Riku Voipio88a8c982009-04-03 10:42:00 +03004660 shm_regions[i].start = raddr;
4661 shm_regions[i].size = shm_info.shm_segsz;
4662 break;
4663 }
4664 }
4665
4666 mmap_unlock();
4667 return raddr;
4668
4669}
4670
4671static inline abi_long do_shmdt(abi_ulong shmaddr)
4672{
4673 int i;
Max Filippov3c5f6a52018-02-28 14:16:04 -08004674 abi_long rv;
4675
Richard Hendersonee1bf832021-02-12 10:48:44 -08004676 /* shmdt pointers are always untagged */
4677
Max Filippov3c5f6a52018-02-28 14:16:04 -08004678 mmap_lock();
Riku Voipio88a8c982009-04-03 10:42:00 +03004679
4680 for (i = 0; i < N_SHM_REGIONS; ++i) {
Peter Maydellb6e17872016-02-09 15:57:11 +00004681 if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
4682 shm_regions[i].in_use = false;
takasi-y@ops.dti.ne.jpe00ac242010-04-11 02:09:57 +09004683 page_set_flags(shmaddr, shmaddr + shm_regions[i].size, 0);
Riku Voipio88a8c982009-04-03 10:42:00 +03004684 break;
4685 }
4686 }
Richard Henderson3e8f1622021-02-12 10:48:43 -08004687 rv = get_errno(shmdt(g2h_untagged(shmaddr)));
Riku Voipio88a8c982009-04-03 10:42:00 +03004688
Max Filippov3c5f6a52018-02-28 14:16:04 -08004689 mmap_unlock();
4690
4691 return rv;
Riku Voipio88a8c982009-04-03 10:42:00 +03004692}
4693
aurel321c54ff92008-10-13 21:08:44 +00004694#ifdef TARGET_NR_ipc
pbrook53a59602006-03-25 19:31:22 +00004695/* ??? This only works with linear mappings. */
ths0da46a62007-10-20 20:23:07 +00004696/* do_ipc() must return target values and target errnos. */
Peter Maydellee8e7612016-07-11 16:48:11 +01004697static abi_long do_ipc(CPUArchState *cpu_env,
4698 unsigned int call, abi_long first,
Tom Musta37ed0952014-08-12 13:53:35 -05004699 abi_long second, abi_long third,
blueswir1992f48a2007-10-14 16:27:31 +00004700 abi_long ptr, abi_long fifth)
bellard8853f862004-02-22 14:57:26 +00004701{
4702 int version;
blueswir1992f48a2007-10-14 16:27:31 +00004703 abi_long ret = 0;
bellard8853f862004-02-22 14:57:26 +00004704
4705 version = call >> 16;
4706 call &= 0xffff;
4707
4708 switch (call) {
thsfa294812007-02-02 22:05:00 +00004709 case IPCOP_semop:
Filip Bozutacac46eb2020-08-25 00:30:50 +02004710 ret = do_semtimedop(first, ptr, second, 0, false);
Matus Kyseld8c08b12020-06-26 14:46:11 +02004711 break;
4712 case IPCOP_semtimedop:
4713 /*
4714 * The s390 sys_ipc variant has only five parameters instead of six
4715 * (as for default variant) and the only difference is the handling of
4716 * SEMTIMEDOP where on s390 the third parameter is used as a pointer
4717 * to a struct timespec where the generic variant uses fifth parameter.
4718 */
4719#if defined(TARGET_S390X)
Filip Bozutacac46eb2020-08-25 00:30:50 +02004720 ret = do_semtimedop(first, ptr, second, third, TARGET_ABI_BITS == 64);
Matus Kyseld8c08b12020-06-26 14:46:11 +02004721#else
Filip Bozutacac46eb2020-08-25 00:30:50 +02004722 ret = do_semtimedop(first, ptr, second, fifth, TARGET_ABI_BITS == 64);
Matus Kyseld8c08b12020-06-26 14:46:11 +02004723#endif
thsfa294812007-02-02 22:05:00 +00004724 break;
4725
4726 case IPCOP_semget:
4727 ret = get_errno(semget(first, second, third));
4728 break;
4729
Tom Musta5d2fa8e2014-08-12 13:53:33 -05004730 case IPCOP_semctl: {
4731 /* The semun argument to semctl is passed by value, so dereference the
4732 * ptr argument. */
4733 abi_ulong atptr;
Tom Musta37ed0952014-08-12 13:53:35 -05004734 get_user_ual(atptr, ptr);
Stefan Weild1c002b2015-02-08 15:40:58 +01004735 ret = do_semctl(first, second, third, atptr);
thsfa294812007-02-02 22:05:00 +00004736 break;
Tom Musta5d2fa8e2014-08-12 13:53:33 -05004737 }
thsd96372e2007-02-02 22:05:44 +00004738
aurel321c54ff92008-10-13 21:08:44 +00004739 case IPCOP_msgget:
4740 ret = get_errno(msgget(first, second));
4741 break;
thsd96372e2007-02-02 22:05:44 +00004742
aurel321c54ff92008-10-13 21:08:44 +00004743 case IPCOP_msgsnd:
4744 ret = do_msgsnd(first, ptr, second, third);
4745 break;
thsd96372e2007-02-02 22:05:44 +00004746
aurel321c54ff92008-10-13 21:08:44 +00004747 case IPCOP_msgctl:
4748 ret = do_msgctl(first, second, ptr);
4749 break;
thsd96372e2007-02-02 22:05:44 +00004750
aurel321c54ff92008-10-13 21:08:44 +00004751 case IPCOP_msgrcv:
4752 switch (version) {
4753 case 0:
4754 {
4755 struct target_ipc_kludge {
4756 abi_long msgp;
4757 abi_long msgtyp;
4758 } *tmp;
thsd96372e2007-02-02 22:05:44 +00004759
aurel321c54ff92008-10-13 21:08:44 +00004760 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
4761 ret = -TARGET_EFAULT;
4762 break;
ths1bc012f2007-06-03 14:27:49 +00004763 }
aurel321c54ff92008-10-13 21:08:44 +00004764
Laurent Vivier79dd77d2012-12-20 11:00:11 +00004765 ret = do_msgrcv(first, tswapal(tmp->msgp), second, tswapal(tmp->msgtyp), third);
aurel321c54ff92008-10-13 21:08:44 +00004766
4767 unlock_user_struct(tmp, ptr, 0);
4768 break;
4769 }
4770 default:
4771 ret = do_msgrcv(first, ptr, second, fifth, third);
4772 }
4773 break;
thsd96372e2007-02-02 22:05:44 +00004774
bellard8853f862004-02-22 14:57:26 +00004775 case IPCOP_shmat:
Riku Voipio88a8c982009-04-03 10:42:00 +03004776 switch (version) {
4777 default:
bellard5a4a8982007-11-11 17:39:18 +00004778 {
4779 abi_ulong raddr;
Peter Maydellee8e7612016-07-11 16:48:11 +01004780 raddr = do_shmat(cpu_env, first, ptr, second);
Riku Voipio88a8c982009-04-03 10:42:00 +03004781 if (is_error(raddr))
4782 return get_errno(raddr);
bellard2f619692007-11-16 10:46:05 +00004783 if (put_user_ual(raddr, third))
bellard5a4a8982007-11-11 17:39:18 +00004784 return -TARGET_EFAULT;
Riku Voipio88a8c982009-04-03 10:42:00 +03004785 break;
4786 }
4787 case 1:
4788 ret = -TARGET_EINVAL;
4789 break;
bellard5a4a8982007-11-11 17:39:18 +00004790 }
bellard8853f862004-02-22 14:57:26 +00004791 break;
4792 case IPCOP_shmdt:
Riku Voipio88a8c982009-04-03 10:42:00 +03004793 ret = do_shmdt(ptr);
bellard8853f862004-02-22 14:57:26 +00004794 break;
4795
4796 case IPCOP_shmget:
4797 /* IPC_* flag values are the same on all linux platforms */
4798 ret = get_errno(shmget(first, second, third));
4799 break;
4800
4801 /* IPC_* and SHM_* command values are the same on all linux platforms */
4802 case IPCOP_shmctl:
Petar Jovanovica2926782013-10-30 14:46:32 +01004803 ret = do_shmctl(first, second, ptr);
bellard8853f862004-02-22 14:57:26 +00004804 break;
4805 default:
Josh Kunz39be5352020-02-03 18:54:13 -08004806 qemu_log_mask(LOG_UNIMP, "Unsupported ipc call: %d (version %d)\n",
4807 call, version);
ths0da46a62007-10-20 20:23:07 +00004808 ret = -TARGET_ENOSYS;
bellard8853f862004-02-22 14:57:26 +00004809 break;
4810 }
4811 return ret;
4812}
j_mayer32407102007-09-26 23:01:49 +00004813#endif
bellard8853f862004-02-22 14:57:26 +00004814
bellard31e31b82003-02-18 22:55:36 +00004815/* kernel structure types definitions */
bellard31e31b82003-02-18 22:55:36 +00004816
Blue Swirl001faf32009-05-13 17:53:17 +00004817#define STRUCT(name, ...) STRUCT_ ## name,
bellard31e31b82003-02-18 22:55:36 +00004818#define STRUCT_SPECIAL(name) STRUCT_ ## name,
4819enum {
4820#include "syscall_types.h"
Alexander Graf8be656b2015-05-06 23:47:32 +02004821STRUCT_MAX
bellard31e31b82003-02-18 22:55:36 +00004822};
4823#undef STRUCT
4824#undef STRUCT_SPECIAL
4825
Blue Swirl001faf32009-05-13 17:53:17 +00004826#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
bellard31e31b82003-02-18 22:55:36 +00004827#define STRUCT_SPECIAL(name)
4828#include "syscall_types.h"
4829#undef STRUCT
4830#undef STRUCT_SPECIAL
4831
bellard31e31b82003-02-18 22:55:36 +00004832#define MAX_STRUCT_SIZE 4096
4833
Peter Maydelldace20d2011-01-10 13:11:24 +00004834#ifdef CONFIG_FIEMAP
Peter Maydell285da2b2011-01-06 15:04:18 +00004835/* So fiemap access checks don't overflow on 32 bit systems.
4836 * This is very slightly smaller than the limit imposed by
4837 * the underlying kernel.
4838 */
4839#define FIEMAP_MAX_EXTENTS ((UINT_MAX - sizeof(struct fiemap)) \
4840 / sizeof(struct fiemap_extent))
4841
4842static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004843 int fd, int cmd, abi_long arg)
Peter Maydell285da2b2011-01-06 15:04:18 +00004844{
4845 /* The parameter for this ioctl is a struct fiemap followed
4846 * by an array of struct fiemap_extent whose size is set
4847 * in fiemap->fm_extent_count. The array is filled in by the
4848 * ioctl.
4849 */
4850 int target_size_in, target_size_out;
4851 struct fiemap *fm;
4852 const argtype *arg_type = ie->arg_type;
4853 const argtype extent_arg_type[] = { MK_STRUCT(STRUCT_fiemap_extent) };
4854 void *argptr, *p;
4855 abi_long ret;
4856 int i, extent_size = thunk_type_size(extent_arg_type, 0);
4857 uint32_t outbufsz;
4858 int free_fm = 0;
4859
4860 assert(arg_type[0] == TYPE_PTR);
4861 assert(ie->access == IOC_RW);
4862 arg_type++;
4863 target_size_in = thunk_type_size(arg_type, 0);
4864 argptr = lock_user(VERIFY_READ, arg, target_size_in, 1);
4865 if (!argptr) {
4866 return -TARGET_EFAULT;
4867 }
4868 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4869 unlock_user(argptr, arg, 0);
4870 fm = (struct fiemap *)buf_temp;
4871 if (fm->fm_extent_count > FIEMAP_MAX_EXTENTS) {
4872 return -TARGET_EINVAL;
4873 }
4874
4875 outbufsz = sizeof (*fm) +
4876 (sizeof(struct fiemap_extent) * fm->fm_extent_count);
4877
4878 if (outbufsz > MAX_STRUCT_SIZE) {
4879 /* We can't fit all the extents into the fixed size buffer.
4880 * Allocate one that is large enough and use it instead.
4881 */
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304882 fm = g_try_malloc(outbufsz);
Peter Maydell285da2b2011-01-06 15:04:18 +00004883 if (!fm) {
4884 return -TARGET_ENOMEM;
4885 }
4886 memcpy(fm, buf_temp, sizeof(struct fiemap));
4887 free_fm = 1;
4888 }
Peter Maydell49ca6f32016-06-06 19:58:14 +01004889 ret = get_errno(safe_ioctl(fd, ie->host_cmd, fm));
Peter Maydell285da2b2011-01-06 15:04:18 +00004890 if (!is_error(ret)) {
4891 target_size_out = target_size_in;
4892 /* An extent_count of 0 means we were only counting the extents
4893 * so there are no structs to copy
4894 */
4895 if (fm->fm_extent_count != 0) {
4896 target_size_out += fm->fm_mapped_extents * extent_size;
4897 }
4898 argptr = lock_user(VERIFY_WRITE, arg, target_size_out, 0);
4899 if (!argptr) {
4900 ret = -TARGET_EFAULT;
4901 } else {
4902 /* Convert the struct fiemap */
4903 thunk_convert(argptr, fm, arg_type, THUNK_TARGET);
4904 if (fm->fm_extent_count != 0) {
4905 p = argptr + target_size_in;
4906 /* ...and then all the struct fiemap_extents */
4907 for (i = 0; i < fm->fm_mapped_extents; i++) {
4908 thunk_convert(p, &fm->fm_extents[i], extent_arg_type,
4909 THUNK_TARGET);
4910 p += extent_size;
4911 }
4912 }
4913 unlock_user(argptr, arg, target_size_out);
4914 }
4915 }
4916 if (free_fm) {
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304917 g_free(fm);
Peter Maydell285da2b2011-01-06 15:04:18 +00004918 }
4919 return ret;
4920}
Peter Maydelldace20d2011-01-10 13:11:24 +00004921#endif
Peter Maydell285da2b2011-01-06 15:04:18 +00004922
Laurent Vivier059c2f22011-03-30 00:12:12 +02004923static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004924 int fd, int cmd, abi_long arg)
Laurent Vivier059c2f22011-03-30 00:12:12 +02004925{
4926 const argtype *arg_type = ie->arg_type;
4927 int target_size;
4928 void *argptr;
4929 int ret;
4930 struct ifconf *host_ifconf;
4931 uint32_t outbufsz;
4932 const argtype ifreq_arg_type[] = { MK_STRUCT(STRUCT_sockaddr_ifreq) };
Stefan4df7b7f2021-01-09 19:59:42 +01004933 const argtype ifreq_max_type[] = { MK_STRUCT(STRUCT_ifmap_ifreq) };
Laurent Vivier059c2f22011-03-30 00:12:12 +02004934 int target_ifreq_size;
4935 int nb_ifreq;
4936 int free_buf = 0;
4937 int i;
4938 int target_ifc_len;
4939 abi_long target_ifc_buf;
4940 int host_ifc_len;
4941 char *host_ifc_buf;
4942
4943 assert(arg_type[0] == TYPE_PTR);
4944 assert(ie->access == IOC_RW);
4945
4946 arg_type++;
4947 target_size = thunk_type_size(arg_type, 0);
4948
4949 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4950 if (!argptr)
4951 return -TARGET_EFAULT;
4952 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4953 unlock_user(argptr, arg, 0);
4954
4955 host_ifconf = (struct ifconf *)(unsigned long)buf_temp;
Laurent Vivier059c2f22011-03-30 00:12:12 +02004956 target_ifc_buf = (abi_long)(unsigned long)host_ifconf->ifc_buf;
Stefan4df7b7f2021-01-09 19:59:42 +01004957 target_ifreq_size = thunk_type_size(ifreq_max_type, 0);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004958
Kan Li22e4a2672018-10-24 20:13:03 +00004959 if (target_ifc_buf != 0) {
4960 target_ifc_len = host_ifconf->ifc_len;
4961 nb_ifreq = target_ifc_len / target_ifreq_size;
4962 host_ifc_len = nb_ifreq * sizeof(struct ifreq);
4963
4964 outbufsz = sizeof(*host_ifconf) + host_ifc_len;
4965 if (outbufsz > MAX_STRUCT_SIZE) {
4966 /*
4967 * We can't fit all the extents into the fixed size buffer.
4968 * Allocate one that is large enough and use it instead.
4969 */
4970 host_ifconf = malloc(outbufsz);
4971 if (!host_ifconf) {
4972 return -TARGET_ENOMEM;
4973 }
4974 memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf));
4975 free_buf = 1;
Laurent Vivier059c2f22011-03-30 00:12:12 +02004976 }
Kan Li22e4a2672018-10-24 20:13:03 +00004977 host_ifc_buf = (char *)host_ifconf + sizeof(*host_ifconf);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004978
Kan Li22e4a2672018-10-24 20:13:03 +00004979 host_ifconf->ifc_len = host_ifc_len;
4980 } else {
4981 host_ifc_buf = NULL;
4982 }
Laurent Vivier059c2f22011-03-30 00:12:12 +02004983 host_ifconf->ifc_buf = host_ifc_buf;
4984
Peter Maydell49ca6f32016-06-06 19:58:14 +01004985 ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_ifconf));
Laurent Vivier059c2f22011-03-30 00:12:12 +02004986 if (!is_error(ret)) {
4987 /* convert host ifc_len to target ifc_len */
4988
4989 nb_ifreq = host_ifconf->ifc_len / sizeof(struct ifreq);
4990 target_ifc_len = nb_ifreq * target_ifreq_size;
4991 host_ifconf->ifc_len = target_ifc_len;
4992
4993 /* restore target ifc_buf */
4994
4995 host_ifconf->ifc_buf = (char *)(unsigned long)target_ifc_buf;
4996
4997 /* copy struct ifconf to target user */
4998
4999 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5000 if (!argptr)
5001 return -TARGET_EFAULT;
5002 thunk_convert(argptr, host_ifconf, arg_type, THUNK_TARGET);
5003 unlock_user(argptr, arg, target_size);
5004
Kan Li22e4a2672018-10-24 20:13:03 +00005005 if (target_ifc_buf != 0) {
5006 /* copy ifreq[] to target user */
5007 argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0);
5008 for (i = 0; i < nb_ifreq ; i++) {
5009 thunk_convert(argptr + i * target_ifreq_size,
5010 host_ifc_buf + i * sizeof(struct ifreq),
5011 ifreq_arg_type, THUNK_TARGET);
5012 }
5013 unlock_user(argptr, target_ifc_buf, target_ifc_len);
Laurent Vivier059c2f22011-03-30 00:12:12 +02005014 }
Laurent Vivier059c2f22011-03-30 00:12:12 +02005015 }
5016
5017 if (free_buf) {
5018 free(host_ifconf);
5019 }
5020
5021 return ret;
5022}
5023
Cortland Tölvaa1333672018-10-08 09:35:21 -07005024#if defined(CONFIG_USBFS)
5025#if HOST_LONG_BITS > 64
5026#error USBDEVFS thunks do not support >64 bit hosts yet.
5027#endif
5028struct live_urb {
5029 uint64_t target_urb_adr;
5030 uint64_t target_buf_adr;
5031 char *target_buf_ptr;
5032 struct usbdevfs_urb host_urb;
5033};
5034
5035static GHashTable *usbdevfs_urb_hashtable(void)
5036{
5037 static GHashTable *urb_hashtable;
5038
5039 if (!urb_hashtable) {
5040 urb_hashtable = g_hash_table_new(g_int64_hash, g_int64_equal);
5041 }
5042 return urb_hashtable;
5043}
5044
5045static void urb_hashtable_insert(struct live_urb *urb)
5046{
5047 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
5048 g_hash_table_insert(urb_hashtable, urb, urb);
5049}
5050
5051static struct live_urb *urb_hashtable_lookup(uint64_t target_urb_adr)
5052{
5053 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
5054 return g_hash_table_lookup(urb_hashtable, &target_urb_adr);
5055}
5056
5057static void urb_hashtable_remove(struct live_urb *urb)
5058{
5059 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
5060 g_hash_table_remove(urb_hashtable, urb);
5061}
5062
5063static abi_long
5064do_ioctl_usbdevfs_reapurb(const IOCTLEntry *ie, uint8_t *buf_temp,
5065 int fd, int cmd, abi_long arg)
5066{
5067 const argtype usbfsurb_arg_type[] = { MK_STRUCT(STRUCT_usbdevfs_urb) };
5068 const argtype ptrvoid_arg_type[] = { TYPE_PTRVOID, 0, 0 };
5069 struct live_urb *lurb;
5070 void *argptr;
5071 uint64_t hurb;
5072 int target_size;
5073 uintptr_t target_urb_adr;
5074 abi_long ret;
5075
5076 target_size = thunk_type_size(usbfsurb_arg_type, THUNK_TARGET);
5077
5078 memset(buf_temp, 0, sizeof(uint64_t));
5079 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
5080 if (is_error(ret)) {
5081 return ret;
5082 }
5083
5084 memcpy(&hurb, buf_temp, sizeof(uint64_t));
5085 lurb = (void *)((uintptr_t)hurb - offsetof(struct live_urb, host_urb));
5086 if (!lurb->target_urb_adr) {
5087 return -TARGET_EFAULT;
5088 }
5089 urb_hashtable_remove(lurb);
5090 unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr,
5091 lurb->host_urb.buffer_length);
5092 lurb->target_buf_ptr = NULL;
5093
5094 /* restore the guest buffer pointer */
5095 lurb->host_urb.buffer = (void *)(uintptr_t)lurb->target_buf_adr;
5096
5097 /* update the guest urb struct */
5098 argptr = lock_user(VERIFY_WRITE, lurb->target_urb_adr, target_size, 0);
5099 if (!argptr) {
5100 g_free(lurb);
5101 return -TARGET_EFAULT;
5102 }
5103 thunk_convert(argptr, &lurb->host_urb, usbfsurb_arg_type, THUNK_TARGET);
5104 unlock_user(argptr, lurb->target_urb_adr, target_size);
5105
5106 target_size = thunk_type_size(ptrvoid_arg_type, THUNK_TARGET);
5107 /* write back the urb handle */
5108 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5109 if (!argptr) {
5110 g_free(lurb);
5111 return -TARGET_EFAULT;
5112 }
5113
5114 /* GHashTable uses 64-bit keys but thunk_convert expects uintptr_t */
5115 target_urb_adr = lurb->target_urb_adr;
5116 thunk_convert(argptr, &target_urb_adr, ptrvoid_arg_type, THUNK_TARGET);
5117 unlock_user(argptr, arg, target_size);
5118
5119 g_free(lurb);
5120 return ret;
5121}
5122
5123static abi_long
5124do_ioctl_usbdevfs_discardurb(const IOCTLEntry *ie,
5125 uint8_t *buf_temp __attribute__((unused)),
5126 int fd, int cmd, abi_long arg)
5127{
5128 struct live_urb *lurb;
5129
5130 /* map target address back to host URB with metadata. */
5131 lurb = urb_hashtable_lookup(arg);
5132 if (!lurb) {
5133 return -TARGET_EFAULT;
5134 }
5135 return get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
5136}
5137
5138static abi_long
5139do_ioctl_usbdevfs_submiturb(const IOCTLEntry *ie, uint8_t *buf_temp,
5140 int fd, int cmd, abi_long arg)
5141{
5142 const argtype *arg_type = ie->arg_type;
5143 int target_size;
5144 abi_long ret;
5145 void *argptr;
5146 int rw_dir;
5147 struct live_urb *lurb;
5148
5149 /*
5150 * each submitted URB needs to map to a unique ID for the
5151 * kernel, and that unique ID needs to be a pointer to
5152 * host memory. hence, we need to malloc for each URB.
5153 * isochronous transfers have a variable length struct.
5154 */
5155 arg_type++;
5156 target_size = thunk_type_size(arg_type, THUNK_TARGET);
5157
5158 /* construct host copy of urb and metadata */
5159 lurb = g_try_malloc0(sizeof(struct live_urb));
5160 if (!lurb) {
5161 return -TARGET_ENOMEM;
5162 }
5163
5164 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5165 if (!argptr) {
5166 g_free(lurb);
5167 return -TARGET_EFAULT;
5168 }
5169 thunk_convert(&lurb->host_urb, argptr, arg_type, THUNK_HOST);
5170 unlock_user(argptr, arg, 0);
5171
5172 lurb->target_urb_adr = arg;
5173 lurb->target_buf_adr = (uintptr_t)lurb->host_urb.buffer;
5174
5175 /* buffer space used depends on endpoint type so lock the entire buffer */
5176 /* control type urbs should check the buffer contents for true direction */
5177 rw_dir = lurb->host_urb.endpoint & USB_DIR_IN ? VERIFY_WRITE : VERIFY_READ;
5178 lurb->target_buf_ptr = lock_user(rw_dir, lurb->target_buf_adr,
5179 lurb->host_urb.buffer_length, 1);
5180 if (lurb->target_buf_ptr == NULL) {
5181 g_free(lurb);
5182 return -TARGET_EFAULT;
5183 }
5184
5185 /* update buffer pointer in host copy */
5186 lurb->host_urb.buffer = lurb->target_buf_ptr;
5187
5188 ret = get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
5189 if (is_error(ret)) {
5190 unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr, 0);
5191 g_free(lurb);
5192 } else {
5193 urb_hashtable_insert(lurb);
5194 }
5195
5196 return ret;
5197}
5198#endif /* CONFIG_USBFS */
5199
Alexander Graf56e904e2012-01-31 18:42:06 +01005200static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
Laurent Vivier45c874e2015-06-16 00:35:28 +02005201 int cmd, abi_long arg)
Alexander Graf56e904e2012-01-31 18:42:06 +01005202{
5203 void *argptr;
5204 struct dm_ioctl *host_dm;
5205 abi_long guest_data;
5206 uint32_t guest_data_size;
5207 int target_size;
5208 const argtype *arg_type = ie->arg_type;
5209 abi_long ret;
5210 void *big_buf = NULL;
5211 char *host_data;
5212
5213 arg_type++;
5214 target_size = thunk_type_size(arg_type, 0);
5215 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5216 if (!argptr) {
5217 ret = -TARGET_EFAULT;
5218 goto out;
5219 }
5220 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5221 unlock_user(argptr, arg, 0);
5222
5223 /* buf_temp is too small, so fetch things into a bigger buffer */
5224 big_buf = g_malloc0(((struct dm_ioctl*)buf_temp)->data_size * 2);
5225 memcpy(big_buf, buf_temp, target_size);
5226 buf_temp = big_buf;
5227 host_dm = big_buf;
5228
5229 guest_data = arg + host_dm->data_start;
5230 if ((guest_data - arg) < 0) {
Peter Maydellf9757b12016-07-12 13:02:14 +01005231 ret = -TARGET_EINVAL;
Alexander Graf56e904e2012-01-31 18:42:06 +01005232 goto out;
5233 }
5234 guest_data_size = host_dm->data_size - host_dm->data_start;
5235 host_data = (char*)host_dm + host_dm->data_start;
5236
5237 argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1);
Peter Maydell32112152016-07-12 13:02:13 +01005238 if (!argptr) {
5239 ret = -TARGET_EFAULT;
5240 goto out;
5241 }
5242
Alexander Graf56e904e2012-01-31 18:42:06 +01005243 switch (ie->host_cmd) {
5244 case DM_REMOVE_ALL:
5245 case DM_LIST_DEVICES:
5246 case DM_DEV_CREATE:
5247 case DM_DEV_REMOVE:
5248 case DM_DEV_SUSPEND:
5249 case DM_DEV_STATUS:
5250 case DM_DEV_WAIT:
5251 case DM_TABLE_STATUS:
5252 case DM_TABLE_CLEAR:
5253 case DM_TABLE_DEPS:
5254 case DM_LIST_VERSIONS:
5255 /* no input data */
5256 break;
5257 case DM_DEV_RENAME:
5258 case DM_DEV_SET_GEOMETRY:
5259 /* data contains only strings */
5260 memcpy(host_data, argptr, guest_data_size);
5261 break;
5262 case DM_TARGET_MSG:
5263 memcpy(host_data, argptr, guest_data_size);
5264 *(uint64_t*)host_data = tswap64(*(uint64_t*)argptr);
5265 break;
5266 case DM_TABLE_LOAD:
5267 {
5268 void *gspec = argptr;
5269 void *cur_data = host_data;
5270 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
5271 int spec_size = thunk_type_size(arg_type, 0);
5272 int i;
5273
5274 for (i = 0; i < host_dm->target_count; i++) {
5275 struct dm_target_spec *spec = cur_data;
5276 uint32_t next;
5277 int slen;
5278
5279 thunk_convert(spec, gspec, arg_type, THUNK_HOST);
5280 slen = strlen((char*)gspec + spec_size) + 1;
5281 next = spec->next;
5282 spec->next = sizeof(*spec) + slen;
5283 strcpy((char*)&spec[1], gspec + spec_size);
5284 gspec += next;
5285 cur_data += spec->next;
5286 }
5287 break;
5288 }
5289 default:
5290 ret = -TARGET_EINVAL;
Chen Gang Sdec04732015-01-25 08:00:42 +08005291 unlock_user(argptr, guest_data, 0);
Alexander Graf56e904e2012-01-31 18:42:06 +01005292 goto out;
5293 }
5294 unlock_user(argptr, guest_data, 0);
5295
Peter Maydell49ca6f32016-06-06 19:58:14 +01005296 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
Alexander Graf56e904e2012-01-31 18:42:06 +01005297 if (!is_error(ret)) {
5298 guest_data = arg + host_dm->data_start;
5299 guest_data_size = host_dm->data_size - host_dm->data_start;
5300 argptr = lock_user(VERIFY_WRITE, guest_data, guest_data_size, 0);
5301 switch (ie->host_cmd) {
5302 case DM_REMOVE_ALL:
5303 case DM_DEV_CREATE:
5304 case DM_DEV_REMOVE:
5305 case DM_DEV_RENAME:
5306 case DM_DEV_SUSPEND:
5307 case DM_DEV_STATUS:
5308 case DM_TABLE_LOAD:
5309 case DM_TABLE_CLEAR:
5310 case DM_TARGET_MSG:
5311 case DM_DEV_SET_GEOMETRY:
5312 /* no return data */
5313 break;
5314 case DM_LIST_DEVICES:
5315 {
5316 struct dm_name_list *nl = (void*)host_dm + host_dm->data_start;
5317 uint32_t remaining_data = guest_data_size;
5318 void *cur_data = argptr;
5319 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
5320 int nl_size = 12; /* can't use thunk_size due to alignment */
5321
5322 while (1) {
5323 uint32_t next = nl->next;
5324 if (next) {
5325 nl->next = nl_size + (strlen(nl->name) + 1);
5326 }
5327 if (remaining_data < nl->next) {
5328 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5329 break;
5330 }
5331 thunk_convert(cur_data, nl, arg_type, THUNK_TARGET);
5332 strcpy(cur_data + nl_size, nl->name);
5333 cur_data += nl->next;
5334 remaining_data -= nl->next;
5335 if (!next) {
5336 break;
5337 }
5338 nl = (void*)nl + next;
5339 }
5340 break;
5341 }
5342 case DM_DEV_WAIT:
5343 case DM_TABLE_STATUS:
5344 {
5345 struct dm_target_spec *spec = (void*)host_dm + host_dm->data_start;
5346 void *cur_data = argptr;
5347 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
5348 int spec_size = thunk_type_size(arg_type, 0);
5349 int i;
5350
5351 for (i = 0; i < host_dm->target_count; i++) {
5352 uint32_t next = spec->next;
5353 int slen = strlen((char*)&spec[1]) + 1;
5354 spec->next = (cur_data - argptr) + spec_size + slen;
5355 if (guest_data_size < spec->next) {
5356 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5357 break;
5358 }
5359 thunk_convert(cur_data, spec, arg_type, THUNK_TARGET);
5360 strcpy(cur_data + spec_size, (char*)&spec[1]);
5361 cur_data = argptr + spec->next;
5362 spec = (void*)host_dm + host_dm->data_start + next;
5363 }
5364 break;
5365 }
5366 case DM_TABLE_DEPS:
5367 {
5368 void *hdata = (void*)host_dm + host_dm->data_start;
5369 int count = *(uint32_t*)hdata;
5370 uint64_t *hdev = hdata + 8;
5371 uint64_t *gdev = argptr + 8;
5372 int i;
5373
5374 *(uint32_t*)argptr = tswap32(count);
5375 for (i = 0; i < count; i++) {
5376 *gdev = tswap64(*hdev);
5377 gdev++;
5378 hdev++;
5379 }
5380 break;
5381 }
5382 case DM_LIST_VERSIONS:
5383 {
5384 struct dm_target_versions *vers = (void*)host_dm + host_dm->data_start;
5385 uint32_t remaining_data = guest_data_size;
5386 void *cur_data = argptr;
5387 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_versions) };
5388 int vers_size = thunk_type_size(arg_type, 0);
5389
5390 while (1) {
5391 uint32_t next = vers->next;
5392 if (next) {
5393 vers->next = vers_size + (strlen(vers->name) + 1);
5394 }
5395 if (remaining_data < vers->next) {
5396 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5397 break;
5398 }
5399 thunk_convert(cur_data, vers, arg_type, THUNK_TARGET);
5400 strcpy(cur_data + vers_size, vers->name);
5401 cur_data += vers->next;
5402 remaining_data -= vers->next;
5403 if (!next) {
5404 break;
5405 }
5406 vers = (void*)vers + next;
5407 }
5408 break;
5409 }
5410 default:
Chen Gang Sdec04732015-01-25 08:00:42 +08005411 unlock_user(argptr, guest_data, 0);
Alexander Graf56e904e2012-01-31 18:42:06 +01005412 ret = -TARGET_EINVAL;
5413 goto out;
5414 }
5415 unlock_user(argptr, guest_data, guest_data_size);
5416
5417 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5418 if (!argptr) {
5419 ret = -TARGET_EFAULT;
5420 goto out;
5421 }
5422 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5423 unlock_user(argptr, arg, target_size);
5424 }
5425out:
Stefan Weilad11ad72012-09-04 22:14:19 +02005426 g_free(big_buf);
Alexander Graf56e904e2012-01-31 18:42:06 +01005427 return ret;
5428}
5429
Alexander Grafa59b5e32014-08-22 13:15:50 +02005430static abi_long do_ioctl_blkpg(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
Laurent Vivier45c874e2015-06-16 00:35:28 +02005431 int cmd, abi_long arg)
Alexander Grafa59b5e32014-08-22 13:15:50 +02005432{
5433 void *argptr;
5434 int target_size;
5435 const argtype *arg_type = ie->arg_type;
5436 const argtype part_arg_type[] = { MK_STRUCT(STRUCT_blkpg_partition) };
5437 abi_long ret;
5438
5439 struct blkpg_ioctl_arg *host_blkpg = (void*)buf_temp;
5440 struct blkpg_partition host_part;
5441
5442 /* Read and convert blkpg */
5443 arg_type++;
5444 target_size = thunk_type_size(arg_type, 0);
5445 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5446 if (!argptr) {
5447 ret = -TARGET_EFAULT;
5448 goto out;
5449 }
5450 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5451 unlock_user(argptr, arg, 0);
5452
5453 switch (host_blkpg->op) {
5454 case BLKPG_ADD_PARTITION:
5455 case BLKPG_DEL_PARTITION:
5456 /* payload is struct blkpg_partition */
5457 break;
5458 default:
5459 /* Unknown opcode */
5460 ret = -TARGET_EINVAL;
5461 goto out;
5462 }
5463
5464 /* Read and convert blkpg->data */
5465 arg = (abi_long)(uintptr_t)host_blkpg->data;
5466 target_size = thunk_type_size(part_arg_type, 0);
5467 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5468 if (!argptr) {
5469 ret = -TARGET_EFAULT;
5470 goto out;
5471 }
5472 thunk_convert(&host_part, argptr, part_arg_type, THUNK_HOST);
5473 unlock_user(argptr, arg, 0);
5474
5475 /* Swizzle the data pointer to our local copy and call! */
5476 host_blkpg->data = &host_part;
Peter Maydell49ca6f32016-06-06 19:58:14 +01005477 ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_blkpg));
Alexander Grafa59b5e32014-08-22 13:15:50 +02005478
5479out:
5480 return ret;
5481}
5482
Laurent Vivier7ff7b662013-07-02 14:04:12 +01005483static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02005484 int fd, int cmd, abi_long arg)
Laurent Vivier7ff7b662013-07-02 14:04:12 +01005485{
5486 const argtype *arg_type = ie->arg_type;
5487 const StructEntry *se;
5488 const argtype *field_types;
5489 const int *dst_offsets, *src_offsets;
5490 int target_size;
5491 void *argptr;
Marc-André Lureaub78c5222019-03-05 16:15:00 +01005492 abi_ulong *target_rt_dev_ptr = NULL;
5493 unsigned long *host_rt_dev_ptr = NULL;
Laurent Vivier7ff7b662013-07-02 14:04:12 +01005494 abi_long ret;
5495 int i;
5496
5497 assert(ie->access == IOC_W);
5498 assert(*arg_type == TYPE_PTR);
5499 arg_type++;
5500 assert(*arg_type == TYPE_STRUCT);
5501 target_size = thunk_type_size(arg_type, 0);
5502 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5503 if (!argptr) {
5504 return -TARGET_EFAULT;
5505 }
5506 arg_type++;
5507 assert(*arg_type == (int)STRUCT_rtentry);
5508 se = struct_entries + *arg_type++;
5509 assert(se->convert[0] == NULL);
5510 /* convert struct here to be able to catch rt_dev string */
5511 field_types = se->field_types;
5512 dst_offsets = se->field_offsets[THUNK_HOST];
5513 src_offsets = se->field_offsets[THUNK_TARGET];
5514 for (i = 0; i < se->nb_fields; i++) {
5515 if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) {
5516 assert(*field_types == TYPE_PTRVOID);
5517 target_rt_dev_ptr = (abi_ulong *)(argptr + src_offsets[i]);
5518 host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]);
5519 if (*target_rt_dev_ptr != 0) {
5520 *host_rt_dev_ptr = (unsigned long)lock_user_string(
5521 tswapal(*target_rt_dev_ptr));
5522 if (!*host_rt_dev_ptr) {
5523 unlock_user(argptr, arg, 0);
5524 return -TARGET_EFAULT;
5525 }
5526 } else {
5527 *host_rt_dev_ptr = 0;
5528 }
5529 field_types++;
5530 continue;
5531 }
5532 field_types = thunk_convert(buf_temp + dst_offsets[i],
5533 argptr + src_offsets[i],
5534 field_types, THUNK_HOST);
5535 }
5536 unlock_user(argptr, arg, 0);
5537
Peter Maydell49ca6f32016-06-06 19:58:14 +01005538 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
Marc-André Lureaub78c5222019-03-05 16:15:00 +01005539
5540 assert(host_rt_dev_ptr != NULL);
5541 assert(target_rt_dev_ptr != NULL);
Laurent Vivier7ff7b662013-07-02 14:04:12 +01005542 if (*host_rt_dev_ptr != 0) {
5543 unlock_user((void *)*host_rt_dev_ptr,
5544 *target_rt_dev_ptr, 0);
5545 }
5546 return ret;
5547}
5548
Paul Burtonca56f5b2014-06-22 11:25:47 +01005549static abi_long do_ioctl_kdsigaccept(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02005550 int fd, int cmd, abi_long arg)
Paul Burtonca56f5b2014-06-22 11:25:47 +01005551{
5552 int sig = target_to_host_signal(arg);
Peter Maydell49ca6f32016-06-06 19:58:14 +01005553 return get_errno(safe_ioctl(fd, ie->host_cmd, sig));
Paul Burtonca56f5b2014-06-22 11:25:47 +01005554}
5555
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02005556static abi_long do_ioctl_SIOCGSTAMP(const IOCTLEntry *ie, uint8_t *buf_temp,
5557 int fd, int cmd, abi_long arg)
5558{
5559 struct timeval tv;
5560 abi_long ret;
5561
5562 ret = get_errno(safe_ioctl(fd, SIOCGSTAMP, &tv));
5563 if (is_error(ret)) {
5564 return ret;
5565 }
5566
5567 if (cmd == (int)TARGET_SIOCGSTAMP_OLD) {
5568 if (copy_to_user_timeval(arg, &tv)) {
5569 return -TARGET_EFAULT;
5570 }
5571 } else {
5572 if (copy_to_user_timeval64(arg, &tv)) {
5573 return -TARGET_EFAULT;
5574 }
5575 }
5576
5577 return ret;
5578}
5579
5580static abi_long do_ioctl_SIOCGSTAMPNS(const IOCTLEntry *ie, uint8_t *buf_temp,
5581 int fd, int cmd, abi_long arg)
5582{
5583 struct timespec ts;
5584 abi_long ret;
5585
5586 ret = get_errno(safe_ioctl(fd, SIOCGSTAMPNS, &ts));
5587 if (is_error(ret)) {
5588 return ret;
5589 }
5590
5591 if (cmd == (int)TARGET_SIOCGSTAMPNS_OLD) {
5592 if (host_to_target_timespec(arg, &ts)) {
5593 return -TARGET_EFAULT;
5594 }
5595 } else{
5596 if (host_to_target_timespec64(arg, &ts)) {
5597 return -TARGET_EFAULT;
5598 }
5599 }
5600
5601 return ret;
5602}
5603
Andreas Schwab2b74f622018-01-29 11:47:06 +01005604#ifdef TIOCGPTPEER
5605static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry *ie, uint8_t *buf_temp,
5606 int fd, int cmd, abi_long arg)
5607{
5608 int flags = target_to_host_bitmask(arg, fcntl_flags_tbl);
5609 return get_errno(safe_ioctl(fd, ie->host_cmd, flags));
5610}
5611#endif
5612
Chen Gange865b972020-06-05 09:32:21 +08005613#ifdef HAVE_DRM_H
5614
5615static void unlock_drm_version(struct drm_version *host_ver,
5616 struct target_drm_version *target_ver,
5617 bool copy)
5618{
5619 unlock_user(host_ver->name, target_ver->name,
5620 copy ? host_ver->name_len : 0);
5621 unlock_user(host_ver->date, target_ver->date,
5622 copy ? host_ver->date_len : 0);
5623 unlock_user(host_ver->desc, target_ver->desc,
5624 copy ? host_ver->desc_len : 0);
5625}
5626
5627static inline abi_long target_to_host_drmversion(struct drm_version *host_ver,
5628 struct target_drm_version *target_ver)
5629{
5630 memset(host_ver, 0, sizeof(*host_ver));
5631
5632 __get_user(host_ver->name_len, &target_ver->name_len);
5633 if (host_ver->name_len) {
5634 host_ver->name = lock_user(VERIFY_WRITE, target_ver->name,
5635 target_ver->name_len, 0);
5636 if (!host_ver->name) {
5637 return -EFAULT;
5638 }
5639 }
5640
5641 __get_user(host_ver->date_len, &target_ver->date_len);
5642 if (host_ver->date_len) {
5643 host_ver->date = lock_user(VERIFY_WRITE, target_ver->date,
5644 target_ver->date_len, 0);
5645 if (!host_ver->date) {
5646 goto err;
5647 }
5648 }
5649
5650 __get_user(host_ver->desc_len, &target_ver->desc_len);
5651 if (host_ver->desc_len) {
5652 host_ver->desc = lock_user(VERIFY_WRITE, target_ver->desc,
5653 target_ver->desc_len, 0);
5654 if (!host_ver->desc) {
5655 goto err;
5656 }
5657 }
5658
5659 return 0;
5660err:
5661 unlock_drm_version(host_ver, target_ver, false);
5662 return -EFAULT;
5663}
5664
5665static inline void host_to_target_drmversion(
5666 struct target_drm_version *target_ver,
5667 struct drm_version *host_ver)
5668{
5669 __put_user(host_ver->version_major, &target_ver->version_major);
5670 __put_user(host_ver->version_minor, &target_ver->version_minor);
5671 __put_user(host_ver->version_patchlevel, &target_ver->version_patchlevel);
5672 __put_user(host_ver->name_len, &target_ver->name_len);
5673 __put_user(host_ver->date_len, &target_ver->date_len);
5674 __put_user(host_ver->desc_len, &target_ver->desc_len);
5675 unlock_drm_version(host_ver, target_ver, true);
5676}
5677
5678static abi_long do_ioctl_drm(const IOCTLEntry *ie, uint8_t *buf_temp,
5679 int fd, int cmd, abi_long arg)
5680{
5681 struct drm_version *ver;
5682 struct target_drm_version *target_ver;
5683 abi_long ret;
5684
5685 switch (ie->host_cmd) {
5686 case DRM_IOCTL_VERSION:
5687 if (!lock_user_struct(VERIFY_WRITE, target_ver, arg, 0)) {
5688 return -TARGET_EFAULT;
5689 }
5690 ver = (struct drm_version *)buf_temp;
5691 ret = target_to_host_drmversion(ver, target_ver);
5692 if (!is_error(ret)) {
5693 ret = get_errno(safe_ioctl(fd, ie->host_cmd, ver));
5694 if (is_error(ret)) {
5695 unlock_drm_version(ver, target_ver, false);
5696 } else {
5697 host_to_target_drmversion(target_ver, ver);
5698 }
5699 }
5700 unlock_user_struct(target_ver, arg, 0);
5701 return ret;
5702 }
5703 return -TARGET_ENOSYS;
5704}
5705
Chen Gang913b03c2020-08-02 21:39:38 +08005706static abi_long do_ioctl_drm_i915_getparam(const IOCTLEntry *ie,
5707 struct drm_i915_getparam *gparam,
5708 int fd, abi_long arg)
5709{
5710 abi_long ret;
5711 int value;
5712 struct target_drm_i915_getparam *target_gparam;
5713
5714 if (!lock_user_struct(VERIFY_READ, target_gparam, arg, 0)) {
5715 return -TARGET_EFAULT;
5716 }
5717
5718 __get_user(gparam->param, &target_gparam->param);
5719 gparam->value = &value;
5720 ret = get_errno(safe_ioctl(fd, ie->host_cmd, gparam));
5721 put_user_s32(value, target_gparam->value);
5722
5723 unlock_user_struct(target_gparam, arg, 0);
5724 return ret;
5725}
5726
5727static abi_long do_ioctl_drm_i915(const IOCTLEntry *ie, uint8_t *buf_temp,
5728 int fd, int cmd, abi_long arg)
5729{
5730 switch (ie->host_cmd) {
5731 case DRM_IOCTL_I915_GETPARAM:
5732 return do_ioctl_drm_i915_getparam(ie,
5733 (struct drm_i915_getparam *)buf_temp,
5734 fd, arg);
5735 default:
5736 return -TARGET_ENOSYS;
5737 }
5738}
5739
Chen Gange865b972020-06-05 09:32:21 +08005740#endif
5741
Shu-Chun Weng6addf062020-09-28 18:48:01 -07005742static abi_long do_ioctl_TUNSETTXFILTER(const IOCTLEntry *ie, uint8_t *buf_temp,
5743 int fd, int cmd, abi_long arg)
5744{
5745 struct tun_filter *filter = (struct tun_filter *)buf_temp;
5746 struct tun_filter *target_filter;
5747 char *target_addr;
5748
5749 assert(ie->access == IOC_W);
5750
5751 target_filter = lock_user(VERIFY_READ, arg, sizeof(*target_filter), 1);
5752 if (!target_filter) {
5753 return -TARGET_EFAULT;
5754 }
5755 filter->flags = tswap16(target_filter->flags);
5756 filter->count = tswap16(target_filter->count);
5757 unlock_user(target_filter, arg, 0);
5758
5759 if (filter->count) {
5760 if (offsetof(struct tun_filter, addr) + filter->count * ETH_ALEN >
5761 MAX_STRUCT_SIZE) {
5762 return -TARGET_EFAULT;
5763 }
5764
5765 target_addr = lock_user(VERIFY_READ,
5766 arg + offsetof(struct tun_filter, addr),
5767 filter->count * ETH_ALEN, 1);
5768 if (!target_addr) {
5769 return -TARGET_EFAULT;
5770 }
5771 memcpy(filter->addr, target_addr, filter->count * ETH_ALEN);
5772 unlock_user(target_addr, arg + offsetof(struct tun_filter, addr), 0);
5773 }
5774
5775 return get_errno(safe_ioctl(fd, ie->host_cmd, filter));
5776}
5777
Filip Bozuta79482e592020-06-19 14:47:27 +02005778IOCTLEntry ioctl_entries[] = {
Blue Swirl001faf32009-05-13 17:53:17 +00005779#define IOCTL(cmd, access, ...) \
Peter Maydelld2ef05b2011-01-06 15:04:17 +00005780 { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
5781#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
5782 { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
Helge Deller8cb762f2016-12-06 16:24:03 +01005783#define IOCTL_IGNORE(cmd) \
5784 { TARGET_ ## cmd, 0, #cmd },
bellard31e31b82003-02-18 22:55:36 +00005785#include "ioctls.h"
5786 { 0, 0, },
5787};
5788
pbrook53a59602006-03-25 19:31:22 +00005789/* ??? Implement proper locking for ioctls. */
ths0da46a62007-10-20 20:23:07 +00005790/* do_ioctl() Must return target values and target errnos. */
Laurent Vivier45c874e2015-06-16 00:35:28 +02005791static abi_long do_ioctl(int fd, int cmd, abi_long arg)
bellard31e31b82003-02-18 22:55:36 +00005792{
5793 const IOCTLEntry *ie;
5794 const argtype *arg_type;
blueswir1992f48a2007-10-14 16:27:31 +00005795 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00005796 uint8_t buf_temp[MAX_STRUCT_SIZE];
pbrook53a59602006-03-25 19:31:22 +00005797 int target_size;
5798 void *argptr;
bellard31e31b82003-02-18 22:55:36 +00005799
5800 ie = ioctl_entries;
5801 for(;;) {
5802 if (ie->target_cmd == 0) {
Josh Kunz39be5352020-02-03 18:54:13 -08005803 qemu_log_mask(
5804 LOG_UNIMP, "Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
ths0da46a62007-10-20 20:23:07 +00005805 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00005806 }
5807 if (ie->target_cmd == cmd)
5808 break;
5809 ie++;
5810 }
5811 arg_type = ie->arg_type;
Peter Maydelld2ef05b2011-01-06 15:04:17 +00005812 if (ie->do_ioctl) {
5813 return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
Helge Deller8cb762f2016-12-06 16:24:03 +01005814 } else if (!ie->host_cmd) {
5815 /* Some architectures define BSD ioctls in their headers
5816 that are not implemented in Linux. */
5817 return -TARGET_ENOSYS;
Peter Maydelld2ef05b2011-01-06 15:04:17 +00005818 }
5819
bellard31e31b82003-02-18 22:55:36 +00005820 switch(arg_type[0]) {
5821 case TYPE_NULL:
5822 /* no argument */
Peter Maydell49ca6f32016-06-06 19:58:14 +01005823 ret = get_errno(safe_ioctl(fd, ie->host_cmd));
bellard31e31b82003-02-18 22:55:36 +00005824 break;
5825 case TYPE_PTRVOID:
5826 case TYPE_INT:
Filip Bozutac858e532020-01-15 20:36:47 +01005827 case TYPE_LONG:
5828 case TYPE_ULONG:
Peter Maydell49ca6f32016-06-06 19:58:14 +01005829 ret = get_errno(safe_ioctl(fd, ie->host_cmd, arg));
bellard31e31b82003-02-18 22:55:36 +00005830 break;
5831 case TYPE_PTR:
5832 arg_type++;
pbrook53a59602006-03-25 19:31:22 +00005833 target_size = thunk_type_size(arg_type, 0);
bellard31e31b82003-02-18 22:55:36 +00005834 switch(ie->access) {
5835 case IOC_R:
Peter Maydell49ca6f32016-06-06 19:58:14 +01005836 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
bellard31e31b82003-02-18 22:55:36 +00005837 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005838 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5839 if (!argptr)
5840 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005841 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5842 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00005843 }
5844 break;
5845 case IOC_W:
bellard579a97f2007-11-11 14:26:47 +00005846 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5847 if (!argptr)
5848 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005849 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5850 unlock_user(argptr, arg, 0);
Peter Maydell49ca6f32016-06-06 19:58:14 +01005851 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
bellard31e31b82003-02-18 22:55:36 +00005852 break;
5853 default:
5854 case IOC_RW:
bellard579a97f2007-11-11 14:26:47 +00005855 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5856 if (!argptr)
5857 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005858 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5859 unlock_user(argptr, arg, 0);
Peter Maydell49ca6f32016-06-06 19:58:14 +01005860 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
bellard31e31b82003-02-18 22:55:36 +00005861 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005862 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5863 if (!argptr)
5864 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005865 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5866 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00005867 }
5868 break;
5869 }
5870 break;
5871 default:
Josh Kunz39be5352020-02-03 18:54:13 -08005872 qemu_log_mask(LOG_UNIMP,
5873 "Unsupported ioctl type: cmd=0x%04lx type=%d\n",
5874 (long)cmd, arg_type[0]);
ths0da46a62007-10-20 20:23:07 +00005875 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00005876 break;
5877 }
5878 return ret;
5879}
5880
blueswir1b39bc502008-10-05 10:51:10 +00005881static const bitmask_transtbl iflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00005882 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
5883 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
5884 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
5885 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
5886 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
5887 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
5888 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
5889 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
5890 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
5891 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
5892 { TARGET_IXON, TARGET_IXON, IXON, IXON },
5893 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
5894 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
5895 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
Filip Bozutac218b4e2020-07-23 23:02:32 +02005896 { TARGET_IUTF8, TARGET_IUTF8, IUTF8, IUTF8},
bellard31e31b82003-02-18 22:55:36 +00005897 { 0, 0, 0, 0 }
5898};
5899
blueswir1b39bc502008-10-05 10:51:10 +00005900static const bitmask_transtbl oflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00005901 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
5902 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
5903 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
5904 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
5905 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
5906 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
5907 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
5908 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
5909 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
5910 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
5911 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
5912 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
5913 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
5914 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
5915 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
5916 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
5917 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
5918 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
5919 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
5920 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
5921 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
5922 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
5923 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
5924 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
5925 { 0, 0, 0, 0 }
5926};
5927
blueswir1b39bc502008-10-05 10:51:10 +00005928static const bitmask_transtbl cflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00005929 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
5930 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
5931 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
5932 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
5933 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
5934 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
5935 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
5936 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
5937 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
5938 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
5939 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
5940 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
5941 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
5942 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
5943 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
5944 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
5945 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
5946 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
5947 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
5948 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
5949 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
5950 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
5951 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
5952 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
5953 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
5954 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
5955 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
5956 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
5957 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
5958 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
5959 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
5960 { 0, 0, 0, 0 }
5961};
5962
blueswir1b39bc502008-10-05 10:51:10 +00005963static const bitmask_transtbl lflag_tbl[] = {
Filip Bozutac218b4e2020-07-23 23:02:32 +02005964 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
5965 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
5966 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
5967 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
5968 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
5969 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
5970 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
5971 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
5972 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
5973 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
5974 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
5975 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
5976 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
5977 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
5978 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
5979 { TARGET_EXTPROC, TARGET_EXTPROC, EXTPROC, EXTPROC},
5980 { 0, 0, 0, 0 }
bellard31e31b82003-02-18 22:55:36 +00005981};
5982
5983static void target_to_host_termios (void *dst, const void *src)
5984{
5985 struct host_termios *host = dst;
5986 const struct target_termios *target = src;
ths3b46e622007-09-17 08:09:54 +00005987
ths5fafdf22007-09-16 21:08:06 +00005988 host->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00005989 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00005990 host->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00005991 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00005992 host->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00005993 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00005994 host->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00005995 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
5996 host->c_line = target->c_line;
ths3b46e622007-09-17 08:09:54 +00005997
Arnaud Patard44607122009-04-21 17:39:08 +03005998 memset(host->c_cc, 0, sizeof(host->c_cc));
ths5fafdf22007-09-16 21:08:06 +00005999 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
6000 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
ths3b46e622007-09-17 08:09:54 +00006001 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
ths5fafdf22007-09-16 21:08:06 +00006002 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
ths3b46e622007-09-17 08:09:54 +00006003 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
ths5fafdf22007-09-16 21:08:06 +00006004 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
ths3b46e622007-09-17 08:09:54 +00006005 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
ths5fafdf22007-09-16 21:08:06 +00006006 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
ths3b46e622007-09-17 08:09:54 +00006007 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
ths5fafdf22007-09-16 21:08:06 +00006008 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
6009 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
ths3b46e622007-09-17 08:09:54 +00006010 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
6011 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
6012 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
6013 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
6014 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
ths5fafdf22007-09-16 21:08:06 +00006015 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
bellard31e31b82003-02-18 22:55:36 +00006016}
ths3b46e622007-09-17 08:09:54 +00006017
bellard31e31b82003-02-18 22:55:36 +00006018static void host_to_target_termios (void *dst, const void *src)
6019{
6020 struct target_termios *target = dst;
6021 const struct host_termios *host = src;
6022
ths5fafdf22007-09-16 21:08:06 +00006023 target->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00006024 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00006025 target->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00006026 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00006027 target->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00006028 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00006029 target->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00006030 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
6031 target->c_line = host->c_line;
ths3b46e622007-09-17 08:09:54 +00006032
Arnaud Patard44607122009-04-21 17:39:08 +03006033 memset(target->c_cc, 0, sizeof(target->c_cc));
bellard31e31b82003-02-18 22:55:36 +00006034 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
6035 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
6036 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
6037 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
6038 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
6039 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
6040 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
6041 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
6042 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
6043 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
6044 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
6045 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
6046 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
6047 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
6048 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
6049 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
6050 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
6051}
6052
blueswir18e853dc2008-10-05 10:49:32 +00006053static const StructEntry struct_termios_def = {
bellard31e31b82003-02-18 22:55:36 +00006054 .convert = { host_to_target_termios, target_to_host_termios },
6055 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
6056 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
Filip Bozuta888468d2020-07-23 23:02:33 +02006057 .print = print_termios,
bellard31e31b82003-02-18 22:55:36 +00006058};
6059
bellard5286db72003-06-05 00:57:30 +00006060static bitmask_transtbl mmap_flags_tbl[] = {
Helge Deller541e1692017-10-31 13:53:58 +01006061 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
6062 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
6063 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
6064 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS,
6065 MAP_ANONYMOUS, MAP_ANONYMOUS },
6066 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN,
6067 MAP_GROWSDOWN, MAP_GROWSDOWN },
6068 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE,
6069 MAP_DENYWRITE, MAP_DENYWRITE },
6070 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE,
6071 MAP_EXECUTABLE, MAP_EXECUTABLE },
6072 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
6073 { TARGET_MAP_NORESERVE, TARGET_MAP_NORESERVE,
6074 MAP_NORESERVE, MAP_NORESERVE },
6075 { TARGET_MAP_HUGETLB, TARGET_MAP_HUGETLB, MAP_HUGETLB, MAP_HUGETLB },
6076 /* MAP_STACK had been ignored by the kernel for quite some time.
6077 Recognize it for the target insofar as we do not want to pass
6078 it through to the host. */
6079 { TARGET_MAP_STACK, TARGET_MAP_STACK, 0, 0 },
6080 { 0, 0, 0, 0 }
bellard5286db72003-06-05 00:57:30 +00006081};
6082
Laurent Vivier9d12f792020-03-10 11:33:55 +01006083/*
6084 * NOTE: TARGET_ABI32 is defined for TARGET_I386 (but not for TARGET_X86_64)
6085 * TARGET_I386 is defined if TARGET_X86_64 is defined
6086 */
bellard2ab83ea2003-06-15 19:56:46 +00006087#if defined(TARGET_I386)
bellard6dbad632003-03-16 18:05:05 +00006088
6089/* NOTE: there is really one LDT for all the threads */
blueswir1b1d8e522008-10-26 13:43:07 +00006090static uint8_t *ldt_table;
bellard6dbad632003-03-16 18:05:05 +00006091
bellard03acab62007-11-11 14:57:14 +00006092static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00006093{
6094 int size;
pbrook53a59602006-03-25 19:31:22 +00006095 void *p;
bellard6dbad632003-03-16 18:05:05 +00006096
6097 if (!ldt_table)
6098 return 0;
6099 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
6100 if (size > bytecount)
6101 size = bytecount;
bellard579a97f2007-11-11 14:26:47 +00006102 p = lock_user(VERIFY_WRITE, ptr, size, 0);
6103 if (!p)
bellard03acab62007-11-11 14:57:14 +00006104 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00006105 /* ??? Should this by byteswapped? */
pbrook53a59602006-03-25 19:31:22 +00006106 memcpy(p, ldt_table, size);
6107 unlock_user(p, ptr, size);
bellard6dbad632003-03-16 18:05:05 +00006108 return size;
6109}
6110
6111/* XXX: add locking support */
bellard03acab62007-11-11 14:57:14 +00006112static abi_long write_ldt(CPUX86State *env,
6113 abi_ulong ptr, unsigned long bytecount, int oldmode)
bellard6dbad632003-03-16 18:05:05 +00006114{
6115 struct target_modify_ldt_ldt_s ldt_info;
pbrook53a59602006-03-25 19:31:22 +00006116 struct target_modify_ldt_ldt_s *target_ldt_info;
bellard6dbad632003-03-16 18:05:05 +00006117 int seg_32bit, contents, read_exec_only, limit_in_pages;
bellard8d18e892007-11-14 15:18:40 +00006118 int seg_not_present, useable, lm;
bellard6dbad632003-03-16 18:05:05 +00006119 uint32_t *lp, entry_1, entry_2;
6120
6121 if (bytecount != sizeof(ldt_info))
bellard03acab62007-11-11 14:57:14 +00006122 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +00006123 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
bellard03acab62007-11-11 14:57:14 +00006124 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00006125 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02006126 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
pbrook53a59602006-03-25 19:31:22 +00006127 ldt_info.limit = tswap32(target_ldt_info->limit);
6128 ldt_info.flags = tswap32(target_ldt_info->flags);
6129 unlock_user_struct(target_ldt_info, ptr, 0);
ths3b46e622007-09-17 08:09:54 +00006130
bellard6dbad632003-03-16 18:05:05 +00006131 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
bellard03acab62007-11-11 14:57:14 +00006132 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00006133 seg_32bit = ldt_info.flags & 1;
6134 contents = (ldt_info.flags >> 1) & 3;
6135 read_exec_only = (ldt_info.flags >> 3) & 1;
6136 limit_in_pages = (ldt_info.flags >> 4) & 1;
6137 seg_not_present = (ldt_info.flags >> 5) & 1;
6138 useable = (ldt_info.flags >> 6) & 1;
bellard8d18e892007-11-14 15:18:40 +00006139#ifdef TARGET_ABI32
6140 lm = 0;
6141#else
6142 lm = (ldt_info.flags >> 7) & 1;
6143#endif
bellard6dbad632003-03-16 18:05:05 +00006144 if (contents == 3) {
6145 if (oldmode)
bellard03acab62007-11-11 14:57:14 +00006146 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00006147 if (seg_not_present == 0)
bellard03acab62007-11-11 14:57:14 +00006148 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00006149 }
6150 /* allocate the LDT */
6151 if (!ldt_table) {
balroge4415702008-11-10 02:55:33 +00006152 env->ldt.base = target_mmap(0,
6153 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
6154 PROT_READ|PROT_WRITE,
6155 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
6156 if (env->ldt.base == -1)
bellard03acab62007-11-11 14:57:14 +00006157 return -TARGET_ENOMEM;
Richard Henderson3e8f1622021-02-12 10:48:43 -08006158 memset(g2h_untagged(env->ldt.base), 0,
balroge4415702008-11-10 02:55:33 +00006159 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
bellard6dbad632003-03-16 18:05:05 +00006160 env->ldt.limit = 0xffff;
Richard Henderson3e8f1622021-02-12 10:48:43 -08006161 ldt_table = g2h_untagged(env->ldt.base);
bellard6dbad632003-03-16 18:05:05 +00006162 }
6163
6164 /* NOTE: same code as Linux kernel */
6165 /* Allow LDTs to be cleared by the user. */
6166 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
6167 if (oldmode ||
6168 (contents == 0 &&
6169 read_exec_only == 1 &&
6170 seg_32bit == 0 &&
6171 limit_in_pages == 0 &&
6172 seg_not_present == 1 &&
6173 useable == 0 )) {
6174 entry_1 = 0;
6175 entry_2 = 0;
6176 goto install;
6177 }
6178 }
ths3b46e622007-09-17 08:09:54 +00006179
bellard6dbad632003-03-16 18:05:05 +00006180 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
6181 (ldt_info.limit & 0x0ffff);
6182 entry_2 = (ldt_info.base_addr & 0xff000000) |
6183 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
6184 (ldt_info.limit & 0xf0000) |
6185 ((read_exec_only ^ 1) << 9) |
6186 (contents << 10) |
6187 ((seg_not_present ^ 1) << 15) |
6188 (seg_32bit << 22) |
6189 (limit_in_pages << 23) |
bellard8d18e892007-11-14 15:18:40 +00006190 (lm << 21) |
bellard6dbad632003-03-16 18:05:05 +00006191 0x7000;
6192 if (!oldmode)
6193 entry_2 |= (useable << 20);
bellard14ae3ba2003-05-27 23:25:06 +00006194
bellard6dbad632003-03-16 18:05:05 +00006195 /* Install the new entry ... */
6196install:
6197 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
6198 lp[0] = tswap32(entry_1);
6199 lp[1] = tswap32(entry_2);
6200 return 0;
6201}
6202
6203/* specific and weird i386 syscalls */
blueswir18fcd3692008-08-17 20:26:25 +00006204static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
6205 unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00006206{
bellard03acab62007-11-11 14:57:14 +00006207 abi_long ret;
ths3b46e622007-09-17 08:09:54 +00006208
bellard6dbad632003-03-16 18:05:05 +00006209 switch (func) {
6210 case 0:
6211 ret = read_ldt(ptr, bytecount);
6212 break;
6213 case 1:
6214 ret = write_ldt(env, ptr, bytecount, 1);
6215 break;
6216 case 0x11:
6217 ret = write_ldt(env, ptr, bytecount, 0);
6218 break;
bellard03acab62007-11-11 14:57:14 +00006219 default:
6220 ret = -TARGET_ENOSYS;
6221 break;
bellard6dbad632003-03-16 18:05:05 +00006222 }
6223 return ret;
6224}
bellard1b6b0292003-03-22 17:31:38 +00006225
Laurent Vivier9d12f792020-03-10 11:33:55 +01006226#if defined(TARGET_ABI32)
Alexander Grafbc22eb42013-07-16 18:44:58 +01006227abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00006228{
Richard Henderson3e8f1622021-02-12 10:48:43 -08006229 uint64_t *gdt_table = g2h_untagged(env->gdt.base);
bellard8d18e892007-11-14 15:18:40 +00006230 struct target_modify_ldt_ldt_s ldt_info;
6231 struct target_modify_ldt_ldt_s *target_ldt_info;
6232 int seg_32bit, contents, read_exec_only, limit_in_pages;
6233 int seg_not_present, useable, lm;
6234 uint32_t *lp, entry_1, entry_2;
6235 int i;
6236
6237 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
6238 if (!target_ldt_info)
6239 return -TARGET_EFAULT;
6240 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02006241 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
bellard8d18e892007-11-14 15:18:40 +00006242 ldt_info.limit = tswap32(target_ldt_info->limit);
6243 ldt_info.flags = tswap32(target_ldt_info->flags);
6244 if (ldt_info.entry_number == -1) {
6245 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
6246 if (gdt_table[i] == 0) {
6247 ldt_info.entry_number = i;
6248 target_ldt_info->entry_number = tswap32(i);
6249 break;
6250 }
6251 }
6252 }
6253 unlock_user_struct(target_ldt_info, ptr, 1);
6254
6255 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
6256 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
6257 return -TARGET_EINVAL;
6258 seg_32bit = ldt_info.flags & 1;
6259 contents = (ldt_info.flags >> 1) & 3;
6260 read_exec_only = (ldt_info.flags >> 3) & 1;
6261 limit_in_pages = (ldt_info.flags >> 4) & 1;
6262 seg_not_present = (ldt_info.flags >> 5) & 1;
6263 useable = (ldt_info.flags >> 6) & 1;
6264#ifdef TARGET_ABI32
6265 lm = 0;
6266#else
6267 lm = (ldt_info.flags >> 7) & 1;
6268#endif
6269
6270 if (contents == 3) {
6271 if (seg_not_present == 0)
6272 return -TARGET_EINVAL;
6273 }
6274
6275 /* NOTE: same code as Linux kernel */
6276 /* Allow LDTs to be cleared by the user. */
6277 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
6278 if ((contents == 0 &&
6279 read_exec_only == 1 &&
6280 seg_32bit == 0 &&
6281 limit_in_pages == 0 &&
6282 seg_not_present == 1 &&
6283 useable == 0 )) {
6284 entry_1 = 0;
6285 entry_2 = 0;
6286 goto install;
6287 }
6288 }
6289
6290 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
6291 (ldt_info.limit & 0x0ffff);
6292 entry_2 = (ldt_info.base_addr & 0xff000000) |
6293 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
6294 (ldt_info.limit & 0xf0000) |
6295 ((read_exec_only ^ 1) << 9) |
6296 (contents << 10) |
6297 ((seg_not_present ^ 1) << 15) |
6298 (seg_32bit << 22) |
6299 (limit_in_pages << 23) |
6300 (useable << 20) |
6301 (lm << 21) |
6302 0x7000;
6303
6304 /* Install the new entry ... */
6305install:
6306 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
6307 lp[0] = tswap32(entry_1);
6308 lp[1] = tswap32(entry_2);
6309 return 0;
6310}
6311
blueswir18fcd3692008-08-17 20:26:25 +00006312static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00006313{
6314 struct target_modify_ldt_ldt_s *target_ldt_info;
Richard Henderson3e8f1622021-02-12 10:48:43 -08006315 uint64_t *gdt_table = g2h_untagged(env->gdt.base);
bellard8d18e892007-11-14 15:18:40 +00006316 uint32_t base_addr, limit, flags;
6317 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
6318 int seg_not_present, useable, lm;
6319 uint32_t *lp, entry_1, entry_2;
6320
6321 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
6322 if (!target_ldt_info)
6323 return -TARGET_EFAULT;
6324 idx = tswap32(target_ldt_info->entry_number);
6325 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
6326 idx > TARGET_GDT_ENTRY_TLS_MAX) {
6327 unlock_user_struct(target_ldt_info, ptr, 1);
6328 return -TARGET_EINVAL;
6329 }
6330 lp = (uint32_t *)(gdt_table + idx);
6331 entry_1 = tswap32(lp[0]);
6332 entry_2 = tswap32(lp[1]);
6333
6334 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
6335 contents = (entry_2 >> 10) & 3;
6336 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
6337 seg_32bit = (entry_2 >> 22) & 1;
6338 limit_in_pages = (entry_2 >> 23) & 1;
6339 useable = (entry_2 >> 20) & 1;
6340#ifdef TARGET_ABI32
6341 lm = 0;
6342#else
6343 lm = (entry_2 >> 21) & 1;
6344#endif
6345 flags = (seg_32bit << 0) | (contents << 1) |
6346 (read_exec_only << 3) | (limit_in_pages << 4) |
6347 (seg_not_present << 5) | (useable << 6) | (lm << 7);
6348 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
6349 base_addr = (entry_1 >> 16) |
6350 (entry_2 & 0xff000000) |
6351 ((entry_2 & 0xff) << 16);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02006352 target_ldt_info->base_addr = tswapal(base_addr);
bellard8d18e892007-11-14 15:18:40 +00006353 target_ldt_info->limit = tswap32(limit);
6354 target_ldt_info->flags = tswap32(flags);
6355 unlock_user_struct(target_ldt_info, ptr, 1);
6356 return 0;
6357}
6358
Laurent Vivier9d12f792020-03-10 11:33:55 +01006359abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
6360{
Helge Deller538fabc2020-04-25 00:00:33 +02006361 return -TARGET_ENOSYS;
Laurent Vivier9d12f792020-03-10 11:33:55 +01006362}
6363#else
Peter Maydell2667e712013-07-16 18:44:59 +01006364abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
bellardd2fd1af2007-11-14 18:08:56 +00006365{
Juan Quintela1add8692011-06-16 17:37:09 +01006366 abi_long ret = 0;
bellardd2fd1af2007-11-14 18:08:56 +00006367 abi_ulong val;
6368 int idx;
Juan Quintela1add8692011-06-16 17:37:09 +01006369
bellardd2fd1af2007-11-14 18:08:56 +00006370 switch(code) {
6371 case TARGET_ARCH_SET_GS:
6372 case TARGET_ARCH_SET_FS:
6373 if (code == TARGET_ARCH_SET_GS)
6374 idx = R_GS;
6375 else
6376 idx = R_FS;
6377 cpu_x86_load_seg(env, idx, 0);
6378 env->segs[idx].base = addr;
6379 break;
6380 case TARGET_ARCH_GET_GS:
6381 case TARGET_ARCH_GET_FS:
6382 if (code == TARGET_ARCH_GET_GS)
6383 idx = R_GS;
6384 else
6385 idx = R_FS;
6386 val = env->segs[idx].base;
6387 if (put_user(val, addr, abi_ulong))
Juan Quintela1add8692011-06-16 17:37:09 +01006388 ret = -TARGET_EFAULT;
bellardd2fd1af2007-11-14 18:08:56 +00006389 break;
6390 default:
6391 ret = -TARGET_EINVAL;
6392 break;
6393 }
Juan Quintela1add8692011-06-16 17:37:09 +01006394 return ret;
bellardd2fd1af2007-11-14 18:08:56 +00006395}
Laurent Vivier9d12f792020-03-10 11:33:55 +01006396#endif /* defined(TARGET_ABI32 */
bellardd2fd1af2007-11-14 18:08:56 +00006397
bellard2ab83ea2003-06-15 19:56:46 +00006398#endif /* defined(TARGET_I386) */
6399
Riku Voipio05098a92011-03-04 15:27:29 +02006400#define NEW_STACK_SIZE 0x40000
pbrookd865bab2008-06-07 22:12:17 +00006401
pbrookd865bab2008-06-07 22:12:17 +00006402
6403static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
6404typedef struct {
Andreas Färber9349b4f2012-03-14 01:38:32 +01006405 CPUArchState *env;
pbrookd865bab2008-06-07 22:12:17 +00006406 pthread_mutex_t mutex;
6407 pthread_cond_t cond;
6408 pthread_t thread;
6409 uint32_t tid;
6410 abi_ulong child_tidptr;
6411 abi_ulong parent_tidptr;
6412 sigset_t sigmask;
6413} new_thread_info;
6414
6415static void *clone_func(void *arg)
6416{
6417 new_thread_info *info = arg;
Andreas Färber9349b4f2012-03-14 01:38:32 +01006418 CPUArchState *env;
Andreas Färber0d342822012-12-17 07:12:13 +01006419 CPUState *cpu;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03006420 TaskState *ts;
pbrookd865bab2008-06-07 22:12:17 +00006421
Emilio G. Cota70903762015-08-23 20:23:41 -04006422 rcu_register_thread();
Emilio G. Cota3468b592017-07-19 18:57:58 -04006423 tcg_register_thread();
pbrookd865bab2008-06-07 22:12:17 +00006424 env = info->env;
Richard Henderson29a0af62019-03-22 16:07:18 -07006425 cpu = env_cpu(env);
Andreas Färbera2247f82013-06-09 19:47:04 +02006426 thread_cpu = cpu;
Andreas Färber0429a972013-08-26 18:14:44 +02006427 ts = (TaskState *)cpu->opaque;
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +00006428 info->tid = sys_gettid();
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03006429 task_settid(ts);
pbrookd865bab2008-06-07 22:12:17 +00006430 if (info->child_tidptr)
6431 put_user_u32(info->tid, info->child_tidptr);
6432 if (info->parent_tidptr)
6433 put_user_u32(info->tid, info->parent_tidptr);
Richard Henderson5ebdd772019-03-14 13:10:53 -07006434 qemu_guest_random_seed_thread_part2(cpu->random_seed);
pbrookd865bab2008-06-07 22:12:17 +00006435 /* Enable signals. */
6436 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
6437 /* Signal to the parent that we're ready. */
6438 pthread_mutex_lock(&info->mutex);
6439 pthread_cond_broadcast(&info->cond);
6440 pthread_mutex_unlock(&info->mutex);
Emilio G. Cotaa4dd3d52017-10-18 18:01:41 -04006441 /* Wait until the parent has finished initializing the tls state. */
pbrookd865bab2008-06-07 22:12:17 +00006442 pthread_mutex_lock(&clone_lock);
6443 pthread_mutex_unlock(&clone_lock);
6444 cpu_loop(env);
6445 /* never exits */
6446 return NULL;
6447}
bellard1b6b0292003-03-22 17:31:38 +00006448
ths0da46a62007-10-20 20:23:07 +00006449/* do_fork() Must return host values and target errnos (unlike most
6450 do_*() functions). */
Andreas Färber9349b4f2012-03-14 01:38:32 +01006451static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
pbrookd865bab2008-06-07 22:12:17 +00006452 abi_ulong parent_tidptr, target_ulong newtls,
6453 abi_ulong child_tidptr)
bellard1b6b0292003-03-22 17:31:38 +00006454{
Richard Henderson29a0af62019-03-22 16:07:18 -07006455 CPUState *cpu = env_cpu(env);
bellard1b6b0292003-03-22 17:31:38 +00006456 int ret;
bellard5cd43932003-03-29 16:54:36 +00006457 TaskState *ts;
Andreas Färber0429a972013-08-26 18:14:44 +02006458 CPUState *new_cpu;
Andreas Färber9349b4f2012-03-14 01:38:32 +01006459 CPUArchState *new_env;
pbrookd865bab2008-06-07 22:12:17 +00006460 sigset_t sigmask;
ths3b46e622007-09-17 08:09:54 +00006461
Peter Maydell5ea2fc82016-08-02 18:41:27 +01006462 flags &= ~CLONE_IGNORED_FLAGS;
6463
balrog436d1242008-09-21 02:39:45 +00006464 /* Emulate vfork() with fork() */
6465 if (flags & CLONE_VFORK)
6466 flags &= ~(CLONE_VFORK | CLONE_VM);
6467
bellard1b6b0292003-03-22 17:31:38 +00006468 if (flags & CLONE_VM) {
Andreas Färber0429a972013-08-26 18:14:44 +02006469 TaskState *parent_ts = (TaskState *)cpu->opaque;
pbrookd865bab2008-06-07 22:12:17 +00006470 new_thread_info info;
6471 pthread_attr_t attr;
Peter Maydell24cb36a2013-07-16 18:45:00 +01006472
Peter Maydell5ea2fc82016-08-02 18:41:27 +01006473 if (((flags & CLONE_THREAD_FLAGS) != CLONE_THREAD_FLAGS) ||
6474 (flags & CLONE_INVALID_THREAD_FLAGS)) {
6475 return -TARGET_EINVAL;
6476 }
6477
Markus Armbrusterc78d65e2015-09-14 13:53:03 +02006478 ts = g_new0(TaskState, 1);
pbrook624f7972008-05-31 16:11:38 +00006479 init_task_state(ts);
Max Filippov73a988d2018-03-30 06:19:58 -07006480
6481 /* Grab a mutex so that thread setup appears atomic. */
6482 pthread_mutex_lock(&clone_lock);
6483
bellard1b6b0292003-03-22 17:31:38 +00006484 /* we create a new CPU instance. */
thsc5be9f02007-02-28 20:20:53 +00006485 new_env = cpu_copy(env);
pbrook6e68e072008-05-30 17:22:15 +00006486 /* Init regs that differ from the parent. */
Richard Henderson608999d2019-11-06 12:33:15 +01006487 cpu_clone_regs_child(new_env, newsp, flags);
Richard Henderson07a6ecf2019-11-06 12:33:16 +01006488 cpu_clone_regs_parent(env, flags);
Richard Henderson29a0af62019-03-22 16:07:18 -07006489 new_cpu = env_cpu(new_env);
Andreas Färber0429a972013-08-26 18:14:44 +02006490 new_cpu->opaque = ts;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03006491 ts->bprm = parent_ts->bprm;
6492 ts->info = parent_ts->info;
Peter Maydell3d3efba2016-05-27 15:51:49 +01006493 ts->signal_mask = parent_ts->signal_mask;
pbrookd865bab2008-06-07 22:12:17 +00006494
Peter Maydell7cfbd382016-08-02 18:41:26 +01006495 if (flags & CLONE_CHILD_CLEARTID) {
pbrookc2764712009-03-07 15:24:59 +00006496 ts->child_tidptr = child_tidptr;
6497 }
6498
Peter Maydell7cfbd382016-08-02 18:41:26 +01006499 if (flags & CLONE_SETTLS) {
pbrookd865bab2008-06-07 22:12:17 +00006500 cpu_set_tls (new_env, newtls);
Peter Maydell7cfbd382016-08-02 18:41:26 +01006501 }
pbrookd865bab2008-06-07 22:12:17 +00006502
pbrookd865bab2008-06-07 22:12:17 +00006503 memset(&info, 0, sizeof(info));
6504 pthread_mutex_init(&info.mutex, NULL);
6505 pthread_mutex_lock(&info.mutex);
6506 pthread_cond_init(&info.cond, NULL);
6507 info.env = new_env;
Peter Maydell7cfbd382016-08-02 18:41:26 +01006508 if (flags & CLONE_CHILD_SETTID) {
pbrookd865bab2008-06-07 22:12:17 +00006509 info.child_tidptr = child_tidptr;
Peter Maydell7cfbd382016-08-02 18:41:26 +01006510 }
6511 if (flags & CLONE_PARENT_SETTID) {
pbrookd865bab2008-06-07 22:12:17 +00006512 info.parent_tidptr = parent_tidptr;
Peter Maydell7cfbd382016-08-02 18:41:26 +01006513 }
pbrookd865bab2008-06-07 22:12:17 +00006514
6515 ret = pthread_attr_init(&attr);
Nathan Froyd48e15fc2010-10-29 07:48:57 -07006516 ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE);
6517 ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pbrookd865bab2008-06-07 22:12:17 +00006518 /* It is not safe to deliver signals until the child has finished
6519 initializing, so temporarily block all signals. */
6520 sigfillset(&sigmask);
6521 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
Richard Henderson5ebdd772019-03-14 13:10:53 -07006522 cpu->random_seed = qemu_guest_random_seed_thread_part1();
pbrookd865bab2008-06-07 22:12:17 +00006523
Alex Bennéeb67cb682016-10-05 11:13:04 -07006524 /* If this is our first additional thread, we need to ensure we
6525 * generate code for parallel execution and flush old translations.
6526 */
6527 if (!parallel_cpus) {
6528 parallel_cpus = true;
6529 tb_flush(cpu);
6530 }
6531
pbrookd865bab2008-06-07 22:12:17 +00006532 ret = pthread_create(&info.thread, &attr, clone_func, &info);
pbrookc2764712009-03-07 15:24:59 +00006533 /* TODO: Free new CPU state if thread creation failed. */
pbrookd865bab2008-06-07 22:12:17 +00006534
6535 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
6536 pthread_attr_destroy(&attr);
6537 if (ret == 0) {
6538 /* Wait for the child to initialize. */
6539 pthread_cond_wait(&info.cond, &info.mutex);
6540 ret = info.tid;
pbrookd865bab2008-06-07 22:12:17 +00006541 } else {
6542 ret = -1;
6543 }
6544 pthread_mutex_unlock(&info.mutex);
6545 pthread_cond_destroy(&info.cond);
6546 pthread_mutex_destroy(&info.mutex);
6547 pthread_mutex_unlock(&clone_lock);
bellard1b6b0292003-03-22 17:31:38 +00006548 } else {
6549 /* if no CLONE_VM, we consider it is a fork */
Peter Maydell5ea2fc82016-08-02 18:41:27 +01006550 if (flags & CLONE_INVALID_FORK_FLAGS) {
6551 return -TARGET_EINVAL;
6552 }
6553
6554 /* We can't support custom termination signals */
6555 if ((flags & CSIGNAL) != TARGET_SIGCHLD) {
Timothy E Baldwin93b4eff2015-08-31 00:26:21 +01006556 return -TARGET_EINVAL;
6557 }
Timothy E Baldwin7d92d342016-05-27 15:51:58 +01006558
6559 if (block_signals()) {
6560 return -TARGET_ERESTARTSYS;
6561 }
6562
pbrookd865bab2008-06-07 22:12:17 +00006563 fork_start();
bellard1b6b0292003-03-22 17:31:38 +00006564 ret = fork();
pbrookd865bab2008-06-07 22:12:17 +00006565 if (ret == 0) {
aurel322b1319c2008-12-18 22:44:04 +00006566 /* Child Process. */
Richard Henderson608999d2019-11-06 12:33:15 +01006567 cpu_clone_regs_child(env, newsp, flags);
pbrookd865bab2008-06-07 22:12:17 +00006568 fork_end(1);
aurel322b1319c2008-12-18 22:44:04 +00006569 /* There is a race condition here. The parent process could
6570 theoretically read the TID in the child process before the child
6571 tid is set. This would require using either ptrace
6572 (not implemented) or having *_tidptr to point at a shared memory
6573 mapping. We can't repeat the spinlock hack used above because
6574 the child process gets its own copy of the lock. */
pbrookd865bab2008-06-07 22:12:17 +00006575 if (flags & CLONE_CHILD_SETTID)
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +00006576 put_user_u32(sys_gettid(), child_tidptr);
pbrookd865bab2008-06-07 22:12:17 +00006577 if (flags & CLONE_PARENT_SETTID)
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +00006578 put_user_u32(sys_gettid(), parent_tidptr);
Andreas Färber0429a972013-08-26 18:14:44 +02006579 ts = (TaskState *)cpu->opaque;
pbrookd865bab2008-06-07 22:12:17 +00006580 if (flags & CLONE_SETTLS)
6581 cpu_set_tls (env, newtls);
pbrookc2764712009-03-07 15:24:59 +00006582 if (flags & CLONE_CHILD_CLEARTID)
6583 ts->child_tidptr = child_tidptr;
pbrookd865bab2008-06-07 22:12:17 +00006584 } else {
Richard Henderson07a6ecf2019-11-06 12:33:16 +01006585 cpu_clone_regs_parent(env, flags);
pbrookd865bab2008-06-07 22:12:17 +00006586 fork_end(0);
6587 }
bellard1b6b0292003-03-22 17:31:38 +00006588 }
6589 return ret;
6590}
6591
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006592/* warning : doesn't handle linux specific flags... */
6593static int target_to_host_fcntl_cmd(int cmd)
6594{
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006595 int ret;
6596
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006597 switch(cmd) {
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006598 case TARGET_F_DUPFD:
6599 case TARGET_F_GETFD:
6600 case TARGET_F_SETFD:
6601 case TARGET_F_GETFL:
6602 case TARGET_F_SETFL:
Andreas Schwab2d92c682020-05-25 09:59:28 +02006603 case TARGET_F_OFD_GETLK:
6604 case TARGET_F_OFD_SETLK:
6605 case TARGET_F_OFD_SETLKW:
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006606 ret = cmd;
6607 break;
6608 case TARGET_F_GETLK:
6609 ret = F_GETLK64;
6610 break;
6611 case TARGET_F_SETLK:
6612 ret = F_SETLK64;
6613 break;
6614 case TARGET_F_SETLKW:
6615 ret = F_SETLKW64;
6616 break;
6617 case TARGET_F_GETOWN:
6618 ret = F_GETOWN;
6619 break;
6620 case TARGET_F_SETOWN:
6621 ret = F_SETOWN;
6622 break;
6623 case TARGET_F_GETSIG:
6624 ret = F_GETSIG;
6625 break;
6626 case TARGET_F_SETSIG:
6627 ret = F_SETSIG;
6628 break;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006629#if TARGET_ABI_BITS == 32
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006630 case TARGET_F_GETLK64:
6631 ret = F_GETLK64;
6632 break;
6633 case TARGET_F_SETLK64:
6634 ret = F_SETLK64;
6635 break;
6636 case TARGET_F_SETLKW64:
6637 ret = F_SETLKW64;
6638 break;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006639#endif
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006640 case TARGET_F_SETLEASE:
6641 ret = F_SETLEASE;
6642 break;
6643 case TARGET_F_GETLEASE:
6644 ret = F_GETLEASE;
6645 break;
malcfbd5de92009-09-06 06:31:59 +04006646#ifdef F_DUPFD_CLOEXEC
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006647 case TARGET_F_DUPFD_CLOEXEC:
6648 ret = F_DUPFD_CLOEXEC;
6649 break;
malcfbd5de92009-09-06 06:31:59 +04006650#endif
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006651 case TARGET_F_NOTIFY:
6652 ret = F_NOTIFY;
6653 break;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006654#ifdef F_GETOWN_EX
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006655 case TARGET_F_GETOWN_EX:
6656 ret = F_GETOWN_EX;
6657 break;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006658#endif
6659#ifdef F_SETOWN_EX
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006660 case TARGET_F_SETOWN_EX:
6661 ret = F_SETOWN_EX;
6662 break;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006663#endif
Peter Maydellddf31aa2016-06-30 17:33:49 +01006664#ifdef F_SETPIPE_SZ
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006665 case TARGET_F_SETPIPE_SZ:
6666 ret = F_SETPIPE_SZ;
6667 break;
6668 case TARGET_F_GETPIPE_SZ:
6669 ret = F_GETPIPE_SZ;
6670 break;
Peter Maydellddf31aa2016-06-30 17:33:49 +01006671#endif
Shu-Chun Weng2bb963f2020-12-18 11:32:10 -08006672#ifdef F_ADD_SEALS
6673 case TARGET_F_ADD_SEALS:
6674 ret = F_ADD_SEALS;
6675 break;
6676 case TARGET_F_GET_SEALS:
6677 ret = F_GET_SEALS;
6678 break;
6679#endif
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006680 default:
6681 ret = -TARGET_EINVAL;
6682 break;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006683 }
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006684
6685#if defined(__powerpc64__)
6686 /* On PPC64, glibc headers has the F_*LK* defined to 12, 13 and 14 and
6687 * is not supported by kernel. The glibc fcntl call actually adjusts
6688 * them to 5, 6 and 7 before making the syscall(). Since we make the
6689 * syscall directly, adjust to what is supported by the kernel.
6690 */
6691 if (ret >= F_GETLK64 && ret <= F_SETLKW64) {
6692 ret -= F_GETLK64 - 5;
6693 }
6694#endif
6695
6696 return ret;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006697}
6698
Laurent Vivierae68ad92018-05-10 01:11:21 +02006699#define FLOCK_TRANSTBL \
6700 switch (type) { \
6701 TRANSTBL_CONVERT(F_RDLCK); \
6702 TRANSTBL_CONVERT(F_WRLCK); \
6703 TRANSTBL_CONVERT(F_UNLCK); \
Laurent Vivierae68ad92018-05-10 01:11:21 +02006704 }
6705
6706static int target_to_host_flock(int type)
6707{
6708#define TRANSTBL_CONVERT(a) case TARGET_##a: return a
6709 FLOCK_TRANSTBL
6710#undef TRANSTBL_CONVERT
6711 return -TARGET_EINVAL;
6712}
6713
6714static int host_to_target_flock(int type)
6715{
6716#define TRANSTBL_CONVERT(a) case a: return TARGET_##a
6717 FLOCK_TRANSTBL
6718#undef TRANSTBL_CONVERT
6719 /* if we don't know how to convert the value coming
6720 * from the host we copy to the target field as-is
6721 */
6722 return type;
6723}
Laurent Vivier2ba7f732013-01-10 21:42:48 +01006724
Peter Maydell213d3e92016-06-13 11:22:05 +01006725static inline abi_long copy_from_user_flock(struct flock64 *fl,
6726 abi_ulong target_flock_addr)
6727{
6728 struct target_flock *target_fl;
Laurent Vivierae68ad92018-05-10 01:11:21 +02006729 int l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006730
6731 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
6732 return -TARGET_EFAULT;
6733 }
6734
6735 __get_user(l_type, &target_fl->l_type);
Laurent Vivierae68ad92018-05-10 01:11:21 +02006736 l_type = target_to_host_flock(l_type);
6737 if (l_type < 0) {
6738 return l_type;
6739 }
6740 fl->l_type = l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006741 __get_user(fl->l_whence, &target_fl->l_whence);
6742 __get_user(fl->l_start, &target_fl->l_start);
6743 __get_user(fl->l_len, &target_fl->l_len);
6744 __get_user(fl->l_pid, &target_fl->l_pid);
6745 unlock_user_struct(target_fl, target_flock_addr, 0);
6746 return 0;
6747}
6748
6749static inline abi_long copy_to_user_flock(abi_ulong target_flock_addr,
6750 const struct flock64 *fl)
6751{
6752 struct target_flock *target_fl;
6753 short l_type;
6754
6755 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
6756 return -TARGET_EFAULT;
6757 }
6758
Laurent Vivierae68ad92018-05-10 01:11:21 +02006759 l_type = host_to_target_flock(fl->l_type);
Peter Maydell213d3e92016-06-13 11:22:05 +01006760 __put_user(l_type, &target_fl->l_type);
6761 __put_user(fl->l_whence, &target_fl->l_whence);
6762 __put_user(fl->l_start, &target_fl->l_start);
6763 __put_user(fl->l_len, &target_fl->l_len);
6764 __put_user(fl->l_pid, &target_fl->l_pid);
6765 unlock_user_struct(target_fl, target_flock_addr, 1);
6766 return 0;
6767}
6768
6769typedef abi_long from_flock64_fn(struct flock64 *fl, abi_ulong target_addr);
6770typedef abi_long to_flock64_fn(abi_ulong target_addr, const struct flock64 *fl);
6771
6772#if defined(TARGET_ARM) && TARGET_ABI_BITS == 32
Laurent Vivier7f254c52018-05-02 23:57:30 +02006773static inline abi_long copy_from_user_oabi_flock64(struct flock64 *fl,
Peter Maydell213d3e92016-06-13 11:22:05 +01006774 abi_ulong target_flock_addr)
6775{
Laurent Vivier7f254c52018-05-02 23:57:30 +02006776 struct target_oabi_flock64 *target_fl;
Laurent Vivierae68ad92018-05-10 01:11:21 +02006777 int l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006778
6779 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
6780 return -TARGET_EFAULT;
6781 }
6782
6783 __get_user(l_type, &target_fl->l_type);
Laurent Vivierae68ad92018-05-10 01:11:21 +02006784 l_type = target_to_host_flock(l_type);
6785 if (l_type < 0) {
6786 return l_type;
6787 }
6788 fl->l_type = l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006789 __get_user(fl->l_whence, &target_fl->l_whence);
6790 __get_user(fl->l_start, &target_fl->l_start);
6791 __get_user(fl->l_len, &target_fl->l_len);
6792 __get_user(fl->l_pid, &target_fl->l_pid);
6793 unlock_user_struct(target_fl, target_flock_addr, 0);
6794 return 0;
6795}
6796
Laurent Vivier7f254c52018-05-02 23:57:30 +02006797static inline abi_long copy_to_user_oabi_flock64(abi_ulong target_flock_addr,
Peter Maydell213d3e92016-06-13 11:22:05 +01006798 const struct flock64 *fl)
6799{
Laurent Vivier7f254c52018-05-02 23:57:30 +02006800 struct target_oabi_flock64 *target_fl;
Peter Maydell213d3e92016-06-13 11:22:05 +01006801 short l_type;
6802
6803 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
6804 return -TARGET_EFAULT;
6805 }
6806
Laurent Vivierae68ad92018-05-10 01:11:21 +02006807 l_type = host_to_target_flock(fl->l_type);
Peter Maydell213d3e92016-06-13 11:22:05 +01006808 __put_user(l_type, &target_fl->l_type);
6809 __put_user(fl->l_whence, &target_fl->l_whence);
6810 __put_user(fl->l_start, &target_fl->l_start);
6811 __put_user(fl->l_len, &target_fl->l_len);
6812 __put_user(fl->l_pid, &target_fl->l_pid);
6813 unlock_user_struct(target_fl, target_flock_addr, 1);
6814 return 0;
6815}
6816#endif
6817
6818static inline abi_long copy_from_user_flock64(struct flock64 *fl,
6819 abi_ulong target_flock_addr)
6820{
6821 struct target_flock64 *target_fl;
Laurent Vivierae68ad92018-05-10 01:11:21 +02006822 int l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006823
6824 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
6825 return -TARGET_EFAULT;
6826 }
6827
6828 __get_user(l_type, &target_fl->l_type);
Laurent Vivierae68ad92018-05-10 01:11:21 +02006829 l_type = target_to_host_flock(l_type);
6830 if (l_type < 0) {
6831 return l_type;
6832 }
6833 fl->l_type = l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006834 __get_user(fl->l_whence, &target_fl->l_whence);
6835 __get_user(fl->l_start, &target_fl->l_start);
6836 __get_user(fl->l_len, &target_fl->l_len);
6837 __get_user(fl->l_pid, &target_fl->l_pid);
6838 unlock_user_struct(target_fl, target_flock_addr, 0);
6839 return 0;
6840}
6841
6842static inline abi_long copy_to_user_flock64(abi_ulong target_flock_addr,
6843 const struct flock64 *fl)
6844{
6845 struct target_flock64 *target_fl;
6846 short l_type;
6847
6848 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
6849 return -TARGET_EFAULT;
6850 }
6851
Laurent Vivierae68ad92018-05-10 01:11:21 +02006852 l_type = host_to_target_flock(fl->l_type);
Peter Maydell213d3e92016-06-13 11:22:05 +01006853 __put_user(l_type, &target_fl->l_type);
6854 __put_user(fl->l_whence, &target_fl->l_whence);
6855 __put_user(fl->l_start, &target_fl->l_start);
6856 __put_user(fl->l_len, &target_fl->l_len);
6857 __put_user(fl->l_pid, &target_fl->l_pid);
6858 unlock_user_struct(target_fl, target_flock_addr, 1);
6859 return 0;
6860}
6861
blueswir1992f48a2007-10-14 16:27:31 +00006862static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
bellard7775e9e2003-05-14 22:46:48 +00006863{
ths43f238d2007-01-05 20:55:49 +00006864 struct flock64 fl64;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006865#ifdef F_GETOWN_EX
6866 struct f_owner_ex fox;
6867 struct target_f_owner_ex *target_fox;
6868#endif
blueswir1992f48a2007-10-14 16:27:31 +00006869 abi_long ret;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006870 int host_cmd = target_to_host_fcntl_cmd(cmd);
6871
6872 if (host_cmd == -TARGET_EINVAL)
6873 return host_cmd;
pbrook53a59602006-03-25 19:31:22 +00006874
bellard7775e9e2003-05-14 22:46:48 +00006875 switch(cmd) {
6876 case TARGET_F_GETLK:
Peter Maydell213d3e92016-06-13 11:22:05 +01006877 ret = copy_from_user_flock(&fl64, arg);
6878 if (ret) {
6879 return ret;
6880 }
Peter Maydell435da5e2016-06-13 11:22:05 +01006881 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00006882 if (ret == 0) {
Peter Maydell213d3e92016-06-13 11:22:05 +01006883 ret = copy_to_user_flock(arg, &fl64);
bellard7775e9e2003-05-14 22:46:48 +00006884 }
6885 break;
ths3b46e622007-09-17 08:09:54 +00006886
bellard7775e9e2003-05-14 22:46:48 +00006887 case TARGET_F_SETLK:
6888 case TARGET_F_SETLKW:
Peter Maydell213d3e92016-06-13 11:22:05 +01006889 ret = copy_from_user_flock(&fl64, arg);
6890 if (ret) {
6891 return ret;
6892 }
Peter Maydell435da5e2016-06-13 11:22:05 +01006893 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00006894 break;
ths3b46e622007-09-17 08:09:54 +00006895
bellard7775e9e2003-05-14 22:46:48 +00006896 case TARGET_F_GETLK64:
Andreas Schwab2d92c682020-05-25 09:59:28 +02006897 case TARGET_F_OFD_GETLK:
Peter Maydell213d3e92016-06-13 11:22:05 +01006898 ret = copy_from_user_flock64(&fl64, arg);
6899 if (ret) {
6900 return ret;
6901 }
Peter Maydell435da5e2016-06-13 11:22:05 +01006902 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
ths43f238d2007-01-05 20:55:49 +00006903 if (ret == 0) {
Peter Maydell213d3e92016-06-13 11:22:05 +01006904 ret = copy_to_user_flock64(arg, &fl64);
ths43f238d2007-01-05 20:55:49 +00006905 }
bellard9ee1fa22007-11-11 15:11:19 +00006906 break;
bellard7775e9e2003-05-14 22:46:48 +00006907 case TARGET_F_SETLK64:
6908 case TARGET_F_SETLKW64:
Andreas Schwab2d92c682020-05-25 09:59:28 +02006909 case TARGET_F_OFD_SETLK:
6910 case TARGET_F_OFD_SETLKW:
Peter Maydell213d3e92016-06-13 11:22:05 +01006911 ret = copy_from_user_flock64(&fl64, arg);
6912 if (ret) {
6913 return ret;
6914 }
Peter Maydell435da5e2016-06-13 11:22:05 +01006915 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00006916 break;
6917
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006918 case TARGET_F_GETFL:
Peter Maydell435da5e2016-06-13 11:22:05 +01006919 ret = get_errno(safe_fcntl(fd, host_cmd, arg));
bellard9ee1fa22007-11-11 15:11:19 +00006920 if (ret >= 0) {
6921 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
6922 }
bellardffa65c32004-01-04 23:57:22 +00006923 break;
6924
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006925 case TARGET_F_SETFL:
Peter Maydell435da5e2016-06-13 11:22:05 +01006926 ret = get_errno(safe_fcntl(fd, host_cmd,
6927 target_to_host_bitmask(arg,
6928 fcntl_flags_tbl)));
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006929 break;
6930
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006931#ifdef F_GETOWN_EX
6932 case TARGET_F_GETOWN_EX:
Peter Maydell435da5e2016-06-13 11:22:05 +01006933 ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006934 if (ret >= 0) {
6935 if (!lock_user_struct(VERIFY_WRITE, target_fox, arg, 0))
6936 return -TARGET_EFAULT;
6937 target_fox->type = tswap32(fox.type);
6938 target_fox->pid = tswap32(fox.pid);
6939 unlock_user_struct(target_fox, arg, 1);
6940 }
6941 break;
6942#endif
6943
6944#ifdef F_SETOWN_EX
6945 case TARGET_F_SETOWN_EX:
6946 if (!lock_user_struct(VERIFY_READ, target_fox, arg, 1))
6947 return -TARGET_EFAULT;
6948 fox.type = tswap32(target_fox->type);
6949 fox.pid = tswap32(target_fox->pid);
6950 unlock_user_struct(target_fox, arg, 0);
Peter Maydell435da5e2016-06-13 11:22:05 +01006951 ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006952 break;
6953#endif
6954
Timothy Baldwina7b4c9b2020-07-29 21:06:44 +01006955 case TARGET_F_SETSIG:
6956 ret = get_errno(safe_fcntl(fd, host_cmd, target_to_host_signal(arg)));
6957 break;
6958
6959 case TARGET_F_GETSIG:
6960 ret = host_to_target_signal(get_errno(safe_fcntl(fd, host_cmd, arg)));
6961 break;
6962
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006963 case TARGET_F_SETOWN:
6964 case TARGET_F_GETOWN:
Ulrich Hecht7e22e542009-07-24 19:10:27 +02006965 case TARGET_F_SETLEASE:
6966 case TARGET_F_GETLEASE:
Peter Maydell7e3b92e2016-06-20 15:50:37 +01006967 case TARGET_F_SETPIPE_SZ:
6968 case TARGET_F_GETPIPE_SZ:
Shu-Chun Weng2bb963f2020-12-18 11:32:10 -08006969 case TARGET_F_ADD_SEALS:
6970 case TARGET_F_GET_SEALS:
Peter Maydell435da5e2016-06-13 11:22:05 +01006971 ret = get_errno(safe_fcntl(fd, host_cmd, arg));
bellardffa65c32004-01-04 23:57:22 +00006972 break;
6973
bellard7775e9e2003-05-14 22:46:48 +00006974 default:
Peter Maydell435da5e2016-06-13 11:22:05 +01006975 ret = get_errno(safe_fcntl(fd, cmd, arg));
bellard7775e9e2003-05-14 22:46:48 +00006976 break;
6977 }
6978 return ret;
6979}
6980
bellard67867302003-11-23 17:05:30 +00006981#ifdef USE_UID16
bellard7775e9e2003-05-14 22:46:48 +00006982
bellard67867302003-11-23 17:05:30 +00006983static inline int high2lowuid(int uid)
6984{
6985 if (uid > 65535)
6986 return 65534;
6987 else
6988 return uid;
6989}
6990
6991static inline int high2lowgid(int gid)
6992{
6993 if (gid > 65535)
6994 return 65534;
6995 else
6996 return gid;
6997}
6998
6999static inline int low2highuid(int uid)
7000{
7001 if ((int16_t)uid == -1)
7002 return -1;
7003 else
7004 return uid;
7005}
7006
7007static inline int low2highgid(int gid)
7008{
7009 if ((int16_t)gid == -1)
7010 return -1;
7011 else
7012 return gid;
7013}
Riku Voipio0c866a72011-04-18 15:23:06 +03007014static inline int tswapid(int id)
7015{
7016 return tswap16(id);
7017}
Peter Maydell76ca3102014-03-02 19:36:41 +00007018
7019#define put_user_id(x, gaddr) put_user_u16(x, gaddr)
7020
Riku Voipio0c866a72011-04-18 15:23:06 +03007021#else /* !USE_UID16 */
7022static inline int high2lowuid(int uid)
7023{
7024 return uid;
7025}
7026static inline int high2lowgid(int gid)
7027{
7028 return gid;
7029}
7030static inline int low2highuid(int uid)
7031{
7032 return uid;
7033}
7034static inline int low2highgid(int gid)
7035{
7036 return gid;
7037}
7038static inline int tswapid(int id)
7039{
7040 return tswap32(id);
7041}
Peter Maydell76ca3102014-03-02 19:36:41 +00007042
7043#define put_user_id(x, gaddr) put_user_u32(x, gaddr)
7044
bellard67867302003-11-23 17:05:30 +00007045#endif /* USE_UID16 */
bellard1b6b0292003-03-22 17:31:38 +00007046
Peter Maydellfd6f7792016-03-01 16:33:02 +00007047/* We must do direct syscalls for setting UID/GID, because we want to
7048 * implement the Linux system call semantics of "change only for this thread",
7049 * not the libc/POSIX semantics of "change for all threads in process".
7050 * (See http://ewontfix.com/17/ for more details.)
7051 * We use the 32-bit version of the syscalls if present; if it is not
7052 * then either the host architecture supports 32-bit UIDs natively with
7053 * the standard syscall, or the 16-bit UID is the best we can do.
7054 */
7055#ifdef __NR_setuid32
7056#define __NR_sys_setuid __NR_setuid32
7057#else
7058#define __NR_sys_setuid __NR_setuid
7059#endif
7060#ifdef __NR_setgid32
7061#define __NR_sys_setgid __NR_setgid32
7062#else
7063#define __NR_sys_setgid __NR_setgid
7064#endif
7065#ifdef __NR_setresuid32
7066#define __NR_sys_setresuid __NR_setresuid32
7067#else
7068#define __NR_sys_setresuid __NR_setresuid
7069#endif
7070#ifdef __NR_setresgid32
7071#define __NR_sys_setresgid __NR_setresgid32
7072#else
7073#define __NR_sys_setresgid __NR_setresgid
7074#endif
7075
7076_syscall1(int, sys_setuid, uid_t, uid)
7077_syscall1(int, sys_setgid, gid_t, gid)
7078_syscall3(int, sys_setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
7079_syscall3(int, sys_setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
7080
bellard31e31b82003-02-18 22:55:36 +00007081void syscall_init(void)
7082{
bellard2ab83ea2003-06-15 19:56:46 +00007083 IOCTLEntry *ie;
7084 const argtype *arg_type;
7085 int size;
thsb92c47c2007-11-01 00:07:38 +00007086 int i;
bellard2ab83ea2003-06-15 19:56:46 +00007087
Alexander Graf8be656b2015-05-06 23:47:32 +02007088 thunk_init(STRUCT_MAX);
7089
Blue Swirl001faf32009-05-13 17:53:17 +00007090#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
ths5fafdf22007-09-16 21:08:06 +00007091#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
bellard31e31b82003-02-18 22:55:36 +00007092#include "syscall_types.h"
7093#undef STRUCT
7094#undef STRUCT_SPECIAL
bellard2ab83ea2003-06-15 19:56:46 +00007095
Peter Maydelldd6e9572012-07-23 08:07:22 +00007096 /* Build target_to_host_errno_table[] table from
7097 * host_to_target_errno_table[]. */
7098 for (i = 0; i < ERRNO_TABLE_SIZE; i++) {
7099 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
7100 }
7101
bellard2ab83ea2003-06-15 19:56:46 +00007102 /* we patch the ioctl size if necessary. We rely on the fact that
7103 no ioctl has all the bits at '1' in the size field */
7104 ie = ioctl_entries;
7105 while (ie->target_cmd != 0) {
7106 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
7107 TARGET_IOC_SIZEMASK) {
7108 arg_type = ie->arg_type;
7109 if (arg_type[0] != TYPE_PTR) {
ths5fafdf22007-09-16 21:08:06 +00007110 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00007111 ie->target_cmd);
7112 exit(1);
7113 }
7114 arg_type++;
7115 size = thunk_type_size(arg_type, 0);
ths5fafdf22007-09-16 21:08:06 +00007116 ie->target_cmd = (ie->target_cmd &
bellard2ab83ea2003-06-15 19:56:46 +00007117 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
7118 (size << TARGET_IOC_SIZESHIFT);
7119 }
thsb92c47c2007-11-01 00:07:38 +00007120
bellard2ab83ea2003-06-15 19:56:46 +00007121 /* automatic consistency check if same arch */
balrog872ea0c2008-09-21 02:31:19 +00007122#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
7123 (defined(__x86_64__) && defined(TARGET_X86_64))
7124 if (unlikely(ie->target_cmd != ie->host_cmd)) {
7125 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
7126 ie->name, ie->target_cmd, ie->host_cmd);
bellard2ab83ea2003-06-15 19:56:46 +00007127 }
7128#endif
7129 ie++;
7130 }
bellard31e31b82003-02-18 22:55:36 +00007131}
bellardc573ff62004-01-04 15:51:36 +00007132
pbrookce4defa2006-02-09 16:49:55 +00007133#ifdef TARGET_NR_truncate64
blueswir1992f48a2007-10-14 16:27:31 +00007134static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
7135 abi_long arg2,
7136 abi_long arg3,
7137 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00007138{
James Clarke8bf8e9d2017-09-15 20:33:13 +01007139 if (regpairs_aligned(cpu_env, TARGET_NR_truncate64)) {
pbrookce4defa2006-02-09 16:49:55 +00007140 arg2 = arg3;
7141 arg3 = arg4;
Riku Voipio48e515d2011-07-12 15:40:51 +03007142 }
pbrookce4defa2006-02-09 16:49:55 +00007143 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
7144}
7145#endif
7146
7147#ifdef TARGET_NR_ftruncate64
blueswir1992f48a2007-10-14 16:27:31 +00007148static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
7149 abi_long arg2,
7150 abi_long arg3,
7151 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00007152{
James Clarke8bf8e9d2017-09-15 20:33:13 +01007153 if (regpairs_aligned(cpu_env, TARGET_NR_ftruncate64)) {
pbrookce4defa2006-02-09 16:49:55 +00007154 arg2 = arg3;
7155 arg3 = arg4;
Riku Voipio48e515d2011-07-12 15:40:51 +03007156 }
pbrookce4defa2006-02-09 16:49:55 +00007157 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
7158}
7159#endif
7160
Alistair Francis859e8a82020-03-12 15:13:49 -07007161#if defined(TARGET_NR_timer_settime) || \
7162 (defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD))
Filip Bozuta2c86c902020-07-22 17:34:20 +02007163static inline abi_long target_to_host_itimerspec(struct itimerspec *host_its,
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007164 abi_ulong target_addr)
7165{
Filip Bozuta2c86c902020-07-22 17:34:20 +02007166 if (target_to_host_timespec(&host_its->it_interval, target_addr +
7167 offsetof(struct target_itimerspec,
7168 it_interval)) ||
7169 target_to_host_timespec(&host_its->it_value, target_addr +
7170 offsetof(struct target_itimerspec,
7171 it_value))) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007172 return -TARGET_EFAULT;
7173 }
7174
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007175 return 0;
7176}
Alistair Francis859e8a82020-03-12 15:13:49 -07007177#endif
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007178
Filip Bozuta828cb3a2020-07-22 17:34:21 +02007179#if defined(TARGET_NR_timer_settime64) || \
7180 (defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD))
7181static inline abi_long target_to_host_itimerspec64(struct itimerspec *host_its,
7182 abi_ulong target_addr)
7183{
7184 if (target_to_host_timespec64(&host_its->it_interval, target_addr +
7185 offsetof(struct target__kernel_itimerspec,
7186 it_interval)) ||
7187 target_to_host_timespec64(&host_its->it_value, target_addr +
7188 offsetof(struct target__kernel_itimerspec,
7189 it_value))) {
7190 return -TARGET_EFAULT;
7191 }
7192
7193 return 0;
7194}
7195#endif
7196
Alistair Francis859e8a82020-03-12 15:13:49 -07007197#if ((defined(TARGET_NR_timerfd_gettime) || \
7198 defined(TARGET_NR_timerfd_settime)) && defined(CONFIG_TIMERFD)) || \
Filip Bozuta2c86c902020-07-22 17:34:20 +02007199 defined(TARGET_NR_timer_gettime) || defined(TARGET_NR_timer_settime)
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007200static inline abi_long host_to_target_itimerspec(abi_ulong target_addr,
Filip Bozuta2c86c902020-07-22 17:34:20 +02007201 struct itimerspec *host_its)
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007202{
Filip Bozuta2c86c902020-07-22 17:34:20 +02007203 if (host_to_target_timespec(target_addr + offsetof(struct target_itimerspec,
7204 it_interval),
7205 &host_its->it_interval) ||
7206 host_to_target_timespec(target_addr + offsetof(struct target_itimerspec,
7207 it_value),
7208 &host_its->it_value)) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007209 return -TARGET_EFAULT;
7210 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007211 return 0;
7212}
Alistair Francis859e8a82020-03-12 15:13:49 -07007213#endif
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007214
Filip Bozuta828cb3a2020-07-22 17:34:21 +02007215#if ((defined(TARGET_NR_timerfd_gettime64) || \
7216 defined(TARGET_NR_timerfd_settime64)) && defined(CONFIG_TIMERFD)) || \
7217 defined(TARGET_NR_timer_gettime64) || defined(TARGET_NR_timer_settime64)
7218static inline abi_long host_to_target_itimerspec64(abi_ulong target_addr,
7219 struct itimerspec *host_its)
7220{
7221 if (host_to_target_timespec64(target_addr +
7222 offsetof(struct target__kernel_itimerspec,
7223 it_interval),
7224 &host_its->it_interval) ||
7225 host_to_target_timespec64(target_addr +
7226 offsetof(struct target__kernel_itimerspec,
7227 it_value),
7228 &host_its->it_value)) {
7229 return -TARGET_EFAULT;
7230 }
7231 return 0;
7232}
7233#endif
7234
Alistair Francis859e8a82020-03-12 15:13:49 -07007235#if defined(TARGET_NR_adjtimex) || \
7236 (defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME))
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +02007237static inline abi_long target_to_host_timex(struct timex *host_tx,
7238 abi_long target_addr)
7239{
7240 struct target_timex *target_tx;
7241
7242 if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) {
7243 return -TARGET_EFAULT;
7244 }
7245
7246 __get_user(host_tx->modes, &target_tx->modes);
7247 __get_user(host_tx->offset, &target_tx->offset);
7248 __get_user(host_tx->freq, &target_tx->freq);
7249 __get_user(host_tx->maxerror, &target_tx->maxerror);
7250 __get_user(host_tx->esterror, &target_tx->esterror);
7251 __get_user(host_tx->status, &target_tx->status);
7252 __get_user(host_tx->constant, &target_tx->constant);
7253 __get_user(host_tx->precision, &target_tx->precision);
7254 __get_user(host_tx->tolerance, &target_tx->tolerance);
7255 __get_user(host_tx->time.tv_sec, &target_tx->time.tv_sec);
7256 __get_user(host_tx->time.tv_usec, &target_tx->time.tv_usec);
7257 __get_user(host_tx->tick, &target_tx->tick);
7258 __get_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7259 __get_user(host_tx->jitter, &target_tx->jitter);
7260 __get_user(host_tx->shift, &target_tx->shift);
7261 __get_user(host_tx->stabil, &target_tx->stabil);
7262 __get_user(host_tx->jitcnt, &target_tx->jitcnt);
7263 __get_user(host_tx->calcnt, &target_tx->calcnt);
7264 __get_user(host_tx->errcnt, &target_tx->errcnt);
7265 __get_user(host_tx->stbcnt, &target_tx->stbcnt);
7266 __get_user(host_tx->tai, &target_tx->tai);
7267
7268 unlock_user_struct(target_tx, target_addr, 0);
7269 return 0;
7270}
7271
7272static inline abi_long host_to_target_timex(abi_long target_addr,
7273 struct timex *host_tx)
7274{
7275 struct target_timex *target_tx;
7276
7277 if (!lock_user_struct(VERIFY_WRITE, target_tx, target_addr, 0)) {
7278 return -TARGET_EFAULT;
7279 }
7280
7281 __put_user(host_tx->modes, &target_tx->modes);
7282 __put_user(host_tx->offset, &target_tx->offset);
7283 __put_user(host_tx->freq, &target_tx->freq);
7284 __put_user(host_tx->maxerror, &target_tx->maxerror);
7285 __put_user(host_tx->esterror, &target_tx->esterror);
7286 __put_user(host_tx->status, &target_tx->status);
7287 __put_user(host_tx->constant, &target_tx->constant);
7288 __put_user(host_tx->precision, &target_tx->precision);
7289 __put_user(host_tx->tolerance, &target_tx->tolerance);
7290 __put_user(host_tx->time.tv_sec, &target_tx->time.tv_sec);
7291 __put_user(host_tx->time.tv_usec, &target_tx->time.tv_usec);
7292 __put_user(host_tx->tick, &target_tx->tick);
7293 __put_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7294 __put_user(host_tx->jitter, &target_tx->jitter);
7295 __put_user(host_tx->shift, &target_tx->shift);
7296 __put_user(host_tx->stabil, &target_tx->stabil);
7297 __put_user(host_tx->jitcnt, &target_tx->jitcnt);
7298 __put_user(host_tx->calcnt, &target_tx->calcnt);
7299 __put_user(host_tx->errcnt, &target_tx->errcnt);
7300 __put_user(host_tx->stbcnt, &target_tx->stbcnt);
7301 __put_user(host_tx->tai, &target_tx->tai);
7302
7303 unlock_user_struct(target_tx, target_addr, 1);
7304 return 0;
7305}
Alistair Francis859e8a82020-03-12 15:13:49 -07007306#endif
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +02007307
Filip Bozuta6ac03b22020-08-24 21:21:15 +02007308
7309#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
7310static inline abi_long target_to_host_timex64(struct timex *host_tx,
7311 abi_long target_addr)
7312{
7313 struct target__kernel_timex *target_tx;
7314
7315 if (copy_from_user_timeval64(&host_tx->time, target_addr +
7316 offsetof(struct target__kernel_timex,
7317 time))) {
7318 return -TARGET_EFAULT;
7319 }
7320
7321 if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) {
7322 return -TARGET_EFAULT;
7323 }
7324
7325 __get_user(host_tx->modes, &target_tx->modes);
7326 __get_user(host_tx->offset, &target_tx->offset);
7327 __get_user(host_tx->freq, &target_tx->freq);
7328 __get_user(host_tx->maxerror, &target_tx->maxerror);
7329 __get_user(host_tx->esterror, &target_tx->esterror);
7330 __get_user(host_tx->status, &target_tx->status);
7331 __get_user(host_tx->constant, &target_tx->constant);
7332 __get_user(host_tx->precision, &target_tx->precision);
7333 __get_user(host_tx->tolerance, &target_tx->tolerance);
7334 __get_user(host_tx->tick, &target_tx->tick);
7335 __get_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7336 __get_user(host_tx->jitter, &target_tx->jitter);
7337 __get_user(host_tx->shift, &target_tx->shift);
7338 __get_user(host_tx->stabil, &target_tx->stabil);
7339 __get_user(host_tx->jitcnt, &target_tx->jitcnt);
7340 __get_user(host_tx->calcnt, &target_tx->calcnt);
7341 __get_user(host_tx->errcnt, &target_tx->errcnt);
7342 __get_user(host_tx->stbcnt, &target_tx->stbcnt);
7343 __get_user(host_tx->tai, &target_tx->tai);
7344
7345 unlock_user_struct(target_tx, target_addr, 0);
7346 return 0;
7347}
7348
7349static inline abi_long host_to_target_timex64(abi_long target_addr,
7350 struct timex *host_tx)
7351{
7352 struct target__kernel_timex *target_tx;
7353
7354 if (copy_to_user_timeval64(target_addr +
7355 offsetof(struct target__kernel_timex, time),
7356 &host_tx->time)) {
7357 return -TARGET_EFAULT;
7358 }
7359
7360 if (!lock_user_struct(VERIFY_WRITE, target_tx, target_addr, 0)) {
7361 return -TARGET_EFAULT;
7362 }
7363
7364 __put_user(host_tx->modes, &target_tx->modes);
7365 __put_user(host_tx->offset, &target_tx->offset);
7366 __put_user(host_tx->freq, &target_tx->freq);
7367 __put_user(host_tx->maxerror, &target_tx->maxerror);
7368 __put_user(host_tx->esterror, &target_tx->esterror);
7369 __put_user(host_tx->status, &target_tx->status);
7370 __put_user(host_tx->constant, &target_tx->constant);
7371 __put_user(host_tx->precision, &target_tx->precision);
7372 __put_user(host_tx->tolerance, &target_tx->tolerance);
7373 __put_user(host_tx->tick, &target_tx->tick);
7374 __put_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7375 __put_user(host_tx->jitter, &target_tx->jitter);
7376 __put_user(host_tx->shift, &target_tx->shift);
7377 __put_user(host_tx->stabil, &target_tx->stabil);
7378 __put_user(host_tx->jitcnt, &target_tx->jitcnt);
7379 __put_user(host_tx->calcnt, &target_tx->calcnt);
7380 __put_user(host_tx->errcnt, &target_tx->errcnt);
7381 __put_user(host_tx->stbcnt, &target_tx->stbcnt);
7382 __put_user(host_tx->tai, &target_tx->tai);
7383
7384 unlock_user_struct(target_tx, target_addr, 1);
7385 return 0;
7386}
7387#endif
7388
Peter Maydellc0659762014-08-09 15:42:32 +01007389static inline abi_long target_to_host_sigevent(struct sigevent *host_sevp,
7390 abi_ulong target_addr)
7391{
7392 struct target_sigevent *target_sevp;
7393
7394 if (!lock_user_struct(VERIFY_READ, target_sevp, target_addr, 1)) {
7395 return -TARGET_EFAULT;
7396 }
7397
7398 /* This union is awkward on 64 bit systems because it has a 32 bit
7399 * integer and a pointer in it; we follow the conversion approach
7400 * used for handling sigval types in signal.c so the guest should get
7401 * the correct value back even if we did a 64 bit byteswap and it's
7402 * using the 32 bit integer.
7403 */
7404 host_sevp->sigev_value.sival_ptr =
7405 (void *)(uintptr_t)tswapal(target_sevp->sigev_value.sival_ptr);
7406 host_sevp->sigev_signo =
7407 target_to_host_signal(tswap32(target_sevp->sigev_signo));
7408 host_sevp->sigev_notify = tswap32(target_sevp->sigev_notify);
7409 host_sevp->_sigev_un._tid = tswap32(target_sevp->_sigev_un._tid);
7410
7411 unlock_user_struct(target_sevp, target_addr, 1);
7412 return 0;
7413}
7414
Tom Musta6f6a4032014-08-12 13:53:42 -05007415#if defined(TARGET_NR_mlockall)
7416static inline int target_to_host_mlockall_arg(int arg)
7417{
7418 int result = 0;
7419
Filip Bozuta02e5d7d2020-08-11 18:45:51 +02007420 if (arg & TARGET_MCL_CURRENT) {
Tom Musta6f6a4032014-08-12 13:53:42 -05007421 result |= MCL_CURRENT;
7422 }
Filip Bozuta02e5d7d2020-08-11 18:45:51 +02007423 if (arg & TARGET_MCL_FUTURE) {
Tom Musta6f6a4032014-08-12 13:53:42 -05007424 result |= MCL_FUTURE;
7425 }
Filip Bozuta02e5d7d2020-08-11 18:45:51 +02007426#ifdef MCL_ONFAULT
7427 if (arg & TARGET_MCL_ONFAULT) {
7428 result |= MCL_ONFAULT;
7429 }
7430#endif
7431
Tom Musta6f6a4032014-08-12 13:53:42 -05007432 return result;
7433}
7434#endif
7435
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02007436#if (defined(TARGET_NR_stat64) || defined(TARGET_NR_lstat64) || \
7437 defined(TARGET_NR_fstat64) || defined(TARGET_NR_fstatat64) || \
7438 defined(TARGET_NR_newfstatat))
balrog6a24a772008-09-20 02:23:36 +00007439static inline abi_long host_to_target_stat64(void *cpu_env,
7440 abi_ulong target_addr,
7441 struct stat *host_st)
7442{
Alexander Graf09701192013-09-03 20:12:15 +01007443#if defined(TARGET_ARM) && defined(TARGET_ABI32)
balrog6a24a772008-09-20 02:23:36 +00007444 if (((CPUARMState *)cpu_env)->eabi) {
7445 struct target_eabi_stat64 *target_st;
7446
7447 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
7448 return -TARGET_EFAULT;
7449 memset(target_st, 0, sizeof(struct target_eabi_stat64));
7450 __put_user(host_st->st_dev, &target_st->st_dev);
7451 __put_user(host_st->st_ino, &target_st->st_ino);
7452#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
7453 __put_user(host_st->st_ino, &target_st->__st_ino);
7454#endif
7455 __put_user(host_st->st_mode, &target_st->st_mode);
7456 __put_user(host_st->st_nlink, &target_st->st_nlink);
7457 __put_user(host_st->st_uid, &target_st->st_uid);
7458 __put_user(host_st->st_gid, &target_st->st_gid);
7459 __put_user(host_st->st_rdev, &target_st->st_rdev);
7460 __put_user(host_st->st_size, &target_st->st_size);
7461 __put_user(host_st->st_blksize, &target_st->st_blksize);
7462 __put_user(host_st->st_blocks, &target_st->st_blocks);
7463 __put_user(host_st->st_atime, &target_st->target_st_atime);
7464 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
7465 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
Chen-Yu Tsai5f992db2019-05-23 00:21:47 +08007466#if _POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700
7467 __put_user(host_st->st_atim.tv_nsec, &target_st->target_st_atime_nsec);
7468 __put_user(host_st->st_mtim.tv_nsec, &target_st->target_st_mtime_nsec);
7469 __put_user(host_st->st_ctim.tv_nsec, &target_st->target_st_ctime_nsec);
7470#endif
balrog6a24a772008-09-20 02:23:36 +00007471 unlock_user_struct(target_st, target_addr, 1);
7472 } else
7473#endif
7474 {
Stefan Weil20d155b2013-10-30 22:52:24 +01007475#if defined(TARGET_HAS_STRUCT_STAT64)
balrog6a24a772008-09-20 02:23:36 +00007476 struct target_stat64 *target_st;
Stefan Weil20d155b2013-10-30 22:52:24 +01007477#else
7478 struct target_stat *target_st;
aurel329d33b762009-04-08 23:07:05 +00007479#endif
balrog6a24a772008-09-20 02:23:36 +00007480
7481 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
7482 return -TARGET_EFAULT;
aurel329d33b762009-04-08 23:07:05 +00007483 memset(target_st, 0, sizeof(*target_st));
balrog6a24a772008-09-20 02:23:36 +00007484 __put_user(host_st->st_dev, &target_st->st_dev);
7485 __put_user(host_st->st_ino, &target_st->st_ino);
7486#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
7487 __put_user(host_st->st_ino, &target_st->__st_ino);
7488#endif
7489 __put_user(host_st->st_mode, &target_st->st_mode);
7490 __put_user(host_st->st_nlink, &target_st->st_nlink);
7491 __put_user(host_st->st_uid, &target_st->st_uid);
7492 __put_user(host_st->st_gid, &target_st->st_gid);
7493 __put_user(host_st->st_rdev, &target_st->st_rdev);
7494 /* XXX: better use of kernel struct */
7495 __put_user(host_st->st_size, &target_st->st_size);
7496 __put_user(host_st->st_blksize, &target_st->st_blksize);
7497 __put_user(host_st->st_blocks, &target_st->st_blocks);
7498 __put_user(host_st->st_atime, &target_st->target_st_atime);
7499 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
7500 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
Chen-Yu Tsai5f992db2019-05-23 00:21:47 +08007501#if _POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700
7502 __put_user(host_st->st_atim.tv_nsec, &target_st->target_st_atime_nsec);
7503 __put_user(host_st->st_mtim.tv_nsec, &target_st->target_st_mtime_nsec);
7504 __put_user(host_st->st_ctim.tv_nsec, &target_st->target_st_ctime_nsec);
7505#endif
balrog6a24a772008-09-20 02:23:36 +00007506 unlock_user_struct(target_st, target_addr, 1);
7507 }
7508
7509 return 0;
7510}
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02007511#endif
balrog6a24a772008-09-20 02:23:36 +00007512
Aleksandar Rikaloefa92182019-06-28 12:43:34 +02007513#if defined(TARGET_NR_statx) && defined(__NR_statx)
7514static inline abi_long host_to_target_statx(struct target_statx *host_stx,
7515 abi_ulong target_addr)
7516{
7517 struct target_statx *target_stx;
7518
7519 if (!lock_user_struct(VERIFY_WRITE, target_stx, target_addr, 0)) {
7520 return -TARGET_EFAULT;
7521 }
7522 memset(target_stx, 0, sizeof(*target_stx));
7523
7524 __put_user(host_stx->stx_mask, &target_stx->stx_mask);
7525 __put_user(host_stx->stx_blksize, &target_stx->stx_blksize);
7526 __put_user(host_stx->stx_attributes, &target_stx->stx_attributes);
7527 __put_user(host_stx->stx_nlink, &target_stx->stx_nlink);
7528 __put_user(host_stx->stx_uid, &target_stx->stx_uid);
7529 __put_user(host_stx->stx_gid, &target_stx->stx_gid);
7530 __put_user(host_stx->stx_mode, &target_stx->stx_mode);
7531 __put_user(host_stx->stx_ino, &target_stx->stx_ino);
7532 __put_user(host_stx->stx_size, &target_stx->stx_size);
7533 __put_user(host_stx->stx_blocks, &target_stx->stx_blocks);
7534 __put_user(host_stx->stx_attributes_mask, &target_stx->stx_attributes_mask);
7535 __put_user(host_stx->stx_atime.tv_sec, &target_stx->stx_atime.tv_sec);
7536 __put_user(host_stx->stx_atime.tv_nsec, &target_stx->stx_atime.tv_nsec);
Ariadne Conilld1e26702019-11-22 11:40:40 -06007537 __put_user(host_stx->stx_btime.tv_sec, &target_stx->stx_btime.tv_sec);
7538 __put_user(host_stx->stx_btime.tv_nsec, &target_stx->stx_btime.tv_nsec);
7539 __put_user(host_stx->stx_ctime.tv_sec, &target_stx->stx_ctime.tv_sec);
7540 __put_user(host_stx->stx_ctime.tv_nsec, &target_stx->stx_ctime.tv_nsec);
7541 __put_user(host_stx->stx_mtime.tv_sec, &target_stx->stx_mtime.tv_sec);
7542 __put_user(host_stx->stx_mtime.tv_nsec, &target_stx->stx_mtime.tv_nsec);
Aleksandar Rikaloefa92182019-06-28 12:43:34 +02007543 __put_user(host_stx->stx_rdev_major, &target_stx->stx_rdev_major);
7544 __put_user(host_stx->stx_rdev_minor, &target_stx->stx_rdev_minor);
7545 __put_user(host_stx->stx_dev_major, &target_stx->stx_dev_major);
7546 __put_user(host_stx->stx_dev_minor, &target_stx->stx_dev_minor);
7547
7548 unlock_user_struct(target_stx, target_addr, 1);
7549
7550 return 0;
7551}
7552#endif
7553
Alistair Francis14690292020-03-18 15:47:01 -07007554static int do_sys_futex(int *uaddr, int op, int val,
7555 const struct timespec *timeout, int *uaddr2,
7556 int val3)
7557{
7558#if HOST_LONG_BITS == 64
7559#if defined(__NR_futex)
7560 /* always a 64-bit time_t, it doesn't define _time64 version */
7561 return sys_futex(uaddr, op, val, timeout, uaddr2, val3);
7562
7563#endif
7564#else /* HOST_LONG_BITS == 64 */
7565#if defined(__NR_futex_time64)
7566 if (sizeof(timeout->tv_sec) == 8) {
7567 /* _time64 function on 32bit arch */
7568 return sys_futex_time64(uaddr, op, val, timeout, uaddr2, val3);
7569 }
7570#endif
7571#if defined(__NR_futex)
7572 /* old function on 32bit arch */
7573 return sys_futex(uaddr, op, val, timeout, uaddr2, val3);
7574#endif
7575#endif /* HOST_LONG_BITS == 64 */
7576 g_assert_not_reached();
7577}
7578
7579static int do_safe_futex(int *uaddr, int op, int val,
7580 const struct timespec *timeout, int *uaddr2,
7581 int val3)
7582{
7583#if HOST_LONG_BITS == 64
7584#if defined(__NR_futex)
7585 /* always a 64-bit time_t, it doesn't define _time64 version */
7586 return get_errno(safe_futex(uaddr, op, val, timeout, uaddr2, val3));
7587#endif
7588#else /* HOST_LONG_BITS == 64 */
7589#if defined(__NR_futex_time64)
7590 if (sizeof(timeout->tv_sec) == 8) {
7591 /* _time64 function on 32bit arch */
7592 return get_errno(safe_futex_time64(uaddr, op, val, timeout, uaddr2,
7593 val3));
7594 }
7595#endif
7596#if defined(__NR_futex)
7597 /* old function on 32bit arch */
7598 return get_errno(safe_futex(uaddr, op, val, timeout, uaddr2, val3));
7599#endif
7600#endif /* HOST_LONG_BITS == 64 */
7601 return -TARGET_ENOSYS;
7602}
Aleksandar Rikaloefa92182019-06-28 12:43:34 +02007603
pbrookbd0c5662008-05-29 14:34:11 +00007604/* ??? Using host futex calls even when target atomic operations
7605 are not really atomic probably breaks things. However implementing
7606 futexes locally would make futexes shared between multiple processes
7607 tricky. However they're probably useless because guest atomic
7608 operations won't work either. */
Alistair Francis859e8a82020-03-12 15:13:49 -07007609#if defined(TARGET_NR_futex)
Richard Henderson3e8f1622021-02-12 10:48:43 -08007610static int do_futex(CPUState *cpu, target_ulong uaddr, int op, int val,
7611 target_ulong timeout, target_ulong uaddr2, int val3)
pbrookbd0c5662008-05-29 14:34:11 +00007612{
7613 struct timespec ts, *pts;
Nathan Froyda16aae02009-08-03 08:43:29 -07007614 int base_op;
pbrookbd0c5662008-05-29 14:34:11 +00007615
7616 /* ??? We assume FUTEX_* constants are the same on both host
7617 and target. */
Martin Mohringa29ccd62009-05-04 21:34:56 +03007618#ifdef FUTEX_CMD_MASK
Nathan Froyda16aae02009-08-03 08:43:29 -07007619 base_op = op & FUTEX_CMD_MASK;
Martin Mohringa29ccd62009-05-04 21:34:56 +03007620#else
Nathan Froyda16aae02009-08-03 08:43:29 -07007621 base_op = op;
Martin Mohringa29ccd62009-05-04 21:34:56 +03007622#endif
Nathan Froyda16aae02009-08-03 08:43:29 -07007623 switch (base_op) {
pbrookbd0c5662008-05-29 14:34:11 +00007624 case FUTEX_WAIT:
John Rigbycce246e2013-02-23 16:14:07 -07007625 case FUTEX_WAIT_BITSET:
pbrookbd0c5662008-05-29 14:34:11 +00007626 if (timeout) {
7627 pts = &ts;
7628 target_to_host_timespec(pts, timeout);
7629 } else {
7630 pts = NULL;
7631 }
Richard Henderson3e8f1622021-02-12 10:48:43 -08007632 return do_safe_futex(g2h(cpu, uaddr),
7633 op, tswap32(val), pts, NULL, val3);
pbrookbd0c5662008-05-29 14:34:11 +00007634 case FUTEX_WAKE:
Richard Henderson3e8f1622021-02-12 10:48:43 -08007635 return do_safe_futex(g2h(cpu, uaddr),
7636 op, val, NULL, NULL, 0);
pbrookbd0c5662008-05-29 14:34:11 +00007637 case FUTEX_FD:
Richard Henderson3e8f1622021-02-12 10:48:43 -08007638 return do_safe_futex(g2h(cpu, uaddr),
7639 op, val, NULL, NULL, 0);
pbrookbd0c5662008-05-29 14:34:11 +00007640 case FUTEX_REQUEUE:
pbrookbd0c5662008-05-29 14:34:11 +00007641 case FUTEX_CMP_REQUEUE:
Nathan Froyda16aae02009-08-03 08:43:29 -07007642 case FUTEX_WAKE_OP:
7643 /* For FUTEX_REQUEUE, FUTEX_CMP_REQUEUE, and FUTEX_WAKE_OP, the
7644 TIMEOUT parameter is interpreted as a uint32_t by the kernel.
7645 But the prototype takes a `struct timespec *'; insert casts
7646 to satisfy the compiler. We do not need to tswap TIMEOUT
7647 since it's not compared to guest memory. */
7648 pts = (struct timespec *)(uintptr_t) timeout;
Richard Henderson3e8f1622021-02-12 10:48:43 -08007649 return do_safe_futex(g2h(cpu, uaddr), op, val, pts, g2h(cpu, uaddr2),
Alistair Francis14690292020-03-18 15:47:01 -07007650 (base_op == FUTEX_CMP_REQUEUE
Richard Henderson3e8f1622021-02-12 10:48:43 -08007651 ? tswap32(val3) : val3));
pbrookbd0c5662008-05-29 14:34:11 +00007652 default:
7653 return -TARGET_ENOSYS;
7654 }
7655}
Alistair Francis859e8a82020-03-12 15:13:49 -07007656#endif
Alistair Francis14690292020-03-18 15:47:01 -07007657
7658#if defined(TARGET_NR_futex_time64)
Richard Henderson3e8f1622021-02-12 10:48:43 -08007659static int do_futex_time64(CPUState *cpu, target_ulong uaddr, int op,
7660 int val, target_ulong timeout,
Alistair Francis14690292020-03-18 15:47:01 -07007661 target_ulong uaddr2, int val3)
7662{
7663 struct timespec ts, *pts;
7664 int base_op;
7665
7666 /* ??? We assume FUTEX_* constants are the same on both host
7667 and target. */
7668#ifdef FUTEX_CMD_MASK
7669 base_op = op & FUTEX_CMD_MASK;
7670#else
7671 base_op = op;
7672#endif
7673 switch (base_op) {
7674 case FUTEX_WAIT:
7675 case FUTEX_WAIT_BITSET:
7676 if (timeout) {
7677 pts = &ts;
Alistair Francise4ce1782020-11-03 11:48:44 -08007678 if (target_to_host_timespec64(pts, timeout)) {
7679 return -TARGET_EFAULT;
7680 }
Alistair Francis14690292020-03-18 15:47:01 -07007681 } else {
7682 pts = NULL;
7683 }
Richard Henderson3e8f1622021-02-12 10:48:43 -08007684 return do_safe_futex(g2h(cpu, uaddr), op,
7685 tswap32(val), pts, NULL, val3);
Alistair Francis14690292020-03-18 15:47:01 -07007686 case FUTEX_WAKE:
Richard Henderson3e8f1622021-02-12 10:48:43 -08007687 return do_safe_futex(g2h(cpu, uaddr), op, val, NULL, NULL, 0);
Alistair Francis14690292020-03-18 15:47:01 -07007688 case FUTEX_FD:
Richard Henderson3e8f1622021-02-12 10:48:43 -08007689 return do_safe_futex(g2h(cpu, uaddr), op, val, NULL, NULL, 0);
Alistair Francis14690292020-03-18 15:47:01 -07007690 case FUTEX_REQUEUE:
7691 case FUTEX_CMP_REQUEUE:
7692 case FUTEX_WAKE_OP:
7693 /* For FUTEX_REQUEUE, FUTEX_CMP_REQUEUE, and FUTEX_WAKE_OP, the
7694 TIMEOUT parameter is interpreted as a uint32_t by the kernel.
7695 But the prototype takes a `struct timespec *'; insert casts
7696 to satisfy the compiler. We do not need to tswap TIMEOUT
7697 since it's not compared to guest memory. */
7698 pts = (struct timespec *)(uintptr_t) timeout;
Richard Henderson3e8f1622021-02-12 10:48:43 -08007699 return do_safe_futex(g2h(cpu, uaddr), op, val, pts, g2h(cpu, uaddr2),
Alistair Francis14690292020-03-18 15:47:01 -07007700 (base_op == FUTEX_CMP_REQUEUE
Richard Henderson3e8f1622021-02-12 10:48:43 -08007701 ? tswap32(val3) : val3));
Alistair Francis14690292020-03-18 15:47:01 -07007702 default:
7703 return -TARGET_ENOSYS;
7704 }
7705}
7706#endif
7707
Laurent Vivier0f0426f2015-09-01 22:27:33 +02007708#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
7709static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname,
7710 abi_long handle, abi_long mount_id,
7711 abi_long flags)
7712{
7713 struct file_handle *target_fh;
7714 struct file_handle *fh;
7715 int mid = 0;
7716 abi_long ret;
7717 char *name;
7718 unsigned int size, total_size;
7719
7720 if (get_user_s32(size, handle)) {
7721 return -TARGET_EFAULT;
7722 }
7723
7724 name = lock_user_string(pathname);
7725 if (!name) {
7726 return -TARGET_EFAULT;
7727 }
7728
7729 total_size = sizeof(struct file_handle) + size;
7730 target_fh = lock_user(VERIFY_WRITE, handle, total_size, 0);
7731 if (!target_fh) {
7732 unlock_user(name, pathname, 0);
7733 return -TARGET_EFAULT;
7734 }
7735
7736 fh = g_malloc0(total_size);
7737 fh->handle_bytes = size;
7738
7739 ret = get_errno(name_to_handle_at(dirfd, path(name), fh, &mid, flags));
7740 unlock_user(name, pathname, 0);
7741
7742 /* man name_to_handle_at(2):
7743 * Other than the use of the handle_bytes field, the caller should treat
7744 * the file_handle structure as an opaque data type
7745 */
7746
7747 memcpy(target_fh, fh, total_size);
7748 target_fh->handle_bytes = tswap32(fh->handle_bytes);
7749 target_fh->handle_type = tswap32(fh->handle_type);
7750 g_free(fh);
7751 unlock_user(target_fh, handle, total_size);
7752
7753 if (put_user_s32(mid, mount_id)) {
7754 return -TARGET_EFAULT;
7755 }
7756
7757 return ret;
7758
7759}
7760#endif
7761
7762#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
7763static abi_long do_open_by_handle_at(abi_long mount_fd, abi_long handle,
7764 abi_long flags)
7765{
7766 struct file_handle *target_fh;
7767 struct file_handle *fh;
7768 unsigned int size, total_size;
7769 abi_long ret;
7770
7771 if (get_user_s32(size, handle)) {
7772 return -TARGET_EFAULT;
7773 }
7774
7775 total_size = sizeof(struct file_handle) + size;
7776 target_fh = lock_user(VERIFY_READ, handle, total_size, 1);
7777 if (!target_fh) {
7778 return -TARGET_EFAULT;
7779 }
7780
Thomas Huthe9d49d52015-10-09 17:56:38 +02007781 fh = g_memdup(target_fh, total_size);
Laurent Vivier0f0426f2015-09-01 22:27:33 +02007782 fh->handle_bytes = size;
7783 fh->handle_type = tswap32(target_fh->handle_type);
7784
7785 ret = get_errno(open_by_handle_at(mount_fd, fh,
7786 target_to_host_bitmask(flags, fcntl_flags_tbl)));
7787
7788 g_free(fh);
7789
7790 unlock_user(target_fh, handle, total_size);
7791
7792 return ret;
7793}
7794#endif
pbrookbd0c5662008-05-29 14:34:11 +00007795
Laurent Viviere36800c2015-10-02 14:48:09 +02007796#if defined(TARGET_NR_signalfd) || defined(TARGET_NR_signalfd4)
7797
Laurent Viviere36800c2015-10-02 14:48:09 +02007798static abi_long do_signalfd4(int fd, abi_long mask, int flags)
7799{
7800 int host_flags;
7801 target_sigset_t *target_mask;
7802 sigset_t host_mask;
7803 abi_long ret;
7804
Helge Deller78721302021-02-10 07:12:14 +01007805 if (flags & ~(TARGET_O_NONBLOCK_MASK | TARGET_O_CLOEXEC)) {
Laurent Viviere36800c2015-10-02 14:48:09 +02007806 return -TARGET_EINVAL;
7807 }
7808 if (!lock_user_struct(VERIFY_READ, target_mask, mask, 1)) {
7809 return -TARGET_EFAULT;
7810 }
7811
7812 target_to_host_sigset(&host_mask, target_mask);
7813
7814 host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
7815
7816 ret = get_errno(signalfd(fd, &host_mask, host_flags));
7817 if (ret >= 0) {
7818 fd_trans_register(ret, &target_signalfd_trans);
7819 }
7820
7821 unlock_user_struct(target_mask, mask, 0);
7822
7823 return ret;
7824}
7825#endif
7826
pbrook1d9d8b52009-04-16 15:17:02 +00007827/* Map host to target signal numbers for the wait family of syscalls.
7828 Assume all other status bits are the same. */
Richard Hendersona05c6402012-09-15 11:34:20 -07007829int host_to_target_waitstatus(int status)
pbrook1d9d8b52009-04-16 15:17:02 +00007830{
7831 if (WIFSIGNALED(status)) {
7832 return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
7833 }
7834 if (WIFSTOPPED(status)) {
7835 return (host_to_target_signal(WSTOPSIG(status)) << 8)
7836 | (status & 0xff);
7837 }
7838 return status;
7839}
7840
Wim Vander Schelden76b94242014-06-18 11:02:39 +02007841static int open_self_cmdline(void *cpu_env, int fd)
7842{
Richard Henderson29a0af62019-03-22 16:07:18 -07007843 CPUState *cpu = env_cpu((CPUArchState *)cpu_env);
Andreas Schwab58de8b92017-03-20 12:31:55 +01007844 struct linux_binprm *bprm = ((TaskState *)cpu->opaque)->bprm;
7845 int i;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02007846
Andreas Schwab58de8b92017-03-20 12:31:55 +01007847 for (i = 0; i < bprm->argc; i++) {
7848 size_t len = strlen(bprm->argv[i]) + 1;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02007849
Andreas Schwab58de8b92017-03-20 12:31:55 +01007850 if (write(fd, bprm->argv[i], len) != len) {
Wim Vander Schelden76b94242014-06-18 11:02:39 +02007851 return -1;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02007852 }
7853 }
7854
Andreas Schwab58de8b92017-03-20 12:31:55 +01007855 return 0;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02007856}
7857
Alexander Graf36c08d42011-11-02 20:23:24 +01007858static int open_self_maps(void *cpu_env, int fd)
7859{
Richard Henderson29a0af62019-03-22 16:07:18 -07007860 CPUState *cpu = env_cpu((CPUArchState *)cpu_env);
Andreas Färber0429a972013-08-26 18:14:44 +02007861 TaskState *ts = cpu->opaque;
Alex Bennée01ef6b92020-04-03 20:11:46 +01007862 GSList *map_info = read_self_maps();
7863 GSList *s;
Alex Bennéebb551732020-04-03 20:11:47 +01007864 int count;
Alexander Graf36c08d42011-11-02 20:23:24 +01007865
Alex Bennée01ef6b92020-04-03 20:11:46 +01007866 for (s = map_info; s; s = g_slist_next(s)) {
7867 MapInfo *e = (MapInfo *) s->data;
Alexander Graf1a49ef22012-05-01 16:30:28 +01007868
Alex Bennée01ef6b92020-04-03 20:11:46 +01007869 if (h2g_valid(e->start)) {
7870 unsigned long min = e->start;
7871 unsigned long max = e->end;
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04007872 int flags = page_get_flags(h2g(min));
Alex Bennée01ef6b92020-04-03 20:11:46 +01007873 const char *path;
7874
7875 max = h2g_valid(max - 1) ?
Richard Henderson3e8f1622021-02-12 10:48:43 -08007876 max : (uintptr_t) g2h_untagged(GUEST_ADDR_MAX) + 1;
Alex Bennée01ef6b92020-04-03 20:11:46 +01007877
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04007878 if (page_check_range(h2g(min), max - min, flags) == -1) {
7879 continue;
7880 }
Alex Bennée01ef6b92020-04-03 20:11:46 +01007881
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04007882 if (h2g(min) == ts->info->stack_limit) {
Alex Bennéebb551732020-04-03 20:11:47 +01007883 path = "[stack]";
Alex Bennée01ef6b92020-04-03 20:11:46 +01007884 } else {
7885 path = e->path;
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04007886 }
Alex Bennée01ef6b92020-04-03 20:11:46 +01007887
Alex Bennéebb551732020-04-03 20:11:47 +01007888 count = dprintf(fd, TARGET_ABI_FMT_ptr "-" TARGET_ABI_FMT_ptr
7889 " %c%c%c%c %08" PRIx64 " %s %"PRId64,
7890 h2g(min), h2g(max - 1) + 1,
7891 e->is_read ? 'r' : '-',
7892 e->is_write ? 'w' : '-',
7893 e->is_exec ? 'x' : '-',
7894 e->is_priv ? 'p' : '-',
7895 (uint64_t) e->offset, e->dev, e->inode);
7896 if (path) {
7897 dprintf(fd, "%*s%s\n", 73 - count, "", path);
7898 } else {
7899 dprintf(fd, "\n");
7900 }
Alexander Graf1a49ef22012-05-01 16:30:28 +01007901 }
7902 }
7903
Alex Bennée01ef6b92020-04-03 20:11:46 +01007904 free_self_maps(map_info);
7905
Richard Hendersonbf02adc2020-02-12 19:22:22 -08007906#ifdef TARGET_VSYSCALL_PAGE
7907 /*
7908 * We only support execution from the vsyscall page.
7909 * This is as if CONFIG_LEGACY_VSYSCALL_XONLY=y from v5.3.
7910 */
Alex Bennéebb551732020-04-03 20:11:47 +01007911 count = dprintf(fd, TARGET_FMT_lx "-" TARGET_FMT_lx
7912 " --xp 00000000 00:00 0",
7913 TARGET_VSYSCALL_PAGE, TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE);
7914 dprintf(fd, "%*s%s\n", 73 - count, "", "[vsyscall]");
Richard Hendersonbf02adc2020-02-12 19:22:22 -08007915#endif
7916
Alexander Graf36c08d42011-11-02 20:23:24 +01007917 return 0;
7918}
7919
Alexander Graf480b8e72011-11-02 20:23:25 +01007920static int open_self_stat(void *cpu_env, int fd)
7921{
Richard Henderson29a0af62019-03-22 16:07:18 -07007922 CPUState *cpu = env_cpu((CPUArchState *)cpu_env);
Andreas Färber0429a972013-08-26 18:14:44 +02007923 TaskState *ts = cpu->opaque;
Alex Bennée7ad4d5a2020-04-14 21:06:23 +01007924 g_autoptr(GString) buf = g_string_new(NULL);
Alexander Graf480b8e72011-11-02 20:23:25 +01007925 int i;
7926
7927 for (i = 0; i < 44; i++) {
Alex Bennée7ad4d5a2020-04-14 21:06:23 +01007928 if (i == 0) {
7929 /* pid */
7930 g_string_printf(buf, FMT_pid " ", getpid());
7931 } else if (i == 1) {
7932 /* app name */
7933 gchar *bin = g_strrstr(ts->bprm->argv[0], "/");
7934 bin = bin ? bin + 1 : ts->bprm->argv[0];
7935 g_string_printf(buf, "(%.15s) ", bin);
7936 } else if (i == 27) {
7937 /* stack bottom */
7938 g_string_printf(buf, TARGET_ABI_FMT_ld " ", ts->info->start_stack);
7939 } else {
7940 /* for the rest, there is MasterCard */
7941 g_string_printf(buf, "0%c", i == 43 ? '\n' : ' ');
7942 }
Alexander Graf480b8e72011-11-02 20:23:25 +01007943
Alex Bennée7ad4d5a2020-04-14 21:06:23 +01007944 if (write(fd, buf->str, buf->len) != buf->len) {
7945 return -1;
7946 }
Alexander Graf480b8e72011-11-02 20:23:25 +01007947 }
7948
7949 return 0;
7950}
7951
Alexander Graf257450e2011-11-02 20:23:26 +01007952static int open_self_auxv(void *cpu_env, int fd)
7953{
Richard Henderson29a0af62019-03-22 16:07:18 -07007954 CPUState *cpu = env_cpu((CPUArchState *)cpu_env);
Andreas Färber0429a972013-08-26 18:14:44 +02007955 TaskState *ts = cpu->opaque;
Alexander Graf257450e2011-11-02 20:23:26 +01007956 abi_ulong auxv = ts->info->saved_auxv;
7957 abi_ulong len = ts->info->auxv_len;
7958 char *ptr;
7959
7960 /*
7961 * Auxiliary vector is stored in target process stack.
7962 * read in whole auxv vector and copy it to file
7963 */
7964 ptr = lock_user(VERIFY_READ, auxv, len, 0);
7965 if (ptr != NULL) {
7966 while (len > 0) {
7967 ssize_t r;
7968 r = write(fd, ptr, len);
7969 if (r <= 0) {
7970 break;
7971 }
7972 len -= r;
7973 ptr += r;
7974 }
7975 lseek(fd, 0, SEEK_SET);
7976 unlock_user(ptr, auxv, len);
7977 }
7978
7979 return 0;
7980}
7981
Andreas Schwab463d8e72013-07-02 14:04:12 +01007982static int is_proc_myself(const char *filename, const char *entry)
7983{
7984 if (!strncmp(filename, "/proc/", strlen("/proc/"))) {
7985 filename += strlen("/proc/");
7986 if (!strncmp(filename, "self/", strlen("self/"))) {
7987 filename += strlen("self/");
7988 } else if (*filename >= '1' && *filename <= '9') {
7989 char myself[80];
7990 snprintf(myself, sizeof(myself), "%d/", getpid());
7991 if (!strncmp(filename, myself, strlen(myself))) {
7992 filename += strlen(myself);
7993 } else {
7994 return 0;
7995 }
7996 } else {
7997 return 0;
7998 }
7999 if (!strcmp(filename, entry)) {
8000 return 1;
8001 }
8002 }
8003 return 0;
8004}
8005
Laurent Vivierfff69382019-05-17 15:31:48 +02008006#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) || \
Helge Deller93a56612020-04-24 23:06:48 +02008007 defined(TARGET_SPARC) || defined(TARGET_M68K) || defined(TARGET_HPPA)
Laurent Vivierde6b9932013-08-30 01:46:40 +02008008static int is_proc(const char *filename, const char *entry)
8009{
8010 return strcmp(filename, entry) == 0;
8011}
Laurent Vivierfff69382019-05-17 15:31:48 +02008012#endif
Laurent Vivierde6b9932013-08-30 01:46:40 +02008013
Laurent Vivierfff69382019-05-17 15:31:48 +02008014#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
Laurent Vivierde6b9932013-08-30 01:46:40 +02008015static int open_net_route(void *cpu_env, int fd)
8016{
8017 FILE *fp;
8018 char *line = NULL;
8019 size_t len = 0;
8020 ssize_t read;
8021
8022 fp = fopen("/proc/net/route", "r");
8023 if (fp == NULL) {
Peter Maydella3ca7bb2016-05-12 18:47:26 +01008024 return -1;
Laurent Vivierde6b9932013-08-30 01:46:40 +02008025 }
8026
8027 /* read header */
8028
8029 read = getline(&line, &len, fp);
8030 dprintf(fd, "%s", line);
8031
8032 /* read routes */
8033
8034 while ((read = getline(&line, &len, fp)) != -1) {
8035 char iface[16];
8036 uint32_t dest, gw, mask;
8037 unsigned int flags, refcnt, use, metric, mtu, window, irtt;
Peter Maydell9d0bd0c2019-02-05 17:42:07 +00008038 int fields;
8039
8040 fields = sscanf(line,
8041 "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
8042 iface, &dest, &gw, &flags, &refcnt, &use, &metric,
8043 &mask, &mtu, &window, &irtt);
8044 if (fields != 11) {
8045 continue;
8046 }
Laurent Vivierde6b9932013-08-30 01:46:40 +02008047 dprintf(fd, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
8048 iface, tswap32(dest), tswap32(gw), flags, refcnt, use,
8049 metric, tswap32(mask), mtu, window, irtt);
8050 }
8051
8052 free(line);
8053 fclose(fp);
8054
8055 return 0;
8056}
8057#endif
8058
Laurent Vivierfff69382019-05-17 15:31:48 +02008059#if defined(TARGET_SPARC)
8060static int open_cpuinfo(void *cpu_env, int fd)
8061{
8062 dprintf(fd, "type\t\t: sun4u\n");
8063 return 0;
8064}
8065#endif
8066
Helge Deller93a56612020-04-24 23:06:48 +02008067#if defined(TARGET_HPPA)
8068static int open_cpuinfo(void *cpu_env, int fd)
8069{
8070 dprintf(fd, "cpu family\t: PA-RISC 1.1e\n");
8071 dprintf(fd, "cpu\t\t: PA7300LC (PCX-L2)\n");
8072 dprintf(fd, "capabilities\t: os32\n");
8073 dprintf(fd, "model\t\t: 9000/778/B160L\n");
8074 dprintf(fd, "model name\t: Merlin L2 160 QEMU (9000/778/B160L)\n");
8075 return 0;
8076}
8077#endif
8078
Laurent Vivier4ab67132019-05-17 15:31:49 +02008079#if defined(TARGET_M68K)
8080static int open_hardware(void *cpu_env, int fd)
8081{
8082 dprintf(fd, "Model:\t\tqemu-m68k\n");
8083 return 0;
8084}
8085#endif
8086
Riku Voipio0b2effd2014-08-06 10:36:37 +03008087static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags, mode_t mode)
Alexander Graf3be14d02011-11-02 20:23:23 +01008088{
8089 struct fake_open {
8090 const char *filename;
8091 int (*fill)(void *cpu_env, int fd);
Laurent Vivierde6b9932013-08-30 01:46:40 +02008092 int (*cmp)(const char *s1, const char *s2);
Alexander Graf3be14d02011-11-02 20:23:23 +01008093 };
8094 const struct fake_open *fake_open;
8095 static const struct fake_open fakes[] = {
Laurent Vivierde6b9932013-08-30 01:46:40 +02008096 { "maps", open_self_maps, is_proc_myself },
8097 { "stat", open_self_stat, is_proc_myself },
8098 { "auxv", open_self_auxv, is_proc_myself },
Wim Vander Schelden76b94242014-06-18 11:02:39 +02008099 { "cmdline", open_self_cmdline, is_proc_myself },
Laurent Vivierde6b9932013-08-30 01:46:40 +02008100#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
8101 { "/proc/net/route", open_net_route, is_proc },
8102#endif
Helge Deller93a56612020-04-24 23:06:48 +02008103#if defined(TARGET_SPARC) || defined(TARGET_HPPA)
Laurent Vivierfff69382019-05-17 15:31:48 +02008104 { "/proc/cpuinfo", open_cpuinfo, is_proc },
8105#endif
Laurent Vivier4ab67132019-05-17 15:31:49 +02008106#if defined(TARGET_M68K)
8107 { "/proc/hardware", open_hardware, is_proc },
8108#endif
Laurent Vivierde6b9932013-08-30 01:46:40 +02008109 { NULL, NULL, NULL }
Alexander Graf3be14d02011-11-02 20:23:23 +01008110 };
8111
Maxim Ostapenkoaa07f5e2014-05-02 11:17:07 +03008112 if (is_proc_myself(pathname, "exe")) {
8113 int execfd = qemu_getauxval(AT_EXECFD);
Timothy E Baldwinc10a0732016-05-12 18:47:48 +01008114 return execfd ? execfd : safe_openat(dirfd, exec_path, flags, mode);
Maxim Ostapenkoaa07f5e2014-05-02 11:17:07 +03008115 }
8116
Alexander Graf3be14d02011-11-02 20:23:23 +01008117 for (fake_open = fakes; fake_open->filename; fake_open++) {
Laurent Vivierde6b9932013-08-30 01:46:40 +02008118 if (fake_open->cmp(pathname, fake_open->filename)) {
Alexander Graf3be14d02011-11-02 20:23:23 +01008119 break;
8120 }
8121 }
8122
8123 if (fake_open->filename) {
8124 const char *tmpdir;
8125 char filename[PATH_MAX];
8126 int fd, r;
8127
8128 /* create temporary file to map stat to */
8129 tmpdir = getenv("TMPDIR");
8130 if (!tmpdir)
8131 tmpdir = "/tmp";
8132 snprintf(filename, sizeof(filename), "%s/qemu-open.XXXXXX", tmpdir);
8133 fd = mkstemp(filename);
8134 if (fd < 0) {
8135 return fd;
8136 }
8137 unlink(filename);
8138
8139 if ((r = fake_open->fill(cpu_env, fd))) {
Peter Maydella3ca7bb2016-05-12 18:47:26 +01008140 int e = errno;
Alexander Graf3be14d02011-11-02 20:23:23 +01008141 close(fd);
Peter Maydella3ca7bb2016-05-12 18:47:26 +01008142 errno = e;
Alexander Graf3be14d02011-11-02 20:23:23 +01008143 return r;
8144 }
8145 lseek(fd, 0, SEEK_SET);
8146
8147 return fd;
8148 }
8149
Timothy E Baldwinc10a0732016-05-12 18:47:48 +01008150 return safe_openat(dirfd, path(pathname), flags, mode);
Alexander Graf3be14d02011-11-02 20:23:23 +01008151}
8152
Alexander Grafaecc8862014-11-10 21:33:03 +01008153#define TIMER_MAGIC 0x0caf0000
8154#define TIMER_MAGIC_MASK 0xffff0000
8155
8156/* Convert QEMU provided timer ID back to internal 16bit index format */
8157static target_timer_t get_timer_id(abi_long arg)
8158{
8159 target_timer_t timerid = arg;
8160
8161 if ((timerid & TIMER_MAGIC_MASK) != TIMER_MAGIC) {
8162 return -TARGET_EINVAL;
8163 }
8164
8165 timerid &= 0xffff;
8166
8167 if (timerid >= ARRAY_SIZE(g_posix_timers)) {
8168 return -TARGET_EINVAL;
8169 }
8170
8171 return timerid;
8172}
8173
Samuel Thibault2e0a8712018-01-09 21:16:43 +01008174static int target_to_host_cpu_mask(unsigned long *host_mask,
8175 size_t host_size,
8176 abi_ulong target_addr,
8177 size_t target_size)
8178{
8179 unsigned target_bits = sizeof(abi_ulong) * 8;
8180 unsigned host_bits = sizeof(*host_mask) * 8;
8181 abi_ulong *target_mask;
8182 unsigned i, j;
8183
8184 assert(host_size >= target_size);
8185
8186 target_mask = lock_user(VERIFY_READ, target_addr, target_size, 1);
8187 if (!target_mask) {
8188 return -TARGET_EFAULT;
8189 }
8190 memset(host_mask, 0, host_size);
8191
8192 for (i = 0 ; i < target_size / sizeof(abi_ulong); i++) {
8193 unsigned bit = i * target_bits;
8194 abi_ulong val;
8195
8196 __get_user(val, &target_mask[i]);
8197 for (j = 0; j < target_bits; j++, bit++) {
8198 if (val & (1UL << j)) {
8199 host_mask[bit / host_bits] |= 1UL << (bit % host_bits);
8200 }
8201 }
8202 }
8203
8204 unlock_user(target_mask, target_addr, 0);
8205 return 0;
8206}
8207
8208static int host_to_target_cpu_mask(const unsigned long *host_mask,
8209 size_t host_size,
8210 abi_ulong target_addr,
8211 size_t target_size)
8212{
8213 unsigned target_bits = sizeof(abi_ulong) * 8;
8214 unsigned host_bits = sizeof(*host_mask) * 8;
8215 abi_ulong *target_mask;
8216 unsigned i, j;
8217
8218 assert(host_size >= target_size);
8219
8220 target_mask = lock_user(VERIFY_WRITE, target_addr, target_size, 0);
8221 if (!target_mask) {
8222 return -TARGET_EFAULT;
8223 }
8224
8225 for (i = 0 ; i < target_size / sizeof(abi_ulong); i++) {
8226 unsigned bit = i * target_bits;
8227 abi_ulong val = 0;
8228
8229 for (j = 0; j < target_bits; j++, bit++) {
8230 if (host_mask[bit / host_bits] & (1UL << (bit % host_bits))) {
8231 val |= 1UL << j;
8232 }
8233 }
8234 __put_user(val, &target_mask[i]);
8235 }
8236
8237 unlock_user(target_mask, target_addr, target_size);
8238 return 0;
8239}
8240
Richard Hendersondc1ce182018-08-18 12:01:04 -07008241/* This is an internal helper for do_syscall so that it is easier
8242 * to have a single return point, so that actions, such as logging
8243 * of syscall results, can be performed.
8244 * All errnos that do_syscall() returns must be -TARGET_<errcode>.
8245 */
8246static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
8247 abi_long arg2, abi_long arg3, abi_long arg4,
8248 abi_long arg5, abi_long arg6, abi_long arg7,
8249 abi_long arg8)
bellard31e31b82003-02-18 22:55:36 +00008250{
Richard Henderson29a0af62019-03-22 16:07:18 -07008251 CPUState *cpu = env_cpu(cpu_env);
blueswir1992f48a2007-10-14 16:27:31 +00008252 abi_long ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008253#if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) \
8254 || defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64) \
Aleksandar Rikaloefa92182019-06-28 12:43:34 +02008255 || defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64) \
8256 || defined(TARGET_NR_statx)
bellard31e31b82003-02-18 22:55:36 +00008257 struct stat st;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008258#endif
8259#if defined(TARGET_NR_statfs) || defined(TARGET_NR_statfs64) \
8260 || defined(TARGET_NR_fstatfs)
bellard56c8f682005-11-28 22:28:41 +00008261 struct statfs stfs;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008262#endif
pbrook53a59602006-03-25 19:31:22 +00008263 void *p;
ths3b46e622007-09-17 08:09:54 +00008264
bellard31e31b82003-02-18 22:55:36 +00008265 switch(num) {
8266 case TARGET_NR_exit:
Andreas Färber9b056fc2013-06-24 23:53:10 +02008267 /* In old applications this may be used to implement _exit(2).
zhaolichang6f9ff552020-09-17 15:50:25 +08008268 However in threaded applications it is used for thread termination,
Andreas Färber9b056fc2013-06-24 23:53:10 +02008269 and _exit_group is used for application termination.
8270 Do thread termination if we have more then one thread. */
Timothy E Baldwina0995882016-05-27 15:51:56 +01008271
8272 if (block_signals()) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008273 return -TARGET_ERESTARTSYS;
Timothy E Baldwina0995882016-05-27 15:51:56 +01008274 }
8275
Alex Bennée1f81ce92020-05-20 15:05:39 +01008276 pthread_mutex_lock(&clone_lock);
Alex Bennéedd1f6342016-09-30 22:31:01 +01008277
Andreas Färberbdc44642013-06-24 23:50:24 +02008278 if (CPU_NEXT(first_cpu)) {
Alex Bennée1f81ce92020-05-20 15:05:39 +01008279 TaskState *ts = cpu->opaque;
pbrookc2764712009-03-07 15:24:59 +00008280
Markus Armbruster5325cc32020-07-07 18:05:54 +02008281 object_property_set_bool(OBJECT(cpu), "realized", false, NULL);
Alex Bennée1f81ce92020-05-20 15:05:39 +01008282 object_unref(OBJECT(cpu));
8283 /*
8284 * At this point the CPU should be unrealized and removed
8285 * from cpu lists. We can clean-up the rest of the thread
8286 * data without the lock held.
8287 */
Alex Bennéedd1f6342016-09-30 22:31:01 +01008288
Alex Bennée1f81ce92020-05-20 15:05:39 +01008289 pthread_mutex_unlock(&clone_lock);
Alex Bennéedd1f6342016-09-30 22:31:01 +01008290
Andreas Färber9b056fc2013-06-24 23:53:10 +02008291 if (ts->child_tidptr) {
8292 put_user_u32(0, ts->child_tidptr);
Richard Henderson3e8f1622021-02-12 10:48:43 -08008293 do_sys_futex(g2h(cpu, ts->child_tidptr),
8294 FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
Andreas Färber9b056fc2013-06-24 23:53:10 +02008295 }
Andreas Färbera2247f82013-06-09 19:47:04 +02008296 thread_cpu = NULL;
Andreas Färber9b056fc2013-06-24 23:53:10 +02008297 g_free(ts);
Emilio G. Cota70903762015-08-23 20:23:41 -04008298 rcu_unregister_thread();
Andreas Färber9b056fc2013-06-24 23:53:10 +02008299 pthread_exit(NULL);
8300 }
Alex Bennéedd1f6342016-09-30 22:31:01 +01008301
Alex Bennée1f81ce92020-05-20 15:05:39 +01008302 pthread_mutex_unlock(&clone_lock);
Alex Bennée708b6a62018-06-22 17:09:10 +01008303 preexit_cleanup(cpu_env, arg1);
pbrookc2764712009-03-07 15:24:59 +00008304 _exit(arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008305 return 0; /* avoid warning */
bellard31e31b82003-02-18 22:55:36 +00008306 case TARGET_NR_read:
Andreas Schwabba584f12019-03-05 17:45:05 +01008307 if (arg2 == 0 && arg3 == 0) {
8308 return get_errno(safe_read(arg1, 0, 0));
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008309 } else {
aurel3238d840e2009-01-30 19:48:17 +00008310 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008311 return -TARGET_EFAULT;
Timothy E Baldwin50afd022016-05-12 18:47:47 +01008312 ret = get_errno(safe_read(arg1, p, arg3));
Laurent Viviere36800c2015-10-02 14:48:09 +02008313 if (ret >= 0 &&
Laurent Vivier5d4d3662015-10-28 21:40:43 +01008314 fd_trans_host_to_target_data(arg1)) {
8315 ret = fd_trans_host_to_target_data(arg1)(p, ret);
Laurent Viviere36800c2015-10-02 14:48:09 +02008316 }
aurel3238d840e2009-01-30 19:48:17 +00008317 unlock_user(p, arg2, ret);
8318 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008319 return ret;
bellard31e31b82003-02-18 22:55:36 +00008320 case TARGET_NR_write:
Tony Garnock-Jones58cfa6c2018-09-08 19:22:05 +01008321 if (arg2 == 0 && arg3 == 0) {
8322 return get_errno(safe_write(arg1, 0, 0));
8323 }
bellard579a97f2007-11-11 14:26:47 +00008324 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008325 return -TARGET_EFAULT;
Laurent Vivier04b9bcf2017-03-01 10:37:47 +01008326 if (fd_trans_target_to_host_data(arg1)) {
8327 void *copy = g_malloc(arg3);
8328 memcpy(copy, p, arg3);
8329 ret = fd_trans_target_to_host_data(arg1)(copy, arg3);
8330 if (ret >= 0) {
8331 ret = get_errno(safe_write(arg1, copy, ret));
8332 }
8333 g_free(copy);
8334 } else {
8335 ret = get_errno(safe_write(arg1, p, arg3));
8336 }
pbrook53a59602006-03-25 19:31:22 +00008337 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008338 return ret;
8339
Chen Gang704eff62015-08-21 05:37:33 +08008340#ifdef TARGET_NR_open
bellard31e31b82003-02-18 22:55:36 +00008341 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00008342 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008343 return -TARGET_EFAULT;
Riku Voipio0b2effd2014-08-06 10:36:37 +03008344 ret = get_errno(do_openat(cpu_env, AT_FDCWD, p,
8345 target_to_host_bitmask(arg2, fcntl_flags_tbl),
8346 arg3));
Laurent Viviere36800c2015-10-02 14:48:09 +02008347 fd_trans_unregister(ret);
pbrook53a59602006-03-25 19:31:22 +00008348 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008349 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008350#endif
ths82424832007-09-24 09:21:55 +00008351 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00008352 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008353 return -TARGET_EFAULT;
Riku Voipio0b2effd2014-08-06 10:36:37 +03008354 ret = get_errno(do_openat(cpu_env, arg1, p,
8355 target_to_host_bitmask(arg3, fcntl_flags_tbl),
8356 arg4));
Laurent Viviere36800c2015-10-02 14:48:09 +02008357 fd_trans_unregister(ret);
bellard579a97f2007-11-11 14:26:47 +00008358 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008359 return ret;
Laurent Vivier0f0426f2015-09-01 22:27:33 +02008360#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
8361 case TARGET_NR_name_to_handle_at:
8362 ret = do_name_to_handle_at(arg1, arg2, arg3, arg4, arg5);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008363 return ret;
Laurent Vivier0f0426f2015-09-01 22:27:33 +02008364#endif
8365#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
8366 case TARGET_NR_open_by_handle_at:
8367 ret = do_open_by_handle_at(arg1, arg2, arg3);
Laurent Viviere36800c2015-10-02 14:48:09 +02008368 fd_trans_unregister(ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008369 return ret;
Laurent Vivier0f0426f2015-09-01 22:27:33 +02008370#endif
bellard31e31b82003-02-18 22:55:36 +00008371 case TARGET_NR_close:
Laurent Viviere36800c2015-10-02 14:48:09 +02008372 fd_trans_unregister(arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008373 return get_errno(close(arg1));
8374
bellard31e31b82003-02-18 22:55:36 +00008375 case TARGET_NR_brk:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008376 return do_brk(arg1);
Chen Gang704eff62015-08-21 05:37:33 +08008377#ifdef TARGET_NR_fork
bellard31e31b82003-02-18 22:55:36 +00008378 case TARGET_NR_fork:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008379 return get_errno(do_fork(cpu_env, TARGET_SIGCHLD, 0, 0, 0, 0));
Chen Gang704eff62015-08-21 05:37:33 +08008380#endif
thse5febef2007-04-01 18:31:35 +00008381#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00008382 case TARGET_NR_waitpid:
8383 {
pbrook53a59602006-03-25 19:31:22 +00008384 int status;
Timothy E Baldwin4af80a32016-05-12 18:47:49 +01008385 ret = get_errno(safe_wait4(arg1, &status, arg3, 0));
Alexander Graf53795572011-11-24 00:44:43 +01008386 if (!is_error(ret) && arg2 && ret
pbrook1d9d8b52009-04-16 15:17:02 +00008387 && put_user_s32(host_to_target_waitstatus(status), arg2))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008388 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00008389 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008390 return ret;
thse5febef2007-04-01 18:31:35 +00008391#endif
pbrookf0cbb612008-05-30 18:20:05 +00008392#ifdef TARGET_NR_waitid
8393 case TARGET_NR_waitid:
8394 {
8395 siginfo_t info;
8396 info.si_pid = 0;
Timothy E Baldwin4af80a32016-05-12 18:47:49 +01008397 ret = get_errno(safe_waitid(arg1, arg2, &info, arg4, NULL));
pbrookf0cbb612008-05-30 18:20:05 +00008398 if (!is_error(ret) && arg3 && info.si_pid != 0) {
Anthony Liguoric227f092009-10-01 16:12:16 -05008399 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008400 return -TARGET_EFAULT;
pbrookf0cbb612008-05-30 18:20:05 +00008401 host_to_target_siginfo(p, &info);
Anthony Liguoric227f092009-10-01 16:12:16 -05008402 unlock_user(p, arg3, sizeof(target_siginfo_t));
pbrookf0cbb612008-05-30 18:20:05 +00008403 }
8404 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008405 return ret;
pbrookf0cbb612008-05-30 18:20:05 +00008406#endif
j_mayer7a3148a2007-04-05 07:13:51 +00008407#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00008408 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00008409 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008410 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008411 ret = get_errno(creat(p, arg2));
Laurent Viviere36800c2015-10-02 14:48:09 +02008412 fd_trans_unregister(ret);
pbrook53a59602006-03-25 19:31:22 +00008413 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008414 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00008415#endif
Chen Gang704eff62015-08-21 05:37:33 +08008416#ifdef TARGET_NR_link
bellard31e31b82003-02-18 22:55:36 +00008417 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00008418 {
8419 void * p2;
8420 p = lock_user_string(arg1);
8421 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00008422 if (!p || !p2)
8423 ret = -TARGET_EFAULT;
8424 else
8425 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00008426 unlock_user(p2, arg2, 0);
8427 unlock_user(p, arg1, 0);
8428 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008429 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008430#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01008431#if defined(TARGET_NR_linkat)
ths64f0ce42007-09-24 09:25:06 +00008432 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00008433 {
8434 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00008435 if (!arg2 || !arg4)
Richard Henderson2852aaf2018-08-18 12:01:06 -07008436 return -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00008437 p = lock_user_string(arg2);
8438 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00008439 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00008440 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00008441 else
Peter Maydellc0d472b2013-06-12 16:20:21 +01008442 ret = get_errno(linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00008443 unlock_user(p, arg2, 0);
8444 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00008445 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008446 return ret;
ths64f0ce42007-09-24 09:25:06 +00008447#endif
Chen Gang704eff62015-08-21 05:37:33 +08008448#ifdef TARGET_NR_unlink
bellard31e31b82003-02-18 22:55:36 +00008449 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00008450 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008451 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008452 ret = get_errno(unlink(p));
8453 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008454 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008455#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01008456#if defined(TARGET_NR_unlinkat)
ths8170f562007-09-24 09:24:11 +00008457 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00008458 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008459 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01008460 ret = get_errno(unlinkat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00008461 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008462 return ret;
balrogb7d35e62007-12-12 00:40:24 +00008463#endif
bellard31e31b82003-02-18 22:55:36 +00008464 case TARGET_NR_execve:
bellard7854b052003-03-29 17:22:23 +00008465 {
8466 char **argp, **envp;
bellardf7341ff2003-03-30 21:00:25 +00008467 int argc, envc;
blueswir1992f48a2007-10-14 16:27:31 +00008468 abi_ulong gp;
8469 abi_ulong guest_argp;
8470 abi_ulong guest_envp;
8471 abi_ulong addr;
bellard7854b052003-03-29 17:22:23 +00008472 char **q;
Ulrich Hechta6f79cc2012-01-31 12:43:16 +01008473 int total_size = 0;
bellard7854b052003-03-29 17:22:23 +00008474
bellardf7341ff2003-03-30 21:00:25 +00008475 argc = 0;
pbrook53a59602006-03-25 19:31:22 +00008476 guest_argp = arg2;
pbrookda94d262008-05-30 18:24:00 +00008477 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00008478 if (get_user_ual(addr, gp))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008479 return -TARGET_EFAULT;
ths03aa1972007-12-02 06:28:08 +00008480 if (!addr)
bellard2f619692007-11-16 10:46:05 +00008481 break;
bellard7854b052003-03-29 17:22:23 +00008482 argc++;
bellard2f619692007-11-16 10:46:05 +00008483 }
bellardf7341ff2003-03-30 21:00:25 +00008484 envc = 0;
pbrook53a59602006-03-25 19:31:22 +00008485 guest_envp = arg3;
pbrookda94d262008-05-30 18:24:00 +00008486 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00008487 if (get_user_ual(addr, gp))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008488 return -TARGET_EFAULT;
ths03aa1972007-12-02 06:28:08 +00008489 if (!addr)
bellard2f619692007-11-16 10:46:05 +00008490 break;
bellard7854b052003-03-29 17:22:23 +00008491 envc++;
bellard2f619692007-11-16 10:46:05 +00008492 }
bellard7854b052003-03-29 17:22:23 +00008493
Prasad J Panditb936cb52017-03-07 12:51:47 +05308494 argp = g_new0(char *, argc + 1);
8495 envp = g_new0(char *, envc + 1);
bellard7854b052003-03-29 17:22:23 +00008496
pbrookda94d262008-05-30 18:24:00 +00008497 for (gp = guest_argp, q = argp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00008498 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00008499 if (get_user_ual(addr, gp))
8500 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00008501 if (!addr)
8502 break;
bellard2f619692007-11-16 10:46:05 +00008503 if (!(*q = lock_user_string(addr)))
8504 goto execve_efault;
Ulrich Hechta6f79cc2012-01-31 12:43:16 +01008505 total_size += strlen(*q) + 1;
pbrook53a59602006-03-25 19:31:22 +00008506 }
bellardf7341ff2003-03-30 21:00:25 +00008507 *q = NULL;
8508
pbrookda94d262008-05-30 18:24:00 +00008509 for (gp = guest_envp, q = envp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00008510 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00008511 if (get_user_ual(addr, gp))
8512 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00008513 if (!addr)
8514 break;
bellard2f619692007-11-16 10:46:05 +00008515 if (!(*q = lock_user_string(addr)))
8516 goto execve_efault;
Ulrich Hechta6f79cc2012-01-31 12:43:16 +01008517 total_size += strlen(*q) + 1;
pbrook53a59602006-03-25 19:31:22 +00008518 }
bellardf7341ff2003-03-30 21:00:25 +00008519 *q = NULL;
bellard7854b052003-03-29 17:22:23 +00008520
bellard2f619692007-11-16 10:46:05 +00008521 if (!(p = lock_user_string(arg1)))
8522 goto execve_efault;
Timothy E Baldwinffdcbe22016-05-12 18:47:50 +01008523 /* Although execve() is not an interruptible syscall it is
8524 * a special case where we must use the safe_syscall wrapper:
8525 * if we allow a signal to happen before we make the host
8526 * syscall then we will 'lose' it, because at the point of
8527 * execve the process leaves QEMU's control. So we use the
8528 * safe syscall wrapper to ensure that we either take the
8529 * signal as a guest signal, or else it does not happen
8530 * before the execve completes and makes it the other
8531 * program's problem.
8532 */
8533 ret = get_errno(safe_execve(p, argp, envp));
pbrook53a59602006-03-25 19:31:22 +00008534 unlock_user(p, arg1, 0);
8535
bellard2f619692007-11-16 10:46:05 +00008536 goto execve_end;
8537
8538 execve_efault:
8539 ret = -TARGET_EFAULT;
8540
8541 execve_end:
pbrook53a59602006-03-25 19:31:22 +00008542 for (gp = guest_argp, q = argp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00008543 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00008544 if (get_user_ual(addr, gp)
8545 || !addr)
8546 break;
pbrook53a59602006-03-25 19:31:22 +00008547 unlock_user(*q, addr, 0);
8548 }
8549 for (gp = guest_envp, q = envp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00008550 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00008551 if (get_user_ual(addr, gp)
8552 || !addr)
8553 break;
pbrook53a59602006-03-25 19:31:22 +00008554 unlock_user(*q, addr, 0);
8555 }
Prasad J Panditb936cb52017-03-07 12:51:47 +05308556
8557 g_free(argp);
8558 g_free(envp);
bellard7854b052003-03-29 17:22:23 +00008559 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008560 return ret;
bellard31e31b82003-02-18 22:55:36 +00008561 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00008562 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008563 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008564 ret = get_errno(chdir(p));
8565 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008566 return ret;
bellarda315a142005-01-30 22:59:18 +00008567#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00008568 case TARGET_NR_time:
8569 {
pbrook53a59602006-03-25 19:31:22 +00008570 time_t host_time;
8571 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00008572 if (!is_error(ret)
8573 && arg1
8574 && put_user_sal(host_time, arg1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008575 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00008576 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008577 return ret;
bellarda315a142005-01-30 22:59:18 +00008578#endif
Chen Gang704eff62015-08-21 05:37:33 +08008579#ifdef TARGET_NR_mknod
bellard31e31b82003-02-18 22:55:36 +00008580 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00008581 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008582 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008583 ret = get_errno(mknod(p, arg2, arg3));
8584 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008585 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008586#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01008587#if defined(TARGET_NR_mknodat)
ths75ac37a2007-09-24 09:23:05 +00008588 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00008589 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008590 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01008591 ret = get_errno(mknodat(arg1, p, arg3, arg4));
bellard579a97f2007-11-11 14:26:47 +00008592 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008593 return ret;
ths75ac37a2007-09-24 09:23:05 +00008594#endif
Chen Gang704eff62015-08-21 05:37:33 +08008595#ifdef TARGET_NR_chmod
bellard31e31b82003-02-18 22:55:36 +00008596 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00008597 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008598 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008599 ret = get_errno(chmod(p, arg2));
8600 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008601 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008602#endif
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008603#ifdef TARGET_NR_lseek
bellard31e31b82003-02-18 22:55:36 +00008604 case TARGET_NR_lseek:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008605 return get_errno(lseek(arg1, arg2, arg3));
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008606#endif
Richard Henderson92317332010-05-03 10:07:53 -07008607#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA)
8608 /* Alpha specific */
j_mayer7a3148a2007-04-05 07:13:51 +00008609 case TARGET_NR_getxpid:
Richard Henderson92317332010-05-03 10:07:53 -07008610 ((CPUAlphaState *)cpu_env)->ir[IR_A4] = getppid();
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008611 return get_errno(getpid());
Richard Henderson92317332010-05-03 10:07:53 -07008612#endif
8613#ifdef TARGET_NR_getpid
8614 case TARGET_NR_getpid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008615 return get_errno(getpid());
Richard Henderson92317332010-05-03 10:07:53 -07008616#endif
bellard31e31b82003-02-18 22:55:36 +00008617 case TARGET_NR_mount:
Paul Burton356d7712014-06-22 11:25:37 +01008618 {
8619 /* need to look at the data field */
8620 void *p2, *p3;
8621
8622 if (arg1) {
8623 p = lock_user_string(arg1);
8624 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008625 return -TARGET_EFAULT;
Paul Burton356d7712014-06-22 11:25:37 +01008626 }
8627 } else {
8628 p = NULL;
8629 }
8630
8631 p2 = lock_user_string(arg2);
8632 if (!p2) {
8633 if (arg1) {
8634 unlock_user(p, arg1, 0);
8635 }
Richard Henderson2852aaf2018-08-18 12:01:06 -07008636 return -TARGET_EFAULT;
Paul Burton356d7712014-06-22 11:25:37 +01008637 }
8638
8639 if (arg3) {
8640 p3 = lock_user_string(arg3);
8641 if (!p3) {
8642 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00008643 unlock_user(p, arg1, 0);
Paul Burton356d7712014-06-22 11:25:37 +01008644 }
8645 unlock_user(p2, arg2, 0);
Richard Henderson2852aaf2018-08-18 12:01:06 -07008646 return -TARGET_EFAULT;
Paul Burton356d7712014-06-22 11:25:37 +01008647 }
8648 } else {
8649 p3 = NULL;
8650 }
8651
8652 /* FIXME - arg5 should be locked, but it isn't clear how to
8653 * do that since it's not guaranteed to be a NULL-terminated
8654 * string.
8655 */
8656 if (!arg5) {
8657 ret = mount(p, p2, p3, (unsigned long)arg4, NULL);
8658 } else {
Richard Henderson3e8f1622021-02-12 10:48:43 -08008659 ret = mount(p, p2, p3, (unsigned long)arg4, g2h(cpu, arg5));
Paul Burton356d7712014-06-22 11:25:37 +01008660 }
8661 ret = get_errno(ret);
8662
8663 if (arg1) {
8664 unlock_user(p, arg1, 0);
8665 }
8666 unlock_user(p2, arg2, 0);
8667 if (arg3) {
8668 unlock_user(p3, arg3, 0);
8669 }
8670 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008671 return ret;
Laurent Vivier6eb9dbf2020-05-02 21:46:42 +02008672#if defined(TARGET_NR_umount) || defined(TARGET_NR_oldumount)
8673#if defined(TARGET_NR_umount)
bellard31e31b82003-02-18 22:55:36 +00008674 case TARGET_NR_umount:
Laurent Vivier6eb9dbf2020-05-02 21:46:42 +02008675#endif
8676#if defined(TARGET_NR_oldumount)
8677 case TARGET_NR_oldumount:
8678#endif
bellard579a97f2007-11-11 14:26:47 +00008679 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008680 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008681 ret = get_errno(umount(p));
8682 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008683 return ret;
thse5febef2007-04-01 18:31:35 +00008684#endif
j_mayer7a3148a2007-04-05 07:13:51 +00008685#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00008686 case TARGET_NR_stime:
8687 {
Laurent Vivier0f1f2d42019-11-12 15:25:56 +01008688 struct timespec ts;
8689 ts.tv_nsec = 0;
8690 if (get_user_sal(ts.tv_sec, arg1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008691 return -TARGET_EFAULT;
Laurent Vivier0f1f2d42019-11-12 15:25:56 +01008692 }
8693 return get_errno(clock_settime(CLOCK_REALTIME, &ts));
bellard31e31b82003-02-18 22:55:36 +00008694 }
j_mayer7a3148a2007-04-05 07:13:51 +00008695#endif
j_mayer7a3148a2007-04-05 07:13:51 +00008696#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00008697 case TARGET_NR_alarm:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008698 return alarm(arg1);
j_mayer7a3148a2007-04-05 07:13:51 +00008699#endif
j_mayer7a3148a2007-04-05 07:13:51 +00008700#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00008701 case TARGET_NR_pause:
Timothy E Baldwinf59ec602016-05-27 15:51:55 +01008702 if (!block_signals()) {
8703 sigsuspend(&((TaskState *)cpu->opaque)->signal_mask);
8704 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008705 return -TARGET_EINTR;
j_mayer7a3148a2007-04-05 07:13:51 +00008706#endif
thse5febef2007-04-01 18:31:35 +00008707#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00008708 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00008709 {
pbrook53a59602006-03-25 19:31:22 +00008710 struct utimbuf tbuf, *host_tbuf;
8711 struct target_utimbuf *target_tbuf;
8712 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00008713 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008714 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02008715 tbuf.actime = tswapal(target_tbuf->actime);
8716 tbuf.modtime = tswapal(target_tbuf->modtime);
pbrook53a59602006-03-25 19:31:22 +00008717 unlock_user_struct(target_tbuf, arg2, 0);
8718 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00008719 } else {
pbrook53a59602006-03-25 19:31:22 +00008720 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00008721 }
bellard579a97f2007-11-11 14:26:47 +00008722 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008723 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008724 ret = get_errno(utime(p, host_tbuf));
8725 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00008726 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008727 return ret;
thse5febef2007-04-01 18:31:35 +00008728#endif
Chen Gang704eff62015-08-21 05:37:33 +08008729#ifdef TARGET_NR_utimes
bellard978a66f2004-12-06 22:58:05 +00008730 case TARGET_NR_utimes:
8731 {
bellard978a66f2004-12-06 22:58:05 +00008732 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00008733 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00008734 if (copy_from_user_timeval(&tv[0], arg2)
8735 || copy_from_user_timeval(&tv[1],
8736 arg2 + sizeof(struct target_timeval)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008737 return -TARGET_EFAULT;
bellard978a66f2004-12-06 22:58:05 +00008738 tvp = tv;
8739 } else {
8740 tvp = NULL;
8741 }
bellard579a97f2007-11-11 14:26:47 +00008742 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008743 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008744 ret = get_errno(utimes(p, tvp));
8745 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00008746 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008747 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008748#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01008749#if defined(TARGET_NR_futimesat)
balrogac8a6552008-09-20 02:25:39 +00008750 case TARGET_NR_futimesat:
8751 {
8752 struct timeval *tvp, tv[2];
8753 if (arg3) {
8754 if (copy_from_user_timeval(&tv[0], arg3)
8755 || copy_from_user_timeval(&tv[1],
8756 arg3 + sizeof(struct target_timeval)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008757 return -TARGET_EFAULT;
balrogac8a6552008-09-20 02:25:39 +00008758 tvp = tv;
8759 } else {
8760 tvp = NULL;
8761 }
Richard Henderson2852aaf2018-08-18 12:01:06 -07008762 if (!(p = lock_user_string(arg2))) {
8763 return -TARGET_EFAULT;
8764 }
Peter Maydellc0d472b2013-06-12 16:20:21 +01008765 ret = get_errno(futimesat(arg1, path(p), tvp));
balrogac8a6552008-09-20 02:25:39 +00008766 unlock_user(p, arg2, 0);
8767 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008768 return ret;
balrogac8a6552008-09-20 02:25:39 +00008769#endif
Chen Gang704eff62015-08-21 05:37:33 +08008770#ifdef TARGET_NR_access
bellard31e31b82003-02-18 22:55:36 +00008771 case TARGET_NR_access:
Richard Henderson2852aaf2018-08-18 12:01:06 -07008772 if (!(p = lock_user_string(arg1))) {
8773 return -TARGET_EFAULT;
8774 }
Ulrich Hecht719f9082009-07-03 17:09:29 +02008775 ret = get_errno(access(path(p), arg2));
pbrook53a59602006-03-25 19:31:22 +00008776 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008777 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008778#endif
ths92a34c12007-09-24 09:27:49 +00008779#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
8780 case TARGET_NR_faccessat:
Richard Henderson2852aaf2018-08-18 12:01:06 -07008781 if (!(p = lock_user_string(arg2))) {
8782 return -TARGET_EFAULT;
8783 }
Peter Maydellc0d472b2013-06-12 16:20:21 +01008784 ret = get_errno(faccessat(arg1, p, arg3, 0));
bellard579a97f2007-11-11 14:26:47 +00008785 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008786 return ret;
ths92a34c12007-09-24 09:27:49 +00008787#endif
j_mayer7a3148a2007-04-05 07:13:51 +00008788#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00008789 case TARGET_NR_nice:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008790 return get_errno(nice(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +00008791#endif
bellard31e31b82003-02-18 22:55:36 +00008792 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00008793 sync();
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008794 return 0;
Aleksandar Markovic5a03cd02016-10-10 13:23:30 +02008795#if defined(TARGET_NR_syncfs) && defined(CONFIG_SYNCFS)
8796 case TARGET_NR_syncfs:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008797 return get_errno(syncfs(arg1));
Aleksandar Markovic5a03cd02016-10-10 13:23:30 +02008798#endif
bellard31e31b82003-02-18 22:55:36 +00008799 case TARGET_NR_kill:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008800 return get_errno(safe_kill(arg1, target_to_host_signal(arg2)));
Chen Gang704eff62015-08-21 05:37:33 +08008801#ifdef TARGET_NR_rename
bellard31e31b82003-02-18 22:55:36 +00008802 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00008803 {
8804 void *p2;
8805 p = lock_user_string(arg1);
8806 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00008807 if (!p || !p2)
8808 ret = -TARGET_EFAULT;
8809 else
8810 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00008811 unlock_user(p2, arg2, 0);
8812 unlock_user(p, arg1, 0);
8813 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008814 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008815#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01008816#if defined(TARGET_NR_renameat)
ths722183f2007-09-24 09:24:37 +00008817 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00008818 {
bellard579a97f2007-11-11 14:26:47 +00008819 void *p2;
ths722183f2007-09-24 09:24:37 +00008820 p = lock_user_string(arg2);
8821 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00008822 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00008823 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00008824 else
Peter Maydellc0d472b2013-06-12 16:20:21 +01008825 ret = get_errno(renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00008826 unlock_user(p2, arg4, 0);
8827 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00008828 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008829 return ret;
ths722183f2007-09-24 09:24:37 +00008830#endif
Andreas Schwab95d03072018-01-23 11:53:31 +01008831#if defined(TARGET_NR_renameat2)
8832 case TARGET_NR_renameat2:
8833 {
8834 void *p2;
8835 p = lock_user_string(arg2);
8836 p2 = lock_user_string(arg4);
8837 if (!p || !p2) {
8838 ret = -TARGET_EFAULT;
8839 } else {
8840 ret = get_errno(sys_renameat2(arg1, p, arg3, p2, arg5));
8841 }
8842 unlock_user(p2, arg4, 0);
8843 unlock_user(p, arg2, 0);
8844 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008845 return ret;
Andreas Schwab95d03072018-01-23 11:53:31 +01008846#endif
Chen Gang704eff62015-08-21 05:37:33 +08008847#ifdef TARGET_NR_mkdir
bellard31e31b82003-02-18 22:55:36 +00008848 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00008849 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008850 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008851 ret = get_errno(mkdir(p, arg2));
8852 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008853 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008854#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01008855#if defined(TARGET_NR_mkdirat)
ths4472ad02007-09-24 09:22:32 +00008856 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00008857 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008858 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01008859 ret = get_errno(mkdirat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00008860 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008861 return ret;
ths4472ad02007-09-24 09:22:32 +00008862#endif
Chen Gang704eff62015-08-21 05:37:33 +08008863#ifdef TARGET_NR_rmdir
bellard31e31b82003-02-18 22:55:36 +00008864 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00008865 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008866 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008867 ret = get_errno(rmdir(p));
8868 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008869 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008870#endif
bellard31e31b82003-02-18 22:55:36 +00008871 case TARGET_NR_dup:
8872 ret = get_errno(dup(arg1));
Laurent Viviere36800c2015-10-02 14:48:09 +02008873 if (ret >= 0) {
8874 fd_trans_dup(arg1, ret);
8875 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008876 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008877#ifdef TARGET_NR_pipe
bellard31e31b82003-02-18 22:55:36 +00008878 case TARGET_NR_pipe:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008879 return do_pipe(cpu_env, arg1, 0, 0);
Chen Gang704eff62015-08-21 05:37:33 +08008880#endif
Riku Voipio099d6b02009-05-05 12:10:04 +03008881#ifdef TARGET_NR_pipe2
8882 case TARGET_NR_pipe2:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008883 return do_pipe(cpu_env, arg1,
8884 target_to_host_bitmask(arg2, fcntl_flags_tbl), 1);
Riku Voipio099d6b02009-05-05 12:10:04 +03008885#endif
bellard31e31b82003-02-18 22:55:36 +00008886 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00008887 {
pbrook53a59602006-03-25 19:31:22 +00008888 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00008889 struct tms tms;
8890 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00008891 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00008892 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
8893 if (!tmsp)
Richard Henderson2852aaf2018-08-18 12:01:06 -07008894 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02008895 tmsp->tms_utime = tswapal(host_to_target_clock_t(tms.tms_utime));
8896 tmsp->tms_stime = tswapal(host_to_target_clock_t(tms.tms_stime));
8897 tmsp->tms_cutime = tswapal(host_to_target_clock_t(tms.tms_cutime));
8898 tmsp->tms_cstime = tswapal(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00008899 }
bellardc596ed12003-07-13 17:32:31 +00008900 if (!is_error(ret))
8901 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00008902 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008903 return ret;
bellard31e31b82003-02-18 22:55:36 +00008904 case TARGET_NR_acct:
aurel3238d840e2009-01-30 19:48:17 +00008905 if (arg1 == 0) {
8906 ret = get_errno(acct(NULL));
8907 } else {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008908 if (!(p = lock_user_string(arg1))) {
8909 return -TARGET_EFAULT;
8910 }
aurel3238d840e2009-01-30 19:48:17 +00008911 ret = get_errno(acct(path(p)));
8912 unlock_user(p, arg1, 0);
8913 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008914 return ret;
Richard Henderson8070e7b2013-07-24 09:50:00 -10008915#ifdef TARGET_NR_umount2
bellard31e31b82003-02-18 22:55:36 +00008916 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00008917 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008918 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008919 ret = get_errno(umount2(p, arg2));
8920 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008921 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00008922#endif
bellard31e31b82003-02-18 22:55:36 +00008923 case TARGET_NR_ioctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008924 return do_ioctl(arg1, arg2, arg3);
Michael Clark47ae93c2018-03-03 01:31:11 +13008925#ifdef TARGET_NR_fcntl
bellard31e31b82003-02-18 22:55:36 +00008926 case TARGET_NR_fcntl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008927 return do_fcntl(arg1, arg2, arg3);
Michael Clark47ae93c2018-03-03 01:31:11 +13008928#endif
bellard31e31b82003-02-18 22:55:36 +00008929 case TARGET_NR_setpgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008930 return get_errno(setpgid(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00008931 case TARGET_NR_umask:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008932 return get_errno(umask(arg1));
bellard31e31b82003-02-18 22:55:36 +00008933 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00008934 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008935 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008936 ret = get_errno(chroot(p));
8937 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008938 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008939#ifdef TARGET_NR_dup2
bellard31e31b82003-02-18 22:55:36 +00008940 case TARGET_NR_dup2:
8941 ret = get_errno(dup2(arg1, arg2));
Laurent Viviere36800c2015-10-02 14:48:09 +02008942 if (ret >= 0) {
8943 fd_trans_dup(arg1, arg2);
8944 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008945 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008946#endif
Ulrich Hechtd0927932009-09-17 20:22:14 +03008947#if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3)
8948 case TARGET_NR_dup3:
Peter Maydell10fa9932017-12-15 15:18:00 +00008949 {
8950 int host_flags;
8951
8952 if ((arg3 & ~TARGET_O_CLOEXEC) != 0) {
8953 return -EINVAL;
8954 }
8955 host_flags = target_to_host_bitmask(arg3, fcntl_flags_tbl);
8956 ret = get_errno(dup3(arg1, arg2, host_flags));
Laurent Viviere36800c2015-10-02 14:48:09 +02008957 if (ret >= 0) {
8958 fd_trans_dup(arg1, arg2);
8959 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008960 return ret;
Peter Maydell10fa9932017-12-15 15:18:00 +00008961 }
Ulrich Hechtd0927932009-09-17 20:22:14 +03008962#endif
j_mayer7a3148a2007-04-05 07:13:51 +00008963#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00008964 case TARGET_NR_getppid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008965 return get_errno(getppid());
j_mayer7a3148a2007-04-05 07:13:51 +00008966#endif
Chen Gang704eff62015-08-21 05:37:33 +08008967#ifdef TARGET_NR_getpgrp
bellard31e31b82003-02-18 22:55:36 +00008968 case TARGET_NR_getpgrp:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008969 return get_errno(getpgrp());
Chen Gang704eff62015-08-21 05:37:33 +08008970#endif
bellard31e31b82003-02-18 22:55:36 +00008971 case TARGET_NR_setsid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008972 return get_errno(setsid());
thse5febef2007-04-01 18:31:35 +00008973#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00008974 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00008975 {
Richard Henderson6049f4f2009-12-27 18:30:03 -08008976#if defined(TARGET_ALPHA)
8977 struct target_sigaction act, oact, *pact = 0;
pbrook53a59602006-03-25 19:31:22 +00008978 struct target_old_sigaction *old_act;
pbrook53a59602006-03-25 19:31:22 +00008979 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00008980 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008981 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +00008982 act._sa_handler = old_act->_sa_handler;
8983 target_siginitset(&act.sa_mask, old_act->sa_mask);
8984 act.sa_flags = old_act->sa_flags;
Richard Henderson6049f4f2009-12-27 18:30:03 -08008985 act.sa_restorer = 0;
pbrook53a59602006-03-25 19:31:22 +00008986 unlock_user_struct(old_act, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00008987 pact = &act;
bellard66fb9762003-03-23 01:06:05 +00008988 }
8989 ret = get_errno(do_sigaction(arg1, pact, &oact));
pbrook53a59602006-03-25 19:31:22 +00008990 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00008991 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008992 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008993 old_act->_sa_handler = oact._sa_handler;
8994 old_act->sa_mask = oact.sa_mask.sig[0];
8995 old_act->sa_flags = oact.sa_flags;
pbrook53a59602006-03-25 19:31:22 +00008996 unlock_user_struct(old_act, arg3, 1);
bellard66fb9762003-03-23 01:06:05 +00008997 }
Richard Henderson6049f4f2009-12-27 18:30:03 -08008998#elif defined(TARGET_MIPS)
bellard106ec872006-06-27 21:08:10 +00008999 struct target_sigaction act, oact, *pact, *old_act;
9000
9001 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00009002 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009003 return -TARGET_EFAULT;
bellard106ec872006-06-27 21:08:10 +00009004 act._sa_handler = old_act->_sa_handler;
9005 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
9006 act.sa_flags = old_act->sa_flags;
9007 unlock_user_struct(old_act, arg2, 0);
9008 pact = &act;
9009 } else {
9010 pact = NULL;
9011 }
9012
9013 ret = get_errno(do_sigaction(arg1, pact, &oact));
9014
9015 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00009016 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009017 return -TARGET_EFAULT;
bellard106ec872006-06-27 21:08:10 +00009018 old_act->_sa_handler = oact._sa_handler;
9019 old_act->sa_flags = oact.sa_flags;
9020 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
9021 old_act->sa_mask.sig[1] = 0;
9022 old_act->sa_mask.sig[2] = 0;
9023 old_act->sa_mask.sig[3] = 0;
9024 unlock_user_struct(old_act, arg3, 1);
9025 }
Richard Henderson6049f4f2009-12-27 18:30:03 -08009026#else
9027 struct target_old_sigaction *old_act;
9028 struct target_sigaction act, oact, *pact;
9029 if (arg2) {
9030 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009031 return -TARGET_EFAULT;
Richard Henderson6049f4f2009-12-27 18:30:03 -08009032 act._sa_handler = old_act->_sa_handler;
9033 target_siginitset(&act.sa_mask, old_act->sa_mask);
9034 act.sa_flags = old_act->sa_flags;
9035 act.sa_restorer = old_act->sa_restorer;
Laurent Vivier5de154e2018-04-02 12:24:52 +02009036#ifdef TARGET_ARCH_HAS_KA_RESTORER
9037 act.ka_restorer = 0;
9038#endif
Richard Henderson6049f4f2009-12-27 18:30:03 -08009039 unlock_user_struct(old_act, arg2, 0);
9040 pact = &act;
9041 } else {
9042 pact = NULL;
9043 }
9044 ret = get_errno(do_sigaction(arg1, pact, &oact));
9045 if (!is_error(ret) && arg3) {
9046 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009047 return -TARGET_EFAULT;
Richard Henderson6049f4f2009-12-27 18:30:03 -08009048 old_act->_sa_handler = oact._sa_handler;
9049 old_act->sa_mask = oact.sa_mask.sig[0];
9050 old_act->sa_flags = oact.sa_flags;
9051 old_act->sa_restorer = oact.sa_restorer;
9052 unlock_user_struct(old_act, arg3, 1);
9053 }
ths388bb212007-05-13 13:58:00 +00009054#endif
bellard31e31b82003-02-18 22:55:36 +00009055 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009056 return ret;
thse5febef2007-04-01 18:31:35 +00009057#endif
bellard66fb9762003-03-23 01:06:05 +00009058 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00009059 {
Richard Henderson6049f4f2009-12-27 18:30:03 -08009060#if defined(TARGET_ALPHA)
Peter Maydell78bfef72017-11-06 18:33:26 +00009061 /* For Alpha and SPARC this is a 5 argument syscall, with
9062 * a 'restorer' parameter which must be copied into the
9063 * sa_restorer field of the sigaction struct.
9064 * For Alpha that 'restorer' is arg5; for SPARC it is arg4,
9065 * and arg5 is the sigsetsize.
9066 * Alpha also has a separate rt_sigaction struct that it uses
9067 * here; SPARC uses the usual sigaction struct.
9068 */
Richard Henderson6049f4f2009-12-27 18:30:03 -08009069 struct target_rt_sigaction *rt_act;
Peter Maydell78bfef72017-11-06 18:33:26 +00009070 struct target_sigaction act, oact, *pact = 0;
Peter Maydellc8157012016-06-30 14:23:24 +01009071
9072 if (arg4 != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009073 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01009074 }
Richard Henderson6049f4f2009-12-27 18:30:03 -08009075 if (arg2) {
9076 if (!lock_user_struct(VERIFY_READ, rt_act, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009077 return -TARGET_EFAULT;
Richard Henderson6049f4f2009-12-27 18:30:03 -08009078 act._sa_handler = rt_act->_sa_handler;
9079 act.sa_mask = rt_act->sa_mask;
9080 act.sa_flags = rt_act->sa_flags;
9081 act.sa_restorer = arg5;
9082 unlock_user_struct(rt_act, arg2, 0);
9083 pact = &act;
9084 }
9085 ret = get_errno(do_sigaction(arg1, pact, &oact));
9086 if (!is_error(ret) && arg3) {
9087 if (!lock_user_struct(VERIFY_WRITE, rt_act, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009088 return -TARGET_EFAULT;
Richard Henderson6049f4f2009-12-27 18:30:03 -08009089 rt_act->_sa_handler = oact._sa_handler;
9090 rt_act->sa_mask = oact.sa_mask;
9091 rt_act->sa_flags = oact.sa_flags;
9092 unlock_user_struct(rt_act, arg3, 1);
9093 }
9094#else
Peter Maydell78bfef72017-11-06 18:33:26 +00009095#ifdef TARGET_SPARC
9096 target_ulong restorer = arg4;
9097 target_ulong sigsetsize = arg5;
9098#else
9099 target_ulong sigsetsize = arg4;
9100#endif
pbrook53a59602006-03-25 19:31:22 +00009101 struct target_sigaction *act;
9102 struct target_sigaction *oact;
9103
Peter Maydell78bfef72017-11-06 18:33:26 +00009104 if (sigsetsize != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009105 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01009106 }
bellard579a97f2007-11-11 14:26:47 +00009107 if (arg2) {
Peter Maydell78bfef72017-11-06 18:33:26 +00009108 if (!lock_user_struct(VERIFY_READ, act, arg2, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009109 return -TARGET_EFAULT;
Peter Maydell78bfef72017-11-06 18:33:26 +00009110 }
Laurent Vivier5de154e2018-04-02 12:24:52 +02009111#ifdef TARGET_ARCH_HAS_KA_RESTORER
9112 act->ka_restorer = restorer;
Peter Maydell78bfef72017-11-06 18:33:26 +00009113#endif
9114 } else {
pbrook53a59602006-03-25 19:31:22 +00009115 act = NULL;
Peter Maydell78bfef72017-11-06 18:33:26 +00009116 }
bellard579a97f2007-11-11 14:26:47 +00009117 if (arg3) {
9118 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
9119 ret = -TARGET_EFAULT;
9120 goto rt_sigaction_fail;
9121 }
9122 } else
pbrook53a59602006-03-25 19:31:22 +00009123 oact = NULL;
9124 ret = get_errno(do_sigaction(arg1, act, oact));
bellard579a97f2007-11-11 14:26:47 +00009125 rt_sigaction_fail:
9126 if (act)
pbrook53a59602006-03-25 19:31:22 +00009127 unlock_user_struct(act, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +00009128 if (oact)
pbrook53a59602006-03-25 19:31:22 +00009129 unlock_user_struct(oact, arg3, 1);
Richard Henderson6049f4f2009-12-27 18:30:03 -08009130#endif
pbrook53a59602006-03-25 19:31:22 +00009131 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009132 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00009133#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009134 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00009135 {
9136 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00009137 abi_ulong target_set;
Peter Maydell3d3efba2016-05-27 15:51:49 +01009138 ret = do_sigprocmask(0, NULL, &cur_set);
9139 if (!ret) {
9140 host_to_target_old_sigset(&target_set, &cur_set);
9141 ret = target_set;
9142 }
bellard66fb9762003-03-23 01:06:05 +00009143 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009144 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00009145#endif
9146#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009147 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00009148 {
Miloš Stojanovića8617d82017-05-15 16:59:43 +02009149 sigset_t set, oset;
blueswir1992f48a2007-10-14 16:27:31 +00009150 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00009151 target_to_host_old_sigset(&set, &target_set);
Peter Maydell3d3efba2016-05-27 15:51:49 +01009152 ret = do_sigprocmask(SIG_SETMASK, &set, &oset);
9153 if (!ret) {
9154 host_to_target_old_sigset(&target_set, &oset);
9155 ret = target_set;
9156 }
bellard66fb9762003-03-23 01:06:05 +00009157 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009158 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00009159#endif
thse5febef2007-04-01 18:31:35 +00009160#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00009161 case TARGET_NR_sigprocmask:
9162 {
Richard Hendersona5b3b132010-05-03 10:07:55 -07009163#if defined(TARGET_ALPHA)
9164 sigset_t set, oldset;
9165 abi_ulong mask;
9166 int how;
9167
9168 switch (arg1) {
9169 case TARGET_SIG_BLOCK:
9170 how = SIG_BLOCK;
9171 break;
9172 case TARGET_SIG_UNBLOCK:
9173 how = SIG_UNBLOCK;
9174 break;
9175 case TARGET_SIG_SETMASK:
9176 how = SIG_SETMASK;
9177 break;
9178 default:
Richard Henderson259841c2018-08-18 12:01:09 -07009179 return -TARGET_EINVAL;
Richard Hendersona5b3b132010-05-03 10:07:55 -07009180 }
9181 mask = arg2;
9182 target_to_host_old_sigset(&set, &mask);
9183
Peter Maydell3d3efba2016-05-27 15:51:49 +01009184 ret = do_sigprocmask(how, &set, &oldset);
Richard Hendersona5b3b132010-05-03 10:07:55 -07009185 if (!is_error(ret)) {
9186 host_to_target_old_sigset(&mask, &oldset);
9187 ret = mask;
Richard Henderson0229f5a2012-06-07 15:02:49 -07009188 ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0; /* force no error */
Richard Hendersona5b3b132010-05-03 10:07:55 -07009189 }
9190#else
bellard66fb9762003-03-23 01:06:05 +00009191 sigset_t set, oldset, *set_ptr;
Richard Hendersona5b3b132010-05-03 10:07:55 -07009192 int how;
ths3b46e622007-09-17 08:09:54 +00009193
pbrook53a59602006-03-25 19:31:22 +00009194 if (arg2) {
Richard Hendersona5b3b132010-05-03 10:07:55 -07009195 switch (arg1) {
bellard66fb9762003-03-23 01:06:05 +00009196 case TARGET_SIG_BLOCK:
9197 how = SIG_BLOCK;
9198 break;
9199 case TARGET_SIG_UNBLOCK:
9200 how = SIG_UNBLOCK;
9201 break;
9202 case TARGET_SIG_SETMASK:
9203 how = SIG_SETMASK;
9204 break;
9205 default:
Richard Henderson259841c2018-08-18 12:01:09 -07009206 return -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00009207 }
Anthony Liguoric227f092009-10-01 16:12:16 -05009208 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009209 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009210 target_to_host_old_sigset(&set, p);
9211 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00009212 set_ptr = &set;
9213 } else {
9214 how = 0;
9215 set_ptr = NULL;
9216 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01009217 ret = do_sigprocmask(how, set_ptr, &oldset);
pbrook53a59602006-03-25 19:31:22 +00009218 if (!is_error(ret) && arg3) {
Anthony Liguoric227f092009-10-01 16:12:16 -05009219 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009220 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009221 host_to_target_old_sigset(p, &oldset);
Anthony Liguoric227f092009-10-01 16:12:16 -05009222 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00009223 }
Richard Hendersona5b3b132010-05-03 10:07:55 -07009224#endif
bellard66fb9762003-03-23 01:06:05 +00009225 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009226 return ret;
thse5febef2007-04-01 18:31:35 +00009227#endif
bellard66fb9762003-03-23 01:06:05 +00009228 case TARGET_NR_rt_sigprocmask:
9229 {
9230 int how = arg1;
9231 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00009232
Peter Maydellc8157012016-06-30 14:23:24 +01009233 if (arg4 != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009234 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01009235 }
9236
pbrook53a59602006-03-25 19:31:22 +00009237 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00009238 switch(how) {
9239 case TARGET_SIG_BLOCK:
9240 how = SIG_BLOCK;
9241 break;
9242 case TARGET_SIG_UNBLOCK:
9243 how = SIG_UNBLOCK;
9244 break;
9245 case TARGET_SIG_SETMASK:
9246 how = SIG_SETMASK;
9247 break;
9248 default:
Richard Henderson259841c2018-08-18 12:01:09 -07009249 return -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00009250 }
Anthony Liguoric227f092009-10-01 16:12:16 -05009251 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009252 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009253 target_to_host_sigset(&set, p);
9254 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00009255 set_ptr = &set;
9256 } else {
9257 how = 0;
9258 set_ptr = NULL;
9259 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01009260 ret = do_sigprocmask(how, set_ptr, &oldset);
pbrook53a59602006-03-25 19:31:22 +00009261 if (!is_error(ret) && arg3) {
Anthony Liguoric227f092009-10-01 16:12:16 -05009262 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009263 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009264 host_to_target_sigset(p, &oldset);
Anthony Liguoric227f092009-10-01 16:12:16 -05009265 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00009266 }
9267 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009268 return ret;
thse5febef2007-04-01 18:31:35 +00009269#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00009270 case TARGET_NR_sigpending:
9271 {
9272 sigset_t set;
9273 ret = get_errno(sigpending(&set));
9274 if (!is_error(ret)) {
Anthony Liguoric227f092009-10-01 16:12:16 -05009275 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009276 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009277 host_to_target_old_sigset(p, &set);
Anthony Liguoric227f092009-10-01 16:12:16 -05009278 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00009279 }
9280 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009281 return ret;
thse5febef2007-04-01 18:31:35 +00009282#endif
bellard66fb9762003-03-23 01:06:05 +00009283 case TARGET_NR_rt_sigpending:
9284 {
9285 sigset_t set;
Peter Maydellc8157012016-06-30 14:23:24 +01009286
9287 /* Yes, this check is >, not != like most. We follow the kernel's
9288 * logic and it does it like this because it implements
9289 * NR_sigpending through the same code path, and in that case
9290 * the old_sigset_t is smaller in size.
9291 */
9292 if (arg2 > sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009293 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01009294 }
9295
bellard66fb9762003-03-23 01:06:05 +00009296 ret = get_errno(sigpending(&set));
9297 if (!is_error(ret)) {
Anthony Liguoric227f092009-10-01 16:12:16 -05009298 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009299 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009300 host_to_target_sigset(p, &set);
Anthony Liguoric227f092009-10-01 16:12:16 -05009301 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00009302 }
9303 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009304 return ret;
thse5febef2007-04-01 18:31:35 +00009305#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00009306 case TARGET_NR_sigsuspend:
9307 {
Peter Maydell3d3efba2016-05-27 15:51:49 +01009308 TaskState *ts = cpu->opaque;
Richard Hendersonf43ce122010-05-03 10:07:54 -07009309#if defined(TARGET_ALPHA)
9310 abi_ulong mask = arg1;
Peter Maydell3d3efba2016-05-27 15:51:49 +01009311 target_to_host_old_sigset(&ts->sigsuspend_mask, &mask);
Richard Hendersonf43ce122010-05-03 10:07:54 -07009312#else
Anthony Liguoric227f092009-10-01 16:12:16 -05009313 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009314 return -TARGET_EFAULT;
Peter Maydell3d3efba2016-05-27 15:51:49 +01009315 target_to_host_old_sigset(&ts->sigsuspend_mask, p);
pbrook53a59602006-03-25 19:31:22 +00009316 unlock_user(p, arg1, 0);
Richard Hendersonf43ce122010-05-03 10:07:54 -07009317#endif
Peter Maydell3d3efba2016-05-27 15:51:49 +01009318 ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
9319 SIGSET_T_SIZE));
9320 if (ret != -TARGET_ERESTARTSYS) {
9321 ts->in_sigsuspend = 1;
9322 }
bellard66fb9762003-03-23 01:06:05 +00009323 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009324 return ret;
thse5febef2007-04-01 18:31:35 +00009325#endif
bellard66fb9762003-03-23 01:06:05 +00009326 case TARGET_NR_rt_sigsuspend:
9327 {
Peter Maydell3d3efba2016-05-27 15:51:49 +01009328 TaskState *ts = cpu->opaque;
Peter Maydellc8157012016-06-30 14:23:24 +01009329
9330 if (arg2 != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009331 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01009332 }
Anthony Liguoric227f092009-10-01 16:12:16 -05009333 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009334 return -TARGET_EFAULT;
Peter Maydell3d3efba2016-05-27 15:51:49 +01009335 target_to_host_sigset(&ts->sigsuspend_mask, p);
pbrook53a59602006-03-25 19:31:22 +00009336 unlock_user(p, arg1, 0);
Peter Maydell3d3efba2016-05-27 15:51:49 +01009337 ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
9338 SIGSET_T_SIZE));
9339 if (ret != -TARGET_ERESTARTSYS) {
9340 ts->in_sigsuspend = 1;
9341 }
bellard66fb9762003-03-23 01:06:05 +00009342 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009343 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -07009344#ifdef TARGET_NR_rt_sigtimedwait
bellard66fb9762003-03-23 01:06:05 +00009345 case TARGET_NR_rt_sigtimedwait:
9346 {
bellard66fb9762003-03-23 01:06:05 +00009347 sigset_t set;
9348 struct timespec uts, *puts;
9349 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00009350
Peter Maydellc8157012016-06-30 14:23:24 +01009351 if (arg4 != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009352 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01009353 }
9354
Anthony Liguoric227f092009-10-01 16:12:16 -05009355 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009356 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009357 target_to_host_sigset(&set, p);
9358 unlock_user(p, arg1, 0);
9359 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00009360 puts = &uts;
Filip Bozuta4d213002020-07-24 20:16:51 +02009361 if (target_to_host_timespec(puts, arg3)) {
9362 return -TARGET_EFAULT;
9363 }
bellard66fb9762003-03-23 01:06:05 +00009364 } else {
9365 puts = NULL;
9366 }
Peter Maydellb3f82332016-06-06 19:58:08 +01009367 ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts,
9368 SIGSET_T_SIZE));
Petar Jovanovic974a1962014-03-03 15:07:41 +01009369 if (!is_error(ret)) {
9370 if (arg2) {
9371 p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t),
9372 0);
9373 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009374 return -TARGET_EFAULT;
Petar Jovanovic974a1962014-03-03 15:07:41 +01009375 }
9376 host_to_target_siginfo(p, &uinfo);
9377 unlock_user(p, arg2, sizeof(target_siginfo_t));
9378 }
9379 ret = host_to_target_signal(ret);
bellard66fb9762003-03-23 01:06:05 +00009380 }
9381 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009382 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -07009383#endif
Filip Bozutaddcbde12020-08-24 21:21:16 +02009384#ifdef TARGET_NR_rt_sigtimedwait_time64
9385 case TARGET_NR_rt_sigtimedwait_time64:
9386 {
9387 sigset_t set;
9388 struct timespec uts, *puts;
9389 siginfo_t uinfo;
9390
9391 if (arg4 != sizeof(target_sigset_t)) {
9392 return -TARGET_EINVAL;
9393 }
9394
9395 p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
9396 if (!p) {
9397 return -TARGET_EFAULT;
9398 }
9399 target_to_host_sigset(&set, p);
9400 unlock_user(p, arg1, 0);
9401 if (arg3) {
9402 puts = &uts;
9403 if (target_to_host_timespec64(puts, arg3)) {
9404 return -TARGET_EFAULT;
9405 }
9406 } else {
9407 puts = NULL;
9408 }
9409 ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts,
9410 SIGSET_T_SIZE));
9411 if (!is_error(ret)) {
9412 if (arg2) {
9413 p = lock_user(VERIFY_WRITE, arg2,
9414 sizeof(target_siginfo_t), 0);
9415 if (!p) {
9416 return -TARGET_EFAULT;
9417 }
9418 host_to_target_siginfo(p, &uinfo);
9419 unlock_user(p, arg2, sizeof(target_siginfo_t));
9420 }
9421 ret = host_to_target_signal(ret);
9422 }
9423 }
9424 return ret;
9425#endif
bellard66fb9762003-03-23 01:06:05 +00009426 case TARGET_NR_rt_sigqueueinfo:
9427 {
9428 siginfo_t uinfo;
Peter Maydell4debae62016-06-20 15:50:36 +01009429
9430 p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
9431 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009432 return -TARGET_EFAULT;
Peter Maydell4debae62016-06-20 15:50:36 +01009433 }
pbrook53a59602006-03-25 19:31:22 +00009434 target_to_host_siginfo(&uinfo, p);
Miloš Stojanovićd8b6d892017-05-15 16:59:44 +02009435 unlock_user(p, arg3, 0);
bellard66fb9762003-03-23 01:06:05 +00009436 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
9437 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009438 return ret;
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +02009439 case TARGET_NR_rt_tgsigqueueinfo:
9440 {
9441 siginfo_t uinfo;
9442
9443 p = lock_user(VERIFY_READ, arg4, sizeof(target_siginfo_t), 1);
9444 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009445 return -TARGET_EFAULT;
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +02009446 }
9447 target_to_host_siginfo(&uinfo, p);
9448 unlock_user(p, arg4, 0);
9449 ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, arg3, &uinfo));
9450 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009451 return ret;
thse5febef2007-04-01 18:31:35 +00009452#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00009453 case TARGET_NR_sigreturn:
Peter Maydell3d3efba2016-05-27 15:51:49 +01009454 if (block_signals()) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009455 return -TARGET_ERESTARTSYS;
Peter Maydell3d3efba2016-05-27 15:51:49 +01009456 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009457 return do_sigreturn(cpu_env);
thse5febef2007-04-01 18:31:35 +00009458#endif
bellard66fb9762003-03-23 01:06:05 +00009459 case TARGET_NR_rt_sigreturn:
Peter Maydell3d3efba2016-05-27 15:51:49 +01009460 if (block_signals()) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009461 return -TARGET_ERESTARTSYS;
Peter Maydell3d3efba2016-05-27 15:51:49 +01009462 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009463 return do_rt_sigreturn(cpu_env);
bellard31e31b82003-02-18 22:55:36 +00009464 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00009465 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009466 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009467 ret = get_errno(sethostname(p, arg2));
9468 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009469 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009470#ifdef TARGET_NR_setrlimit
bellard31e31b82003-02-18 22:55:36 +00009471 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +00009472 {
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03009473 int resource = target_to_host_resource(arg1);
pbrook53a59602006-03-25 19:31:22 +00009474 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00009475 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +00009476 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009477 return -TARGET_EFAULT;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09009478 rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
9479 rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00009480 unlock_user_struct(target_rlim, arg2, 0);
Max Filippov5dfa88f2018-09-17 11:13:14 -07009481 /*
9482 * If we just passed through resource limit settings for memory then
9483 * they would also apply to QEMU's own allocations, and QEMU will
9484 * crash or hang or die if its allocations fail. Ideally we would
9485 * track the guest allocations in QEMU and apply the limits ourselves.
9486 * For now, just tell the guest the call succeeded but don't actually
9487 * limit anything.
9488 */
9489 if (resource != RLIMIT_AS &&
9490 resource != RLIMIT_DATA &&
9491 resource != RLIMIT_STACK) {
9492 return get_errno(setrlimit(resource, &rlim));
9493 } else {
9494 return 0;
9495 }
bellard9de5e442003-03-23 16:49:39 +00009496 }
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009497#endif
9498#ifdef TARGET_NR_getrlimit
bellard31e31b82003-02-18 22:55:36 +00009499 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00009500 {
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03009501 int resource = target_to_host_resource(arg1);
pbrook53a59602006-03-25 19:31:22 +00009502 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00009503 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00009504
bellard9de5e442003-03-23 16:49:39 +00009505 ret = get_errno(getrlimit(resource, &rlim));
9506 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00009507 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009508 return -TARGET_EFAULT;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09009509 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
9510 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00009511 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00009512 }
9513 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009514 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009515#endif
bellard31e31b82003-02-18 22:55:36 +00009516 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00009517 {
9518 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00009519 ret = get_errno(getrusage(arg1, &rusage));
9520 if (!is_error(ret)) {
Petar Jovanovica39fb272014-04-08 19:24:30 +02009521 ret = host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00009522 }
9523 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009524 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -07009525#if defined(TARGET_NR_gettimeofday)
bellard31e31b82003-02-18 22:55:36 +00009526 case TARGET_NR_gettimeofday:
9527 {
bellard31e31b82003-02-18 22:55:36 +00009528 struct timeval tv;
Richard Hendersona52f5f82020-02-12 19:22:23 -08009529 struct timezone tz;
9530
9531 ret = get_errno(gettimeofday(&tv, &tz));
bellard31e31b82003-02-18 22:55:36 +00009532 if (!is_error(ret)) {
Richard Hendersona52f5f82020-02-12 19:22:23 -08009533 if (arg1 && copy_to_user_timeval(arg1, &tv)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009534 return -TARGET_EFAULT;
Richard Hendersona52f5f82020-02-12 19:22:23 -08009535 }
9536 if (arg2 && copy_to_user_timezone(arg2, &tz)) {
9537 return -TARGET_EFAULT;
9538 }
bellard31e31b82003-02-18 22:55:36 +00009539 }
9540 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009541 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -07009542#endif
9543#if defined(TARGET_NR_settimeofday)
bellard31e31b82003-02-18 22:55:36 +00009544 case TARGET_NR_settimeofday:
9545 {
Paul Burtonb67d8032014-06-22 11:25:41 +01009546 struct timeval tv, *ptv = NULL;
Paul Burtonef4467e2014-06-22 11:25:40 +01009547 struct timezone tz, *ptz = NULL;
9548
Paul Burtonb67d8032014-06-22 11:25:41 +01009549 if (arg1) {
9550 if (copy_from_user_timeval(&tv, arg1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009551 return -TARGET_EFAULT;
Paul Burtonb67d8032014-06-22 11:25:41 +01009552 }
9553 ptv = &tv;
9554 }
Paul Burtonef4467e2014-06-22 11:25:40 +01009555
9556 if (arg2) {
9557 if (copy_from_user_timezone(&tz, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009558 return -TARGET_EFAULT;
Paul Burtonef4467e2014-06-22 11:25:40 +01009559 }
9560 ptz = &tz;
9561 }
9562
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009563 return get_errno(settimeofday(ptv, ptz));
bellard31e31b82003-02-18 22:55:36 +00009564 }
Alistair Francis859e8a82020-03-12 15:13:49 -07009565#endif
Laurent Vivier9468a5d2013-01-10 22:30:50 +01009566#if defined(TARGET_NR_select)
bellard31e31b82003-02-18 22:55:36 +00009567 case TARGET_NR_select:
Laurent Vivier5457dc92016-07-08 01:17:27 +02009568#if defined(TARGET_WANT_NI_OLD_SELECT)
9569 /* some architectures used to have old_select here
9570 * but now ENOSYS it.
9571 */
9572 ret = -TARGET_ENOSYS;
9573#elif defined(TARGET_WANT_OLD_SYS_SELECT)
9574 ret = do_old_select(arg1);
Laurent Vivier9468a5d2013-01-10 22:30:50 +01009575#else
Laurent Vivier5457dc92016-07-08 01:17:27 +02009576 ret = do_select(arg1, arg2, arg3, arg4, arg5);
Laurent Vivier9468a5d2013-01-10 22:30:50 +01009577#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009578 return ret;
bellard048f6b42005-11-26 18:47:20 +00009579#endif
Riku Voipio9e423822010-05-07 12:28:05 +00009580#ifdef TARGET_NR_pselect6
9581 case TARGET_NR_pselect6:
Filip Bozutae5ce9682020-08-25 00:30:49 +02009582 return do_pselect6(arg1, arg2, arg3, arg4, arg5, arg6, false);
9583#endif
9584#ifdef TARGET_NR_pselect6_time64
9585 case TARGET_NR_pselect6_time64:
9586 return do_pselect6(arg1, arg2, arg3, arg4, arg5, arg6, true);
Riku Voipio9e423822010-05-07 12:28:05 +00009587#endif
Chen Gang704eff62015-08-21 05:37:33 +08009588#ifdef TARGET_NR_symlink
bellard31e31b82003-02-18 22:55:36 +00009589 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00009590 {
9591 void *p2;
9592 p = lock_user_string(arg1);
9593 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00009594 if (!p || !p2)
9595 ret = -TARGET_EFAULT;
9596 else
9597 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00009598 unlock_user(p2, arg2, 0);
9599 unlock_user(p, arg1, 0);
9600 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009601 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009602#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01009603#if defined(TARGET_NR_symlinkat)
thsf0b62432007-09-24 09:25:40 +00009604 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00009605 {
bellard579a97f2007-11-11 14:26:47 +00009606 void *p2;
thsf0b62432007-09-24 09:25:40 +00009607 p = lock_user_string(arg1);
9608 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00009609 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00009610 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00009611 else
Peter Maydellc0d472b2013-06-12 16:20:21 +01009612 ret = get_errno(symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00009613 unlock_user(p2, arg3, 0);
9614 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00009615 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009616 return ret;
thsf0b62432007-09-24 09:25:40 +00009617#endif
Chen Gang704eff62015-08-21 05:37:33 +08009618#ifdef TARGET_NR_readlink
bellard31e31b82003-02-18 22:55:36 +00009619 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00009620 {
Andreas Schwab463d8e72013-07-02 14:04:12 +01009621 void *p2;
pbrook53a59602006-03-25 19:31:22 +00009622 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00009623 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
Andreas Schwab463d8e72013-07-02 14:04:12 +01009624 if (!p || !p2) {
bellard579a97f2007-11-11 14:26:47 +00009625 ret = -TARGET_EFAULT;
Mike Frysingerf17f4982014-08-08 09:40:25 +09009626 } else if (!arg3) {
9627 /* Short circuit this for the magic exe check. */
9628 ret = -TARGET_EINVAL;
Andreas Schwab463d8e72013-07-02 14:04:12 +01009629 } else if (is_proc_myself((const char *)p, "exe")) {
9630 char real[PATH_MAX], *temp;
9631 temp = realpath(exec_path, real);
Mike Frysingerf17f4982014-08-08 09:40:25 +09009632 /* Return value is # of bytes that we wrote to the buffer. */
9633 if (temp == NULL) {
9634 ret = get_errno(-1);
9635 } else {
9636 /* Don't worry about sign mismatch as earlier mapping
9637 * logic would have thrown a bad address error. */
9638 ret = MIN(strlen(real), arg3);
9639 /* We cannot NUL terminate the string. */
9640 memcpy(p2, real, ret);
9641 }
Andreas Schwab463d8e72013-07-02 14:04:12 +01009642 } else {
9643 ret = get_errno(readlink(path(p), p2, arg3));
aurel32d088d662009-01-30 20:09:01 +00009644 }
pbrook53a59602006-03-25 19:31:22 +00009645 unlock_user(p2, arg2, ret);
9646 unlock_user(p, arg1, 0);
9647 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009648 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009649#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01009650#if defined(TARGET_NR_readlinkat)
ths5e0ccb12007-09-24 09:26:10 +00009651 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +00009652 {
bellard579a97f2007-11-11 14:26:47 +00009653 void *p2;
ths5e0ccb12007-09-24 09:26:10 +00009654 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00009655 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
Andreas Schwab463d8e72013-07-02 14:04:12 +01009656 if (!p || !p2) {
9657 ret = -TARGET_EFAULT;
9658 } else if (is_proc_myself((const char *)p, "exe")) {
9659 char real[PATH_MAX], *temp;
9660 temp = realpath(exec_path, real);
9661 ret = temp == NULL ? get_errno(-1) : strlen(real) ;
9662 snprintf((char *)p2, arg4, "%s", real);
9663 } else {
Peter Maydellc0d472b2013-06-12 16:20:21 +01009664 ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
Andreas Schwab463d8e72013-07-02 14:04:12 +01009665 }
bellard579a97f2007-11-11 14:26:47 +00009666 unlock_user(p2, arg3, ret);
9667 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +00009668 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009669 return ret;
ths5e0ccb12007-09-24 09:26:10 +00009670#endif
thse5febef2007-04-01 18:31:35 +00009671#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +00009672 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +00009673 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009674 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009675 ret = get_errno(swapon(p, arg2));
9676 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009677 return ret;
thse5febef2007-04-01 18:31:35 +00009678#endif
bellard31e31b82003-02-18 22:55:36 +00009679 case TARGET_NR_reboot:
Laurent Vivierc07ecc62013-01-07 11:40:06 +00009680 if (arg3 == LINUX_REBOOT_CMD_RESTART2) {
9681 /* arg4 must be ignored in all other cases */
9682 p = lock_user_string(arg4);
9683 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009684 return -TARGET_EFAULT;
Laurent Vivierc07ecc62013-01-07 11:40:06 +00009685 }
9686 ret = get_errno(reboot(arg1, arg2, arg3, p));
9687 unlock_user(p, arg4, 0);
9688 } else {
9689 ret = get_errno(reboot(arg1, arg2, arg3, NULL));
9690 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009691 return ret;
thse5febef2007-04-01 18:31:35 +00009692#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +00009693 case TARGET_NR_mmap:
Alexander Graf09701192013-09-03 20:12:15 +01009694#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
9695 (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
Ulrich Hechta4c075f2009-07-24 16:57:31 +02009696 defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \
9697 || defined(TARGET_S390X)
bellard31e31b82003-02-18 22:55:36 +00009698 {
blueswir1992f48a2007-10-14 16:27:31 +00009699 abi_ulong *v;
9700 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +00009701 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009702 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02009703 v1 = tswapal(v[0]);
9704 v2 = tswapal(v[1]);
9705 v3 = tswapal(v[2]);
9706 v4 = tswapal(v[3]);
9707 v5 = tswapal(v[4]);
9708 v6 = tswapal(v[5]);
pbrook53a59602006-03-25 19:31:22 +00009709 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +00009710 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +00009711 target_to_host_bitmask(v4, mmap_flags_tbl),
9712 v5, v6));
bellard31e31b82003-02-18 22:55:36 +00009713 }
bellard31e31b82003-02-18 22:55:36 +00009714#else
Richard Hendersonee1bf832021-02-12 10:48:44 -08009715 /* mmap pointers are always untagged */
ths5fafdf22007-09-16 21:08:06 +00009716 ret = get_errno(target_mmap(arg1, arg2, arg3,
9717 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +00009718 arg5,
9719 arg6));
bellard31e31b82003-02-18 22:55:36 +00009720#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009721 return ret;
thse5febef2007-04-01 18:31:35 +00009722#endif
bellarda315a142005-01-30 22:59:18 +00009723#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +00009724 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +00009725#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +00009726#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +00009727#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009728 ret = target_mmap(arg1, arg2, arg3,
9729 target_to_host_bitmask(arg4, mmap_flags_tbl),
9730 arg5, arg6 << MMAP_SHIFT);
9731 return get_errno(ret);
bellarda315a142005-01-30 22:59:18 +00009732#endif
bellard31e31b82003-02-18 22:55:36 +00009733 case TARGET_NR_munmap:
Richard Hendersonee1bf832021-02-12 10:48:44 -08009734 arg1 = cpu_untagged_addr(cpu, arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009735 return get_errno(target_munmap(arg1, arg2));
bellard9de5e442003-03-23 16:49:39 +00009736 case TARGET_NR_mprotect:
Richard Hendersonee1bf832021-02-12 10:48:44 -08009737 arg1 = cpu_untagged_addr(cpu, arg1);
Paul Brook97374d32010-06-16 13:03:51 +01009738 {
Andreas Färber0429a972013-08-26 18:14:44 +02009739 TaskState *ts = cpu->opaque;
Paul Brook97374d32010-06-16 13:03:51 +01009740 /* Special hack to detect libc making the stack executable. */
9741 if ((arg3 & PROT_GROWSDOWN)
9742 && arg1 >= ts->info->stack_limit
9743 && arg1 <= ts->info->start_stack) {
9744 arg3 &= ~PROT_GROWSDOWN;
9745 arg2 = arg2 + arg1 - ts->info->stack_limit;
9746 arg1 = ts->info->stack_limit;
9747 }
9748 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009749 return get_errno(target_mprotect(arg1, arg2, arg3));
thse5febef2007-04-01 18:31:35 +00009750#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +00009751 case TARGET_NR_mremap:
Richard Hendersonee1bf832021-02-12 10:48:44 -08009752 arg1 = cpu_untagged_addr(cpu, arg1);
9753 /* mremap new_addr (arg5) is always untagged */
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009754 return get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
thse5febef2007-04-01 18:31:35 +00009755#endif
pbrook53a59602006-03-25 19:31:22 +00009756 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +00009757#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +00009758 case TARGET_NR_msync:
Richard Henderson3e8f1622021-02-12 10:48:43 -08009759 return get_errno(msync(g2h(cpu, arg1), arg2, arg3));
thse5febef2007-04-01 18:31:35 +00009760#endif
9761#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +00009762 case TARGET_NR_mlock:
Richard Henderson3e8f1622021-02-12 10:48:43 -08009763 return get_errno(mlock(g2h(cpu, arg1), arg2));
thse5febef2007-04-01 18:31:35 +00009764#endif
9765#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +00009766 case TARGET_NR_munlock:
Richard Henderson3e8f1622021-02-12 10:48:43 -08009767 return get_errno(munlock(g2h(cpu, arg1), arg2));
thse5febef2007-04-01 18:31:35 +00009768#endif
9769#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +00009770 case TARGET_NR_mlockall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009771 return get_errno(mlockall(target_to_host_mlockall_arg(arg1)));
thse5febef2007-04-01 18:31:35 +00009772#endif
9773#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +00009774 case TARGET_NR_munlockall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009775 return get_errno(munlockall());
thse5febef2007-04-01 18:31:35 +00009776#endif
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009777#ifdef TARGET_NR_truncate
bellard31e31b82003-02-18 22:55:36 +00009778 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +00009779 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009780 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009781 ret = get_errno(truncate(p, arg2));
9782 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009783 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009784#endif
9785#ifdef TARGET_NR_ftruncate
bellard31e31b82003-02-18 22:55:36 +00009786 case TARGET_NR_ftruncate:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009787 return get_errno(ftruncate(arg1, arg2));
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009788#endif
bellard31e31b82003-02-18 22:55:36 +00009789 case TARGET_NR_fchmod:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009790 return get_errno(fchmod(arg1, arg2));
Peter Maydellc0d472b2013-06-12 16:20:21 +01009791#if defined(TARGET_NR_fchmodat)
ths814d7972007-09-24 09:26:51 +00009792 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +00009793 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009794 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01009795 ret = get_errno(fchmodat(arg1, p, arg3, 0));
bellard579a97f2007-11-11 14:26:47 +00009796 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009797 return ret;
ths814d7972007-09-24 09:26:51 +00009798#endif
bellard31e31b82003-02-18 22:55:36 +00009799 case TARGET_NR_getpriority:
Richard Henderson95c09822012-06-07 15:14:50 -07009800 /* Note that negative values are valid for getpriority, so we must
9801 differentiate based on errno settings. */
9802 errno = 0;
9803 ret = getpriority(arg1, arg2);
9804 if (ret == -1 && errno != 0) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009805 return -host_to_target_errno(errno);
Richard Henderson95c09822012-06-07 15:14:50 -07009806 }
9807#ifdef TARGET_ALPHA
9808 /* Return value is the unbiased priority. Signal no error. */
9809 ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0;
9810#else
9811 /* Return value is a biased priority to avoid negative numbers. */
9812 ret = 20 - ret;
9813#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009814 return ret;
bellard31e31b82003-02-18 22:55:36 +00009815 case TARGET_NR_setpriority:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009816 return get_errno(setpriority(arg1, arg2, arg3));
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009817#ifdef TARGET_NR_statfs
bellard31e31b82003-02-18 22:55:36 +00009818 case TARGET_NR_statfs:
Richard Henderson2852aaf2018-08-18 12:01:06 -07009819 if (!(p = lock_user_string(arg1))) {
9820 return -TARGET_EFAULT;
9821 }
pbrook53a59602006-03-25 19:31:22 +00009822 ret = get_errno(statfs(path(p), &stfs));
9823 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00009824 convert_statfs:
9825 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00009826 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +00009827
bellard579a97f2007-11-11 14:26:47 +00009828 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009829 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00009830 __put_user(stfs.f_type, &target_stfs->f_type);
9831 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
9832 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
9833 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
9834 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
9835 __put_user(stfs.f_files, &target_stfs->f_files);
9836 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
9837 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
9838 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
9839 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
Alexander Graf229d3372012-09-19 04:39:53 +02009840 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
Shea Levyd4247ec2018-03-01 06:15:00 -05009841#ifdef _STATFS_F_FLAGS
9842 __put_user(stfs.f_flags, &target_stfs->f_flags);
9843#else
9844 __put_user(0, &target_stfs->f_flags);
9845#endif
Alexander Graf229d3372012-09-19 04:39:53 +02009846 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
pbrook53a59602006-03-25 19:31:22 +00009847 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00009848 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009849 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009850#endif
9851#ifdef TARGET_NR_fstatfs
bellard31e31b82003-02-18 22:55:36 +00009852 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +00009853 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +00009854 goto convert_statfs;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009855#endif
bellard56c8f682005-11-28 22:28:41 +00009856#ifdef TARGET_NR_statfs64
9857 case TARGET_NR_statfs64:
Richard Henderson2852aaf2018-08-18 12:01:06 -07009858 if (!(p = lock_user_string(arg1))) {
9859 return -TARGET_EFAULT;
9860 }
pbrook53a59602006-03-25 19:31:22 +00009861 ret = get_errno(statfs(path(p), &stfs));
9862 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +00009863 convert_statfs64:
9864 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00009865 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +00009866
bellard579a97f2007-11-11 14:26:47 +00009867 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009868 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00009869 __put_user(stfs.f_type, &target_stfs->f_type);
9870 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
9871 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
9872 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
9873 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
9874 __put_user(stfs.f_files, &target_stfs->f_files);
9875 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
9876 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
9877 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
9878 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
Alexander Graf229d3372012-09-19 04:39:53 +02009879 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
Frajob94e2b42020-01-30 15:00:30 +02009880#ifdef _STATFS_F_FLAGS
9881 __put_user(stfs.f_flags, &target_stfs->f_flags);
9882#else
9883 __put_user(0, &target_stfs->f_flags);
9884#endif
Alexander Graf229d3372012-09-19 04:39:53 +02009885 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
bellard579a97f2007-11-11 14:26:47 +00009886 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +00009887 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009888 return ret;
bellard56c8f682005-11-28 22:28:41 +00009889 case TARGET_NR_fstatfs64:
9890 ret = get_errno(fstatfs(arg1, &stfs));
9891 goto convert_statfs64;
9892#endif
thse5febef2007-04-01 18:31:35 +00009893#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +00009894 case TARGET_NR_socketcall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009895 return do_socketcall(arg1, arg2);
thse5febef2007-04-01 18:31:35 +00009896#endif
bellard3532fa72006-06-24 15:06:03 +00009897#ifdef TARGET_NR_accept
9898 case TARGET_NR_accept:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009899 return do_accept4(arg1, arg2, arg3, 0);
Peter Maydella94b4982013-02-08 04:35:04 +00009900#endif
9901#ifdef TARGET_NR_accept4
9902 case TARGET_NR_accept4:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009903 return do_accept4(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00009904#endif
9905#ifdef TARGET_NR_bind
9906 case TARGET_NR_bind:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009907 return do_bind(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00009908#endif
9909#ifdef TARGET_NR_connect
9910 case TARGET_NR_connect:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009911 return do_connect(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00009912#endif
9913#ifdef TARGET_NR_getpeername
9914 case TARGET_NR_getpeername:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009915 return do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00009916#endif
9917#ifdef TARGET_NR_getsockname
9918 case TARGET_NR_getsockname:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009919 return do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00009920#endif
9921#ifdef TARGET_NR_getsockopt
9922 case TARGET_NR_getsockopt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009923 return do_getsockopt(arg1, arg2, arg3, arg4, arg5);
bellard3532fa72006-06-24 15:06:03 +00009924#endif
9925#ifdef TARGET_NR_listen
9926 case TARGET_NR_listen:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009927 return get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00009928#endif
9929#ifdef TARGET_NR_recv
9930 case TARGET_NR_recv:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009931 return do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00009932#endif
9933#ifdef TARGET_NR_recvfrom
9934 case TARGET_NR_recvfrom:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009935 return do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00009936#endif
9937#ifdef TARGET_NR_recvmsg
9938 case TARGET_NR_recvmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009939 return do_sendrecvmsg(arg1, arg2, arg3, 0);
bellard3532fa72006-06-24 15:06:03 +00009940#endif
9941#ifdef TARGET_NR_send
9942 case TARGET_NR_send:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009943 return do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00009944#endif
9945#ifdef TARGET_NR_sendmsg
9946 case TARGET_NR_sendmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009947 return do_sendrecvmsg(arg1, arg2, arg3, 1);
bellard3532fa72006-06-24 15:06:03 +00009948#endif
Alexander Graff19e00d2014-03-02 19:36:42 +00009949#ifdef TARGET_NR_sendmmsg
9950 case TARGET_NR_sendmmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009951 return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1);
Alistair Francis859e8a82020-03-12 15:13:49 -07009952#endif
9953#ifdef TARGET_NR_recvmmsg
Alexander Graff19e00d2014-03-02 19:36:42 +00009954 case TARGET_NR_recvmmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009955 return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0);
Alexander Graff19e00d2014-03-02 19:36:42 +00009956#endif
bellard3532fa72006-06-24 15:06:03 +00009957#ifdef TARGET_NR_sendto
9958 case TARGET_NR_sendto:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009959 return do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00009960#endif
9961#ifdef TARGET_NR_shutdown
9962 case TARGET_NR_shutdown:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009963 return get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00009964#endif
Laurent Vivierf894efd2016-02-21 10:56:23 +01009965#if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
9966 case TARGET_NR_getrandom:
9967 p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
9968 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009969 return -TARGET_EFAULT;
Laurent Vivierf894efd2016-02-21 10:56:23 +01009970 }
9971 ret = get_errno(getrandom(p, arg2, arg3));
9972 unlock_user(p, arg1, ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009973 return ret;
Laurent Vivierf894efd2016-02-21 10:56:23 +01009974#endif
bellard3532fa72006-06-24 15:06:03 +00009975#ifdef TARGET_NR_socket
9976 case TARGET_NR_socket:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009977 return do_socket(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00009978#endif
9979#ifdef TARGET_NR_socketpair
9980 case TARGET_NR_socketpair:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009981 return do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00009982#endif
9983#ifdef TARGET_NR_setsockopt
9984 case TARGET_NR_setsockopt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009985 return do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
bellard3532fa72006-06-24 15:06:03 +00009986#endif
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02009987#if defined(TARGET_NR_syslog)
bellard31e31b82003-02-18 22:55:36 +00009988 case TARGET_NR_syslog:
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02009989 {
9990 int len = arg2;
ths7494b0f2007-02-11 18:26:53 +00009991
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02009992 switch (arg1) {
9993 case TARGET_SYSLOG_ACTION_CLOSE: /* Close log */
9994 case TARGET_SYSLOG_ACTION_OPEN: /* Open log */
9995 case TARGET_SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
9996 case TARGET_SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging */
9997 case TARGET_SYSLOG_ACTION_CONSOLE_ON: /* Enable logging */
9998 case TARGET_SYSLOG_ACTION_CONSOLE_LEVEL: /* Set messages level */
9999 case TARGET_SYSLOG_ACTION_SIZE_UNREAD: /* Number of chars */
10000 case TARGET_SYSLOG_ACTION_SIZE_BUFFER: /* Size of the buffer */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010001 return get_errno(sys_syslog((int)arg1, NULL, (int)arg3));
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010002 case TARGET_SYSLOG_ACTION_READ: /* Read from log */
10003 case TARGET_SYSLOG_ACTION_READ_CLEAR: /* Read/clear msgs */
10004 case TARGET_SYSLOG_ACTION_READ_ALL: /* Read last messages */
10005 {
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010006 if (len < 0) {
Richard Henderson259841c2018-08-18 12:01:09 -070010007 return -TARGET_EINVAL;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010008 }
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010009 if (len == 0) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010010 return 0;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010011 }
10012 p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
10013 if (!p) {
Richard Henderson259841c2018-08-18 12:01:09 -070010014 return -TARGET_EFAULT;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010015 }
10016 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
10017 unlock_user(p, arg2, arg3);
10018 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010019 return ret;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010020 default:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010021 return -TARGET_EINVAL;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010022 }
10023 }
10024 break;
10025#endif
bellard31e31b82003-02-18 22:55:36 +000010026 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +000010027 {
bellard66fb9762003-03-23 01:06:05 +000010028 struct itimerval value, ovalue, *pvalue;
10029
pbrook53a59602006-03-25 19:31:22 +000010030 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +000010031 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +000010032 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
10033 || copy_from_user_timeval(&pvalue->it_value,
10034 arg2 + sizeof(struct target_timeval)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010035 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +000010036 } else {
10037 pvalue = NULL;
10038 }
10039 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +000010040 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +000010041 if (copy_to_user_timeval(arg3,
10042 &ovalue.it_interval)
10043 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
10044 &ovalue.it_value))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010045 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +000010046 }
10047 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010048 return ret;
bellard31e31b82003-02-18 22:55:36 +000010049 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +000010050 {
bellard66fb9762003-03-23 01:06:05 +000010051 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +000010052
bellard66fb9762003-03-23 01:06:05 +000010053 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +000010054 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +000010055 if (copy_to_user_timeval(arg2,
10056 &value.it_interval)
10057 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
10058 &value.it_value))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010059 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +000010060 }
10061 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010062 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080010063#ifdef TARGET_NR_stat
bellard31e31b82003-02-18 22:55:36 +000010064 case TARGET_NR_stat:
Richard Henderson2852aaf2018-08-18 12:01:06 -070010065 if (!(p = lock_user_string(arg1))) {
10066 return -TARGET_EFAULT;
10067 }
pbrook53a59602006-03-25 19:31:22 +000010068 ret = get_errno(stat(path(p), &st));
10069 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +000010070 goto do_stat;
Chen Gang704eff62015-08-21 05:37:33 +080010071#endif
10072#ifdef TARGET_NR_lstat
bellard31e31b82003-02-18 22:55:36 +000010073 case TARGET_NR_lstat:
Richard Henderson2852aaf2018-08-18 12:01:06 -070010074 if (!(p = lock_user_string(arg1))) {
10075 return -TARGET_EFAULT;
10076 }
pbrook53a59602006-03-25 19:31:22 +000010077 ret = get_errno(lstat(path(p), &st));
10078 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +000010079 goto do_stat;
Chen Gang704eff62015-08-21 05:37:33 +080010080#endif
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010081#ifdef TARGET_NR_fstat
bellard31e31b82003-02-18 22:55:36 +000010082 case TARGET_NR_fstat:
10083 {
10084 ret = get_errno(fstat(arg1, &st));
Chen Gang704eff62015-08-21 05:37:33 +080010085#if defined(TARGET_NR_stat) || defined(TARGET_NR_lstat)
bellard31e31b82003-02-18 22:55:36 +000010086 do_stat:
Chen Gang704eff62015-08-21 05:37:33 +080010087#endif
bellard31e31b82003-02-18 22:55:36 +000010088 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +000010089 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +000010090
bellard579a97f2007-11-11 14:26:47 +000010091 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010092 return -TARGET_EFAULT;
Ulrich Hecht12727912009-07-24 19:10:32 +020010093 memset(target_st, 0, sizeof(*target_st));
bellardd2fd1af2007-11-14 18:08:56 +000010094 __put_user(st.st_dev, &target_st->st_dev);
10095 __put_user(st.st_ino, &target_st->st_ino);
10096 __put_user(st.st_mode, &target_st->st_mode);
10097 __put_user(st.st_uid, &target_st->st_uid);
10098 __put_user(st.st_gid, &target_st->st_gid);
10099 __put_user(st.st_nlink, &target_st->st_nlink);
10100 __put_user(st.st_rdev, &target_st->st_rdev);
10101 __put_user(st.st_size, &target_st->st_size);
10102 __put_user(st.st_blksize, &target_st->st_blksize);
10103 __put_user(st.st_blocks, &target_st->st_blocks);
10104 __put_user(st.st_atime, &target_st->target_st_atime);
10105 __put_user(st.st_mtime, &target_st->target_st_mtime);
10106 __put_user(st.st_ctime, &target_st->target_st_ctime);
Chen-Yu Tsai5f992db2019-05-23 00:21:47 +080010107#if (_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) && \
10108 defined(TARGET_STAT_HAVE_NSEC)
10109 __put_user(st.st_atim.tv_nsec,
10110 &target_st->target_st_atime_nsec);
10111 __put_user(st.st_mtim.tv_nsec,
10112 &target_st->target_st_mtime_nsec);
10113 __put_user(st.st_ctim.tv_nsec,
10114 &target_st->target_st_ctime_nsec);
10115#endif
pbrook53a59602006-03-25 19:31:22 +000010116 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +000010117 }
10118 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010119 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010120#endif
bellard31e31b82003-02-18 22:55:36 +000010121 case TARGET_NR_vhangup:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010122 return get_errno(vhangup());
bellard42ad6ae2005-01-03 22:48:11 +000010123#ifdef TARGET_NR_syscall
10124 case TARGET_NR_syscall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010125 return do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5,
10126 arg6, arg7, arg8, 0);
bellard42ad6ae2005-01-03 22:48:11 +000010127#endif
Alistair Francis859e8a82020-03-12 15:13:49 -070010128#if defined(TARGET_NR_wait4)
bellard31e31b82003-02-18 22:55:36 +000010129 case TARGET_NR_wait4:
10130 {
10131 int status;
blueswir1992f48a2007-10-14 16:27:31 +000010132 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +000010133 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +000010134 abi_ulong target_rusage = arg4;
Petar Jovanovica39fb272014-04-08 19:24:30 +020010135 abi_long rusage_err;
bellard31e31b82003-02-18 22:55:36 +000010136 if (target_rusage)
10137 rusage_ptr = &rusage;
10138 else
10139 rusage_ptr = NULL;
Timothy E Baldwin4af80a32016-05-12 18:47:49 +010010140 ret = get_errno(safe_wait4(arg1, &status, arg3, rusage_ptr));
bellard31e31b82003-02-18 22:55:36 +000010141 if (!is_error(ret)) {
Alexander Graf53795572011-11-24 00:44:43 +010010142 if (status_ptr && ret) {
pbrook1d9d8b52009-04-16 15:17:02 +000010143 status = host_to_target_waitstatus(status);
bellard2f619692007-11-16 10:46:05 +000010144 if (put_user_s32(status, status_ptr))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010145 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +000010146 }
Petar Jovanovica39fb272014-04-08 19:24:30 +020010147 if (target_rusage) {
10148 rusage_err = host_to_target_rusage(target_rusage, &rusage);
10149 if (rusage_err) {
10150 ret = rusage_err;
10151 }
10152 }
bellard31e31b82003-02-18 22:55:36 +000010153 }
10154 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010155 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070010156#endif
thse5febef2007-04-01 18:31:35 +000010157#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +000010158 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +000010159 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010160 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010161 ret = get_errno(swapoff(p));
10162 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010163 return ret;
thse5febef2007-04-01 18:31:35 +000010164#endif
bellard31e31b82003-02-18 22:55:36 +000010165 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +000010166 {
pbrook53a59602006-03-25 19:31:22 +000010167 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +000010168 struct sysinfo value;
10169 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +000010170 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +000010171 {
bellard579a97f2007-11-11 14:26:47 +000010172 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010173 return -TARGET_EFAULT;
bellarda5448a72004-06-19 16:59:03 +000010174 __put_user(value.uptime, &target_value->uptime);
10175 __put_user(value.loads[0], &target_value->loads[0]);
10176 __put_user(value.loads[1], &target_value->loads[1]);
10177 __put_user(value.loads[2], &target_value->loads[2]);
10178 __put_user(value.totalram, &target_value->totalram);
10179 __put_user(value.freeram, &target_value->freeram);
10180 __put_user(value.sharedram, &target_value->sharedram);
10181 __put_user(value.bufferram, &target_value->bufferram);
10182 __put_user(value.totalswap, &target_value->totalswap);
10183 __put_user(value.freeswap, &target_value->freeswap);
10184 __put_user(value.procs, &target_value->procs);
10185 __put_user(value.totalhigh, &target_value->totalhigh);
10186 __put_user(value.freehigh, &target_value->freehigh);
10187 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +000010188 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +000010189 }
10190 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010191 return ret;
thse5febef2007-04-01 18:31:35 +000010192#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +000010193 case TARGET_NR_ipc:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010194 return do_ipc(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
thse5febef2007-04-01 18:31:35 +000010195#endif
aurel32e5289082009-04-18 16:16:12 +000010196#ifdef TARGET_NR_semget
10197 case TARGET_NR_semget:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010198 return get_errno(semget(arg1, arg2, arg3));
aurel32e5289082009-04-18 16:16:12 +000010199#endif
10200#ifdef TARGET_NR_semop
10201 case TARGET_NR_semop:
Filip Bozutacac46eb2020-08-25 00:30:50 +020010202 return do_semtimedop(arg1, arg2, arg3, 0, false);
Matus Kyseld8c08b12020-06-26 14:46:11 +020010203#endif
10204#ifdef TARGET_NR_semtimedop
10205 case TARGET_NR_semtimedop:
Filip Bozutacac46eb2020-08-25 00:30:50 +020010206 return do_semtimedop(arg1, arg2, arg3, arg4, false);
10207#endif
10208#ifdef TARGET_NR_semtimedop_time64
10209 case TARGET_NR_semtimedop_time64:
10210 return do_semtimedop(arg1, arg2, arg3, arg4, true);
aurel32e5289082009-04-18 16:16:12 +000010211#endif
10212#ifdef TARGET_NR_semctl
10213 case TARGET_NR_semctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010214 return do_semctl(arg1, arg2, arg3, arg4);
aurel32e5289082009-04-18 16:16:12 +000010215#endif
aurel32eeb438c2008-10-13 21:08:55 +000010216#ifdef TARGET_NR_msgctl
10217 case TARGET_NR_msgctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010218 return do_msgctl(arg1, arg2, arg3);
aurel32eeb438c2008-10-13 21:08:55 +000010219#endif
10220#ifdef TARGET_NR_msgget
10221 case TARGET_NR_msgget:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010222 return get_errno(msgget(arg1, arg2));
aurel32eeb438c2008-10-13 21:08:55 +000010223#endif
10224#ifdef TARGET_NR_msgrcv
10225 case TARGET_NR_msgrcv:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010226 return do_msgrcv(arg1, arg2, arg3, arg4, arg5);
aurel32eeb438c2008-10-13 21:08:55 +000010227#endif
10228#ifdef TARGET_NR_msgsnd
10229 case TARGET_NR_msgsnd:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010230 return do_msgsnd(arg1, arg2, arg3, arg4);
aurel32eeb438c2008-10-13 21:08:55 +000010231#endif
Riku Voipio88a8c982009-04-03 10:42:00 +030010232#ifdef TARGET_NR_shmget
10233 case TARGET_NR_shmget:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010234 return get_errno(shmget(arg1, arg2, arg3));
Riku Voipio88a8c982009-04-03 10:42:00 +030010235#endif
10236#ifdef TARGET_NR_shmctl
10237 case TARGET_NR_shmctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010238 return do_shmctl(arg1, arg2, arg3);
Riku Voipio88a8c982009-04-03 10:42:00 +030010239#endif
10240#ifdef TARGET_NR_shmat
10241 case TARGET_NR_shmat:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010242 return do_shmat(cpu_env, arg1, arg2, arg3);
Riku Voipio88a8c982009-04-03 10:42:00 +030010243#endif
10244#ifdef TARGET_NR_shmdt
10245 case TARGET_NR_shmdt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010246 return do_shmdt(arg1);
Riku Voipio88a8c982009-04-03 10:42:00 +030010247#endif
bellard31e31b82003-02-18 22:55:36 +000010248 case TARGET_NR_fsync:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010249 return get_errno(fsync(arg1));
bellard31e31b82003-02-18 22:55:36 +000010250 case TARGET_NR_clone:
Peter Maydell4ce62432013-07-16 18:44:57 +010010251 /* Linux manages to have three different orderings for its
10252 * arguments to clone(); the BACKWARDS and BACKWARDS2 defines
10253 * match the kernel's CONFIG_CLONE_* settings.
10254 * Microblaze is further special in that it uses a sixth
10255 * implicit argument to clone for the TLS pointer.
10256 */
10257#if defined(TARGET_MICROBLAZE)
Edgar E. Iglesiasa5b3bdc2012-04-26 14:17:41 +020010258 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5));
Peter Maydell4ce62432013-07-16 18:44:57 +010010259#elif defined(TARGET_CLONE_BACKWARDS)
10260 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
10261#elif defined(TARGET_CLONE_BACKWARDS2)
Ulrich Hechta4c075f2009-07-24 16:57:31 +020010262 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
aurel320b6d3ae2008-09-15 07:43:43 +000010263#else
Peter Maydell4ce62432013-07-16 18:44:57 +010010264 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
aurel320b6d3ae2008-09-15 07:43:43 +000010265#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010266 return ret;
bellardec86b0f2003-04-11 00:15:04 +000010267#ifdef __NR_exit_group
10268 /* new thread calls */
10269 case TARGET_NR_exit_group:
Alex Bennée708b6a62018-06-22 17:09:10 +010010270 preexit_cleanup(cpu_env, arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010271 return get_errno(exit_group(arg1));
bellardec86b0f2003-04-11 00:15:04 +000010272#endif
bellard31e31b82003-02-18 22:55:36 +000010273 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +000010274 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010275 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010276 ret = get_errno(setdomainname(p, arg2));
10277 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010278 return ret;
bellard31e31b82003-02-18 22:55:36 +000010279 case TARGET_NR_uname:
10280 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +000010281 {
10282 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +000010283
bellard579a97f2007-11-11 14:26:47 +000010284 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010285 return -TARGET_EFAULT;
bellard29e619b2004-09-13 21:41:04 +000010286 ret = get_errno(sys_uname(buf));
10287 if (!is_error(ret)) {
Peter Maydell332c9782016-07-12 13:02:16 +010010288 /* Overwrite the native machine name with whatever is being
bellard29e619b2004-09-13 21:41:04 +000010289 emulated. */
Philippe Mathieu-Daudé871f95c2017-07-24 15:27:47 -030010290 g_strlcpy(buf->machine, cpu_to_uname_machine(cpu_env),
10291 sizeof(buf->machine));
pbrookc5937222006-05-14 11:30:38 +000010292 /* Allow the user to override the reported release. */
Peter Maydell332c9782016-07-12 13:02:16 +010010293 if (qemu_uname_release && *qemu_uname_release) {
10294 g_strlcpy(buf->release, qemu_uname_release,
10295 sizeof(buf->release));
10296 }
bellard29e619b2004-09-13 21:41:04 +000010297 }
pbrook53a59602006-03-25 19:31:22 +000010298 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +000010299 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010300 return ret;
bellard6dbad632003-03-16 18:05:05 +000010301#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +000010302 case TARGET_NR_modify_ldt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010303 return do_modify_ldt(cpu_env, arg1, arg2, arg3);
j_mayer84409dd2007-04-06 08:56:50 +000010304#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +000010305 case TARGET_NR_vm86:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010306 return do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +000010307#endif
j_mayer84409dd2007-04-06 08:56:50 +000010308#endif
Alistair Francis859e8a82020-03-12 15:13:49 -070010309#if defined(TARGET_NR_adjtimex)
bellard31e31b82003-02-18 22:55:36 +000010310 case TARGET_NR_adjtimex:
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +020010311 {
10312 struct timex host_buf;
10313
10314 if (target_to_host_timex(&host_buf, arg1) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010315 return -TARGET_EFAULT;
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +020010316 }
10317 ret = get_errno(adjtimex(&host_buf));
10318 if (!is_error(ret)) {
10319 if (host_to_target_timex(arg1, &host_buf) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010320 return -TARGET_EFAULT;
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +020010321 }
10322 }
10323 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010324 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070010325#endif
Aleksandar Markovic38860a02016-10-10 13:23:29 +020010326#if defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME)
10327 case TARGET_NR_clock_adjtime:
10328 {
10329 struct timex htx, *phtx = &htx;
10330
10331 if (target_to_host_timex(phtx, arg2) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010332 return -TARGET_EFAULT;
Aleksandar Markovic38860a02016-10-10 13:23:29 +020010333 }
10334 ret = get_errno(clock_adjtime(arg1, phtx));
10335 if (!is_error(ret) && phtx) {
10336 if (host_to_target_timex(arg2, phtx) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010337 return -TARGET_EFAULT;
Aleksandar Markovic38860a02016-10-10 13:23:29 +020010338 }
10339 }
10340 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010341 return ret;
Aleksandar Markovic38860a02016-10-10 13:23:29 +020010342#endif
Filip Bozuta6ac03b22020-08-24 21:21:15 +020010343#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
10344 case TARGET_NR_clock_adjtime64:
10345 {
10346 struct timex htx;
10347
10348 if (target_to_host_timex64(&htx, arg2) != 0) {
10349 return -TARGET_EFAULT;
10350 }
10351 ret = get_errno(clock_adjtime(arg1, &htx));
10352 if (!is_error(ret) && host_to_target_timex64(arg2, &htx)) {
10353 return -TARGET_EFAULT;
10354 }
10355 }
10356 return ret;
10357#endif
bellard31e31b82003-02-18 22:55:36 +000010358 case TARGET_NR_getpgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010359 return get_errno(getpgid(arg1));
bellard31e31b82003-02-18 22:55:36 +000010360 case TARGET_NR_fchdir:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010361 return get_errno(fchdir(arg1));
bellard31e31b82003-02-18 22:55:36 +000010362 case TARGET_NR_personality:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010363 return get_errno(personality(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +000010364#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +000010365 case TARGET_NR__llseek:
10366 {
10367 int64_t res;
Peter Maydell0c1592d2011-02-22 13:02:26 +000010368#if !defined(__NR_llseek)
Peter Maydell9fea2732016-08-11 18:59:39 +010010369 res = lseek(arg1, ((uint64_t)arg2 << 32) | (abi_ulong)arg3, arg5);
Peter Maydell0c1592d2011-02-22 13:02:26 +000010370 if (res == -1) {
10371 ret = get_errno(res);
10372 } else {
10373 ret = 0;
10374 }
10375#else
bellard31e31b82003-02-18 22:55:36 +000010376 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard4f2ac232004-04-26 19:44:02 +000010377#endif
Peter Maydell0c1592d2011-02-22 13:02:26 +000010378 if ((ret == 0) && put_user_s64(res, arg4)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010379 return -TARGET_EFAULT;
Peter Maydell0c1592d2011-02-22 13:02:26 +000010380 }
bellard31e31b82003-02-18 22:55:36 +000010381 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010382 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +000010383#endif
Chen Gang704eff62015-08-21 05:37:33 +080010384#ifdef TARGET_NR_getdents
bellard31e31b82003-02-18 22:55:36 +000010385 case TARGET_NR_getdents:
Peter Maydell2b3f64c2018-04-19 13:57:40 +010010386#ifdef EMULATE_GETDENTS_WITH_GETDENTS
Ulrich Hechtd83c8732009-07-24 19:10:28 +020010387#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
bellard4add45b2003-06-05 01:52:59 +000010388 {
pbrook53a59602006-03-25 19:31:22 +000010389 struct target_dirent *target_dirp;
aurel326556a832008-10-13 21:08:17 +000010390 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +000010391 abi_long count = arg3;
bellard4add45b2003-06-05 01:52:59 +000010392
Harmandeep Kaur0e173b22015-10-06 21:47:12 +053010393 dirp = g_try_malloc(count);
10394 if (!dirp) {
Richard Henderson259841c2018-08-18 12:01:09 -070010395 return -TARGET_ENOMEM;
ths0da46a62007-10-20 20:23:07 +000010396 }
ths3b46e622007-09-17 08:09:54 +000010397
bellard4add45b2003-06-05 01:52:59 +000010398 ret = get_errno(sys_getdents(arg1, dirp, count));
10399 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +000010400 struct linux_dirent *de;
bellard4add45b2003-06-05 01:52:59 +000010401 struct target_dirent *tde;
10402 int len = ret;
10403 int reclen, treclen;
10404 int count1, tnamelen;
10405
10406 count1 = 0;
10407 de = dirp;
bellard579a97f2007-11-11 14:26:47 +000010408 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010409 return -TARGET_EFAULT;
bellard4add45b2003-06-05 01:52:59 +000010410 tde = target_dirp;
10411 while (len > 0) {
10412 reclen = de->d_reclen;
Dmitry V. Levin333858b2012-08-21 02:13:12 +040010413 tnamelen = reclen - offsetof(struct linux_dirent, d_name);
10414 assert(tnamelen >= 0);
10415 treclen = tnamelen + offsetof(struct target_dirent, d_name);
10416 assert(count1 + treclen <= count);
bellard4add45b2003-06-05 01:52:59 +000010417 tde->d_reclen = tswap16(treclen);
Matthias Brauncbb21ee2011-08-12 19:57:41 +020010418 tde->d_ino = tswapal(de->d_ino);
10419 tde->d_off = tswapal(de->d_off);
Dmitry V. Levin333858b2012-08-21 02:13:12 +040010420 memcpy(tde->d_name, de->d_name, tnamelen);
aurel326556a832008-10-13 21:08:17 +000010421 de = (struct linux_dirent *)((char *)de + reclen);
bellard4add45b2003-06-05 01:52:59 +000010422 len -= reclen;
j_mayer1c5bf3b2007-04-14 12:17:59 +000010423 tde = (struct target_dirent *)((char *)tde + treclen);
bellard4add45b2003-06-05 01:52:59 +000010424 count1 += treclen;
10425 }
10426 ret = count1;
bellard579a97f2007-11-11 14:26:47 +000010427 unlock_user(target_dirp, arg2, ret);
bellard4add45b2003-06-05 01:52:59 +000010428 }
Harmandeep Kaur0e173b22015-10-06 21:47:12 +053010429 g_free(dirp);
bellard4add45b2003-06-05 01:52:59 +000010430 }
10431#else
bellard31e31b82003-02-18 22:55:36 +000010432 {
aurel326556a832008-10-13 21:08:17 +000010433 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +000010434 abi_long count = arg3;
bellarddab2ed92003-03-22 15:23:14 +000010435
bellard579a97f2007-11-11 14:26:47 +000010436 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010437 return -TARGET_EFAULT;
bellard72f03902003-02-18 23:33:18 +000010438 ret = get_errno(sys_getdents(arg1, dirp, count));
bellard31e31b82003-02-18 22:55:36 +000010439 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +000010440 struct linux_dirent *de;
bellard31e31b82003-02-18 22:55:36 +000010441 int len = ret;
10442 int reclen;
10443 de = dirp;
10444 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +000010445 reclen = de->d_reclen;
bellard31e31b82003-02-18 22:55:36 +000010446 if (reclen > len)
10447 break;
bellard8083a3e2003-03-24 23:12:16 +000010448 de->d_reclen = tswap16(reclen);
bellard31e31b82003-02-18 22:55:36 +000010449 tswapls(&de->d_ino);
10450 tswapls(&de->d_off);
aurel326556a832008-10-13 21:08:17 +000010451 de = (struct linux_dirent *)((char *)de + reclen);
bellard31e31b82003-02-18 22:55:36 +000010452 len -= reclen;
10453 }
10454 }
pbrook53a59602006-03-25 19:31:22 +000010455 unlock_user(dirp, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +000010456 }
bellard4add45b2003-06-05 01:52:59 +000010457#endif
Peter Maydell3307e232013-06-12 16:20:21 +010010458#else
10459 /* Implement getdents in terms of getdents64 */
10460 {
10461 struct linux_dirent64 *dirp;
10462 abi_long count = arg3;
10463
10464 dirp = lock_user(VERIFY_WRITE, arg2, count, 0);
10465 if (!dirp) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010466 return -TARGET_EFAULT;
Peter Maydell3307e232013-06-12 16:20:21 +010010467 }
10468 ret = get_errno(sys_getdents64(arg1, dirp, count));
10469 if (!is_error(ret)) {
10470 /* Convert the dirent64 structs to target dirent. We do this
10471 * in-place, since we can guarantee that a target_dirent is no
10472 * larger than a dirent64; however this means we have to be
10473 * careful to read everything before writing in the new format.
10474 */
10475 struct linux_dirent64 *de;
10476 struct target_dirent *tde;
10477 int len = ret;
10478 int tlen = 0;
10479
10480 de = dirp;
10481 tde = (struct target_dirent *)dirp;
10482 while (len > 0) {
10483 int namelen, treclen;
10484 int reclen = de->d_reclen;
10485 uint64_t ino = de->d_ino;
10486 int64_t off = de->d_off;
10487 uint8_t type = de->d_type;
10488
10489 namelen = strlen(de->d_name);
10490 treclen = offsetof(struct target_dirent, d_name)
10491 + namelen + 2;
10492 treclen = QEMU_ALIGN_UP(treclen, sizeof(abi_long));
10493
10494 memmove(tde->d_name, de->d_name, namelen + 1);
10495 tde->d_ino = tswapal(ino);
10496 tde->d_off = tswapal(off);
10497 tde->d_reclen = tswap16(treclen);
10498 /* The target_dirent type is in what was formerly a padding
10499 * byte at the end of the structure:
10500 */
10501 *(((char *)tde) + treclen - 1) = type;
10502
10503 de = (struct linux_dirent64 *)((char *)de + reclen);
10504 tde = (struct target_dirent *)((char *)tde + treclen);
10505 len -= reclen;
10506 tlen += treclen;
10507 }
10508 ret = tlen;
10509 }
10510 unlock_user(dirp, arg2, ret);
10511 }
10512#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010513 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080010514#endif /* TARGET_NR_getdents */
ths3ae43202007-09-16 21:39:48 +000010515#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +000010516 case TARGET_NR_getdents64:
10517 {
aurel326556a832008-10-13 21:08:17 +000010518 struct linux_dirent64 *dirp;
blueswir1992f48a2007-10-14 16:27:31 +000010519 abi_long count = arg3;
bellard579a97f2007-11-11 14:26:47 +000010520 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010521 return -TARGET_EFAULT;
bellarddab2ed92003-03-22 15:23:14 +000010522 ret = get_errno(sys_getdents64(arg1, dirp, count));
10523 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +000010524 struct linux_dirent64 *de;
bellarddab2ed92003-03-22 15:23:14 +000010525 int len = ret;
10526 int reclen;
10527 de = dirp;
10528 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +000010529 reclen = de->d_reclen;
bellarddab2ed92003-03-22 15:23:14 +000010530 if (reclen > len)
10531 break;
bellard8083a3e2003-03-24 23:12:16 +000010532 de->d_reclen = tswap16(reclen);
bellard8582a532007-11-11 23:11:36 +000010533 tswap64s((uint64_t *)&de->d_ino);
10534 tswap64s((uint64_t *)&de->d_off);
aurel326556a832008-10-13 21:08:17 +000010535 de = (struct linux_dirent64 *)((char *)de + reclen);
bellarddab2ed92003-03-22 15:23:14 +000010536 len -= reclen;
10537 }
10538 }
pbrook53a59602006-03-25 19:31:22 +000010539 unlock_user(dirp, arg2, ret);
bellarddab2ed92003-03-22 15:23:14 +000010540 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010541 return ret;
bellarda541f292004-04-12 20:39:29 +000010542#endif /* TARGET_NR_getdents64 */
Laurent Vivier9468a5d2013-01-10 22:30:50 +010010543#if defined(TARGET_NR__newselect)
bellard31e31b82003-02-18 22:55:36 +000010544 case TARGET_NR__newselect:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010545 return do_select(arg1, arg2, arg3, arg4, arg5);
thse5febef2007-04-01 18:31:35 +000010546#endif
Filip Bozutae5ce9682020-08-25 00:30:49 +020010547#ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +000010548 case TARGET_NR_poll:
Filip Bozutae5ce9682020-08-25 00:30:49 +020010549 return do_ppoll(arg1, arg2, arg3, arg4, arg5, false, false);
10550#endif
10551#ifdef TARGET_NR_ppoll
Mike Frysingerd8035d42011-02-07 01:05:51 -050010552 case TARGET_NR_ppoll:
Filip Bozutae5ce9682020-08-25 00:30:49 +020010553 return do_ppoll(arg1, arg2, arg3, arg4, arg5, true, false);
10554#endif
10555#ifdef TARGET_NR_ppoll_time64
10556 case TARGET_NR_ppoll_time64:
10557 return do_ppoll(arg1, arg2, arg3, arg4, arg5, true, true);
thse5febef2007-04-01 18:31:35 +000010558#endif
bellard31e31b82003-02-18 22:55:36 +000010559 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +000010560 /* NOTE: the flock constant seems to be the same for every
10561 Linux platform */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010562 return get_errno(safe_flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +000010563 case TARGET_NR_readv:
10564 {
Richard Hendersonf287b2c2012-09-15 13:20:25 -070010565 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
10566 if (vec != NULL) {
Peter Maydell918c03e2016-06-06 19:58:02 +010010567 ret = get_errno(safe_readv(arg1, vec, arg3));
Richard Hendersonf287b2c2012-09-15 13:20:25 -070010568 unlock_iovec(vec, arg2, arg3, 1);
10569 } else {
10570 ret = -host_to_target_errno(errno);
10571 }
bellard31e31b82003-02-18 22:55:36 +000010572 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010573 return ret;
bellard31e31b82003-02-18 22:55:36 +000010574 case TARGET_NR_writev:
10575 {
Richard Hendersonf287b2c2012-09-15 13:20:25 -070010576 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
10577 if (vec != NULL) {
Peter Maydell918c03e2016-06-06 19:58:02 +010010578 ret = get_errno(safe_writev(arg1, vec, arg3));
Richard Hendersonf287b2c2012-09-15 13:20:25 -070010579 unlock_iovec(vec, arg2, arg3, 0);
10580 } else {
10581 ret = -host_to_target_errno(errno);
10582 }
bellard31e31b82003-02-18 22:55:36 +000010583 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010584 return ret;
Dejan Jovicevic0f263862016-10-11 11:52:46 +020010585#if defined(TARGET_NR_preadv)
10586 case TARGET_NR_preadv:
10587 {
10588 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
10589 if (vec != NULL) {
Max Filippov9ac22512018-04-04 17:30:41 -070010590 unsigned long low, high;
10591
10592 target_to_host_low_high(arg4, arg5, &low, &high);
10593 ret = get_errno(safe_preadv(arg1, vec, arg3, low, high));
Dejan Jovicevic0f263862016-10-11 11:52:46 +020010594 unlock_iovec(vec, arg2, arg3, 1);
10595 } else {
10596 ret = -host_to_target_errno(errno);
10597 }
10598 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010599 return ret;
Dejan Jovicevic0f263862016-10-11 11:52:46 +020010600#endif
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +020010601#if defined(TARGET_NR_pwritev)
10602 case TARGET_NR_pwritev:
10603 {
10604 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
10605 if (vec != NULL) {
Max Filippov9ac22512018-04-04 17:30:41 -070010606 unsigned long low, high;
10607
10608 target_to_host_low_high(arg4, arg5, &low, &high);
10609 ret = get_errno(safe_pwritev(arg1, vec, arg3, low, high));
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +020010610 unlock_iovec(vec, arg2, arg3, 0);
10611 } else {
10612 ret = -host_to_target_errno(errno);
10613 }
10614 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010615 return ret;
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +020010616#endif
bellard31e31b82003-02-18 22:55:36 +000010617 case TARGET_NR_getsid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010618 return get_errno(getsid(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +000010619#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +000010620 case TARGET_NR_fdatasync:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010621 return get_errno(fdatasync(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +000010622#endif
Mike Frysinger737de1d2011-02-07 01:05:55 -050010623 case TARGET_NR_sched_getaffinity:
10624 {
10625 unsigned int mask_size;
10626 unsigned long *mask;
10627
10628 /*
10629 * sched_getaffinity needs multiples of ulong, so need to take
10630 * care of mismatches between target ulong and host ulong sizes.
10631 */
10632 if (arg2 & (sizeof(abi_ulong) - 1)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010633 return -TARGET_EINVAL;
Mike Frysinger737de1d2011-02-07 01:05:55 -050010634 }
10635 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
10636
10637 mask = alloca(mask_size);
Samuel Thibault2e0a8712018-01-09 21:16:43 +010010638 memset(mask, 0, mask_size);
Mike Frysinger737de1d2011-02-07 01:05:55 -050010639 ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
10640
10641 if (!is_error(ret)) {
Peter Maydellbe3bd282014-05-15 14:40:23 +010010642 if (ret > arg2) {
10643 /* More data returned than the caller's buffer will fit.
10644 * This only happens if sizeof(abi_long) < sizeof(long)
10645 * and the caller passed us a buffer holding an odd number
10646 * of abi_longs. If the host kernel is actually using the
10647 * extra 4 bytes then fail EINVAL; otherwise we can just
10648 * ignore them and only copy the interesting part.
10649 */
10650 int numcpus = sysconf(_SC_NPROCESSORS_CONF);
10651 if (numcpus > arg2 * 8) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010652 return -TARGET_EINVAL;
Peter Maydellbe3bd282014-05-15 14:40:23 +010010653 }
10654 ret = arg2;
10655 }
10656
Samuel Thibault5fdefcf2018-02-11 18:47:04 +010010657 if (host_to_target_cpu_mask(mask, mask_size, arg3, ret)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010658 return -TARGET_EFAULT;
Samuel Thibault5fdefcf2018-02-11 18:47:04 +010010659 }
Mike Frysinger737de1d2011-02-07 01:05:55 -050010660 }
10661 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010662 return ret;
Mike Frysinger737de1d2011-02-07 01:05:55 -050010663 case TARGET_NR_sched_setaffinity:
10664 {
10665 unsigned int mask_size;
10666 unsigned long *mask;
10667
10668 /*
10669 * sched_setaffinity needs multiples of ulong, so need to take
10670 * care of mismatches between target ulong and host ulong sizes.
10671 */
10672 if (arg2 & (sizeof(abi_ulong) - 1)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010673 return -TARGET_EINVAL;
Mike Frysinger737de1d2011-02-07 01:05:55 -050010674 }
10675 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
Mike Frysinger737de1d2011-02-07 01:05:55 -050010676 mask = alloca(mask_size);
Samuel Thibault2e0a8712018-01-09 21:16:43 +010010677
10678 ret = target_to_host_cpu_mask(mask, mask_size, arg3, arg2);
10679 if (ret) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010680 return ret;
Mike Frysinger737de1d2011-02-07 01:05:55 -050010681 }
Mike Frysinger737de1d2011-02-07 01:05:55 -050010682
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010683 return get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
Mike Frysinger737de1d2011-02-07 01:05:55 -050010684 }
Samuel Thibaultb827c3e2018-01-12 09:14:35 +010010685 case TARGET_NR_getcpu:
10686 {
10687 unsigned cpu, node;
10688 ret = get_errno(sys_getcpu(arg1 ? &cpu : NULL,
10689 arg2 ? &node : NULL,
10690 NULL));
10691 if (is_error(ret)) {
Richard Henderson259841c2018-08-18 12:01:09 -070010692 return ret;
Samuel Thibaultb827c3e2018-01-12 09:14:35 +010010693 }
10694 if (arg1 && put_user_u32(cpu, arg1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010695 return -TARGET_EFAULT;
Samuel Thibaultb827c3e2018-01-12 09:14:35 +010010696 }
10697 if (arg2 && put_user_u32(node, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010698 return -TARGET_EFAULT;
Samuel Thibaultb827c3e2018-01-12 09:14:35 +010010699 }
10700 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010701 return ret;
bellard31e31b82003-02-18 22:55:36 +000010702 case TARGET_NR_sched_setparam:
bellard5cd43932003-03-29 16:54:36 +000010703 {
pbrook53a59602006-03-25 19:31:22 +000010704 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +000010705 struct sched_param schp;
pbrook53a59602006-03-25 19:31:22 +000010706
Tom Mustaa1d5c5b2014-08-12 13:53:38 -050010707 if (arg2 == 0) {
10708 return -TARGET_EINVAL;
10709 }
bellard579a97f2007-11-11 14:26:47 +000010710 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010711 return -TARGET_EFAULT;
bellard5cd43932003-03-29 16:54:36 +000010712 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +000010713 unlock_user_struct(target_schp, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010714 return get_errno(sched_setparam(arg1, &schp));
bellard5cd43932003-03-29 16:54:36 +000010715 }
bellard31e31b82003-02-18 22:55:36 +000010716 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +000010717 {
pbrook53a59602006-03-25 19:31:22 +000010718 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +000010719 struct sched_param schp;
Tom Mustaa1d5c5b2014-08-12 13:53:38 -050010720
10721 if (arg2 == 0) {
10722 return -TARGET_EINVAL;
10723 }
bellard5cd43932003-03-29 16:54:36 +000010724 ret = get_errno(sched_getparam(arg1, &schp));
10725 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +000010726 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010727 return -TARGET_EFAULT;
bellard5cd43932003-03-29 16:54:36 +000010728 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +000010729 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +000010730 }
10731 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010732 return ret;
bellard31e31b82003-02-18 22:55:36 +000010733 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +000010734 {
pbrook53a59602006-03-25 19:31:22 +000010735 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +000010736 struct sched_param schp;
Tom Mustaa1d5c5b2014-08-12 13:53:38 -050010737 if (arg3 == 0) {
10738 return -TARGET_EINVAL;
10739 }
bellard579a97f2007-11-11 14:26:47 +000010740 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010741 return -TARGET_EFAULT;
bellard5cd43932003-03-29 16:54:36 +000010742 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +000010743 unlock_user_struct(target_schp, arg3, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010744 return get_errno(sched_setscheduler(arg1, arg2, &schp));
bellard5cd43932003-03-29 16:54:36 +000010745 }
bellard31e31b82003-02-18 22:55:36 +000010746 case TARGET_NR_sched_getscheduler:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010747 return get_errno(sched_getscheduler(arg1));
bellard31e31b82003-02-18 22:55:36 +000010748 case TARGET_NR_sched_yield:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010749 return get_errno(sched_yield());
bellard31e31b82003-02-18 22:55:36 +000010750 case TARGET_NR_sched_get_priority_max:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010751 return get_errno(sched_get_priority_max(arg1));
bellard31e31b82003-02-18 22:55:36 +000010752 case TARGET_NR_sched_get_priority_min:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010753 return get_errno(sched_get_priority_min(arg1));
Alistair Francis859e8a82020-03-12 15:13:49 -070010754#ifdef TARGET_NR_sched_rr_get_interval
bellard31e31b82003-02-18 22:55:36 +000010755 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +000010756 {
bellard5cd43932003-03-29 16:54:36 +000010757 struct timespec ts;
10758 ret = get_errno(sched_rr_get_interval(arg1, &ts));
10759 if (!is_error(ret)) {
Tom Mustad4290c42014-08-12 13:53:39 -050010760 ret = host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +000010761 }
10762 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010763 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070010764#endif
Filip Bozutaddcbde12020-08-24 21:21:16 +020010765#ifdef TARGET_NR_sched_rr_get_interval_time64
10766 case TARGET_NR_sched_rr_get_interval_time64:
10767 {
10768 struct timespec ts;
10769 ret = get_errno(sched_rr_get_interval(arg1, &ts));
10770 if (!is_error(ret)) {
10771 ret = host_to_target_timespec64(arg2, &ts);
10772 }
10773 }
10774 return ret;
10775#endif
Alistair Francis859e8a82020-03-12 15:13:49 -070010776#if defined(TARGET_NR_nanosleep)
bellard31e31b82003-02-18 22:55:36 +000010777 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +000010778 {
bellard1b6b0292003-03-22 17:31:38 +000010779 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +000010780 target_to_host_timespec(&req, arg1);
Peter Maydell9e518222016-06-06 19:58:09 +010010781 ret = get_errno(safe_nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +000010782 if (is_error(ret) && arg2) {
10783 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +000010784 }
10785 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010786 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070010787#endif
bellard31e31b82003-02-18 22:55:36 +000010788 case TARGET_NR_prctl:
Peter Maydell1e6722f2012-02-03 14:48:03 +000010789 switch (arg1) {
10790 case PR_GET_PDEATHSIG:
10791 {
10792 int deathsig;
10793 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
10794 if (!is_error(ret) && arg2
Stephen Longd9a5eba2020-05-07 06:03:02 -070010795 && put_user_s32(deathsig, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010796 return -TARGET_EFAULT;
thse5574482007-02-11 20:03:13 +000010797 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010798 return ret;
Peter Maydell1e6722f2012-02-03 14:48:03 +000010799 }
Peter Maydelldb9526b2012-02-03 14:48:03 +000010800#ifdef PR_GET_NAME
10801 case PR_GET_NAME:
10802 {
10803 void *name = lock_user(VERIFY_WRITE, arg2, 16, 1);
10804 if (!name) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010805 return -TARGET_EFAULT;
Peter Maydelldb9526b2012-02-03 14:48:03 +000010806 }
10807 ret = get_errno(prctl(arg1, (unsigned long)name,
10808 arg3, arg4, arg5));
10809 unlock_user(name, arg2, 16);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010810 return ret;
Peter Maydelldb9526b2012-02-03 14:48:03 +000010811 }
10812 case PR_SET_NAME:
10813 {
10814 void *name = lock_user(VERIFY_READ, arg2, 16, 1);
10815 if (!name) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010816 return -TARGET_EFAULT;
Peter Maydelldb9526b2012-02-03 14:48:03 +000010817 }
10818 ret = get_errno(prctl(arg1, (unsigned long)name,
10819 arg3, arg4, arg5));
10820 unlock_user(name, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010821 return ret;
Peter Maydelldb9526b2012-02-03 14:48:03 +000010822 }
10823#endif
Stefan Markovic5b702ff2018-10-12 12:57:35 +020010824#ifdef TARGET_MIPS
10825 case TARGET_PR_GET_FP_MODE:
Stefan Markovic64ea3d62018-10-26 13:17:43 +020010826 {
10827 CPUMIPSState *env = ((CPUMIPSState *)cpu_env);
10828 ret = 0;
10829 if (env->CP0_Status & (1 << CP0St_FR)) {
10830 ret |= TARGET_PR_FP_MODE_FR;
10831 }
10832 if (env->CP0_Config5 & (1 << CP0C5_FRE)) {
10833 ret |= TARGET_PR_FP_MODE_FRE;
10834 }
10835 return ret;
10836 }
Stefan Markovic5b702ff2018-10-12 12:57:35 +020010837 case TARGET_PR_SET_FP_MODE:
Stefan Markovic64ea3d62018-10-26 13:17:43 +020010838 {
10839 CPUMIPSState *env = ((CPUMIPSState *)cpu_env);
10840 bool old_fr = env->CP0_Status & (1 << CP0St_FR);
Stefan Markovic6456c512018-11-14 14:37:08 +010010841 bool old_fre = env->CP0_Config5 & (1 << CP0C5_FRE);
Stefan Markovic64ea3d62018-10-26 13:17:43 +020010842 bool new_fr = arg2 & TARGET_PR_FP_MODE_FR;
10843 bool new_fre = arg2 & TARGET_PR_FP_MODE_FRE;
10844
Stefan Markovic6456c512018-11-14 14:37:08 +010010845 const unsigned int known_bits = TARGET_PR_FP_MODE_FR |
10846 TARGET_PR_FP_MODE_FRE;
10847
10848 /* If nothing to change, return right away, successfully. */
10849 if (old_fr == new_fr && old_fre == new_fre) {
10850 return 0;
10851 }
10852 /* Check the value is valid */
10853 if (arg2 & ~known_bits) {
10854 return -TARGET_EOPNOTSUPP;
10855 }
10856 /* Setting FRE without FR is not supported. */
10857 if (new_fre && !new_fr) {
10858 return -TARGET_EOPNOTSUPP;
10859 }
Stefan Markovic64ea3d62018-10-26 13:17:43 +020010860 if (new_fr && !(env->active_fpu.fcr0 & (1 << FCR0_F64))) {
10861 /* FR1 is not supported */
10862 return -TARGET_EOPNOTSUPP;
10863 }
10864 if (!new_fr && (env->active_fpu.fcr0 & (1 << FCR0_F64))
10865 && !(env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
10866 /* cannot set FR=0 */
10867 return -TARGET_EOPNOTSUPP;
10868 }
10869 if (new_fre && !(env->active_fpu.fcr0 & (1 << FCR0_FREP))) {
10870 /* Cannot set FRE=1 */
10871 return -TARGET_EOPNOTSUPP;
10872 }
10873
10874 int i;
10875 fpr_t *fpr = env->active_fpu.fpr;
10876 for (i = 0; i < 32 ; i += 2) {
10877 if (!old_fr && new_fr) {
10878 fpr[i].w[!FP_ENDIAN_IDX] = fpr[i + 1].w[FP_ENDIAN_IDX];
10879 } else if (old_fr && !new_fr) {
10880 fpr[i + 1].w[FP_ENDIAN_IDX] = fpr[i].w[!FP_ENDIAN_IDX];
10881 }
10882 }
10883
10884 if (new_fr) {
10885 env->CP0_Status |= (1 << CP0St_FR);
10886 env->hflags |= MIPS_HFLAG_F64;
10887 } else {
10888 env->CP0_Status &= ~(1 << CP0St_FR);
Stefan Markovic6456c512018-11-14 14:37:08 +010010889 env->hflags &= ~MIPS_HFLAG_F64;
Stefan Markovic64ea3d62018-10-26 13:17:43 +020010890 }
10891 if (new_fre) {
10892 env->CP0_Config5 |= (1 << CP0C5_FRE);
10893 if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
10894 env->hflags |= MIPS_HFLAG_FRE;
10895 }
10896 } else {
10897 env->CP0_Config5 &= ~(1 << CP0C5_FRE);
Stefan Markovic6456c512018-11-14 14:37:08 +010010898 env->hflags &= ~MIPS_HFLAG_FRE;
Stefan Markovic64ea3d62018-10-26 13:17:43 +020010899 }
10900
10901 return 0;
10902 }
Stefan Markovic5b702ff2018-10-12 12:57:35 +020010903#endif /* MIPS */
Richard Henderson85fc7162018-03-09 17:09:43 +000010904#ifdef TARGET_AARCH64
10905 case TARGET_PR_SVE_SET_VL:
Richard Hendersonadf92ea2018-08-16 14:05:28 +010010906 /*
10907 * We cannot support either PR_SVE_SET_VL_ONEXEC or
10908 * PR_SVE_VL_INHERIT. Note the kernel definition
10909 * of sve_vl_valid allows for VQ=512, i.e. VL=8192,
10910 * even though the current architectural maximum is VQ=16.
10911 */
Richard Henderson85fc7162018-03-09 17:09:43 +000010912 ret = -TARGET_EINVAL;
Richard Henderson2fc0cc02019-03-22 17:41:14 -070010913 if (cpu_isar_feature(aa64_sve, env_archcpu(cpu_env))
Richard Hendersonadf92ea2018-08-16 14:05:28 +010010914 && arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
Richard Henderson85fc7162018-03-09 17:09:43 +000010915 CPUARMState *env = cpu_env;
Richard Henderson2fc0cc02019-03-22 17:41:14 -070010916 ARMCPU *cpu = env_archcpu(env);
Richard Hendersonadf92ea2018-08-16 14:05:28 +010010917 uint32_t vq, old_vq;
10918
10919 old_vq = (env->vfp.zcr_el[1] & 0xf) + 1;
10920 vq = MAX(arg2 / 16, 1);
10921 vq = MIN(vq, cpu->sve_max_vq);
Richard Henderson85fc7162018-03-09 17:09:43 +000010922
10923 if (vq < old_vq) {
10924 aarch64_sve_narrow_vq(env, vq);
10925 }
10926 env->vfp.zcr_el[1] = vq - 1;
Richard Hendersona8a79c72019-10-23 11:00:49 -040010927 arm_rebuild_hflags(env);
Richard Henderson85fc7162018-03-09 17:09:43 +000010928 ret = vq * 16;
10929 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010930 return ret;
Richard Henderson85fc7162018-03-09 17:09:43 +000010931 case TARGET_PR_SVE_GET_VL:
10932 ret = -TARGET_EINVAL;
Richard Hendersoncd208a12018-10-24 07:50:17 +010010933 {
Richard Henderson2fc0cc02019-03-22 17:41:14 -070010934 ARMCPU *cpu = env_archcpu(cpu_env);
Richard Hendersoncd208a12018-10-24 07:50:17 +010010935 if (cpu_isar_feature(aa64_sve, cpu)) {
10936 ret = ((cpu->env.vfp.zcr_el[1] & 0xf) + 1) * 16;
10937 }
Richard Henderson85fc7162018-03-09 17:09:43 +000010938 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010939 return ret;
Richard Hendersonbff63fb2019-02-05 16:52:39 +000010940 case TARGET_PR_PAC_RESET_KEYS:
10941 {
10942 CPUARMState *env = cpu_env;
Richard Henderson2fc0cc02019-03-22 17:41:14 -070010943 ARMCPU *cpu = env_archcpu(env);
Richard Hendersonbff63fb2019-02-05 16:52:39 +000010944
10945 if (arg3 || arg4 || arg5) {
10946 return -TARGET_EINVAL;
10947 }
10948 if (cpu_isar_feature(aa64_pauth, cpu)) {
10949 int all = (TARGET_PR_PAC_APIAKEY | TARGET_PR_PAC_APIBKEY |
10950 TARGET_PR_PAC_APDAKEY | TARGET_PR_PAC_APDBKEY |
10951 TARGET_PR_PAC_APGAKEY);
Richard Henderson51977e22019-03-12 19:22:20 -070010952 int ret = 0;
10953 Error *err = NULL;
10954
Richard Hendersonbff63fb2019-02-05 16:52:39 +000010955 if (arg2 == 0) {
10956 arg2 = all;
10957 } else if (arg2 & ~all) {
10958 return -TARGET_EINVAL;
10959 }
10960 if (arg2 & TARGET_PR_PAC_APIAKEY) {
Richard Henderson108b3ba2019-03-14 17:28:32 -070010961 ret |= qemu_guest_getrandom(&env->keys.apia,
Richard Henderson51977e22019-03-12 19:22:20 -070010962 sizeof(ARMPACKey), &err);
Richard Hendersonbff63fb2019-02-05 16:52:39 +000010963 }
10964 if (arg2 & TARGET_PR_PAC_APIBKEY) {
Richard Henderson108b3ba2019-03-14 17:28:32 -070010965 ret |= qemu_guest_getrandom(&env->keys.apib,
Richard Henderson51977e22019-03-12 19:22:20 -070010966 sizeof(ARMPACKey), &err);
Richard Hendersonbff63fb2019-02-05 16:52:39 +000010967 }
10968 if (arg2 & TARGET_PR_PAC_APDAKEY) {
Richard Henderson108b3ba2019-03-14 17:28:32 -070010969 ret |= qemu_guest_getrandom(&env->keys.apda,
Richard Henderson51977e22019-03-12 19:22:20 -070010970 sizeof(ARMPACKey), &err);
Richard Hendersonbff63fb2019-02-05 16:52:39 +000010971 }
10972 if (arg2 & TARGET_PR_PAC_APDBKEY) {
Richard Henderson108b3ba2019-03-14 17:28:32 -070010973 ret |= qemu_guest_getrandom(&env->keys.apdb,
Richard Henderson51977e22019-03-12 19:22:20 -070010974 sizeof(ARMPACKey), &err);
Richard Hendersonbff63fb2019-02-05 16:52:39 +000010975 }
10976 if (arg2 & TARGET_PR_PAC_APGAKEY) {
Richard Henderson108b3ba2019-03-14 17:28:32 -070010977 ret |= qemu_guest_getrandom(&env->keys.apga,
Richard Henderson51977e22019-03-12 19:22:20 -070010978 sizeof(ARMPACKey), &err);
10979 }
10980 if (ret != 0) {
10981 /*
10982 * Some unknown failure in the crypto. The best
10983 * we can do is log it and fail the syscall.
10984 * The real syscall cannot fail this way.
10985 */
10986 qemu_log_mask(LOG_UNIMP,
10987 "PR_PAC_RESET_KEYS: Crypto failure: %s",
10988 error_get_pretty(err));
10989 error_free(err);
10990 return -TARGET_EIO;
Richard Hendersonbff63fb2019-02-05 16:52:39 +000010991 }
10992 return 0;
10993 }
10994 }
10995 return -TARGET_EINVAL;
Richard Henderson0e0c0302021-02-12 10:48:51 -080010996 case TARGET_PR_SET_TAGGED_ADDR_CTRL:
10997 {
10998 abi_ulong valid_mask = TARGET_PR_TAGGED_ADDR_ENABLE;
10999 CPUARMState *env = cpu_env;
Richard Hendersonbfd05722021-02-12 10:48:54 -080011000 ARMCPU *cpu = env_archcpu(env);
11001
11002 if (cpu_isar_feature(aa64_mte, cpu)) {
11003 valid_mask |= TARGET_PR_MTE_TCF_MASK;
11004 valid_mask |= TARGET_PR_MTE_TAG_MASK;
11005 }
Richard Henderson0e0c0302021-02-12 10:48:51 -080011006
11007 if ((arg2 & ~valid_mask) || arg3 || arg4 || arg5) {
11008 return -TARGET_EINVAL;
11009 }
11010 env->tagged_addr_enable = arg2 & TARGET_PR_TAGGED_ADDR_ENABLE;
Richard Hendersonbfd05722021-02-12 10:48:54 -080011011
11012 if (cpu_isar_feature(aa64_mte, cpu)) {
11013 switch (arg2 & TARGET_PR_MTE_TCF_MASK) {
11014 case TARGET_PR_MTE_TCF_NONE:
11015 case TARGET_PR_MTE_TCF_SYNC:
11016 case TARGET_PR_MTE_TCF_ASYNC:
11017 break;
11018 default:
11019 return -EINVAL;
11020 }
11021
11022 /*
11023 * Write PR_MTE_TCF to SCTLR_EL1[TCF0].
11024 * Note that the syscall values are consistent with hw.
11025 */
11026 env->cp15.sctlr_el[1] =
11027 deposit64(env->cp15.sctlr_el[1], 38, 2,
11028 arg2 >> TARGET_PR_MTE_TCF_SHIFT);
11029
11030 /*
11031 * Write PR_MTE_TAG to GCR_EL1[Exclude].
11032 * Note that the syscall uses an include mask,
11033 * and hardware uses an exclude mask -- invert.
11034 */
11035 env->cp15.gcr_el1 =
11036 deposit64(env->cp15.gcr_el1, 0, 16,
11037 ~arg2 >> TARGET_PR_MTE_TAG_SHIFT);
11038 arm_rebuild_hflags(env);
11039 }
Richard Henderson0e0c0302021-02-12 10:48:51 -080011040 return 0;
11041 }
11042 case TARGET_PR_GET_TAGGED_ADDR_CTRL:
11043 {
11044 abi_long ret = 0;
11045 CPUARMState *env = cpu_env;
Richard Hendersonbfd05722021-02-12 10:48:54 -080011046 ARMCPU *cpu = env_archcpu(env);
Richard Henderson0e0c0302021-02-12 10:48:51 -080011047
11048 if (arg2 || arg3 || arg4 || arg5) {
11049 return -TARGET_EINVAL;
11050 }
11051 if (env->tagged_addr_enable) {
11052 ret |= TARGET_PR_TAGGED_ADDR_ENABLE;
11053 }
Richard Hendersonbfd05722021-02-12 10:48:54 -080011054 if (cpu_isar_feature(aa64_mte, cpu)) {
11055 /* See above. */
11056 ret |= (extract64(env->cp15.sctlr_el[1], 38, 2)
11057 << TARGET_PR_MTE_TCF_SHIFT);
11058 ret = deposit64(ret, TARGET_PR_MTE_TAG_SHIFT, 16,
11059 ~env->cp15.gcr_el1);
11060 }
Richard Henderson0e0c0302021-02-12 10:48:51 -080011061 return ret;
11062 }
Richard Henderson85fc7162018-03-09 17:09:43 +000011063#endif /* AARCH64 */
James Cowgilla8b154a2017-11-06 18:03:51 +000011064 case PR_GET_SECCOMP:
11065 case PR_SET_SECCOMP:
11066 /* Disable seccomp to prevent the target disabling syscalls we
11067 * need. */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011068 return -TARGET_EINVAL;
Peter Maydell1e6722f2012-02-03 14:48:03 +000011069 default:
11070 /* Most prctl options have no pointer arguments */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011071 return get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
Peter Maydell1e6722f2012-02-03 14:48:03 +000011072 }
ths39b9aae2007-02-11 18:36:44 +000011073 break;
bellardd2fd1af2007-11-14 18:08:56 +000011074#ifdef TARGET_NR_arch_prctl
11075 case TARGET_NR_arch_prctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011076 return do_arch_prctl(cpu_env, arg1, arg2);
bellardd2fd1af2007-11-14 18:08:56 +000011077#endif
aurel32f2c7ba12008-03-28 22:32:06 +000011078#ifdef TARGET_NR_pread64
11079 case TARGET_NR_pread64:
James Clarke8bf8e9d2017-09-15 20:33:13 +010011080 if (regpairs_aligned(cpu_env, num)) {
Alexander Grafae017a52012-09-29 15:32:39 +000011081 arg4 = arg5;
11082 arg5 = arg6;
11083 }
Peter Maydell2bd3f892019-01-08 18:49:00 +000011084 if (arg2 == 0 && arg3 == 0) {
11085 /* Special-case NULL buffer and zero length, which should succeed */
11086 p = 0;
11087 } else {
11088 p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
11089 if (!p) {
11090 return -TARGET_EFAULT;
11091 }
11092 }
aurel32f2c7ba12008-03-28 22:32:06 +000011093 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
11094 unlock_user(p, arg2, ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011095 return ret;
aurel32f2c7ba12008-03-28 22:32:06 +000011096 case TARGET_NR_pwrite64:
James Clarke8bf8e9d2017-09-15 20:33:13 +010011097 if (regpairs_aligned(cpu_env, num)) {
Alexander Grafae017a52012-09-29 15:32:39 +000011098 arg4 = arg5;
11099 arg5 = arg6;
11100 }
Peter Maydell2bd3f892019-01-08 18:49:00 +000011101 if (arg2 == 0 && arg3 == 0) {
11102 /* Special-case NULL buffer and zero length, which should succeed */
11103 p = 0;
11104 } else {
11105 p = lock_user(VERIFY_READ, arg2, arg3, 1);
11106 if (!p) {
11107 return -TARGET_EFAULT;
11108 }
11109 }
aurel32f2c7ba12008-03-28 22:32:06 +000011110 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
11111 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011112 return ret;
aurel32f2c7ba12008-03-28 22:32:06 +000011113#endif
bellard31e31b82003-02-18 22:55:36 +000011114 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +000011115 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011116 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011117 ret = get_errno(sys_getcwd1(p, arg2));
11118 unlock_user(p, arg1, ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011119 return ret;
bellard31e31b82003-02-18 22:55:36 +000011120 case TARGET_NR_capget:
11121 case TARGET_NR_capset:
Peter Maydelle0eb2102014-03-17 12:15:35 +000011122 {
11123 struct target_user_cap_header *target_header;
11124 struct target_user_cap_data *target_data = NULL;
11125 struct __user_cap_header_struct header;
11126 struct __user_cap_data_struct data[2];
11127 struct __user_cap_data_struct *dataptr = NULL;
11128 int i, target_datalen;
11129 int data_items = 1;
11130
11131 if (!lock_user_struct(VERIFY_WRITE, target_header, arg1, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011132 return -TARGET_EFAULT;
Peter Maydelle0eb2102014-03-17 12:15:35 +000011133 }
11134 header.version = tswap32(target_header->version);
11135 header.pid = tswap32(target_header->pid);
11136
Peter Maydellec864872014-03-19 16:07:30 +000011137 if (header.version != _LINUX_CAPABILITY_VERSION) {
Peter Maydelle0eb2102014-03-17 12:15:35 +000011138 /* Version 2 and up takes pointer to two user_data structs */
11139 data_items = 2;
11140 }
11141
11142 target_datalen = sizeof(*target_data) * data_items;
11143
11144 if (arg2) {
11145 if (num == TARGET_NR_capget) {
11146 target_data = lock_user(VERIFY_WRITE, arg2, target_datalen, 0);
11147 } else {
11148 target_data = lock_user(VERIFY_READ, arg2, target_datalen, 1);
11149 }
11150 if (!target_data) {
11151 unlock_user_struct(target_header, arg1, 0);
Richard Henderson2852aaf2018-08-18 12:01:06 -070011152 return -TARGET_EFAULT;
Peter Maydelle0eb2102014-03-17 12:15:35 +000011153 }
11154
11155 if (num == TARGET_NR_capset) {
11156 for (i = 0; i < data_items; i++) {
11157 data[i].effective = tswap32(target_data[i].effective);
11158 data[i].permitted = tswap32(target_data[i].permitted);
11159 data[i].inheritable = tswap32(target_data[i].inheritable);
11160 }
11161 }
11162
11163 dataptr = data;
11164 }
11165
11166 if (num == TARGET_NR_capget) {
11167 ret = get_errno(capget(&header, dataptr));
11168 } else {
11169 ret = get_errno(capset(&header, dataptr));
11170 }
11171
11172 /* The kernel always updates version for both capget and capset */
11173 target_header->version = tswap32(header.version);
11174 unlock_user_struct(target_header, arg1, 1);
11175
11176 if (arg2) {
11177 if (num == TARGET_NR_capget) {
11178 for (i = 0; i < data_items; i++) {
11179 target_data[i].effective = tswap32(data[i].effective);
11180 target_data[i].permitted = tswap32(data[i].permitted);
11181 target_data[i].inheritable = tswap32(data[i].inheritable);
11182 }
11183 unlock_user(target_data, arg2, target_datalen);
11184 } else {
11185 unlock_user(target_data, arg2, 0);
11186 }
11187 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011188 return ret;
Peter Maydelle0eb2102014-03-17 12:15:35 +000011189 }
bellard31e31b82003-02-18 22:55:36 +000011190 case TARGET_NR_sigaltstack:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011191 return do_sigaltstack(arg1, arg2,
11192 get_sp_from_cpustate((CPUArchState *)cpu_env));
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011193
11194#ifdef CONFIG_SENDFILE
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020011195#ifdef TARGET_NR_sendfile
bellard31e31b82003-02-18 22:55:36 +000011196 case TARGET_NR_sendfile:
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011197 {
11198 off_t *offp = NULL;
11199 off_t off;
11200 if (arg3) {
11201 ret = get_user_sal(off, arg3);
11202 if (is_error(ret)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011203 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011204 }
11205 offp = &off;
11206 }
11207 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
11208 if (!is_error(ret) && arg3) {
11209 abi_long ret2 = put_user_sal(off, arg3);
11210 if (is_error(ret2)) {
11211 ret = ret2;
11212 }
11213 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011214 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011215 }
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020011216#endif
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011217#ifdef TARGET_NR_sendfile64
11218 case TARGET_NR_sendfile64:
11219 {
11220 off_t *offp = NULL;
11221 off_t off;
11222 if (arg3) {
11223 ret = get_user_s64(off, arg3);
11224 if (is_error(ret)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011225 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011226 }
11227 offp = &off;
11228 }
11229 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
11230 if (!is_error(ret) && arg3) {
11231 abi_long ret2 = put_user_s64(off, arg3);
11232 if (is_error(ret2)) {
11233 ret = ret2;
11234 }
11235 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011236 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011237 }
11238#endif
bellardebc05482003-09-30 21:08:41 +000011239#endif
bellard048f6b42005-11-26 18:47:20 +000011240#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +000011241 case TARGET_NR_vfork:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011242 return get_errno(do_fork(cpu_env,
11243 CLONE_VFORK | CLONE_VM | TARGET_SIGCHLD,
11244 0, 0, 0, 0));
bellard048f6b42005-11-26 18:47:20 +000011245#endif
bellardebc05482003-09-30 21:08:41 +000011246#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +000011247 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +000011248 {
11249 struct rlimit rlim;
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +030011250 int resource = target_to_host_resource(arg1);
11251 ret = get_errno(getrlimit(resource, &rlim));
bellard728584b2003-04-29 20:43:36 +000011252 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +000011253 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +000011254 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011255 return -TARGET_EFAULT;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +090011256 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
11257 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +000011258 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +000011259 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011260 return ret;
bellard728584b2003-04-29 20:43:36 +000011261 }
bellardebc05482003-09-30 21:08:41 +000011262#endif
bellarda315a142005-01-30 22:59:18 +000011263#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +000011264 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +000011265 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011266 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011267 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
11268 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011269 return ret;
bellarda315a142005-01-30 22:59:18 +000011270#endif
11271#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +000011272 case TARGET_NR_ftruncate64:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011273 return target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellarda315a142005-01-30 22:59:18 +000011274#endif
11275#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +000011276 case TARGET_NR_stat64:
Richard Henderson2852aaf2018-08-18 12:01:06 -070011277 if (!(p = lock_user_string(arg1))) {
11278 return -TARGET_EFAULT;
11279 }
pbrook53a59602006-03-25 19:31:22 +000011280 ret = get_errno(stat(path(p), &st));
11281 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +000011282 if (!is_error(ret))
11283 ret = host_to_target_stat64(cpu_env, arg2, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011284 return ret;
bellarda315a142005-01-30 22:59:18 +000011285#endif
11286#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +000011287 case TARGET_NR_lstat64:
Richard Henderson2852aaf2018-08-18 12:01:06 -070011288 if (!(p = lock_user_string(arg1))) {
11289 return -TARGET_EFAULT;
11290 }
pbrook53a59602006-03-25 19:31:22 +000011291 ret = get_errno(lstat(path(p), &st));
11292 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +000011293 if (!is_error(ret))
11294 ret = host_to_target_stat64(cpu_env, arg2, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011295 return ret;
bellarda315a142005-01-30 22:59:18 +000011296#endif
11297#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +000011298 case TARGET_NR_fstat64:
balrog6a24a772008-09-20 02:23:36 +000011299 ret = get_errno(fstat(arg1, &st));
11300 if (!is_error(ret))
11301 ret = host_to_target_stat64(cpu_env, arg2, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011302 return ret;
bellardec86b0f2003-04-11 00:15:04 +000011303#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +010011304#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat))
aurel329d33b762009-04-08 23:07:05 +000011305#ifdef TARGET_NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +000011306 case TARGET_NR_fstatat64:
aurel329d33b762009-04-08 23:07:05 +000011307#endif
11308#ifdef TARGET_NR_newfstatat
11309 case TARGET_NR_newfstatat:
11310#endif
Richard Henderson2852aaf2018-08-18 12:01:06 -070011311 if (!(p = lock_user_string(arg2))) {
11312 return -TARGET_EFAULT;
11313 }
Peter Maydellc0d472b2013-06-12 16:20:21 +010011314 ret = get_errno(fstatat(arg1, path(p), &st, arg4));
Richard Henderson2852aaf2018-08-18 12:01:06 -070011315 unlock_user(p, arg2, 0);
balrog6a24a772008-09-20 02:23:36 +000011316 if (!is_error(ret))
11317 ret = host_to_target_stat64(cpu_env, arg3, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011318 return ret;
bellarda315a142005-01-30 22:59:18 +000011319#endif
Aleksandar Rikaloefa92182019-06-28 12:43:34 +020011320#if defined(TARGET_NR_statx)
11321 case TARGET_NR_statx:
11322 {
11323 struct target_statx *target_stx;
11324 int dirfd = arg1;
11325 int flags = arg3;
11326
11327 p = lock_user_string(arg2);
11328 if (p == NULL) {
11329 return -TARGET_EFAULT;
11330 }
11331#if defined(__NR_statx)
11332 {
11333 /*
11334 * It is assumed that struct statx is architecture independent.
11335 */
11336 struct target_statx host_stx;
11337 int mask = arg4;
11338
11339 ret = get_errno(sys_statx(dirfd, p, flags, mask, &host_stx));
11340 if (!is_error(ret)) {
11341 if (host_to_target_statx(&host_stx, arg5) != 0) {
11342 unlock_user(p, arg2, 0);
11343 return -TARGET_EFAULT;
11344 }
11345 }
11346
11347 if (ret != -TARGET_ENOSYS) {
11348 unlock_user(p, arg2, 0);
11349 return ret;
11350 }
11351 }
11352#endif
11353 ret = get_errno(fstatat(dirfd, path(p), &st, flags));
11354 unlock_user(p, arg2, 0);
11355
11356 if (!is_error(ret)) {
11357 if (!lock_user_struct(VERIFY_WRITE, target_stx, arg5, 0)) {
11358 return -TARGET_EFAULT;
11359 }
11360 memset(target_stx, 0, sizeof(*target_stx));
11361 __put_user(major(st.st_dev), &target_stx->stx_dev_major);
11362 __put_user(minor(st.st_dev), &target_stx->stx_dev_minor);
11363 __put_user(st.st_ino, &target_stx->stx_ino);
11364 __put_user(st.st_mode, &target_stx->stx_mode);
11365 __put_user(st.st_uid, &target_stx->stx_uid);
11366 __put_user(st.st_gid, &target_stx->stx_gid);
11367 __put_user(st.st_nlink, &target_stx->stx_nlink);
11368 __put_user(major(st.st_rdev), &target_stx->stx_rdev_major);
11369 __put_user(minor(st.st_rdev), &target_stx->stx_rdev_minor);
11370 __put_user(st.st_size, &target_stx->stx_size);
11371 __put_user(st.st_blksize, &target_stx->stx_blksize);
11372 __put_user(st.st_blocks, &target_stx->stx_blocks);
11373 __put_user(st.st_atime, &target_stx->stx_atime.tv_sec);
11374 __put_user(st.st_mtime, &target_stx->stx_mtime.tv_sec);
11375 __put_user(st.st_ctime, &target_stx->stx_ctime.tv_sec);
11376 unlock_user_struct(target_stx, arg5, 1);
11377 }
11378 }
11379 return ret;
11380#endif
Chen Gang704eff62015-08-21 05:37:33 +080011381#ifdef TARGET_NR_lchown
bellard67867302003-11-23 17:05:30 +000011382 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +000011383 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011384 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011385 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
11386 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011387 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080011388#endif
Riku Voipio0c866a72011-04-18 15:23:06 +030011389#ifdef TARGET_NR_getuid
bellard67867302003-11-23 17:05:30 +000011390 case TARGET_NR_getuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011391 return get_errno(high2lowuid(getuid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030011392#endif
11393#ifdef TARGET_NR_getgid
bellard67867302003-11-23 17:05:30 +000011394 case TARGET_NR_getgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011395 return get_errno(high2lowgid(getgid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030011396#endif
11397#ifdef TARGET_NR_geteuid
bellard67867302003-11-23 17:05:30 +000011398 case TARGET_NR_geteuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011399 return get_errno(high2lowuid(geteuid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030011400#endif
11401#ifdef TARGET_NR_getegid
bellard67867302003-11-23 17:05:30 +000011402 case TARGET_NR_getegid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011403 return get_errno(high2lowgid(getegid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030011404#endif
bellard67867302003-11-23 17:05:30 +000011405 case TARGET_NR_setreuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011406 return get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
bellard67867302003-11-23 17:05:30 +000011407 case TARGET_NR_setregid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011408 return get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
bellard67867302003-11-23 17:05:30 +000011409 case TARGET_NR_getgroups:
11410 {
11411 int gidsetsize = arg1;
Riku Voipio0c866a72011-04-18 15:23:06 +030011412 target_id *target_grouplist;
bellard67867302003-11-23 17:05:30 +000011413 gid_t *grouplist;
11414 int i;
11415
11416 grouplist = alloca(gidsetsize * sizeof(gid_t));
11417 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +000011418 if (gidsetsize == 0)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011419 return ret;
bellard67867302003-11-23 17:05:30 +000011420 if (!is_error(ret)) {
Andreas Schwab03903ff2013-04-09 05:41:33 +000011421 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * sizeof(target_id), 0);
bellard579a97f2007-11-11 14:26:47 +000011422 if (!target_grouplist)
Richard Henderson2852aaf2018-08-18 12:01:06 -070011423 return -TARGET_EFAULT;
balroga2155fc2008-09-20 02:12:08 +000011424 for(i = 0;i < ret; i++)
Riku Voipio0c866a72011-04-18 15:23:06 +030011425 target_grouplist[i] = tswapid(high2lowgid(grouplist[i]));
Andreas Schwab03903ff2013-04-09 05:41:33 +000011426 unlock_user(target_grouplist, arg2, gidsetsize * sizeof(target_id));
bellard67867302003-11-23 17:05:30 +000011427 }
11428 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011429 return ret;
bellard67867302003-11-23 17:05:30 +000011430 case TARGET_NR_setgroups:
11431 {
11432 int gidsetsize = arg1;
Riku Voipio0c866a72011-04-18 15:23:06 +030011433 target_id *target_grouplist;
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050011434 gid_t *grouplist = NULL;
bellard67867302003-11-23 17:05:30 +000011435 int i;
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050011436 if (gidsetsize) {
11437 grouplist = alloca(gidsetsize * sizeof(gid_t));
Andreas Schwab03903ff2013-04-09 05:41:33 +000011438 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * sizeof(target_id), 1);
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050011439 if (!target_grouplist) {
Richard Henderson259841c2018-08-18 12:01:09 -070011440 return -TARGET_EFAULT;
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050011441 }
11442 for (i = 0; i < gidsetsize; i++) {
11443 grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
11444 }
11445 unlock_user(target_grouplist, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +000011446 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011447 return get_errno(setgroups(gidsetsize, grouplist));
bellard67867302003-11-23 17:05:30 +000011448 }
bellard67867302003-11-23 17:05:30 +000011449 case TARGET_NR_fchown:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011450 return get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
Peter Maydellc0d472b2013-06-12 16:20:21 +010011451#if defined(TARGET_NR_fchownat)
thsccfa72b2007-09-24 09:23:34 +000011452 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +000011453 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011454 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +010011455 ret = get_errno(fchownat(arg1, p, low2highuid(arg3),
11456 low2highgid(arg4), arg5));
bellard579a97f2007-11-11 14:26:47 +000011457 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011458 return ret;
thsccfa72b2007-09-24 09:23:34 +000011459#endif
bellard67867302003-11-23 17:05:30 +000011460#ifdef TARGET_NR_setresuid
11461 case TARGET_NR_setresuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011462 return get_errno(sys_setresuid(low2highuid(arg1),
11463 low2highuid(arg2),
11464 low2highuid(arg3)));
bellard67867302003-11-23 17:05:30 +000011465#endif
11466#ifdef TARGET_NR_getresuid
11467 case TARGET_NR_getresuid:
11468 {
pbrook53a59602006-03-25 19:31:22 +000011469 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +000011470 ret = get_errno(getresuid(&ruid, &euid, &suid));
11471 if (!is_error(ret)) {
Peter Maydell76ca3102014-03-02 19:36:41 +000011472 if (put_user_id(high2lowuid(ruid), arg1)
11473 || put_user_id(high2lowuid(euid), arg2)
11474 || put_user_id(high2lowuid(suid), arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011475 return -TARGET_EFAULT;
bellard67867302003-11-23 17:05:30 +000011476 }
11477 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011478 return ret;
bellard67867302003-11-23 17:05:30 +000011479#endif
11480#ifdef TARGET_NR_getresgid
11481 case TARGET_NR_setresgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011482 return get_errno(sys_setresgid(low2highgid(arg1),
11483 low2highgid(arg2),
11484 low2highgid(arg3)));
bellard67867302003-11-23 17:05:30 +000011485#endif
11486#ifdef TARGET_NR_getresgid
11487 case TARGET_NR_getresgid:
11488 {
pbrook53a59602006-03-25 19:31:22 +000011489 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +000011490 ret = get_errno(getresgid(&rgid, &egid, &sgid));
11491 if (!is_error(ret)) {
Peter Maydell76ca3102014-03-02 19:36:41 +000011492 if (put_user_id(high2lowgid(rgid), arg1)
11493 || put_user_id(high2lowgid(egid), arg2)
11494 || put_user_id(high2lowgid(sgid), arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011495 return -TARGET_EFAULT;
bellard67867302003-11-23 17:05:30 +000011496 }
11497 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011498 return ret;
bellard67867302003-11-23 17:05:30 +000011499#endif
Chen Gang704eff62015-08-21 05:37:33 +080011500#ifdef TARGET_NR_chown
bellard67867302003-11-23 17:05:30 +000011501 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +000011502 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011503 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011504 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
11505 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011506 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080011507#endif
bellard67867302003-11-23 17:05:30 +000011508 case TARGET_NR_setuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011509 return get_errno(sys_setuid(low2highuid(arg1)));
bellard67867302003-11-23 17:05:30 +000011510 case TARGET_NR_setgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011511 return get_errno(sys_setgid(low2highgid(arg1)));
bellard67867302003-11-23 17:05:30 +000011512 case TARGET_NR_setfsuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011513 return get_errno(setfsuid(arg1));
bellard67867302003-11-23 17:05:30 +000011514 case TARGET_NR_setfsgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011515 return get_errno(setfsgid(arg1));
bellard67867302003-11-23 17:05:30 +000011516
bellarda315a142005-01-30 22:59:18 +000011517#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +000011518 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +000011519 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011520 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011521 ret = get_errno(lchown(p, arg2, arg3));
11522 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011523 return ret;
bellarda315a142005-01-30 22:59:18 +000011524#endif
11525#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +000011526 case TARGET_NR_getuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011527 return get_errno(getuid());
bellarda315a142005-01-30 22:59:18 +000011528#endif
aurel3264b4d282008-11-14 17:20:15 +000011529
11530#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
11531 /* Alpha specific */
11532 case TARGET_NR_getxuid:
Richard Hendersonba0e2762009-12-09 15:56:29 -080011533 {
11534 uid_t euid;
11535 euid=geteuid();
11536 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
11537 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011538 return get_errno(getuid());
aurel3264b4d282008-11-14 17:20:15 +000011539#endif
11540#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
11541 /* Alpha specific */
11542 case TARGET_NR_getxgid:
Richard Hendersonba0e2762009-12-09 15:56:29 -080011543 {
11544 uid_t egid;
11545 egid=getegid();
11546 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
11547 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011548 return get_errno(getgid());
aurel3264b4d282008-11-14 17:20:15 +000011549#endif
Richard Hendersonba0e2762009-12-09 15:56:29 -080011550#if defined(TARGET_NR_osf_getsysinfo) && defined(TARGET_ALPHA)
11551 /* Alpha specific */
11552 case TARGET_NR_osf_getsysinfo:
11553 ret = -TARGET_EOPNOTSUPP;
11554 switch (arg1) {
11555 case TARGET_GSI_IEEE_FP_CONTROL:
11556 {
Richard Henderson21ba8562019-04-26 15:20:51 -070011557 uint64_t fpcr = cpu_alpha_load_fpcr(cpu_env);
11558 uint64_t swcr = ((CPUAlphaState *)cpu_env)->swcr;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011559
Richard Henderson21ba8562019-04-26 15:20:51 -070011560 swcr &= ~SWCR_STATUS_MASK;
11561 swcr |= (fpcr >> 35) & SWCR_STATUS_MASK;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011562
11563 if (put_user_u64 (swcr, arg2))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011564 return -TARGET_EFAULT;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011565 ret = 0;
11566 }
11567 break;
11568
11569 /* case GSI_IEEE_STATE_AT_SIGNAL:
11570 -- Not implemented in linux kernel.
11571 case GSI_UACPROC:
11572 -- Retrieves current unaligned access state; not much used.
11573 case GSI_PROC_TYPE:
11574 -- Retrieves implver information; surely not used.
11575 case GSI_GET_HWRPB:
11576 -- Grabs a copy of the HWRPB; surely not used.
11577 */
11578 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011579 return ret;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011580#endif
11581#if defined(TARGET_NR_osf_setsysinfo) && defined(TARGET_ALPHA)
11582 /* Alpha specific */
11583 case TARGET_NR_osf_setsysinfo:
11584 ret = -TARGET_EOPNOTSUPP;
11585 switch (arg1) {
11586 case TARGET_SSI_IEEE_FP_CONTROL:
Richard Hendersonba0e2762009-12-09 15:56:29 -080011587 {
Richard Henderson21ba8562019-04-26 15:20:51 -070011588 uint64_t swcr, fpcr;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011589
Richard Henderson6e06d512012-06-01 09:08:21 -070011590 if (get_user_u64 (swcr, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011591 return -TARGET_EFAULT;
Richard Henderson6e06d512012-06-01 09:08:21 -070011592 }
Richard Hendersonba0e2762009-12-09 15:56:29 -080011593
Richard Henderson21ba8562019-04-26 15:20:51 -070011594 /*
11595 * The kernel calls swcr_update_status to update the
11596 * status bits from the fpcr at every point that it
11597 * could be queried. Therefore, we store the status
11598 * bits only in FPCR.
11599 */
11600 ((CPUAlphaState *)cpu_env)->swcr
11601 = swcr & (SWCR_TRAP_ENABLE_MASK | SWCR_MAP_MASK);
Richard Hendersonba0e2762009-12-09 15:56:29 -080011602
Richard Henderson21ba8562019-04-26 15:20:51 -070011603 fpcr = cpu_alpha_load_fpcr(cpu_env);
11604 fpcr &= ((uint64_t)FPCR_DYN_MASK << 32);
11605 fpcr |= alpha_ieee_swcr_to_fpcr(swcr);
Richard Henderson6e06d512012-06-01 09:08:21 -070011606 cpu_alpha_store_fpcr(cpu_env, fpcr);
11607 ret = 0;
11608 }
11609 break;
11610
11611 case TARGET_SSI_IEEE_RAISE_EXCEPTION:
11612 {
Richard Henderson21ba8562019-04-26 15:20:51 -070011613 uint64_t exc, fpcr, fex;
Richard Henderson6e06d512012-06-01 09:08:21 -070011614
11615 if (get_user_u64(exc, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011616 return -TARGET_EFAULT;
Richard Henderson6e06d512012-06-01 09:08:21 -070011617 }
Richard Henderson21ba8562019-04-26 15:20:51 -070011618 exc &= SWCR_STATUS_MASK;
11619 fpcr = cpu_alpha_load_fpcr(cpu_env);
Richard Hendersonba0e2762009-12-09 15:56:29 -080011620
Richard Henderson6e06d512012-06-01 09:08:21 -070011621 /* Old exceptions are not signaled. */
Richard Henderson21ba8562019-04-26 15:20:51 -070011622 fex = alpha_ieee_fpcr_to_swcr(fpcr);
11623 fex = exc & ~fex;
11624 fex >>= SWCR_STATUS_TO_EXCSUM_SHIFT;
11625 fex &= ((CPUArchState *)cpu_env)->swcr;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011626
Richard Henderson21ba8562019-04-26 15:20:51 -070011627 /* Update the hardware fpcr. */
11628 fpcr |= alpha_ieee_swcr_to_fpcr(exc);
11629 cpu_alpha_store_fpcr(cpu_env, fpcr);
11630
11631 if (fex) {
11632 int si_code = TARGET_FPE_FLTUNK;
Richard Henderson6e06d512012-06-01 09:08:21 -070011633 target_siginfo_t info;
Richard Henderson21ba8562019-04-26 15:20:51 -070011634
11635 if (fex & SWCR_TRAP_ENABLE_DNO) {
11636 si_code = TARGET_FPE_FLTUND;
11637 }
11638 if (fex & SWCR_TRAP_ENABLE_INE) {
11639 si_code = TARGET_FPE_FLTRES;
11640 }
11641 if (fex & SWCR_TRAP_ENABLE_UNF) {
11642 si_code = TARGET_FPE_FLTUND;
11643 }
11644 if (fex & SWCR_TRAP_ENABLE_OVF) {
11645 si_code = TARGET_FPE_FLTOVF;
11646 }
11647 if (fex & SWCR_TRAP_ENABLE_DZE) {
11648 si_code = TARGET_FPE_FLTDIV;
11649 }
11650 if (fex & SWCR_TRAP_ENABLE_INV) {
11651 si_code = TARGET_FPE_FLTINV;
11652 }
11653
Richard Henderson6e06d512012-06-01 09:08:21 -070011654 info.si_signo = SIGFPE;
11655 info.si_errno = 0;
11656 info.si_code = si_code;
11657 info._sifields._sigfault._addr
11658 = ((CPUArchState *)cpu_env)->pc;
Peter Maydell9d2803f2016-07-28 16:44:46 +010011659 queue_signal((CPUArchState *)cpu_env, info.si_signo,
11660 QEMU_SI_FAULT, &info);
Richard Hendersonba0e2762009-12-09 15:56:29 -080011661 }
Richard Henderson21ba8562019-04-26 15:20:51 -070011662 ret = 0;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011663 }
11664 break;
11665
11666 /* case SSI_NVPAIRS:
11667 -- Used with SSIN_UACPROC to enable unaligned accesses.
11668 case SSI_IEEE_STATE_AT_SIGNAL:
11669 case SSI_IEEE_IGNORE_STATE_AT_SIGNAL:
11670 -- Not implemented in linux kernel
11671 */
11672 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011673 return ret;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011674#endif
11675#ifdef TARGET_NR_osf_sigprocmask
11676 /* Alpha specific. */
11677 case TARGET_NR_osf_sigprocmask:
11678 {
11679 abi_ulong mask;
Juan Quintelabc088ba2011-06-16 17:37:10 +010011680 int how;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011681 sigset_t set, oldset;
11682
11683 switch(arg1) {
11684 case TARGET_SIG_BLOCK:
11685 how = SIG_BLOCK;
11686 break;
11687 case TARGET_SIG_UNBLOCK:
11688 how = SIG_UNBLOCK;
11689 break;
11690 case TARGET_SIG_SETMASK:
11691 how = SIG_SETMASK;
11692 break;
11693 default:
Richard Henderson259841c2018-08-18 12:01:09 -070011694 return -TARGET_EINVAL;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011695 }
11696 mask = arg2;
11697 target_to_host_old_sigset(&set, &mask);
Peter Maydell3d3efba2016-05-27 15:51:49 +010011698 ret = do_sigprocmask(how, &set, &oldset);
11699 if (!ret) {
11700 host_to_target_old_sigset(&mask, &oldset);
11701 ret = mask;
11702 }
Richard Hendersonba0e2762009-12-09 15:56:29 -080011703 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011704 return ret;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011705#endif
aurel3264b4d282008-11-14 17:20:15 +000011706
bellarda315a142005-01-30 22:59:18 +000011707#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +000011708 case TARGET_NR_getgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011709 return get_errno(getgid());
bellarda315a142005-01-30 22:59:18 +000011710#endif
11711#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +000011712 case TARGET_NR_geteuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011713 return get_errno(geteuid());
bellarda315a142005-01-30 22:59:18 +000011714#endif
11715#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +000011716 case TARGET_NR_getegid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011717 return get_errno(getegid());
bellarda315a142005-01-30 22:59:18 +000011718#endif
11719#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +000011720 case TARGET_NR_setreuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011721 return get_errno(setreuid(arg1, arg2));
bellarda315a142005-01-30 22:59:18 +000011722#endif
11723#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +000011724 case TARGET_NR_setregid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011725 return get_errno(setregid(arg1, arg2));
bellarda315a142005-01-30 22:59:18 +000011726#endif
11727#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +000011728 case TARGET_NR_getgroups32:
bellard99c475a2005-01-31 20:45:13 +000011729 {
11730 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +000011731 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +000011732 gid_t *grouplist;
11733 int i;
11734
11735 grouplist = alloca(gidsetsize * sizeof(gid_t));
11736 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +000011737 if (gidsetsize == 0)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011738 return ret;
bellard99c475a2005-01-31 20:45:13 +000011739 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +000011740 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
11741 if (!target_grouplist) {
Richard Henderson259841c2018-08-18 12:01:09 -070011742 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000011743 }
balroga2155fc2008-09-20 02:12:08 +000011744 for(i = 0;i < ret; i++)
pbrook53a59602006-03-25 19:31:22 +000011745 target_grouplist[i] = tswap32(grouplist[i]);
11746 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +000011747 }
11748 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011749 return ret;
bellarda315a142005-01-30 22:59:18 +000011750#endif
11751#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +000011752 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +000011753 {
11754 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +000011755 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +000011756 gid_t *grouplist;
11757 int i;
ths3b46e622007-09-17 08:09:54 +000011758
bellard99c475a2005-01-31 20:45:13 +000011759 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +000011760 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
11761 if (!target_grouplist) {
Richard Henderson259841c2018-08-18 12:01:09 -070011762 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000011763 }
bellard99c475a2005-01-31 20:45:13 +000011764 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +000011765 grouplist[i] = tswap32(target_grouplist[i]);
11766 unlock_user(target_grouplist, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011767 return get_errno(setgroups(gidsetsize, grouplist));
bellard99c475a2005-01-31 20:45:13 +000011768 }
bellarda315a142005-01-30 22:59:18 +000011769#endif
11770#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +000011771 case TARGET_NR_fchown32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011772 return get_errno(fchown(arg1, arg2, arg3));
bellarda315a142005-01-30 22:59:18 +000011773#endif
11774#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +000011775 case TARGET_NR_setresuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011776 return get_errno(sys_setresuid(arg1, arg2, arg3));
bellarda315a142005-01-30 22:59:18 +000011777#endif
11778#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +000011779 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +000011780 {
pbrook53a59602006-03-25 19:31:22 +000011781 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +000011782 ret = get_errno(getresuid(&ruid, &euid, &suid));
11783 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +000011784 if (put_user_u32(ruid, arg1)
11785 || put_user_u32(euid, arg2)
11786 || put_user_u32(suid, arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011787 return -TARGET_EFAULT;
bellardb03c60f2003-03-23 17:19:56 +000011788 }
11789 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011790 return ret;
bellarda315a142005-01-30 22:59:18 +000011791#endif
11792#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +000011793 case TARGET_NR_setresgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011794 return get_errno(sys_setresgid(arg1, arg2, arg3));
bellarda315a142005-01-30 22:59:18 +000011795#endif
11796#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +000011797 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +000011798 {
pbrook53a59602006-03-25 19:31:22 +000011799 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +000011800 ret = get_errno(getresgid(&rgid, &egid, &sgid));
11801 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +000011802 if (put_user_u32(rgid, arg1)
11803 || put_user_u32(egid, arg2)
11804 || put_user_u32(sgid, arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011805 return -TARGET_EFAULT;
bellardb03c60f2003-03-23 17:19:56 +000011806 }
11807 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011808 return ret;
bellarda315a142005-01-30 22:59:18 +000011809#endif
11810#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +000011811 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +000011812 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011813 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011814 ret = get_errno(chown(p, arg2, arg3));
11815 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011816 return ret;
bellarda315a142005-01-30 22:59:18 +000011817#endif
11818#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +000011819 case TARGET_NR_setuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011820 return get_errno(sys_setuid(arg1));
bellarda315a142005-01-30 22:59:18 +000011821#endif
11822#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +000011823 case TARGET_NR_setgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011824 return get_errno(sys_setgid(arg1));
bellarda315a142005-01-30 22:59:18 +000011825#endif
11826#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +000011827 case TARGET_NR_setfsuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011828 return get_errno(setfsuid(arg1));
bellarda315a142005-01-30 22:59:18 +000011829#endif
11830#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +000011831 case TARGET_NR_setfsgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011832 return get_errno(setfsgid(arg1));
bellarda315a142005-01-30 22:59:18 +000011833#endif
bellardffa65c32004-01-04 23:57:22 +000011834#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +000011835 case TARGET_NR_mincore:
aurel3204bb9ac2008-10-01 21:46:41 +000011836 {
Richard Henderson259841c2018-08-18 12:01:09 -070011837 void *a = lock_user(VERIFY_READ, arg1, arg2, 0);
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000011838 if (!a) {
Richard Henderson259841c2018-08-18 12:01:09 -070011839 return -TARGET_ENOMEM;
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000011840 }
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000011841 p = lock_user_string(arg3);
11842 if (!p) {
Richard Henderson259841c2018-08-18 12:01:09 -070011843 ret = -TARGET_EFAULT;
11844 } else {
11845 ret = get_errno(mincore(a, arg2, p));
11846 unlock_user(p, arg3, ret);
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000011847 }
aurel3204bb9ac2008-10-01 21:46:41 +000011848 unlock_user(a, arg1, 0);
11849 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011850 return ret;
bellardffa65c32004-01-04 23:57:22 +000011851#endif
aurel32408321b2008-10-01 21:46:32 +000011852#ifdef TARGET_NR_arm_fadvise64_64
11853 case TARGET_NR_arm_fadvise64_64:
Peter Maydelle0156a92016-05-31 15:45:09 +010011854 /* arm_fadvise64_64 looks like fadvise64_64 but
11855 * with different argument order: fd, advice, offset, len
11856 * rather than the usual fd, offset, len, advice.
11857 * Note that offset and len are both 64-bit so appear as
11858 * pairs of 32-bit registers.
11859 */
11860 ret = posix_fadvise(arg1, target_offset64(arg3, arg4),
11861 target_offset64(arg5, arg6), arg2);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011862 return -host_to_target_errno(ret);
aurel32408321b2008-10-01 21:46:32 +000011863#endif
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011864
11865#if TARGET_ABI_BITS == 32
11866
11867#ifdef TARGET_NR_fadvise64_64
11868 case TARGET_NR_fadvise64_64:
Max Filippov64a563d2018-04-01 15:02:34 -070011869#if defined(TARGET_PPC) || defined(TARGET_XTENSA)
Laurent Vivier43046b52017-03-02 01:11:45 +010011870 /* 6 args: fd, advice, offset (high, low), len (high, low) */
11871 ret = arg2;
11872 arg2 = arg3;
11873 arg3 = arg4;
11874 arg4 = arg5;
11875 arg5 = arg6;
11876 arg6 = ret;
11877#else
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011878 /* 6 args: fd, offset (high, low), len (high, low), advice */
James Clarke8bf8e9d2017-09-15 20:33:13 +010011879 if (regpairs_aligned(cpu_env, num)) {
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011880 /* offset is in (3,4), len in (5,6) and advice in 7 */
11881 arg2 = arg3;
11882 arg3 = arg4;
11883 arg4 = arg5;
11884 arg5 = arg6;
11885 arg6 = arg7;
11886 }
Laurent Vivier43046b52017-03-02 01:11:45 +010011887#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011888 ret = posix_fadvise(arg1, target_offset64(arg2, arg3),
11889 target_offset64(arg4, arg5), arg6);
11890 return -host_to_target_errno(ret);
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011891#endif
11892
11893#ifdef TARGET_NR_fadvise64
11894 case TARGET_NR_fadvise64:
11895 /* 5 args: fd, offset (high, low), len, advice */
James Clarke8bf8e9d2017-09-15 20:33:13 +010011896 if (regpairs_aligned(cpu_env, num)) {
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011897 /* offset is in (3,4), len in 5 and advice in 6 */
11898 arg2 = arg3;
11899 arg3 = arg4;
11900 arg4 = arg5;
11901 arg5 = arg6;
11902 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011903 ret = posix_fadvise(arg1, target_offset64(arg2, arg3), arg4, arg5);
11904 return -host_to_target_errno(ret);
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011905#endif
11906
11907#else /* not a 32-bit ABI */
Peter Maydelle0156a92016-05-31 15:45:09 +010011908#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_fadvise64)
aurel32408321b2008-10-01 21:46:32 +000011909#ifdef TARGET_NR_fadvise64_64
11910 case TARGET_NR_fadvise64_64:
11911#endif
Ulrich Hechte72d2cc2009-07-24 19:10:31 +020011912#ifdef TARGET_NR_fadvise64
11913 case TARGET_NR_fadvise64:
11914#endif
11915#ifdef TARGET_S390X
11916 switch (arg4) {
11917 case 4: arg4 = POSIX_FADV_NOREUSE + 1; break; /* make sure it's an invalid value */
11918 case 5: arg4 = POSIX_FADV_NOREUSE + 2; break; /* ditto */
11919 case 6: arg4 = POSIX_FADV_DONTNEED; break;
11920 case 7: arg4 = POSIX_FADV_NOREUSE; break;
11921 default: break;
11922 }
11923#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011924 return -host_to_target_errno(posix_fadvise(arg1, arg2, arg3, arg4));
aurel32408321b2008-10-01 21:46:32 +000011925#endif
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011926#endif /* end of 64-bit ABI fadvise handling */
11927
bellardffa65c32004-01-04 23:57:22 +000011928#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +000011929 case TARGET_NR_madvise:
pbrook24836682006-04-16 14:14:53 +000011930 /* A straight passthrough may not be safe because qemu sometimes
Lei Lid2d6b852013-05-20 17:20:50 +080011931 turns private file-backed mappings into anonymous mappings.
pbrook24836682006-04-16 14:14:53 +000011932 This will break MADV_DONTNEED.
11933 This is a hint, so ignoring and returning success is ok. */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011934 return 0;
bellardffa65c32004-01-04 23:57:22 +000011935#endif
Alex Bennéebbf5f2a2020-04-03 20:11:40 +010011936#ifdef TARGET_NR_fcntl64
bellard31e31b82003-02-18 22:55:36 +000011937 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +000011938 {
Alex Bennéebbf5f2a2020-04-03 20:11:40 +010011939 int cmd;
11940 struct flock64 fl;
Peter Maydell213d3e92016-06-13 11:22:05 +010011941 from_flock64_fn *copyfrom = copy_from_user_flock64;
11942 to_flock64_fn *copyto = copy_to_user_flock64;
11943
pbrookce4defa2006-02-09 16:49:55 +000011944#ifdef TARGET_ARM
Laurent Vivier7f254c52018-05-02 23:57:30 +020011945 if (!((CPUARMState *)cpu_env)->eabi) {
11946 copyfrom = copy_from_user_oabi_flock64;
11947 copyto = copy_to_user_oabi_flock64;
Peter Maydell213d3e92016-06-13 11:22:05 +010011948 }
pbrookce4defa2006-02-09 16:49:55 +000011949#endif
bellard77e46722003-04-29 20:39:06 +000011950
Alex Bennéebbf5f2a2020-04-03 20:11:40 +010011951 cmd = target_to_host_fcntl_cmd(arg2);
Peter Maydell31b63192011-12-05 23:11:50 +000011952 if (cmd == -TARGET_EINVAL) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011953 return cmd;
Peter Maydell31b63192011-12-05 23:11:50 +000011954 }
thsb1e341e2007-03-20 21:50:52 +000011955
bellard60cd49d2003-03-16 22:53:56 +000011956 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +000011957 case TARGET_F_GETLK64:
Peter Maydell213d3e92016-06-13 11:22:05 +010011958 ret = copyfrom(&fl, arg3);
11959 if (ret) {
11960 break;
ths58134272007-03-31 18:59:32 +000011961 }
Laurent Vivieraf8ab2b2018-07-13 14:58:05 +020011962 ret = get_errno(safe_fcntl(arg1, cmd, &fl));
Peter Maydell213d3e92016-06-13 11:22:05 +010011963 if (ret == 0) {
11964 ret = copyto(arg3, &fl);
11965 }
bellard77e46722003-04-29 20:39:06 +000011966 break;
11967
thsb1e341e2007-03-20 21:50:52 +000011968 case TARGET_F_SETLK64:
11969 case TARGET_F_SETLKW64:
Peter Maydell213d3e92016-06-13 11:22:05 +010011970 ret = copyfrom(&fl, arg3);
11971 if (ret) {
11972 break;
pbrookce4defa2006-02-09 16:49:55 +000011973 }
Peter Maydell435da5e2016-06-13 11:22:05 +010011974 ret = get_errno(safe_fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +000011975 break;
bellard60cd49d2003-03-16 22:53:56 +000011976 default:
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +020011977 ret = do_fcntl(arg1, arg2, arg3);
bellard60cd49d2003-03-16 22:53:56 +000011978 break;
11979 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011980 return ret;
bellard77e46722003-04-29 20:39:06 +000011981 }
bellard60cd49d2003-03-16 22:53:56 +000011982#endif
ths7d600c82006-12-08 01:32:58 +000011983#ifdef TARGET_NR_cacheflush
11984 case TARGET_NR_cacheflush:
11985 /* self-modifying code is handled automatically, so nothing needed */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011986 return 0;
ths7d600c82006-12-08 01:32:58 +000011987#endif
bellardc573ff62004-01-04 15:51:36 +000011988#ifdef TARGET_NR_getpagesize
11989 case TARGET_NR_getpagesize:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011990 return TARGET_PAGE_SIZE;
bellardc573ff62004-01-04 15:51:36 +000011991#endif
bellard31e31b82003-02-18 22:55:36 +000011992 case TARGET_NR_gettid:
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +000011993 return get_errno(sys_gettid());
thse5febef2007-04-01 18:31:35 +000011994#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +000011995 case TARGET_NR_readahead:
aurel322054ac92008-10-13 21:08:07 +000011996#if TARGET_ABI_BITS == 32
James Clarke8bf8e9d2017-09-15 20:33:13 +010011997 if (regpairs_aligned(cpu_env, num)) {
aurel322054ac92008-10-13 21:08:07 +000011998 arg2 = arg3;
11999 arg3 = arg4;
12000 arg4 = arg5;
12001 }
Lena Djokic77c68502016-11-24 17:08:56 +010012002 ret = get_errno(readahead(arg1, target_offset64(arg2, arg3) , arg4));
aurel322054ac92008-10-13 21:08:07 +000012003#else
12004 ret = get_errno(readahead(arg1, arg2, arg3));
12005#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012006 return ret;
thse5febef2007-04-01 18:31:35 +000012007#endif
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012008#ifdef CONFIG_ATTR
bellardebc05482003-09-30 21:08:41 +000012009#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +000012010 case TARGET_NR_listxattr:
12011 case TARGET_NR_llistxattr:
Peter Maydellfb5590f2011-12-14 15:37:19 +000012012 {
12013 void *p, *b = 0;
12014 if (arg2) {
12015 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
12016 if (!b) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012017 return -TARGET_EFAULT;
Peter Maydellfb5590f2011-12-14 15:37:19 +000012018 }
12019 }
12020 p = lock_user_string(arg1);
12021 if (p) {
12022 if (num == TARGET_NR_listxattr) {
12023 ret = get_errno(listxattr(p, b, arg3));
12024 } else {
12025 ret = get_errno(llistxattr(p, b, arg3));
12026 }
12027 } else {
12028 ret = -TARGET_EFAULT;
12029 }
12030 unlock_user(p, arg1, 0);
12031 unlock_user(b, arg2, arg3);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012032 return ret;
Peter Maydellfb5590f2011-12-14 15:37:19 +000012033 }
12034 case TARGET_NR_flistxattr:
12035 {
12036 void *b = 0;
12037 if (arg2) {
12038 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
12039 if (!b) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012040 return -TARGET_EFAULT;
Peter Maydellfb5590f2011-12-14 15:37:19 +000012041 }
12042 }
12043 ret = get_errno(flistxattr(arg1, b, arg3));
12044 unlock_user(b, arg2, arg3);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012045 return ret;
Peter Maydellfb5590f2011-12-14 15:37:19 +000012046 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012047 case TARGET_NR_setxattr:
Peter Maydell30297b52011-12-14 15:37:18 +000012048 case TARGET_NR_lsetxattr:
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012049 {
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012050 void *p, *n, *v = 0;
12051 if (arg3) {
12052 v = lock_user(VERIFY_READ, arg3, arg4, 1);
12053 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012054 return -TARGET_EFAULT;
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012055 }
12056 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012057 p = lock_user_string(arg1);
12058 n = lock_user_string(arg2);
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012059 if (p && n) {
Peter Maydell30297b52011-12-14 15:37:18 +000012060 if (num == TARGET_NR_setxattr) {
12061 ret = get_errno(setxattr(p, n, v, arg4, arg5));
12062 } else {
12063 ret = get_errno(lsetxattr(p, n, v, arg4, arg5));
12064 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012065 } else {
12066 ret = -TARGET_EFAULT;
12067 }
12068 unlock_user(p, arg1, 0);
12069 unlock_user(n, arg2, 0);
12070 unlock_user(v, arg3, 0);
12071 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012072 return ret;
Peter Maydell30297b52011-12-14 15:37:18 +000012073 case TARGET_NR_fsetxattr:
12074 {
12075 void *n, *v = 0;
12076 if (arg3) {
12077 v = lock_user(VERIFY_READ, arg3, arg4, 1);
12078 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012079 return -TARGET_EFAULT;
Peter Maydell30297b52011-12-14 15:37:18 +000012080 }
12081 }
12082 n = lock_user_string(arg2);
12083 if (n) {
12084 ret = get_errno(fsetxattr(arg1, n, v, arg4, arg5));
12085 } else {
12086 ret = -TARGET_EFAULT;
12087 }
12088 unlock_user(n, arg2, 0);
12089 unlock_user(v, arg3, 0);
12090 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012091 return ret;
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012092 case TARGET_NR_getxattr:
Peter Maydell30297b52011-12-14 15:37:18 +000012093 case TARGET_NR_lgetxattr:
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012094 {
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012095 void *p, *n, *v = 0;
12096 if (arg3) {
12097 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
12098 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012099 return -TARGET_EFAULT;
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012100 }
12101 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012102 p = lock_user_string(arg1);
12103 n = lock_user_string(arg2);
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012104 if (p && n) {
Peter Maydell30297b52011-12-14 15:37:18 +000012105 if (num == TARGET_NR_getxattr) {
12106 ret = get_errno(getxattr(p, n, v, arg4));
12107 } else {
12108 ret = get_errno(lgetxattr(p, n, v, arg4));
12109 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012110 } else {
12111 ret = -TARGET_EFAULT;
12112 }
12113 unlock_user(p, arg1, 0);
12114 unlock_user(n, arg2, 0);
12115 unlock_user(v, arg3, arg4);
12116 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012117 return ret;
Peter Maydell30297b52011-12-14 15:37:18 +000012118 case TARGET_NR_fgetxattr:
12119 {
12120 void *n, *v = 0;
12121 if (arg3) {
12122 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
12123 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012124 return -TARGET_EFAULT;
Peter Maydell30297b52011-12-14 15:37:18 +000012125 }
12126 }
12127 n = lock_user_string(arg2);
12128 if (n) {
12129 ret = get_errno(fgetxattr(arg1, n, v, arg4));
12130 } else {
12131 ret = -TARGET_EFAULT;
12132 }
12133 unlock_user(n, arg2, 0);
12134 unlock_user(v, arg3, arg4);
12135 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012136 return ret;
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012137 case TARGET_NR_removexattr:
Peter Maydell30297b52011-12-14 15:37:18 +000012138 case TARGET_NR_lremovexattr:
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012139 {
12140 void *p, *n;
12141 p = lock_user_string(arg1);
12142 n = lock_user_string(arg2);
12143 if (p && n) {
Peter Maydell30297b52011-12-14 15:37:18 +000012144 if (num == TARGET_NR_removexattr) {
12145 ret = get_errno(removexattr(p, n));
12146 } else {
12147 ret = get_errno(lremovexattr(p, n));
12148 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012149 } else {
12150 ret = -TARGET_EFAULT;
12151 }
12152 unlock_user(p, arg1, 0);
12153 unlock_user(n, arg2, 0);
12154 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012155 return ret;
Peter Maydell30297b52011-12-14 15:37:18 +000012156 case TARGET_NR_fremovexattr:
12157 {
12158 void *n;
12159 n = lock_user_string(arg2);
12160 if (n) {
12161 ret = get_errno(fremovexattr(arg1, n));
12162 } else {
12163 ret = -TARGET_EFAULT;
12164 }
12165 unlock_user(n, arg2, 0);
12166 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012167 return ret;
bellardebc05482003-09-30 21:08:41 +000012168#endif
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012169#endif /* CONFIG_ATTR */
bellardebc05482003-09-30 21:08:41 +000012170#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +000012171 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +000012172#if defined(TARGET_MIPS)
Petar Jovanovicd2792792014-06-18 17:48:20 +020012173 ((CPUMIPSState *) cpu_env)->active_tc.CP0_UserLocal = arg1;
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012174 return 0;
edgar_iglef967792009-01-07 14:19:38 +000012175#elif defined(TARGET_CRIS)
12176 if (arg1 & 0xff)
12177 ret = -TARGET_EINVAL;
12178 else {
12179 ((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1;
12180 ret = 0;
12181 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012182 return ret;
bellard8d18e892007-11-14 15:18:40 +000012183#elif defined(TARGET_I386) && defined(TARGET_ABI32)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012184 return do_set_thread_area(cpu_env, arg1);
Peter Maydell1ccd9372013-07-16 18:44:55 +010012185#elif defined(TARGET_M68K)
12186 {
Andreas Färber0429a972013-08-26 18:14:44 +020012187 TaskState *ts = cpu->opaque;
Peter Maydell1ccd9372013-07-16 18:44:55 +010012188 ts->tp_value = arg1;
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012189 return 0;
Peter Maydell1ccd9372013-07-16 18:44:55 +010012190 }
ths6f5b89a2007-03-02 20:48:00 +000012191#else
Richard Henderson10f45d92018-08-18 12:01:07 -070012192 return -TARGET_ENOSYS;
ths6f5b89a2007-03-02 20:48:00 +000012193#endif
12194#endif
12195#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +000012196 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +000012197#if defined(TARGET_I386) && defined(TARGET_ABI32)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012198 return do_get_thread_area(cpu_env, arg1);
Peter Maydell1ccd9372013-07-16 18:44:55 +010012199#elif defined(TARGET_M68K)
12200 {
Andreas Färber0429a972013-08-26 18:14:44 +020012201 TaskState *ts = cpu->opaque;
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012202 return ts->tp_value;
Peter Maydell1ccd9372013-07-16 18:44:55 +010012203 }
bellard8d18e892007-11-14 15:18:40 +000012204#else
Richard Henderson10f45d92018-08-18 12:01:07 -070012205 return -TARGET_ENOSYS;
bellardebc05482003-09-30 21:08:41 +000012206#endif
bellard8d18e892007-11-14 15:18:40 +000012207#endif
bellard48dc41e2006-06-21 18:15:50 +000012208#ifdef TARGET_NR_getdomainname
12209 case TARGET_NR_getdomainname:
Richard Henderson10f45d92018-08-18 12:01:07 -070012210 return -TARGET_ENOSYS;
bellard48dc41e2006-06-21 18:15:50 +000012211#endif
ths6f5b89a2007-03-02 20:48:00 +000012212
Max Filippov12e33402018-04-01 13:13:49 -070012213#ifdef TARGET_NR_clock_settime
12214 case TARGET_NR_clock_settime:
12215 {
12216 struct timespec ts;
12217
12218 ret = target_to_host_timespec(&ts, arg2);
12219 if (!is_error(ret)) {
12220 ret = get_errno(clock_settime(arg1, &ts));
12221 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012222 return ret;
Max Filippov12e33402018-04-01 13:13:49 -070012223 }
12224#endif
Alistair Francisc6c8d102020-03-12 15:13:53 -070012225#ifdef TARGET_NR_clock_settime64
12226 case TARGET_NR_clock_settime64:
12227 {
12228 struct timespec ts;
12229
12230 ret = target_to_host_timespec64(&ts, arg2);
12231 if (!is_error(ret)) {
12232 ret = get_errno(clock_settime(arg1, &ts));
12233 }
12234 return ret;
12235 }
12236#endif
thsb5906f92007-03-19 13:32:45 +000012237#ifdef TARGET_NR_clock_gettime
12238 case TARGET_NR_clock_gettime:
12239 {
12240 struct timespec ts;
12241 ret = get_errno(clock_gettime(arg1, &ts));
12242 if (!is_error(ret)) {
Max Filippovb9f99082018-04-01 13:14:04 -070012243 ret = host_to_target_timespec(arg2, &ts);
thsb5906f92007-03-19 13:32:45 +000012244 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012245 return ret;
thsb5906f92007-03-19 13:32:45 +000012246 }
12247#endif
Alistair Francisc6c8d102020-03-12 15:13:53 -070012248#ifdef TARGET_NR_clock_gettime64
12249 case TARGET_NR_clock_gettime64:
12250 {
12251 struct timespec ts;
12252 ret = get_errno(clock_gettime(arg1, &ts));
12253 if (!is_error(ret)) {
12254 ret = host_to_target_timespec64(arg2, &ts);
12255 }
12256 return ret;
12257 }
12258#endif
thsb5906f92007-03-19 13:32:45 +000012259#ifdef TARGET_NR_clock_getres
12260 case TARGET_NR_clock_getres:
12261 {
12262 struct timespec ts;
12263 ret = get_errno(clock_getres(arg1, &ts));
12264 if (!is_error(ret)) {
12265 host_to_target_timespec(arg2, &ts);
12266 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012267 return ret;
thsb5906f92007-03-19 13:32:45 +000012268 }
12269#endif
Filip Bozuta828cb3a2020-07-22 17:34:21 +020012270#ifdef TARGET_NR_clock_getres_time64
12271 case TARGET_NR_clock_getres_time64:
12272 {
12273 struct timespec ts;
12274 ret = get_errno(clock_getres(arg1, &ts));
12275 if (!is_error(ret)) {
12276 host_to_target_timespec64(arg2, &ts);
12277 }
12278 return ret;
12279 }
12280#endif
pbrook63d76512008-05-29 13:43:29 +000012281#ifdef TARGET_NR_clock_nanosleep
12282 case TARGET_NR_clock_nanosleep:
12283 {
12284 struct timespec ts;
Filip Bozutab09d6402020-07-27 22:13:26 +020012285 if (target_to_host_timespec(&ts, arg3)) {
12286 return -TARGET_EFAULT;
12287 }
Peter Maydell9e518222016-06-06 19:58:09 +010012288 ret = get_errno(safe_clock_nanosleep(arg1, arg2,
12289 &ts, arg4 ? &ts : NULL));
Laurent Vivier8ec68a02020-07-24 07:45:05 +010012290 /*
12291 * if the call is interrupted by a signal handler, it fails
12292 * with error -TARGET_EINTR and if arg4 is not NULL and arg2 is not
12293 * TIMER_ABSTIME, it returns the remaining unslept time in arg4.
12294 */
Filip Bozutab09d6402020-07-27 22:13:26 +020012295 if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME &&
12296 host_to_target_timespec(arg4, &ts)) {
12297 return -TARGET_EFAULT;
Laurent Vivier8ec68a02020-07-24 07:45:05 +010012298 }
Tom Musta8fbe8fd2014-08-12 13:53:41 -050012299
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012300 return ret;
pbrook63d76512008-05-29 13:43:29 +000012301 }
12302#endif
Filip Bozuta6ac03b22020-08-24 21:21:15 +020012303#ifdef TARGET_NR_clock_nanosleep_time64
12304 case TARGET_NR_clock_nanosleep_time64:
12305 {
12306 struct timespec ts;
12307
12308 if (target_to_host_timespec64(&ts, arg3)) {
12309 return -TARGET_EFAULT;
12310 }
12311
12312 ret = get_errno(safe_clock_nanosleep(arg1, arg2,
12313 &ts, arg4 ? &ts : NULL));
12314
12315 if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME &&
12316 host_to_target_timespec64(arg4, &ts)) {
12317 return -TARGET_EFAULT;
12318 }
12319 return ret;
12320 }
12321#endif
thsb5906f92007-03-19 13:32:45 +000012322
ths6f5b89a2007-03-02 20:48:00 +000012323#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
12324 case TARGET_NR_set_tid_address:
Richard Henderson3e8f1622021-02-12 10:48:43 -080012325 return get_errno(set_tid_address((int *)g2h(cpu, arg1)));
ths6f5b89a2007-03-02 20:48:00 +000012326#endif
12327
ths4cae1d12007-07-12 11:06:53 +000012328 case TARGET_NR_tkill:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012329 return get_errno(safe_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +000012330
ths71455572007-06-21 21:45:30 +000012331 case TARGET_NR_tgkill:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012332 return get_errno(safe_tgkill((int)arg1, (int)arg2,
12333 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +000012334
ths4f2b1fe2007-06-21 21:57:12 +000012335#ifdef TARGET_NR_set_robust_list
12336 case TARGET_NR_set_robust_list:
Peter Maydelle9a970a2013-02-08 04:34:54 +000012337 case TARGET_NR_get_robust_list:
12338 /* The ABI for supporting robust futexes has userspace pass
12339 * the kernel a pointer to a linked list which is updated by
12340 * userspace after the syscall; the list is walked by the kernel
12341 * when the thread exits. Since the linked list in QEMU guest
12342 * memory isn't a valid linked list for the host and we have
12343 * no way to reliably intercept the thread-death event, we can't
12344 * support these. Silently return ENOSYS so that guest userspace
12345 * falls back to a non-robust futex implementation (which should
12346 * be OK except in the corner case of the guest crashing while
12347 * holding a mutex that is shared with another process via
12348 * shared memory).
12349 */
Richard Henderson10f45d92018-08-18 12:01:07 -070012350 return -TARGET_ENOSYS;
ths4f2b1fe2007-06-21 21:57:12 +000012351#endif
12352
Peter Maydell1acae9f2013-07-02 14:04:12 +010012353#if defined(TARGET_NR_utimensat)
ths9007f0e2007-09-25 17:50:37 +000012354 case TARGET_NR_utimensat:
12355 {
Riku Voipioebc996f2009-04-21 15:01:51 +030012356 struct timespec *tsp, ts[2];
12357 if (!arg3) {
12358 tsp = NULL;
12359 } else {
Filip Bozutab3a3af72020-08-11 13:31:01 +020012360 if (target_to_host_timespec(ts, arg3)) {
12361 return -TARGET_EFAULT;
12362 }
12363 if (target_to_host_timespec(ts + 1, arg3 +
12364 sizeof(struct target_timespec))) {
12365 return -TARGET_EFAULT;
12366 }
Riku Voipioebc996f2009-04-21 15:01:51 +030012367 tsp = ts;
12368 }
ths9007f0e2007-09-25 17:50:37 +000012369 if (!arg2)
Riku Voipioebc996f2009-04-21 15:01:51 +030012370 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
ths9007f0e2007-09-25 17:50:37 +000012371 else {
bellard579a97f2007-11-11 14:26:47 +000012372 if (!(p = lock_user_string(arg2))) {
Richard Henderson259841c2018-08-18 12:01:09 -070012373 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000012374 }
Riku Voipioebc996f2009-04-21 15:01:51 +030012375 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
bellard579a97f2007-11-11 14:26:47 +000012376 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +000012377 }
12378 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012379 return ret;
ths9007f0e2007-09-25 17:50:37 +000012380#endif
Filip Bozutacac46eb2020-08-25 00:30:50 +020012381#ifdef TARGET_NR_utimensat_time64
12382 case TARGET_NR_utimensat_time64:
12383 {
12384 struct timespec *tsp, ts[2];
12385 if (!arg3) {
12386 tsp = NULL;
12387 } else {
12388 if (target_to_host_timespec64(ts, arg3)) {
12389 return -TARGET_EFAULT;
12390 }
12391 if (target_to_host_timespec64(ts + 1, arg3 +
12392 sizeof(struct target__kernel_timespec))) {
12393 return -TARGET_EFAULT;
12394 }
12395 tsp = ts;
12396 }
12397 if (!arg2)
12398 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
12399 else {
12400 p = lock_user_string(arg2);
12401 if (!p) {
12402 return -TARGET_EFAULT;
12403 }
12404 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
12405 unlock_user(p, arg2, 0);
12406 }
12407 }
12408 return ret;
12409#endif
Alistair Francis859e8a82020-03-12 15:13:49 -070012410#ifdef TARGET_NR_futex
pbrookbd0c5662008-05-29 14:34:11 +000012411 case TARGET_NR_futex:
Richard Henderson3e8f1622021-02-12 10:48:43 -080012412 return do_futex(cpu, arg1, arg2, arg3, arg4, arg5, arg6);
Alistair Francis859e8a82020-03-12 15:13:49 -070012413#endif
Alistair Francis14690292020-03-18 15:47:01 -070012414#ifdef TARGET_NR_futex_time64
12415 case TARGET_NR_futex_time64:
Richard Henderson3e8f1622021-02-12 10:48:43 -080012416 return do_futex_time64(cpu, arg1, arg2, arg3, arg4, arg5, arg6);
Alistair Francis14690292020-03-18 15:47:01 -070012417#endif
aurel32dbfe4c32009-04-08 21:29:30 +000012418#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
aurel3239b59762008-10-01 21:46:50 +000012419 case TARGET_NR_inotify_init:
12420 ret = get_errno(sys_inotify_init());
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030012421 if (ret >= 0) {
12422 fd_trans_register(ret, &target_inotify_trans);
12423 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012424 return ret;
aurel3239b59762008-10-01 21:46:50 +000012425#endif
Stefan Weila1606b02010-03-28 11:44:41 +020012426#ifdef CONFIG_INOTIFY1
Riku Voipioc05c7a72010-03-26 15:25:11 +000012427#if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1)
12428 case TARGET_NR_inotify_init1:
Lena Djokicfea243e2016-11-24 17:08:53 +010012429 ret = get_errno(sys_inotify_init1(target_to_host_bitmask(arg1,
12430 fcntl_flags_tbl)));
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030012431 if (ret >= 0) {
12432 fd_trans_register(ret, &target_inotify_trans);
12433 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012434 return ret;
Riku Voipioc05c7a72010-03-26 15:25:11 +000012435#endif
Stefan Weila1606b02010-03-28 11:44:41 +020012436#endif
aurel32dbfe4c32009-04-08 21:29:30 +000012437#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
aurel3239b59762008-10-01 21:46:50 +000012438 case TARGET_NR_inotify_add_watch:
12439 p = lock_user_string(arg2);
12440 ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3));
12441 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012442 return ret;
aurel3239b59762008-10-01 21:46:50 +000012443#endif
aurel32dbfe4c32009-04-08 21:29:30 +000012444#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
aurel3239b59762008-10-01 21:46:50 +000012445 case TARGET_NR_inotify_rm_watch:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012446 return get_errno(sys_inotify_rm_watch(arg1, arg2));
aurel3239b59762008-10-01 21:46:50 +000012447#endif
ths9007f0e2007-09-25 17:50:37 +000012448
Nathan Froyd8ec9cf82009-07-22 09:14:36 -070012449#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
aurel3224e10032009-04-15 16:11:43 +000012450 case TARGET_NR_mq_open:
12451 {
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020012452 struct mq_attr posix_mq_attr;
Lena Djokic26400772016-11-24 17:08:58 +010012453 struct mq_attr *pposix_mq_attr;
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020012454 int host_flags;
aurel3224e10032009-04-15 16:11:43 +000012455
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020012456 host_flags = target_to_host_bitmask(arg2, fcntl_flags_tbl);
Lena Djokic26400772016-11-24 17:08:58 +010012457 pposix_mq_attr = NULL;
12458 if (arg4) {
12459 if (copy_from_user_mq_attr(&posix_mq_attr, arg4) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012460 return -TARGET_EFAULT;
Lena Djokic26400772016-11-24 17:08:58 +010012461 }
12462 pposix_mq_attr = &posix_mq_attr;
Tom Mustab6ce1f62014-08-12 13:53:36 -050012463 }
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020012464 p = lock_user_string(arg1 - 1);
12465 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012466 return -TARGET_EFAULT;
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020012467 }
Lena Djokic26400772016-11-24 17:08:58 +010012468 ret = get_errno(mq_open(p, host_flags, arg3, pposix_mq_attr));
aurel3224e10032009-04-15 16:11:43 +000012469 unlock_user (p, arg1, 0);
12470 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012471 return ret;
aurel3224e10032009-04-15 16:11:43 +000012472
12473 case TARGET_NR_mq_unlink:
12474 p = lock_user_string(arg1 - 1);
Peter Maydell32112152016-07-12 13:02:13 +010012475 if (!p) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012476 return -TARGET_EFAULT;
Peter Maydell32112152016-07-12 13:02:13 +010012477 }
aurel3224e10032009-04-15 16:11:43 +000012478 ret = get_errno(mq_unlink(p));
12479 unlock_user (p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012480 return ret;
aurel3224e10032009-04-15 16:11:43 +000012481
Alistair Francis859e8a82020-03-12 15:13:49 -070012482#ifdef TARGET_NR_mq_timedsend
aurel3224e10032009-04-15 16:11:43 +000012483 case TARGET_NR_mq_timedsend:
12484 {
12485 struct timespec ts;
12486
12487 p = lock_user (VERIFY_READ, arg2, arg3, 1);
12488 if (arg5 != 0) {
Filip Bozutadcbcf5c2020-08-24 21:37:51 +020012489 if (target_to_host_timespec(&ts, arg5)) {
12490 return -TARGET_EFAULT;
12491 }
Peter Maydelld40ecd62016-06-06 19:58:06 +010012492 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts));
Filip Bozutadcbcf5c2020-08-24 21:37:51 +020012493 if (!is_error(ret) && host_to_target_timespec(arg5, &ts)) {
12494 return -TARGET_EFAULT;
12495 }
Peter Maydelld40ecd62016-06-06 19:58:06 +010012496 } else {
12497 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL));
aurel3224e10032009-04-15 16:11:43 +000012498 }
aurel3224e10032009-04-15 16:11:43 +000012499 unlock_user (p, arg2, arg3);
12500 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012501 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070012502#endif
Filip Bozutad107e372020-08-24 21:37:52 +020012503#ifdef TARGET_NR_mq_timedsend_time64
12504 case TARGET_NR_mq_timedsend_time64:
12505 {
12506 struct timespec ts;
12507
12508 p = lock_user(VERIFY_READ, arg2, arg3, 1);
12509 if (arg5 != 0) {
12510 if (target_to_host_timespec64(&ts, arg5)) {
12511 return -TARGET_EFAULT;
12512 }
12513 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts));
12514 if (!is_error(ret) && host_to_target_timespec64(arg5, &ts)) {
12515 return -TARGET_EFAULT;
12516 }
12517 } else {
12518 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL));
12519 }
12520 unlock_user(p, arg2, arg3);
12521 }
12522 return ret;
12523#endif
aurel3224e10032009-04-15 16:11:43 +000012524
Alistair Francis859e8a82020-03-12 15:13:49 -070012525#ifdef TARGET_NR_mq_timedreceive
aurel3224e10032009-04-15 16:11:43 +000012526 case TARGET_NR_mq_timedreceive:
12527 {
12528 struct timespec ts;
12529 unsigned int prio;
12530
12531 p = lock_user (VERIFY_READ, arg2, arg3, 1);
12532 if (arg5 != 0) {
Filip Bozutadcbcf5c2020-08-24 21:37:51 +020012533 if (target_to_host_timespec(&ts, arg5)) {
12534 return -TARGET_EFAULT;
12535 }
Peter Maydelld40ecd62016-06-06 19:58:06 +010012536 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12537 &prio, &ts));
Filip Bozutadcbcf5c2020-08-24 21:37:51 +020012538 if (!is_error(ret) && host_to_target_timespec(arg5, &ts)) {
12539 return -TARGET_EFAULT;
12540 }
Peter Maydelld40ecd62016-06-06 19:58:06 +010012541 } else {
12542 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12543 &prio, NULL));
aurel3224e10032009-04-15 16:11:43 +000012544 }
aurel3224e10032009-04-15 16:11:43 +000012545 unlock_user (p, arg2, arg3);
12546 if (arg4 != 0)
12547 put_user_u32(prio, arg4);
12548 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012549 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070012550#endif
Filip Bozutad107e372020-08-24 21:37:52 +020012551#ifdef TARGET_NR_mq_timedreceive_time64
12552 case TARGET_NR_mq_timedreceive_time64:
12553 {
12554 struct timespec ts;
12555 unsigned int prio;
12556
12557 p = lock_user(VERIFY_READ, arg2, arg3, 1);
12558 if (arg5 != 0) {
12559 if (target_to_host_timespec64(&ts, arg5)) {
12560 return -TARGET_EFAULT;
12561 }
12562 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12563 &prio, &ts));
12564 if (!is_error(ret) && host_to_target_timespec64(arg5, &ts)) {
12565 return -TARGET_EFAULT;
12566 }
12567 } else {
12568 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12569 &prio, NULL));
12570 }
12571 unlock_user(p, arg2, arg3);
12572 if (arg4 != 0) {
12573 put_user_u32(prio, arg4);
12574 }
12575 }
12576 return ret;
12577#endif
aurel3224e10032009-04-15 16:11:43 +000012578
12579 /* Not implemented for now... */
12580/* case TARGET_NR_mq_notify: */
12581/* break; */
12582
12583 case TARGET_NR_mq_getsetattr:
12584 {
12585 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
12586 ret = 0;
aurel3224e10032009-04-15 16:11:43 +000012587 if (arg2 != 0) {
12588 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
Max Filippova23ea402018-03-31 08:20:15 -070012589 ret = get_errno(mq_setattr(arg1, &posix_mq_attr_in,
12590 &posix_mq_attr_out));
12591 } else if (arg3 != 0) {
12592 ret = get_errno(mq_getattr(arg1, &posix_mq_attr_out));
aurel3224e10032009-04-15 16:11:43 +000012593 }
Max Filippova23ea402018-03-31 08:20:15 -070012594 if (ret == 0 && arg3 != 0) {
12595 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
12596 }
aurel3224e10032009-04-15 16:11:43 +000012597 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012598 return ret;
aurel3224e10032009-04-15 16:11:43 +000012599#endif
12600
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012601#ifdef CONFIG_SPLICE
12602#ifdef TARGET_NR_tee
12603 case TARGET_NR_tee:
12604 {
12605 ret = get_errno(tee(arg1,arg2,arg3,arg4));
12606 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012607 return ret;
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012608#endif
12609#ifdef TARGET_NR_splice
12610 case TARGET_NR_splice:
12611 {
12612 loff_t loff_in, loff_out;
12613 loff_t *ploff_in = NULL, *ploff_out = NULL;
Andreas Schwab17644b32015-03-10 17:11:35 +010012614 if (arg2) {
12615 if (get_user_u64(loff_in, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012616 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010012617 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012618 ploff_in = &loff_in;
12619 }
Andreas Schwab17644b32015-03-10 17:11:35 +010012620 if (arg4) {
12621 if (get_user_u64(loff_out, arg4)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012622 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010012623 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012624 ploff_out = &loff_out;
12625 }
12626 ret = get_errno(splice(arg1, ploff_in, arg3, ploff_out, arg5, arg6));
Andreas Schwab17644b32015-03-10 17:11:35 +010012627 if (arg2) {
12628 if (put_user_u64(loff_in, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012629 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010012630 }
12631 }
12632 if (arg4) {
12633 if (put_user_u64(loff_out, arg4)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012634 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010012635 }
12636 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012637 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012638 return ret;
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012639#endif
12640#ifdef TARGET_NR_vmsplice
12641 case TARGET_NR_vmsplice:
12642 {
Richard Hendersonf287b2c2012-09-15 13:20:25 -070012643 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
12644 if (vec != NULL) {
12645 ret = get_errno(vmsplice(arg1, vec, arg3, arg4));
12646 unlock_iovec(vec, arg2, arg3, 0);
12647 } else {
12648 ret = -host_to_target_errno(errno);
12649 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012650 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012651 return ret;
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012652#endif
12653#endif /* CONFIG_SPLICE */
Riku Voipioc2882b92009-08-12 15:08:24 +030012654#ifdef CONFIG_EVENTFD
12655#if defined(TARGET_NR_eventfd)
12656 case TARGET_NR_eventfd:
12657 ret = get_errno(eventfd(arg1, 0));
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030012658 if (ret >= 0) {
12659 fd_trans_register(ret, &target_eventfd_trans);
12660 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012661 return ret;
Riku Voipioc2882b92009-08-12 15:08:24 +030012662#endif
12663#if defined(TARGET_NR_eventfd2)
12664 case TARGET_NR_eventfd2:
Petar Jovanovic5947c692013-04-08 20:26:10 +020012665 {
Helge Deller78721302021-02-10 07:12:14 +010012666 int host_flags = arg2 & (~(TARGET_O_NONBLOCK_MASK | TARGET_O_CLOEXEC));
Petar Jovanovic5947c692013-04-08 20:26:10 +020012667 if (arg2 & TARGET_O_NONBLOCK) {
12668 host_flags |= O_NONBLOCK;
12669 }
12670 if (arg2 & TARGET_O_CLOEXEC) {
12671 host_flags |= O_CLOEXEC;
12672 }
12673 ret = get_errno(eventfd(arg1, host_flags));
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030012674 if (ret >= 0) {
12675 fd_trans_register(ret, &target_eventfd_trans);
12676 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012677 return ret;
Petar Jovanovic5947c692013-04-08 20:26:10 +020012678 }
Riku Voipioc2882b92009-08-12 15:08:24 +030012679#endif
12680#endif /* CONFIG_EVENTFD */
Ulrich Hechtd0927932009-09-17 20:22:14 +030012681#if defined(CONFIG_FALLOCATE) && defined(TARGET_NR_fallocate)
12682 case TARGET_NR_fallocate:
Alexander Graf20249ae2012-02-06 21:37:07 +010012683#if TARGET_ABI_BITS == 32
12684 ret = get_errno(fallocate(arg1, arg2, target_offset64(arg3, arg4),
12685 target_offset64(arg5, arg6)));
12686#else
Ulrich Hechtd0927932009-09-17 20:22:14 +030012687 ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
Alexander Graf20249ae2012-02-06 21:37:07 +010012688#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012689 return ret;
Ulrich Hechtd0927932009-09-17 20:22:14 +030012690#endif
Peter Maydellc727f472011-01-06 11:05:10 +000012691#if defined(CONFIG_SYNC_FILE_RANGE)
12692#if defined(TARGET_NR_sync_file_range)
12693 case TARGET_NR_sync_file_range:
12694#if TARGET_ABI_BITS == 32
Riku Voipiobfcedc52011-06-20 16:24:39 +030012695#if defined(TARGET_MIPS)
12696 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
12697 target_offset64(arg5, arg6), arg7));
12698#else
Peter Maydellc727f472011-01-06 11:05:10 +000012699 ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3),
12700 target_offset64(arg4, arg5), arg6));
Riku Voipiobfcedc52011-06-20 16:24:39 +030012701#endif /* !TARGET_MIPS */
Peter Maydellc727f472011-01-06 11:05:10 +000012702#else
12703 ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4));
12704#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012705 return ret;
Peter Maydellc727f472011-01-06 11:05:10 +000012706#endif
Laurent Vivier5bcb4982020-03-10 11:33:50 +010012707#if defined(TARGET_NR_sync_file_range2) || \
12708 defined(TARGET_NR_arm_sync_file_range)
Peter Maydellc727f472011-01-06 11:05:10 +000012709#if defined(TARGET_NR_sync_file_range2)
12710 case TARGET_NR_sync_file_range2:
Laurent Vivier5bcb4982020-03-10 11:33:50 +010012711#endif
12712#if defined(TARGET_NR_arm_sync_file_range)
12713 case TARGET_NR_arm_sync_file_range:
12714#endif
Peter Maydellc727f472011-01-06 11:05:10 +000012715 /* This is like sync_file_range but the arguments are reordered */
12716#if TARGET_ABI_BITS == 32
12717 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
12718 target_offset64(arg5, arg6), arg2));
12719#else
12720 ret = get_errno(sync_file_range(arg1, arg3, arg4, arg2));
12721#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012722 return ret;
Peter Maydellc727f472011-01-06 11:05:10 +000012723#endif
12724#endif
Laurent Viviere36800c2015-10-02 14:48:09 +020012725#if defined(TARGET_NR_signalfd4)
12726 case TARGET_NR_signalfd4:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012727 return do_signalfd4(arg1, arg2, arg4);
Laurent Viviere36800c2015-10-02 14:48:09 +020012728#endif
12729#if defined(TARGET_NR_signalfd)
12730 case TARGET_NR_signalfd:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012731 return do_signalfd4(arg1, arg2, 0);
Laurent Viviere36800c2015-10-02 14:48:09 +020012732#endif
Peter Maydell3b6edd12011-02-15 18:35:05 +000012733#if defined(CONFIG_EPOLL)
12734#if defined(TARGET_NR_epoll_create)
12735 case TARGET_NR_epoll_create:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012736 return get_errno(epoll_create(arg1));
Peter Maydell3b6edd12011-02-15 18:35:05 +000012737#endif
12738#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1)
12739 case TARGET_NR_epoll_create1:
Sergei Trofimovich386d3862020-04-15 23:05:08 +010012740 return get_errno(epoll_create1(target_to_host_bitmask(arg1, fcntl_flags_tbl)));
Peter Maydell3b6edd12011-02-15 18:35:05 +000012741#endif
12742#if defined(TARGET_NR_epoll_ctl)
12743 case TARGET_NR_epoll_ctl:
12744 {
12745 struct epoll_event ep;
12746 struct epoll_event *epp = 0;
12747 if (arg4) {
LemonBoyc7811022020-04-17 17:34:54 +020012748 if (arg2 != EPOLL_CTL_DEL) {
12749 struct target_epoll_event *target_ep;
12750 if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) {
12751 return -TARGET_EFAULT;
12752 }
12753 ep.events = tswap32(target_ep->events);
12754 /*
12755 * The epoll_data_t union is just opaque data to the kernel,
12756 * so we transfer all 64 bits across and need not worry what
12757 * actual data type it is.
12758 */
12759 ep.data.u64 = tswap64(target_ep->data.u64);
12760 unlock_user_struct(target_ep, arg4, 0);
Peter Maydell3b6edd12011-02-15 18:35:05 +000012761 }
LemonBoyc7811022020-04-17 17:34:54 +020012762 /*
12763 * before kernel 2.6.9, EPOLL_CTL_DEL operation required a
12764 * non-null pointer, even though this argument is ignored.
12765 *
Peter Maydell3b6edd12011-02-15 18:35:05 +000012766 */
Peter Maydell3b6edd12011-02-15 18:35:05 +000012767 epp = &ep;
12768 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012769 return get_errno(epoll_ctl(arg1, arg2, arg3, epp));
Peter Maydell3b6edd12011-02-15 18:35:05 +000012770 }
12771#endif
12772
Peter Maydell227f0212016-06-06 19:58:11 +010012773#if defined(TARGET_NR_epoll_wait) || defined(TARGET_NR_epoll_pwait)
Peter Maydell3b6edd12011-02-15 18:35:05 +000012774#if defined(TARGET_NR_epoll_wait)
12775 case TARGET_NR_epoll_wait:
12776#endif
Peter Maydell227f0212016-06-06 19:58:11 +010012777#if defined(TARGET_NR_epoll_pwait)
Peter Maydell3b6edd12011-02-15 18:35:05 +000012778 case TARGET_NR_epoll_pwait:
12779#endif
12780 {
12781 struct target_epoll_event *target_ep;
12782 struct epoll_event *ep;
12783 int epfd = arg1;
12784 int maxevents = arg3;
12785 int timeout = arg4;
12786
Peter Maydell2ba7fae32016-07-18 15:35:59 +010012787 if (maxevents <= 0 || maxevents > TARGET_EP_MAX_EVENTS) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012788 return -TARGET_EINVAL;
Peter Maydell2ba7fae32016-07-18 15:35:59 +010012789 }
12790
Peter Maydell3b6edd12011-02-15 18:35:05 +000012791 target_ep = lock_user(VERIFY_WRITE, arg2,
12792 maxevents * sizeof(struct target_epoll_event), 1);
12793 if (!target_ep) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012794 return -TARGET_EFAULT;
Peter Maydell3b6edd12011-02-15 18:35:05 +000012795 }
12796
Peter Maydell04c95f42016-07-18 15:36:00 +010012797 ep = g_try_new(struct epoll_event, maxevents);
12798 if (!ep) {
12799 unlock_user(target_ep, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012800 return -TARGET_ENOMEM;
Peter Maydell04c95f42016-07-18 15:36:00 +010012801 }
Peter Maydell3b6edd12011-02-15 18:35:05 +000012802
12803 switch (num) {
Peter Maydell227f0212016-06-06 19:58:11 +010012804#if defined(TARGET_NR_epoll_pwait)
Peter Maydell3b6edd12011-02-15 18:35:05 +000012805 case TARGET_NR_epoll_pwait:
12806 {
12807 target_sigset_t *target_set;
12808 sigset_t _set, *set = &_set;
12809
12810 if (arg5) {
Peter Maydellc8157012016-06-30 14:23:24 +010012811 if (arg6 != sizeof(target_sigset_t)) {
12812 ret = -TARGET_EINVAL;
12813 break;
12814 }
12815
Peter Maydell3b6edd12011-02-15 18:35:05 +000012816 target_set = lock_user(VERIFY_READ, arg5,
12817 sizeof(target_sigset_t), 1);
12818 if (!target_set) {
Peter Maydell04c95f42016-07-18 15:36:00 +010012819 ret = -TARGET_EFAULT;
12820 break;
Peter Maydell3b6edd12011-02-15 18:35:05 +000012821 }
12822 target_to_host_sigset(set, target_set);
12823 unlock_user(target_set, arg5, 0);
12824 } else {
12825 set = NULL;
12826 }
12827
Peter Maydell227f0212016-06-06 19:58:11 +010012828 ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
12829 set, SIGSET_T_SIZE));
Peter Maydell3b6edd12011-02-15 18:35:05 +000012830 break;
12831 }
12832#endif
12833#if defined(TARGET_NR_epoll_wait)
12834 case TARGET_NR_epoll_wait:
Peter Maydell227f0212016-06-06 19:58:11 +010012835 ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
12836 NULL, 0));
Peter Maydell3b6edd12011-02-15 18:35:05 +000012837 break;
12838#endif
12839 default:
12840 ret = -TARGET_ENOSYS;
12841 }
12842 if (!is_error(ret)) {
12843 int i;
12844 for (i = 0; i < ret; i++) {
12845 target_ep[i].events = tswap32(ep[i].events);
12846 target_ep[i].data.u64 = tswap64(ep[i].data.u64);
12847 }
Peter Maydell04c95f42016-07-18 15:36:00 +010012848 unlock_user(target_ep, arg2,
12849 ret * sizeof(struct target_epoll_event));
12850 } else {
12851 unlock_user(target_ep, arg2, 0);
Peter Maydell3b6edd12011-02-15 18:35:05 +000012852 }
Peter Maydell04c95f42016-07-18 15:36:00 +010012853 g_free(ep);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012854 return ret;
Peter Maydell3b6edd12011-02-15 18:35:05 +000012855 }
12856#endif
12857#endif
Peter Maydell163a05a2011-06-27 17:44:52 +010012858#ifdef TARGET_NR_prlimit64
12859 case TARGET_NR_prlimit64:
12860 {
12861 /* args: pid, resource number, ptr to new rlimit, ptr to old rlimit */
12862 struct target_rlimit64 *target_rnew, *target_rold;
12863 struct host_rlimit64 rnew, rold, *rnewp = 0;
Felix Janda95018012014-12-02 22:11:17 +010012864 int resource = target_to_host_resource(arg2);
Tobias Koch055d92f2020-03-05 21:24:00 +010012865
12866 if (arg3 && (resource != RLIMIT_AS &&
12867 resource != RLIMIT_DATA &&
12868 resource != RLIMIT_STACK)) {
Peter Maydell163a05a2011-06-27 17:44:52 +010012869 if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012870 return -TARGET_EFAULT;
Peter Maydell163a05a2011-06-27 17:44:52 +010012871 }
12872 rnew.rlim_cur = tswap64(target_rnew->rlim_cur);
12873 rnew.rlim_max = tswap64(target_rnew->rlim_max);
12874 unlock_user_struct(target_rnew, arg3, 0);
12875 rnewp = &rnew;
12876 }
12877
Felix Janda95018012014-12-02 22:11:17 +010012878 ret = get_errno(sys_prlimit64(arg1, resource, rnewp, arg4 ? &rold : 0));
Peter Maydell163a05a2011-06-27 17:44:52 +010012879 if (!is_error(ret) && arg4) {
12880 if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012881 return -TARGET_EFAULT;
Peter Maydell163a05a2011-06-27 17:44:52 +010012882 }
12883 target_rold->rlim_cur = tswap64(rold.rlim_cur);
12884 target_rold->rlim_max = tswap64(rold.rlim_max);
12885 unlock_user_struct(target_rold, arg4, 1);
12886 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012887 return ret;
Peter Maydell163a05a2011-06-27 17:44:52 +010012888 }
12889#endif
Richard Henderson3d21d292012-09-15 13:20:46 -070012890#ifdef TARGET_NR_gethostname
12891 case TARGET_NR_gethostname:
12892 {
12893 char *name = lock_user(VERIFY_WRITE, arg1, arg2, 0);
12894 if (name) {
12895 ret = get_errno(gethostname(name, arg2));
12896 unlock_user(name, arg1, arg2);
12897 } else {
12898 ret = -TARGET_EFAULT;
12899 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012900 return ret;
Richard Henderson3d21d292012-09-15 13:20:46 -070012901 }
12902#endif
Riku Voipio89aaf1a2013-07-24 09:44:26 +030012903#ifdef TARGET_NR_atomic_cmpxchg_32
12904 case TARGET_NR_atomic_cmpxchg_32:
12905 {
12906 /* should use start_exclusive from main.c */
12907 abi_ulong mem_value;
12908 if (get_user_u32(mem_value, arg6)) {
12909 target_siginfo_t info;
12910 info.si_signo = SIGSEGV;
12911 info.si_errno = 0;
12912 info.si_code = TARGET_SEGV_MAPERR;
12913 info._sifields._sigfault._addr = arg6;
Peter Maydell9d2803f2016-07-28 16:44:46 +010012914 queue_signal((CPUArchState *)cpu_env, info.si_signo,
12915 QEMU_SI_FAULT, &info);
Riku Voipio89aaf1a2013-07-24 09:44:26 +030012916 ret = 0xdeadbeef;
12917
12918 }
12919 if (mem_value == arg2)
12920 put_user_u32(arg1, arg6);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012921 return mem_value;
Riku Voipio89aaf1a2013-07-24 09:44:26 +030012922 }
12923#endif
12924#ifdef TARGET_NR_atomic_barrier
12925 case TARGET_NR_atomic_barrier:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012926 /* Like the kernel implementation and the
12927 qemu arm barrier, no-op this? */
12928 return 0;
Riku Voipio89aaf1a2013-07-24 09:44:26 +030012929#endif
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012930
12931#ifdef TARGET_NR_timer_create
12932 case TARGET_NR_timer_create:
12933 {
12934 /* args: clockid_t clockid, struct sigevent *sevp, timer_t *timerid */
12935
12936 struct sigevent host_sevp = { {0}, }, *phost_sevp = NULL;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012937
12938 int clkid = arg1;
12939 int timer_index = next_free_host_timer();
12940
12941 if (timer_index < 0) {
12942 ret = -TARGET_EAGAIN;
12943 } else {
12944 timer_t *phtimer = g_posix_timers + timer_index;
12945
12946 if (arg2) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012947 phost_sevp = &host_sevp;
Peter Maydellc0659762014-08-09 15:42:32 +010012948 ret = target_to_host_sigevent(phost_sevp, arg2);
12949 if (ret != 0) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012950 return ret;
Peter Maydellc0659762014-08-09 15:42:32 +010012951 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012952 }
12953
12954 ret = get_errno(timer_create(clkid, phost_sevp, phtimer));
12955 if (ret) {
12956 phtimer = NULL;
12957 } else {
Alexander Grafaecc8862014-11-10 21:33:03 +010012958 if (put_user(TIMER_MAGIC | timer_index, arg3, target_timer_t)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012959 return -TARGET_EFAULT;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012960 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012961 }
12962 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012963 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012964 }
12965#endif
12966
12967#ifdef TARGET_NR_timer_settime
12968 case TARGET_NR_timer_settime:
12969 {
12970 /* args: timer_t timerid, int flags, const struct itimerspec *new_value,
12971 * struct itimerspec * old_value */
Alexander Grafaecc8862014-11-10 21:33:03 +010012972 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020012973
Alexander Grafaecc8862014-11-10 21:33:03 +010012974 if (timerid < 0) {
12975 ret = timerid;
12976 } else if (arg3 == 0) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012977 ret = -TARGET_EINVAL;
12978 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020012979 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012980 struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
12981
Marc-André Lureau40c80b52017-01-19 10:15:32 -050012982 if (target_to_host_itimerspec(&hspec_new, arg3)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012983 return -TARGET_EFAULT;
Marc-André Lureau40c80b52017-01-19 10:15:32 -050012984 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012985 ret = get_errno(
12986 timer_settime(htimer, arg2, &hspec_new, &hspec_old));
Marc-André Lureau40c80b52017-01-19 10:15:32 -050012987 if (arg4 && host_to_target_itimerspec(arg4, &hspec_old)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012988 return -TARGET_EFAULT;
Marc-André Lureau40c80b52017-01-19 10:15:32 -050012989 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012990 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012991 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012992 }
12993#endif
12994
Filip Bozuta828cb3a2020-07-22 17:34:21 +020012995#ifdef TARGET_NR_timer_settime64
12996 case TARGET_NR_timer_settime64:
12997 {
12998 target_timer_t timerid = get_timer_id(arg1);
12999
13000 if (timerid < 0) {
13001 ret = timerid;
13002 } else if (arg3 == 0) {
13003 ret = -TARGET_EINVAL;
13004 } else {
13005 timer_t htimer = g_posix_timers[timerid];
13006 struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
13007
13008 if (target_to_host_itimerspec64(&hspec_new, arg3)) {
13009 return -TARGET_EFAULT;
13010 }
13011 ret = get_errno(
13012 timer_settime(htimer, arg2, &hspec_new, &hspec_old));
13013 if (arg4 && host_to_target_itimerspec64(arg4, &hspec_old)) {
13014 return -TARGET_EFAULT;
13015 }
13016 }
13017 return ret;
13018 }
13019#endif
13020
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013021#ifdef TARGET_NR_timer_gettime
13022 case TARGET_NR_timer_gettime:
13023 {
13024 /* args: timer_t timerid, struct itimerspec *curr_value */
Alexander Grafaecc8862014-11-10 21:33:03 +010013025 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020013026
Alexander Grafaecc8862014-11-10 21:33:03 +010013027 if (timerid < 0) {
13028 ret = timerid;
13029 } else if (!arg2) {
13030 ret = -TARGET_EFAULT;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013031 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020013032 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013033 struct itimerspec hspec;
13034 ret = get_errno(timer_gettime(htimer, &hspec));
13035
13036 if (host_to_target_itimerspec(arg2, &hspec)) {
13037 ret = -TARGET_EFAULT;
13038 }
13039 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013040 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013041 }
13042#endif
13043
Filip Bozuta828cb3a2020-07-22 17:34:21 +020013044#ifdef TARGET_NR_timer_gettime64
13045 case TARGET_NR_timer_gettime64:
13046 {
13047 /* args: timer_t timerid, struct itimerspec64 *curr_value */
13048 target_timer_t timerid = get_timer_id(arg1);
13049
13050 if (timerid < 0) {
13051 ret = timerid;
13052 } else if (!arg2) {
13053 ret = -TARGET_EFAULT;
13054 } else {
13055 timer_t htimer = g_posix_timers[timerid];
13056 struct itimerspec hspec;
13057 ret = get_errno(timer_gettime(htimer, &hspec));
13058
13059 if (host_to_target_itimerspec64(arg2, &hspec)) {
13060 ret = -TARGET_EFAULT;
13061 }
13062 }
13063 return ret;
13064 }
13065#endif
13066
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013067#ifdef TARGET_NR_timer_getoverrun
13068 case TARGET_NR_timer_getoverrun:
13069 {
13070 /* args: timer_t timerid */
Alexander Grafaecc8862014-11-10 21:33:03 +010013071 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020013072
Alexander Grafaecc8862014-11-10 21:33:03 +010013073 if (timerid < 0) {
13074 ret = timerid;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013075 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020013076 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013077 ret = get_errno(timer_getoverrun(htimer));
13078 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013079 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013080 }
13081#endif
13082
13083#ifdef TARGET_NR_timer_delete
13084 case TARGET_NR_timer_delete:
13085 {
13086 /* args: timer_t timerid */
Alexander Grafaecc8862014-11-10 21:33:03 +010013087 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020013088
Alexander Grafaecc8862014-11-10 21:33:03 +010013089 if (timerid < 0) {
13090 ret = timerid;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013091 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020013092 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013093 ret = get_errno(timer_delete(htimer));
Alexander Grafe52a99f2014-08-22 13:56:18 +020013094 g_posix_timers[timerid] = 0;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013095 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013096 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013097 }
13098#endif
13099
Riku Voipio51834342014-06-22 11:25:42 +010013100#if defined(TARGET_NR_timerfd_create) && defined(CONFIG_TIMERFD)
13101 case TARGET_NR_timerfd_create:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013102 return get_errno(timerfd_create(arg1,
13103 target_to_host_bitmask(arg2, fcntl_flags_tbl)));
Riku Voipio51834342014-06-22 11:25:42 +010013104#endif
13105
13106#if defined(TARGET_NR_timerfd_gettime) && defined(CONFIG_TIMERFD)
13107 case TARGET_NR_timerfd_gettime:
13108 {
13109 struct itimerspec its_curr;
13110
13111 ret = get_errno(timerfd_gettime(arg1, &its_curr));
13112
13113 if (arg2 && host_to_target_itimerspec(arg2, &its_curr)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013114 return -TARGET_EFAULT;
Riku Voipio51834342014-06-22 11:25:42 +010013115 }
13116 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013117 return ret;
Riku Voipio51834342014-06-22 11:25:42 +010013118#endif
13119
Filip Bozuta828cb3a2020-07-22 17:34:21 +020013120#if defined(TARGET_NR_timerfd_gettime64) && defined(CONFIG_TIMERFD)
13121 case TARGET_NR_timerfd_gettime64:
13122 {
13123 struct itimerspec its_curr;
13124
13125 ret = get_errno(timerfd_gettime(arg1, &its_curr));
13126
13127 if (arg2 && host_to_target_itimerspec64(arg2, &its_curr)) {
13128 return -TARGET_EFAULT;
13129 }
13130 }
13131 return ret;
13132#endif
13133
Riku Voipio51834342014-06-22 11:25:42 +010013134#if defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD)
13135 case TARGET_NR_timerfd_settime:
13136 {
13137 struct itimerspec its_new, its_old, *p_new;
13138
13139 if (arg3) {
13140 if (target_to_host_itimerspec(&its_new, arg3)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013141 return -TARGET_EFAULT;
Riku Voipio51834342014-06-22 11:25:42 +010013142 }
13143 p_new = &its_new;
13144 } else {
13145 p_new = NULL;
13146 }
13147
13148 ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
13149
13150 if (arg4 && host_to_target_itimerspec(arg4, &its_old)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013151 return -TARGET_EFAULT;
Riku Voipio51834342014-06-22 11:25:42 +010013152 }
13153 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013154 return ret;
Riku Voipio51834342014-06-22 11:25:42 +010013155#endif
13156
Filip Bozuta828cb3a2020-07-22 17:34:21 +020013157#if defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)
13158 case TARGET_NR_timerfd_settime64:
13159 {
13160 struct itimerspec its_new, its_old, *p_new;
13161
13162 if (arg3) {
13163 if (target_to_host_itimerspec64(&its_new, arg3)) {
13164 return -TARGET_EFAULT;
13165 }
13166 p_new = &its_new;
13167 } else {
13168 p_new = NULL;
13169 }
13170
13171 ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
13172
13173 if (arg4 && host_to_target_itimerspec64(arg4, &its_old)) {
13174 return -TARGET_EFAULT;
13175 }
13176 }
13177 return ret;
13178#endif
13179
Paul Burtonab31cda2014-06-22 11:25:43 +010013180#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
13181 case TARGET_NR_ioprio_get:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013182 return get_errno(ioprio_get(arg1, arg2));
Paul Burtonab31cda2014-06-22 11:25:43 +010013183#endif
13184
13185#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
13186 case TARGET_NR_ioprio_set:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013187 return get_errno(ioprio_set(arg1, arg2, arg3));
Paul Burtonab31cda2014-06-22 11:25:43 +010013188#endif
13189
Riku Voipio9af5c902014-08-12 15:58:57 +030013190#if defined(TARGET_NR_setns) && defined(CONFIG_SETNS)
13191 case TARGET_NR_setns:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013192 return get_errno(setns(arg1, arg2));
Riku Voipio9af5c902014-08-12 15:58:57 +030013193#endif
13194#if defined(TARGET_NR_unshare) && defined(CONFIG_SETNS)
13195 case TARGET_NR_unshare:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013196 return get_errno(unshare(arg1));
Riku Voipio9af5c902014-08-12 15:58:57 +030013197#endif
Laurent Vivier2f147882016-09-25 22:20:20 +020013198#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
13199 case TARGET_NR_kcmp:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013200 return get_errno(kcmp(arg1, arg2, arg3, arg4, arg5));
Laurent Vivier2f147882016-09-25 22:20:20 +020013201#endif
Richard Hendersonfa97e382018-07-18 13:06:48 -070013202#ifdef TARGET_NR_swapcontext
13203 case TARGET_NR_swapcontext:
13204 /* PowerPC specific. */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013205 return do_swapcontext(cpu_env, arg1, arg2, arg3);
Richard Hendersonfa97e382018-07-18 13:06:48 -070013206#endif
Shu-Chun Weng9bdfa4d2019-08-19 11:09:47 -070013207#ifdef TARGET_NR_memfd_create
13208 case TARGET_NR_memfd_create:
13209 p = lock_user_string(arg1);
13210 if (!p) {
13211 return -TARGET_EFAULT;
13212 }
13213 ret = get_errno(memfd_create(p, arg2));
13214 fd_trans_unregister(ret);
13215 unlock_user(p, arg1, 0);
13216 return ret;
13217#endif
Andreas Schwab85004762019-05-13 11:02:53 +020013218#if defined TARGET_NR_membarrier && defined __NR_membarrier
13219 case TARGET_NR_membarrier:
13220 return get_errno(membarrier(arg1, arg2));
13221#endif
Riku Voipio9af5c902014-08-12 15:58:57 +030013222
Andreas Schwab84946452020-11-12 12:45:16 +010013223#if defined(TARGET_NR_copy_file_range) && defined(__NR_copy_file_range)
13224 case TARGET_NR_copy_file_range:
13225 {
13226 loff_t inoff, outoff;
13227 loff_t *pinoff = NULL, *poutoff = NULL;
13228
13229 if (arg2) {
13230 if (get_user_u64(inoff, arg2)) {
13231 return -TARGET_EFAULT;
13232 }
13233 pinoff = &inoff;
13234 }
13235 if (arg4) {
13236 if (get_user_u64(outoff, arg4)) {
13237 return -TARGET_EFAULT;
13238 }
13239 poutoff = &outoff;
13240 }
13241 ret = get_errno(safe_copy_file_range(arg1, pinoff, arg3, poutoff,
13242 arg5, arg6));
13243 if (!is_error(ret) && ret > 0) {
13244 if (arg2) {
13245 if (put_user_u64(inoff, arg2)) {
13246 return -TARGET_EFAULT;
13247 }
13248 }
13249 if (arg4) {
13250 if (put_user_u64(outoff, arg4)) {
13251 return -TARGET_EFAULT;
13252 }
13253 }
13254 }
13255 }
13256 return ret;
13257#endif
13258
bellard31e31b82003-02-18 22:55:36 +000013259 default:
Philippe Mathieu-Daudé122f9c82018-07-06 12:51:25 -030013260 qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013261 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +000013262 }
bellard31e31b82003-02-18 22:55:36 +000013263 return ret;
13264}
Richard Hendersondc1ce182018-08-18 12:01:04 -070013265
13266abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
13267 abi_long arg2, abi_long arg3, abi_long arg4,
13268 abi_long arg5, abi_long arg6, abi_long arg7,
13269 abi_long arg8)
13270{
Richard Henderson29a0af62019-03-22 16:07:18 -070013271 CPUState *cpu = env_cpu(cpu_env);
Richard Hendersondc1ce182018-08-18 12:01:04 -070013272 abi_long ret;
13273
13274#ifdef DEBUG_ERESTARTSYS
13275 /* Debug-only code for exercising the syscall-restart code paths
13276 * in the per-architecture cpu main loops: restart every syscall
13277 * the guest makes once before letting it through.
13278 */
13279 {
13280 static bool flag;
13281 flag = !flag;
13282 if (flag) {
13283 return -TARGET_ERESTARTSYS;
13284 }
13285 }
13286#endif
13287
Emilio G. Cotac36f7a62018-10-21 13:27:44 -040013288 record_syscall_start(cpu, num, arg1,
13289 arg2, arg3, arg4, arg5, arg6, arg7, arg8);
Richard Hendersondc1ce182018-08-18 12:01:04 -070013290
Josh Kunz4b25a502020-02-03 18:54:14 -080013291 if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
Filip Bozutae400e112020-08-11 18:45:49 +020013292 print_syscall(cpu_env, num, arg1, arg2, arg3, arg4, arg5, arg6);
Josh Kunz4b25a502020-02-03 18:54:14 -080013293 }
13294
13295 ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4,
13296 arg5, arg6, arg7, arg8);
13297
13298 if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
Filip Bozutae400e112020-08-11 18:45:49 +020013299 print_syscall_ret(cpu_env, num, ret, arg1, arg2,
13300 arg3, arg4, arg5, arg6);
Richard Hendersondc1ce182018-08-18 12:01:04 -070013301 }
13302
Emilio G. Cotac36f7a62018-10-21 13:27:44 -040013303 record_syscall_return(cpu, num, ret);
Richard Hendersondc1ce182018-08-18 12:01:04 -070013304 return ret;
13305}