blob: 8367cb138dfe075e06ca455009cc9b8aee41f78c [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"
bellard31e31b82003-02-18 22:55:36 +000023#include <elf.h>
24#include <endian.h>
John Spencerc56dc772012-12-10 07:59:46 +010025#include <grp.h>
thsd08d3bb2007-03-19 13:09:22 +000026#include <sys/ipc.h>
27#include <sys/msg.h>
bellard31e31b82003-02-18 22:55:36 +000028#include <sys/wait.h>
bellard31e31b82003-02-18 22:55:36 +000029#include <sys/mount.h>
John Spencer586b0be2012-12-26 00:49:49 +010030#include <sys/file.h>
31#include <sys/fsuid.h>
32#include <sys/personality.h>
ths39b9aae2007-02-11 18:36:44 +000033#include <sys/prctl.h>
bellard31e31b82003-02-18 22:55:36 +000034#include <sys/resource.h>
bellard31e31b82003-02-18 22:55:36 +000035#include <sys/swap.h>
Peter Maydelle0eb2102014-03-17 12:15:35 +000036#include <linux/capability.h>
bellard31e31b82003-02-18 22:55:36 +000037#include <sched.h>
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +020038#include <sys/timex.h>
bellard31e31b82003-02-18 22:55:36 +000039#include <sys/socket.h>
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +020040#include <linux/sockios.h>
aurel32607175e2009-04-15 16:11:59 +000041#include <sys/un.h>
bellard31e31b82003-02-18 22:55:36 +000042#include <sys/uio.h>
Felix Janda0839f112016-09-30 19:40:21 -040043#include <poll.h>
bellard32f36bc2003-03-30 21:29:48 +000044#include <sys/times.h>
bellard8853f862004-02-22 14:57:26 +000045#include <sys/shm.h>
thsfa294812007-02-02 22:05:00 +000046#include <sys/sem.h>
bellard56c8f682005-11-28 22:28:41 +000047#include <sys/statfs.h>
bellardebc05482003-09-30 21:08:41 +000048#include <utime.h>
bellarda5448a72004-06-19 16:59:03 +000049#include <sys/sysinfo.h>
Laurent Viviere36800c2015-10-02 14:48:09 +020050#include <sys/signalfd.h>
bellard72f03902003-02-18 23:33:18 +000051//#include <sys/user.h>
bellard8853f862004-02-22 14:57:26 +000052#include <netinet/ip.h>
bellard7854b052003-03-29 17:22:23 +000053#include <netinet/tcp.h>
Laurent Vivier86fcd942011-03-30 01:35:23 +020054#include <linux/wireless.h>
Jing Huang920394d2012-07-24 13:59:23 +000055#include <linux/icmp.h>
Helge Delleree1ac3a2017-02-18 23:31:30 +010056#include <linux/icmpv6.h>
57#include <linux/errqueue.h>
Marco A L Barbosad6d6d6f2017-10-05 10:55:30 -030058#include <linux/random.h>
Riku Voipiod80a1902014-10-01 16:05:46 +030059#ifdef CONFIG_TIMERFD
60#include <sys/timerfd.h>
61#endif
Riku Voipioc2882b92009-08-12 15:08:24 +030062#ifdef CONFIG_EVENTFD
63#include <sys/eventfd.h>
64#endif
Peter Maydell3b6edd12011-02-15 18:35:05 +000065#ifdef CONFIG_EPOLL
66#include <sys/epoll.h>
67#endif
An-Cheng Huanga790ae32011-08-09 12:34:06 -070068#ifdef CONFIG_ATTR
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010069#include "qemu/xattr.h"
An-Cheng Huanga790ae32011-08-09 12:34:06 -070070#endif
Peter Maydella8fd1ab2013-02-08 07:31:55 +000071#ifdef CONFIG_SENDFILE
72#include <sys/sendfile.h>
73#endif
bellard31e31b82003-02-18 22:55:36 +000074
75#define termios host_termios
76#define winsize host_winsize
77#define termio host_termio
bellard04369ff2003-03-20 22:33:23 +000078#define sgttyb host_sgttyb /* same as target */
79#define tchars host_tchars /* same as target */
80#define ltchars host_ltchars /* same as target */
bellard31e31b82003-02-18 22:55:36 +000081
82#include <linux/termios.h>
83#include <linux/unistd.h>
bellard31e31b82003-02-18 22:55:36 +000084#include <linux/cdrom.h>
85#include <linux/hdreg.h>
86#include <linux/soundcard.h>
bellard19b84f32003-05-08 15:41:49 +000087#include <linux/kd.h>
balrog8fbd6b52008-09-20 03:03:09 +000088#include <linux/mtio.h>
Martin Mohring350d1772009-05-04 21:21:41 +030089#include <linux/fs.h>
Peter Maydelldace20d2011-01-10 13:11:24 +000090#if defined(CONFIG_FIEMAP)
Peter Maydell285da2b2011-01-06 15:04:18 +000091#include <linux/fiemap.h>
Peter Maydelldace20d2011-01-10 13:11:24 +000092#endif
Ulrich Hechtf7680a52009-10-16 17:00:44 +020093#include <linux/fb.h>
Cortland Tölva6c753a62018-10-08 09:35:20 -070094#if defined(CONFIG_USBFS)
95#include <linux/usbdevice_fs.h>
Cortland Tölvaa1333672018-10-08 09:35:21 -070096#include <linux/usb/ch9.h>
Cortland Tölva6c753a62018-10-08 09:35:20 -070097#endif
Ulrich Hechtf7680a52009-10-16 17:00:44 +020098#include <linux/vt.h>
Alexander Graf56e904e2012-01-31 18:42:06 +010099#include <linux/dm-ioctl.h>
Laurent Vivierc07ecc62013-01-07 11:40:06 +0000100#include <linux/reboot.h>
Laurent Vivier7ff7b662013-07-02 14:04:12 +0100101#include <linux/route.h>
Laurent Vivierf57d4192013-08-30 01:46:41 +0200102#include <linux/filter.h>
Andreas Färberfff8c532014-01-18 07:38:30 +0100103#include <linux/blkpg.h>
Laurent Viviera82ea932016-06-27 00:18:22 +0200104#include <netpacket/packet.h>
Laurent Vivier6c5b5642016-05-22 18:56:19 +0200105#include <linux/netlink.h>
Yunqiang Suf31dddd2019-06-19 16:17:11 +0200106#include <linux/if_alg.h>
pbrookd7e40362008-05-23 16:06:43 +0000107#include "linux_loop.h"
Riku Voipio18cb0082014-02-19 12:59:58 +0200108#include "uname.h"
bellard31e31b82003-02-18 22:55:36 +0000109
bellard3ef693a2003-03-23 20:17:16 +0000110#include "qemu.h"
Richard Henderson5ebdd772019-03-14 13:10:53 -0700111#include "qemu/guest-random.h"
Richard Henderson51977e22019-03-12 19:22:20 -0700112#include "qapi/error.h"
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200113#include "fd-trans.h"
bellard31e31b82003-02-18 22:55:36 +0000114
Peter Maydell5ea2fc82016-08-02 18:41:27 +0100115#ifndef CLONE_IO
116#define CLONE_IO 0x80000000 /* Clone io context */
117#endif
118
119/* We can't directly call the host clone syscall, because this will
120 * badly confuse libc (breaking mutexes, for example). So we must
121 * divide clone flags into:
122 * * flag combinations that look like pthread_create()
123 * * flag combinations that look like fork()
124 * * flags we can implement within QEMU itself
125 * * flags we can't support and will return an error for
126 */
127/* For thread creation, all these flags must be present; for
128 * fork, none must be present.
129 */
130#define CLONE_THREAD_FLAGS \
131 (CLONE_VM | CLONE_FS | CLONE_FILES | \
132 CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM)
133
134/* These flags are ignored:
135 * CLONE_DETACHED is now ignored by the kernel;
136 * CLONE_IO is just an optimisation hint to the I/O scheduler
137 */
138#define CLONE_IGNORED_FLAGS \
139 (CLONE_DETACHED | CLONE_IO)
140
141/* Flags for fork which we can implement within QEMU itself */
142#define CLONE_OPTIONAL_FORK_FLAGS \
143 (CLONE_SETTLS | CLONE_PARENT_SETTID | \
144 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID)
145
146/* Flags for thread creation which we can implement within QEMU itself */
147#define CLONE_OPTIONAL_THREAD_FLAGS \
148 (CLONE_SETTLS | CLONE_PARENT_SETTID | \
149 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | CLONE_PARENT)
150
151#define CLONE_INVALID_FORK_FLAGS \
152 (~(CSIGNAL | CLONE_OPTIONAL_FORK_FLAGS | CLONE_IGNORED_FLAGS))
153
154#define CLONE_INVALID_THREAD_FLAGS \
155 (~(CSIGNAL | CLONE_THREAD_FLAGS | CLONE_OPTIONAL_THREAD_FLAGS | \
156 CLONE_IGNORED_FLAGS))
157
158/* CLONE_VFORK is special cased early in do_fork(). The other flag bits
159 * have almost all been allocated. We cannot support any of
160 * CLONE_NEWNS, CLONE_NEWCGROUP, CLONE_NEWUTS, CLONE_NEWIPC,
161 * CLONE_NEWUSER, CLONE_NEWPID, CLONE_NEWNET, CLONE_PTRACE, CLONE_UNTRACED.
162 * The checks against the invalid thread masks above will catch these.
163 * (The one remaining unallocated bit is 0x1000 which used to be CLONE_PID.)
164 */
pbrook30813ce2008-06-02 15:45:44 +0000165
Timothy E Baldwin71a8f7f2016-05-12 18:47:45 +0100166/* Define DEBUG_ERESTARTSYS to force every syscall to be restarted
167 * once. This exercises the codepaths for restart.
168 */
169//#define DEBUG_ERESTARTSYS
bellard31e31b82003-02-18 22:55:36 +0000170
bellard1a9353d2003-03-16 20:28:50 +0000171//#include <linux/msdos_fs.h>
aurel326556a832008-10-13 21:08:17 +0000172#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2])
173#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct linux_dirent [2])
bellard1a9353d2003-03-16 20:28:50 +0000174
bellard70a194b2003-08-11 22:20:16 +0000175#undef _syscall0
176#undef _syscall1
177#undef _syscall2
178#undef _syscall3
179#undef _syscall4
180#undef _syscall5
bellard83fcb512006-06-14 13:37:16 +0000181#undef _syscall6
bellard70a194b2003-08-11 22:20:16 +0000182
bellard83fcb512006-06-14 13:37:16 +0000183#define _syscall0(type,name) \
blueswir18fcd3692008-08-17 20:26:25 +0000184static type name (void) \
bellard83fcb512006-06-14 13:37:16 +0000185{ \
186 return syscall(__NR_##name); \
bellard70a194b2003-08-11 22:20:16 +0000187}
188
bellard83fcb512006-06-14 13:37:16 +0000189#define _syscall1(type,name,type1,arg1) \
blueswir18fcd3692008-08-17 20:26:25 +0000190static type name (type1 arg1) \
bellard83fcb512006-06-14 13:37:16 +0000191{ \
192 return syscall(__NR_##name, arg1); \
bellard70a194b2003-08-11 22:20:16 +0000193}
194
bellard83fcb512006-06-14 13:37:16 +0000195#define _syscall2(type,name,type1,arg1,type2,arg2) \
blueswir18fcd3692008-08-17 20:26:25 +0000196static type name (type1 arg1,type2 arg2) \
bellard83fcb512006-06-14 13:37:16 +0000197{ \
198 return syscall(__NR_##name, arg1, arg2); \
bellard70a194b2003-08-11 22:20:16 +0000199}
200
bellard83fcb512006-06-14 13:37:16 +0000201#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
blueswir18fcd3692008-08-17 20:26:25 +0000202static type name (type1 arg1,type2 arg2,type3 arg3) \
bellard83fcb512006-06-14 13:37:16 +0000203{ \
204 return syscall(__NR_##name, arg1, arg2, arg3); \
bellard70a194b2003-08-11 22:20:16 +0000205}
206
bellard83fcb512006-06-14 13:37:16 +0000207#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
blueswir18fcd3692008-08-17 20:26:25 +0000208static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
bellard83fcb512006-06-14 13:37:16 +0000209{ \
210 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
bellard70a194b2003-08-11 22:20:16 +0000211}
212
bellard83fcb512006-06-14 13:37:16 +0000213#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
214 type5,arg5) \
blueswir18fcd3692008-08-17 20:26:25 +0000215static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
bellard83fcb512006-06-14 13:37:16 +0000216{ \
217 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
bellard70a194b2003-08-11 22:20:16 +0000218}
bellard83fcb512006-06-14 13:37:16 +0000219
220
221#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
222 type5,arg5,type6,arg6) \
blueswir18fcd3692008-08-17 20:26:25 +0000223static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
224 type6 arg6) \
bellard83fcb512006-06-14 13:37:16 +0000225{ \
226 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
227}
228
bellard70a194b2003-08-11 22:20:16 +0000229
bellard31e31b82003-02-18 22:55:36 +0000230#define __NR_sys_uname __NR_uname
bellard72f03902003-02-18 23:33:18 +0000231#define __NR_sys_getcwd1 __NR_getcwd
bellard72f03902003-02-18 23:33:18 +0000232#define __NR_sys_getdents __NR_getdents
bellarddab2ed92003-03-22 15:23:14 +0000233#define __NR_sys_getdents64 __NR_getdents64
thsc6cda172007-10-09 03:42:34 +0000234#define __NR_sys_getpriority __NR_getpriority
bellard66fb9762003-03-23 01:06:05 +0000235#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +0200236#define __NR_sys_rt_tgsigqueueinfo __NR_rt_tgsigqueueinfo
ths7494b0f2007-02-11 18:26:53 +0000237#define __NR_sys_syslog __NR_syslog
pbrookbd0c5662008-05-29 14:34:11 +0000238#define __NR_sys_futex __NR_futex
aurel3239b59762008-10-01 21:46:50 +0000239#define __NR_sys_inotify_init __NR_inotify_init
240#define __NR_sys_inotify_add_watch __NR_inotify_add_watch
241#define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch
Aleksandar Rikaloefa92182019-06-28 12:43:34 +0200242#define __NR_sys_statx __NR_statx
bellard31e31b82003-02-18 22:55:36 +0000243
Peter Maydellb1cef6d2018-01-25 16:19:49 +0000244#if defined(__alpha__) || defined(__x86_64__) || defined(__s390x__)
bellard9af9eaa2003-04-07 21:34:41 +0000245#define __NR__llseek __NR_lseek
246#endif
247
James Hogana29e5ba2014-03-25 21:51:08 +0000248/* Newer kernel ports have llseek() instead of _llseek() */
249#if defined(TARGET_NR_llseek) && !defined(TARGET_NR__llseek)
250#define TARGET_NR__llseek TARGET_NR_llseek
251#endif
252
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +0000253#define __NR_sys_gettid __NR_gettid
254_syscall0(int, sys_gettid)
Peter Maydell2b3f64c2018-04-19 13:57:40 +0100255
256/* For the 64-bit guest on 32-bit host case we must emulate
257 * getdents using getdents64, because otherwise the host
258 * might hand us back more dirent records than we can fit
259 * into the guest buffer after structure format conversion.
260 * Otherwise we emulate getdents with getdents if the host has it.
261 */
262#if defined(__NR_getdents) && HOST_LONG_BITS >= TARGET_ABI_BITS
263#define EMULATE_GETDENTS_WITH_GETDENTS
264#endif
265
266#if defined(TARGET_NR_getdents) && defined(EMULATE_GETDENTS_WITH_GETDENTS)
aurel323b3f24a2009-04-15 16:12:13 +0000267_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
Peter Maydell3307e232013-06-12 16:20:21 +0100268#endif
Peter Maydell2b3f64c2018-04-19 13:57:40 +0100269#if (defined(TARGET_NR_getdents) && \
270 !defined(EMULATE_GETDENTS_WITH_GETDENTS)) || \
Peter Maydell3307e232013-06-12 16:20:21 +0100271 (defined(TARGET_NR_getdents64) && defined(__NR_getdents64))
aurel323b3f24a2009-04-15 16:12:13 +0000272_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
273#endif
Richard Hendersond35b2612010-06-04 12:14:10 -0700274#if defined(TARGET_NR__llseek) && defined(__NR_llseek)
aurel323b3f24a2009-04-15 16:12:13 +0000275_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
276 loff_t *, res, uint, wh);
277#endif
Miloš Stojanovićc1a402a2017-05-15 16:59:45 +0200278_syscall3(int, sys_rt_sigqueueinfo, pid_t, pid, int, sig, siginfo_t *, uinfo)
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +0200279_syscall4(int, sys_rt_tgsigqueueinfo, pid_t, pid, pid_t, tid, int, sig,
280 siginfo_t *, uinfo)
aurel323b3f24a2009-04-15 16:12:13 +0000281_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
aurel323b3f24a2009-04-15 16:12:13 +0000282#ifdef __NR_exit_group
283_syscall1(int,exit_group,int,error_code)
284#endif
285#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
286_syscall1(int,set_tid_address,int *,tidptr)
287#endif
aurel323b3f24a2009-04-15 16:12:13 +0000288#if defined(TARGET_NR_futex) && defined(__NR_futex)
289_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
290 const struct timespec *,timeout,int *,uaddr2,int,val3)
291#endif
Mike Frysinger737de1d2011-02-07 01:05:55 -0500292#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
293_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
294 unsigned long *, user_mask_ptr);
295#define __NR_sys_sched_setaffinity __NR_sched_setaffinity
296_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
297 unsigned long *, user_mask_ptr);
Samuel Thibaultb827c3e2018-01-12 09:14:35 +0100298#define __NR_sys_getcpu __NR_getcpu
299_syscall3(int, sys_getcpu, unsigned *, cpu, unsigned *, node, void *, tcache);
Alexander Graf0f6b4d22011-09-27 14:39:42 +0200300_syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd,
301 void *, arg);
Peter Maydelle0eb2102014-03-17 12:15:35 +0000302_syscall2(int, capget, struct __user_cap_header_struct *, header,
303 struct __user_cap_data_struct *, data);
304_syscall2(int, capset, struct __user_cap_header_struct *, header,
305 struct __user_cap_data_struct *, data);
Paul Burtonab31cda2014-06-22 11:25:43 +0100306#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
307_syscall2(int, ioprio_get, int, which, int, who)
308#endif
309#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
310_syscall3(int, ioprio_set, int, which, int, who, int, ioprio)
311#endif
Laurent Vivierf894efd2016-02-21 10:56:23 +0100312#if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
313_syscall3(int, getrandom, void *, buf, size_t, buflen, unsigned int, flags)
314#endif
aurel323b3f24a2009-04-15 16:12:13 +0000315
Laurent Vivier2f147882016-09-25 22:20:20 +0200316#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
317_syscall5(int, kcmp, pid_t, pid1, pid_t, pid2, int, type,
318 unsigned long, idx1, unsigned long, idx2)
319#endif
320
Aleksandar Rikaloefa92182019-06-28 12:43:34 +0200321/*
322 * It is assumed that struct statx is architecture independent.
323 */
324#if defined(TARGET_NR_statx) && defined(__NR_statx)
325_syscall5(int, sys_statx, int, dirfd, const char *, pathname, int, flags,
326 unsigned int, mask, struct target_statx *, statxbuf)
327#endif
328
aurel323b3f24a2009-04-15 16:12:13 +0000329static bitmask_transtbl fcntl_flags_tbl[] = {
330 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
331 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
332 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
333 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
334 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
335 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
336 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
337 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
Richard Hendersonafc87632012-07-25 14:30:34 -0700338 { TARGET_O_SYNC, TARGET_O_DSYNC, O_SYNC, O_DSYNC, },
aurel323b3f24a2009-04-15 16:12:13 +0000339 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
340 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
341 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
342 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
aurel323b3f24a2009-04-15 16:12:13 +0000343#if defined(O_DIRECT)
344 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
345#endif
Richard Hendersonafc87632012-07-25 14:30:34 -0700346#if defined(O_NOATIME)
347 { TARGET_O_NOATIME, TARGET_O_NOATIME, O_NOATIME, O_NOATIME },
348#endif
349#if defined(O_CLOEXEC)
350 { TARGET_O_CLOEXEC, TARGET_O_CLOEXEC, O_CLOEXEC, O_CLOEXEC },
351#endif
352#if defined(O_PATH)
353 { TARGET_O_PATH, TARGET_O_PATH, O_PATH, O_PATH },
354#endif
Riku Voipio5f9cee42017-08-08 16:01:19 +0300355#if defined(O_TMPFILE)
356 { TARGET_O_TMPFILE, TARGET_O_TMPFILE, O_TMPFILE, O_TMPFILE },
357#endif
Richard Hendersonafc87632012-07-25 14:30:34 -0700358 /* Don't terminate the list prematurely on 64-bit host+guest. */
359#if TARGET_O_LARGEFILE != 0 || O_LARGEFILE != 0
360 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
361#endif
aurel323b3f24a2009-04-15 16:12:13 +0000362 { 0, 0, 0, 0 }
363};
364
aurel323b3f24a2009-04-15 16:12:13 +0000365static int sys_getcwd1(char *buf, size_t size)
366{
367 if (getcwd(buf, size) == NULL) {
368 /* getcwd() sets errno */
369 return (-1);
370 }
aurel32aaf4ad32009-04-16 14:17:14 +0000371 return strlen(buf)+1;
aurel323b3f24a2009-04-15 16:12:13 +0000372}
373
Peter Maydell1acae9f2013-07-02 14:04:12 +0100374#ifdef TARGET_NR_utimensat
Peter Maydell700fa582016-07-18 11:47:55 +0100375#if defined(__NR_utimensat)
Peter Maydell1acae9f2013-07-02 14:04:12 +0100376#define __NR_sys_utimensat __NR_utimensat
ths9007f0e2007-09-25 17:50:37 +0000377_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
378 const struct timespec *,tsp,int,flags)
Peter Maydell1acae9f2013-07-02 14:04:12 +0100379#else
380static int sys_utimensat(int dirfd, const char *pathname,
381 const struct timespec times[2], int flags)
382{
383 errno = ENOSYS;
384 return -1;
385}
ths9007f0e2007-09-25 17:50:37 +0000386#endif
Peter Maydell1acae9f2013-07-02 14:04:12 +0100387#endif /* TARGET_NR_utimensat */
aurel323b3f24a2009-04-15 16:12:13 +0000388
Andreas Schwab95d03072018-01-23 11:53:31 +0100389#ifdef TARGET_NR_renameat2
390#if defined(__NR_renameat2)
391#define __NR_sys_renameat2 __NR_renameat2
392_syscall5(int, sys_renameat2, int, oldfd, const char *, old, int, newfd,
393 const char *, new, unsigned int, flags)
394#else
395static int sys_renameat2(int oldfd, const char *old,
396 int newfd, const char *new, int flags)
397{
398 if (flags == 0) {
399 return renameat(oldfd, old, newfd, new);
400 }
401 errno = ENOSYS;
402 return -1;
403}
404#endif
405#endif /* TARGET_NR_renameat2 */
406
aurel323b3f24a2009-04-15 16:12:13 +0000407#ifdef CONFIG_INOTIFY
aurel328690e422009-04-17 13:50:32 +0000408#include <sys/inotify.h>
aurel323b3f24a2009-04-15 16:12:13 +0000409
aurel3239b59762008-10-01 21:46:50 +0000410#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
aurel323b3f24a2009-04-15 16:12:13 +0000411static int sys_inotify_init(void)
412{
413 return (inotify_init());
414}
aurel3239b59762008-10-01 21:46:50 +0000415#endif
416#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
aurel323b3f24a2009-04-15 16:12:13 +0000417static int sys_inotify_add_watch(int fd,const char *pathname, int32_t mask)
418{
419 return (inotify_add_watch(fd, pathname, mask));
420}
aurel3239b59762008-10-01 21:46:50 +0000421#endif
422#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
aurel323b3f24a2009-04-15 16:12:13 +0000423static int sys_inotify_rm_watch(int fd, int32_t wd)
424{
aurel328690e422009-04-17 13:50:32 +0000425 return (inotify_rm_watch(fd, wd));
aurel323b3f24a2009-04-15 16:12:13 +0000426}
aurel3239b59762008-10-01 21:46:50 +0000427#endif
Riku Voipioc05c7a72010-03-26 15:25:11 +0000428#ifdef CONFIG_INOTIFY1
429#if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1)
430static int sys_inotify_init1(int flags)
431{
432 return (inotify_init1(flags));
433}
434#endif
435#endif
aurel323b3f24a2009-04-15 16:12:13 +0000436#else
437/* Userspace can usually survive runtime without inotify */
438#undef TARGET_NR_inotify_init
Riku Voipioc05c7a72010-03-26 15:25:11 +0000439#undef TARGET_NR_inotify_init1
aurel323b3f24a2009-04-15 16:12:13 +0000440#undef TARGET_NR_inotify_add_watch
441#undef TARGET_NR_inotify_rm_watch
442#endif /* CONFIG_INOTIFY */
443
Peter Maydell163a05a2011-06-27 17:44:52 +0100444#if defined(TARGET_NR_prlimit64)
445#ifndef __NR_prlimit64
446# define __NR_prlimit64 -1
447#endif
448#define __NR_sys_prlimit64 __NR_prlimit64
449/* The glibc rlimit structure may not be that used by the underlying syscall */
450struct host_rlimit64 {
451 uint64_t rlim_cur;
452 uint64_t rlim_max;
453};
454_syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
455 const struct host_rlimit64 *, new_limit,
456 struct host_rlimit64 *, old_limit)
457#endif
458
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +1100459
460#if defined(TARGET_NR_timer_create)
461/* Maxiumum of 32 active POSIX timers allowed at any one time. */
462static timer_t g_posix_timers[32] = { 0, } ;
463
464static inline int next_free_host_timer(void)
465{
466 int k ;
467 /* FIXME: Does finding the next free slot require a lock? */
468 for (k = 0; k < ARRAY_SIZE(g_posix_timers); k++) {
469 if (g_posix_timers[k] == 0) {
470 g_posix_timers[k] = (timer_t) 1;
471 return k;
472 }
473 }
474 return -1;
475}
476#endif
477
Riku Voipio48e515d2011-07-12 15:40:51 +0300478/* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
Alexander Graf4a1def42012-09-29 15:32:38 +0000479#ifdef TARGET_ARM
James Clarke8bf8e9d2017-09-15 20:33:13 +0100480static inline int regpairs_aligned(void *cpu_env, int num)
481{
Riku Voipio48e515d2011-07-12 15:40:51 +0300482 return ((((CPUARMState *)cpu_env)->eabi) == 1) ;
483}
Aleksandar Markovicd7779ac2016-09-19 13:44:42 +0200484#elif defined(TARGET_MIPS) && (TARGET_ABI_BITS == 32)
James Clarke8bf8e9d2017-09-15 20:33:13 +0100485static inline int regpairs_aligned(void *cpu_env, int num) { return 1; }
Alexander Graf4a1def42012-09-29 15:32:38 +0000486#elif defined(TARGET_PPC) && !defined(TARGET_PPC64)
487/* SysV AVI for PPC32 expects 64bit parameters to be passed on odd/even pairs
488 * of registers which translates to the same as ARM/MIPS, because we start with
489 * r3 as arg1 */
James Clarke8bf8e9d2017-09-15 20:33:13 +0100490static inline int regpairs_aligned(void *cpu_env, int num) { return 1; }
491#elif defined(TARGET_SH4)
492/* SH4 doesn't align register pairs, except for p{read,write}64 */
493static inline int regpairs_aligned(void *cpu_env, int num)
494{
495 switch (num) {
496 case TARGET_NR_pread64:
497 case TARGET_NR_pwrite64:
498 return 1;
499
500 default:
501 return 0;
502 }
503}
Max Filippovba7651f2017-01-25 10:54:11 -0800504#elif defined(TARGET_XTENSA)
505static inline int regpairs_aligned(void *cpu_env, int num) { return 1; }
Riku Voipio48e515d2011-07-12 15:40:51 +0300506#else
James Clarke8bf8e9d2017-09-15 20:33:13 +0100507static inline int regpairs_aligned(void *cpu_env, int num) { return 0; }
Riku Voipio48e515d2011-07-12 15:40:51 +0300508#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)
Timothy E Baldwin4af80a32016-05-12 18:47:49 +0100732safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \
733 struct rusage *, rusage)
734safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \
735 int, options, struct rusage *, rusage)
Timothy E Baldwinffdcbe22016-05-12 18:47:50 +0100736safe_syscall3(int, execve, const char *, filename, char **, argv, char **, envp)
Peter Maydell6df9d382016-05-12 18:47:51 +0100737safe_syscall6(int, pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, \
738 fd_set *, exceptfds, struct timespec *, timeout, void *, sig)
Peter Maydella6130232016-06-06 19:58:10 +0100739safe_syscall5(int, ppoll, struct pollfd *, ufds, unsigned int, nfds,
740 struct timespec *, tsp, const sigset_t *, sigmask,
741 size_t, sigsetsize)
Peter Maydell227f0212016-06-06 19:58:11 +0100742safe_syscall6(int, epoll_pwait, int, epfd, struct epoll_event *, events,
743 int, maxevents, int, timeout, const sigset_t *, sigmask,
744 size_t, sigsetsize)
Peter Maydelld509eeb2016-05-12 18:47:52 +0100745safe_syscall6(int,futex,int *,uaddr,int,op,int,val, \
746 const struct timespec *,timeout,int *,uaddr2,int,val3)
Peter Maydell2fe4fba2016-05-27 15:51:48 +0100747safe_syscall2(int, rt_sigsuspend, sigset_t *, newset, size_t, sigsetsize)
Peter Maydellbef653d2016-05-27 15:51:57 +0100748safe_syscall2(int, kill, pid_t, pid, int, sig)
749safe_syscall2(int, tkill, int, tid, int, sig)
750safe_syscall3(int, tgkill, int, tgid, int, pid, int, sig)
Peter Maydell918c03e2016-06-06 19:58:02 +0100751safe_syscall3(ssize_t, readv, int, fd, const struct iovec *, iov, int, iovcnt)
752safe_syscall3(ssize_t, writev, int, fd, const struct iovec *, iov, int, iovcnt)
Dejan Jovicevic0f263862016-10-11 11:52:46 +0200753safe_syscall5(ssize_t, preadv, int, fd, const struct iovec *, iov, int, iovcnt,
754 unsigned long, pos_l, unsigned long, pos_h)
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +0200755safe_syscall5(ssize_t, pwritev, int, fd, const struct iovec *, iov, int, iovcnt,
756 unsigned long, pos_l, unsigned long, pos_h)
Peter Maydell2a3c7612016-06-06 19:58:03 +0100757safe_syscall3(int, connect, int, fd, const struct sockaddr *, addr,
758 socklen_t, addrlen)
Peter Maydell66687532016-06-06 19:58:04 +0100759safe_syscall6(ssize_t, sendto, int, fd, const void *, buf, size_t, len,
760 int, flags, const struct sockaddr *, addr, socklen_t, addrlen)
761safe_syscall6(ssize_t, recvfrom, int, fd, void *, buf, size_t, len,
762 int, flags, struct sockaddr *, addr, socklen_t *, addrlen)
763safe_syscall3(ssize_t, sendmsg, int, fd, const struct msghdr *, msg, int, flags)
764safe_syscall3(ssize_t, recvmsg, int, fd, struct msghdr *, msg, int, flags)
Peter Maydell2a845982016-06-06 19:58:07 +0100765safe_syscall2(int, flock, int, fd, int, operation)
Peter Maydellb3f82332016-06-06 19:58:08 +0100766safe_syscall4(int, rt_sigtimedwait, const sigset_t *, these, siginfo_t *, uinfo,
767 const struct timespec *, uts, size_t, sigsetsize)
Peter Maydellff6dc132016-06-06 19:58:13 +0100768safe_syscall4(int, accept4, int, fd, struct sockaddr *, addr, socklen_t *, len,
769 int, flags)
Peter Maydell9e518222016-06-06 19:58:09 +0100770safe_syscall2(int, nanosleep, const struct timespec *, req,
771 struct timespec *, rem)
772#ifdef TARGET_NR_clock_nanosleep
773safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags,
774 const struct timespec *, req, struct timespec *, rem)
775#endif
Laurent Vivier524fa342019-05-29 10:48:04 +0200776#ifdef __NR_ipc
Peter Maydell89f9fe42016-06-06 19:58:05 +0100777safe_syscall6(int, ipc, int, call, long, first, long, second, long, third,
778 void *, ptr, long, fifth)
Laurent Vivier86e63692019-05-23 19:54:13 +0200779#endif
780#ifdef __NR_msgsnd
781safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz,
782 int, flags)
Laurent Vivier86e63692019-05-23 19:54:13 +0200783#endif
784#ifdef __NR_msgrcv
785safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz,
786 long, msgtype, int, flags)
Laurent Vivier86e63692019-05-23 19:54:13 +0200787#endif
788#ifdef __NR_semtimedop
789safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops,
790 unsigned, nsops, const struct timespec *, timeout)
Peter Maydell89f9fe42016-06-06 19:58:05 +0100791#endif
Peter Maydelld40ecd62016-06-06 19:58:06 +0100792#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
793safe_syscall5(int, mq_timedsend, int, mqdes, const char *, msg_ptr,
794 size_t, len, unsigned, prio, const struct timespec *, timeout)
795safe_syscall5(int, mq_timedreceive, int, mqdes, char *, msg_ptr,
796 size_t, len, unsigned *, prio, const struct timespec *, timeout)
797#endif
Peter Maydell49ca6f32016-06-06 19:58:14 +0100798/* We do ioctl like this rather than via safe_syscall3 to preserve the
799 * "third argument might be integer or pointer or not present" behaviour of
800 * the libc function.
801 */
802#define safe_ioctl(...) safe_syscall(__NR_ioctl, __VA_ARGS__)
Peter Maydell435da5e2016-06-13 11:22:05 +0100803/* Similarly for fcntl. Note that callers must always:
804 * pass the F_GETLK64 etc constants rather than the unsuffixed F_GETLK
805 * use the flock64 struct rather than unsuffixed flock
806 * This will then work and use a 64-bit offset for both 32-bit and 64-bit hosts.
807 */
808#ifdef __NR_fcntl64
809#define safe_fcntl(...) safe_syscall(__NR_fcntl64, __VA_ARGS__)
810#else
811#define safe_fcntl(...) safe_syscall(__NR_fcntl, __VA_ARGS__)
812#endif
Timothy E Baldwin50afd022016-05-12 18:47:47 +0100813
Paul Burton8289d112014-06-22 11:25:33 +0100814static inline int host_to_target_sock_type(int host_type)
815{
816 int target_type;
817
818 switch (host_type & 0xf /* SOCK_TYPE_MASK */) {
819 case SOCK_DGRAM:
820 target_type = TARGET_SOCK_DGRAM;
821 break;
822 case SOCK_STREAM:
823 target_type = TARGET_SOCK_STREAM;
824 break;
825 default:
826 target_type = host_type & 0xf /* SOCK_TYPE_MASK */;
827 break;
828 }
829
830#if defined(SOCK_CLOEXEC)
831 if (host_type & SOCK_CLOEXEC) {
832 target_type |= TARGET_SOCK_CLOEXEC;
833 }
834#endif
835
836#if defined(SOCK_NONBLOCK)
837 if (host_type & SOCK_NONBLOCK) {
838 target_type |= TARGET_SOCK_NONBLOCK;
839 }
840#endif
841
842 return target_type;
843}
844
blueswir1992f48a2007-10-14 16:27:31 +0000845static abi_ulong target_brk;
846static abi_ulong target_original_brk;
vincent4d1de872011-06-14 21:56:33 +0000847static abi_ulong brk_page;
bellard31e31b82003-02-18 22:55:36 +0000848
blueswir1992f48a2007-10-14 16:27:31 +0000849void target_set_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000850{
blueswir14c1de732007-07-07 20:45:44 +0000851 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
vincent4d1de872011-06-14 21:56:33 +0000852 brk_page = HOST_PAGE_ALIGN(target_brk);
bellard31e31b82003-02-18 22:55:36 +0000853}
854
vincent4d1de872011-06-14 21:56:33 +0000855//#define DEBUGF_BRK(message, args...) do { fprintf(stderr, (message), ## args); } while (0)
856#define DEBUGF_BRK(message, args...)
857
ths0da46a62007-10-20 20:23:07 +0000858/* do_brk() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000859abi_long do_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000860{
blueswir1992f48a2007-10-14 16:27:31 +0000861 abi_long mapped_addr;
Peter Maydellef4330c2016-07-22 13:41:52 +0100862 abi_ulong new_alloc_size;
bellard31e31b82003-02-18 22:55:36 +0000863
Paul Brook3a0c6c42012-02-09 19:04:27 +0000864 DEBUGF_BRK("do_brk(" TARGET_ABI_FMT_lx ") -> ", new_brk);
ths3b46e622007-09-17 08:09:54 +0000865
vincent4d1de872011-06-14 21:56:33 +0000866 if (!new_brk) {
Paul Brook3a0c6c42012-02-09 19:04:27 +0000867 DEBUGF_BRK(TARGET_ABI_FMT_lx " (!new_brk)\n", target_brk);
vincent4d1de872011-06-14 21:56:33 +0000868 return target_brk;
869 }
870 if (new_brk < target_original_brk) {
Paul Brook3a0c6c42012-02-09 19:04:27 +0000871 DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk < target_original_brk)\n",
872 target_brk);
vincent4d1de872011-06-14 21:56:33 +0000873 return target_brk;
874 }
bellard31e31b82003-02-18 22:55:36 +0000875
vincent4d1de872011-06-14 21:56:33 +0000876 /* If the new brk is less than the highest page reserved to the
877 * target heap allocation, set it and we're almost done... */
878 if (new_brk <= brk_page) {
879 /* Heap contents are initialized to zero, as for anonymous
880 * mapped pages. */
881 if (new_brk > target_brk) {
882 memset(g2h(target_brk), 0, new_brk - target_brk);
883 }
bellard31e31b82003-02-18 22:55:36 +0000884 target_brk = new_brk;
Paul Brook3a0c6c42012-02-09 19:04:27 +0000885 DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk <= brk_page)\n", target_brk);
Paolo Bonzini72e21db2018-12-13 23:37:36 +0100886 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000887 }
888
Peter Maydell00faf082011-04-18 16:34:24 +0100889 /* We need to allocate more memory after the brk... Note that
890 * we don't use MAP_FIXED because that will map over the top of
891 * any existing mapping (like the one with the host libc or qemu
892 * itself); instead we treat "mapped but at wrong address" as
893 * a failure and unmap again.
894 */
vincent4d1de872011-06-14 21:56:33 +0000895 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page);
ths5fafdf22007-09-16 21:08:06 +0000896 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
bellard54936002003-05-13 00:25:15 +0000897 PROT_READ|PROT_WRITE,
Peter Maydell00faf082011-04-18 16:34:24 +0100898 MAP_ANON|MAP_PRIVATE, 0, 0));
899
900 if (mapped_addr == brk_page) {
Cédric VINCENT70afc342011-08-26 10:56:50 +0200901 /* Heap contents are initialized to zero, as for anonymous
902 * mapped pages. Technically the new pages are already
903 * initialized to zero since they *are* anonymous mapped
904 * pages, however we have to take care with the contents that
905 * come from the remaining part of the previous page: it may
906 * contains garbage data due to a previous heap usage (grown
907 * then shrunken). */
908 memset(g2h(target_brk), 0, brk_page - target_brk);
909
Peter Maydell00faf082011-04-18 16:34:24 +0100910 target_brk = new_brk;
vincent4d1de872011-06-14 21:56:33 +0000911 brk_page = HOST_PAGE_ALIGN(target_brk);
Paul Brook3a0c6c42012-02-09 19:04:27 +0000912 DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr == brk_page)\n",
913 target_brk);
Peter Maydell00faf082011-04-18 16:34:24 +0100914 return target_brk;
915 } else if (mapped_addr != -1) {
916 /* Mapped but at wrong address, meaning there wasn't actually
917 * enough space for this brk.
918 */
919 target_munmap(mapped_addr, new_alloc_size);
920 mapped_addr = -1;
Paul Brook3a0c6c42012-02-09 19:04:27 +0000921 DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr != -1)\n", target_brk);
vincent4d1de872011-06-14 21:56:33 +0000922 }
923 else {
Paul Brook3a0c6c42012-02-09 19:04:27 +0000924 DEBUGF_BRK(TARGET_ABI_FMT_lx " (otherwise)\n", target_brk);
Peter Maydell00faf082011-04-18 16:34:24 +0100925 }
balrog7ab240a2008-04-26 12:17:34 +0000926
Richard Henderson7dd46c02010-05-03 10:07:49 -0700927#if defined(TARGET_ALPHA)
928 /* We (partially) emulate OSF/1 on Alpha, which requires we
929 return a proper errno, not an unchanged brk value. */
Peter Maydell00faf082011-04-18 16:34:24 +0100930 return -TARGET_ENOMEM;
Richard Henderson7dd46c02010-05-03 10:07:49 -0700931#endif
Peter Maydell00faf082011-04-18 16:34:24 +0100932 /* For everything else, return the previous break. */
balrog7ab240a2008-04-26 12:17:34 +0000933 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000934}
935
ths26edcf42007-12-09 02:25:24 +0000936static inline abi_long copy_from_user_fdset(fd_set *fds,
937 abi_ulong target_fds_addr,
938 int n)
bellard31e31b82003-02-18 22:55:36 +0000939{
ths26edcf42007-12-09 02:25:24 +0000940 int i, nw, j, k;
941 abi_ulong b, *target_fds;
942
Laurent Vivierb1b2db22016-05-31 18:36:02 +0200943 nw = DIV_ROUND_UP(n, TARGET_ABI_BITS);
ths26edcf42007-12-09 02:25:24 +0000944 if (!(target_fds = lock_user(VERIFY_READ,
945 target_fds_addr,
946 sizeof(abi_ulong) * nw,
947 1)))
948 return -TARGET_EFAULT;
949
950 FD_ZERO(fds);
951 k = 0;
952 for (i = 0; i < nw; i++) {
953 /* grab the abi_ulong */
954 __get_user(b, &target_fds[i]);
955 for (j = 0; j < TARGET_ABI_BITS; j++) {
956 /* check the bit inside the abi_ulong */
957 if ((b >> j) & 1)
958 FD_SET(k, fds);
959 k++;
bellard31e31b82003-02-18 22:55:36 +0000960 }
bellard31e31b82003-02-18 22:55:36 +0000961 }
ths26edcf42007-12-09 02:25:24 +0000962
963 unlock_user(target_fds, target_fds_addr, 0);
964
965 return 0;
bellard31e31b82003-02-18 22:55:36 +0000966}
967
Mike Frysinger055e0902011-06-03 17:01:49 -0400968static inline abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr,
969 abi_ulong target_fds_addr,
970 int n)
971{
972 if (target_fds_addr) {
973 if (copy_from_user_fdset(fds, target_fds_addr, n))
974 return -TARGET_EFAULT;
975 *fds_ptr = fds;
976 } else {
977 *fds_ptr = NULL;
978 }
979 return 0;
980}
981
ths26edcf42007-12-09 02:25:24 +0000982static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
983 const fd_set *fds,
984 int n)
bellard31e31b82003-02-18 22:55:36 +0000985{
bellard31e31b82003-02-18 22:55:36 +0000986 int i, nw, j, k;
blueswir1992f48a2007-10-14 16:27:31 +0000987 abi_long v;
ths26edcf42007-12-09 02:25:24 +0000988 abi_ulong *target_fds;
bellard31e31b82003-02-18 22:55:36 +0000989
Laurent Vivierb1b2db22016-05-31 18:36:02 +0200990 nw = DIV_ROUND_UP(n, TARGET_ABI_BITS);
ths26edcf42007-12-09 02:25:24 +0000991 if (!(target_fds = lock_user(VERIFY_WRITE,
992 target_fds_addr,
993 sizeof(abi_ulong) * nw,
994 0)))
995 return -TARGET_EFAULT;
996
997 k = 0;
998 for (i = 0; i < nw; i++) {
999 v = 0;
1000 for (j = 0; j < TARGET_ABI_BITS; j++) {
Andreas Schwab9ab709b2013-04-09 01:02:34 +00001001 v |= ((abi_ulong)(FD_ISSET(k, fds) != 0) << j);
ths26edcf42007-12-09 02:25:24 +00001002 k++;
bellard31e31b82003-02-18 22:55:36 +00001003 }
ths26edcf42007-12-09 02:25:24 +00001004 __put_user(v, &target_fds[i]);
bellard31e31b82003-02-18 22:55:36 +00001005 }
ths26edcf42007-12-09 02:25:24 +00001006
1007 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
1008
1009 return 0;
bellard31e31b82003-02-18 22:55:36 +00001010}
1011
bellardc596ed12003-07-13 17:32:31 +00001012#if defined(__alpha__)
1013#define HOST_HZ 1024
1014#else
1015#define HOST_HZ 100
1016#endif
1017
blueswir1992f48a2007-10-14 16:27:31 +00001018static inline abi_long host_to_target_clock_t(long ticks)
bellardc596ed12003-07-13 17:32:31 +00001019{
1020#if HOST_HZ == TARGET_HZ
1021 return ticks;
1022#else
1023 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
1024#endif
1025}
1026
bellard579a97f2007-11-11 14:26:47 +00001027static inline abi_long host_to_target_rusage(abi_ulong target_addr,
1028 const struct rusage *rusage)
bellardb4091862003-05-16 15:39:34 +00001029{
pbrook53a59602006-03-25 19:31:22 +00001030 struct target_rusage *target_rusage;
1031
bellard579a97f2007-11-11 14:26:47 +00001032 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
1033 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001034 target_rusage->ru_utime.tv_sec = tswapal(rusage->ru_utime.tv_sec);
1035 target_rusage->ru_utime.tv_usec = tswapal(rusage->ru_utime.tv_usec);
1036 target_rusage->ru_stime.tv_sec = tswapal(rusage->ru_stime.tv_sec);
1037 target_rusage->ru_stime.tv_usec = tswapal(rusage->ru_stime.tv_usec);
1038 target_rusage->ru_maxrss = tswapal(rusage->ru_maxrss);
1039 target_rusage->ru_ixrss = tswapal(rusage->ru_ixrss);
1040 target_rusage->ru_idrss = tswapal(rusage->ru_idrss);
1041 target_rusage->ru_isrss = tswapal(rusage->ru_isrss);
1042 target_rusage->ru_minflt = tswapal(rusage->ru_minflt);
1043 target_rusage->ru_majflt = tswapal(rusage->ru_majflt);
1044 target_rusage->ru_nswap = tswapal(rusage->ru_nswap);
1045 target_rusage->ru_inblock = tswapal(rusage->ru_inblock);
1046 target_rusage->ru_oublock = tswapal(rusage->ru_oublock);
1047 target_rusage->ru_msgsnd = tswapal(rusage->ru_msgsnd);
1048 target_rusage->ru_msgrcv = tswapal(rusage->ru_msgrcv);
1049 target_rusage->ru_nsignals = tswapal(rusage->ru_nsignals);
1050 target_rusage->ru_nvcsw = tswapal(rusage->ru_nvcsw);
1051 target_rusage->ru_nivcsw = tswapal(rusage->ru_nivcsw);
pbrook53a59602006-03-25 19:31:22 +00001052 unlock_user_struct(target_rusage, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001053
1054 return 0;
bellardb4091862003-05-16 15:39:34 +00001055}
1056
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001057static inline rlim_t target_to_host_rlim(abi_ulong target_rlim)
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001058{
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001059 abi_ulong target_rlim_swap;
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001060 rlim_t result;
1061
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001062 target_rlim_swap = tswapal(target_rlim);
1063 if (target_rlim_swap == TARGET_RLIM_INFINITY)
1064 return RLIM_INFINITY;
1065
1066 result = target_rlim_swap;
1067 if (target_rlim_swap != (rlim_t)result)
1068 return RLIM_INFINITY;
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001069
1070 return result;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001071}
1072
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001073static inline abi_ulong host_to_target_rlim(rlim_t rlim)
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001074{
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001075 abi_ulong target_rlim_swap;
1076 abi_ulong result;
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001077
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001078 if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim)
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001079 target_rlim_swap = TARGET_RLIM_INFINITY;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001080 else
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001081 target_rlim_swap = rlim;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001082 result = tswapal(target_rlim_swap);
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001083
1084 return result;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001085}
1086
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03001087static inline int target_to_host_resource(int code)
1088{
1089 switch (code) {
1090 case TARGET_RLIMIT_AS:
1091 return RLIMIT_AS;
1092 case TARGET_RLIMIT_CORE:
1093 return RLIMIT_CORE;
1094 case TARGET_RLIMIT_CPU:
1095 return RLIMIT_CPU;
1096 case TARGET_RLIMIT_DATA:
1097 return RLIMIT_DATA;
1098 case TARGET_RLIMIT_FSIZE:
1099 return RLIMIT_FSIZE;
1100 case TARGET_RLIMIT_LOCKS:
1101 return RLIMIT_LOCKS;
1102 case TARGET_RLIMIT_MEMLOCK:
1103 return RLIMIT_MEMLOCK;
1104 case TARGET_RLIMIT_MSGQUEUE:
1105 return RLIMIT_MSGQUEUE;
1106 case TARGET_RLIMIT_NICE:
1107 return RLIMIT_NICE;
1108 case TARGET_RLIMIT_NOFILE:
1109 return RLIMIT_NOFILE;
1110 case TARGET_RLIMIT_NPROC:
1111 return RLIMIT_NPROC;
1112 case TARGET_RLIMIT_RSS:
1113 return RLIMIT_RSS;
1114 case TARGET_RLIMIT_RTPRIO:
1115 return RLIMIT_RTPRIO;
1116 case TARGET_RLIMIT_SIGPENDING:
1117 return RLIMIT_SIGPENDING;
1118 case TARGET_RLIMIT_STACK:
1119 return RLIMIT_STACK;
1120 default:
1121 return code;
1122 }
1123}
1124
ths788f5ec2007-12-09 02:37:05 +00001125static inline abi_long copy_from_user_timeval(struct timeval *tv,
1126 abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +00001127{
pbrook53a59602006-03-25 19:31:22 +00001128 struct target_timeval *target_tv;
1129
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001130 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) {
bellard579a97f2007-11-11 14:26:47 +00001131 return -TARGET_EFAULT;
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001132 }
ths788f5ec2007-12-09 02:37:05 +00001133
1134 __get_user(tv->tv_sec, &target_tv->tv_sec);
1135 __get_user(tv->tv_usec, &target_tv->tv_usec);
1136
1137 unlock_user_struct(target_tv, target_tv_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001138
1139 return 0;
bellard31e31b82003-02-18 22:55:36 +00001140}
1141
ths788f5ec2007-12-09 02:37:05 +00001142static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
1143 const struct timeval *tv)
bellard31e31b82003-02-18 22:55:36 +00001144{
pbrook53a59602006-03-25 19:31:22 +00001145 struct target_timeval *target_tv;
1146
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001147 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
bellard579a97f2007-11-11 14:26:47 +00001148 return -TARGET_EFAULT;
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001149 }
ths788f5ec2007-12-09 02:37:05 +00001150
1151 __put_user(tv->tv_sec, &target_tv->tv_sec);
1152 __put_user(tv->tv_usec, &target_tv->tv_usec);
1153
1154 unlock_user_struct(target_tv, target_tv_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001155
1156 return 0;
bellard31e31b82003-02-18 22:55:36 +00001157}
1158
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001159static inline abi_long copy_to_user_timeval64(abi_ulong target_tv_addr,
1160 const struct timeval *tv)
1161{
1162 struct target__kernel_sock_timeval *target_tv;
1163
1164 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
1165 return -TARGET_EFAULT;
1166 }
1167
1168 __put_user(tv->tv_sec, &target_tv->tv_sec);
1169 __put_user(tv->tv_usec, &target_tv->tv_usec);
1170
1171 unlock_user_struct(target_tv, target_tv_addr, 1);
1172
1173 return 0;
1174}
1175
1176static inline abi_long target_to_host_timespec(struct timespec *host_ts,
1177 abi_ulong target_addr)
1178{
1179 struct target_timespec *target_ts;
1180
1181 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) {
1182 return -TARGET_EFAULT;
1183 }
1184 __get_user(host_ts->tv_sec, &target_ts->tv_sec);
1185 __get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1186 unlock_user_struct(target_ts, target_addr, 0);
1187 return 0;
1188}
1189
1190static inline abi_long host_to_target_timespec(abi_ulong target_addr,
1191 struct timespec *host_ts)
1192{
1193 struct target_timespec *target_ts;
1194
1195 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) {
1196 return -TARGET_EFAULT;
1197 }
1198 __put_user(host_ts->tv_sec, &target_ts->tv_sec);
1199 __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1200 unlock_user_struct(target_ts, target_addr, 1);
1201 return 0;
1202}
1203
1204static inline abi_long host_to_target_timespec64(abi_ulong target_addr,
1205 struct timespec *host_ts)
1206{
1207 struct target__kernel_timespec *target_ts;
1208
1209 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) {
1210 return -TARGET_EFAULT;
1211 }
1212 __put_user(host_ts->tv_sec, &target_ts->tv_sec);
1213 __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1214 unlock_user_struct(target_ts, target_addr, 1);
1215 return 0;
1216}
1217
Paul Burtonef4467e2014-06-22 11:25:40 +01001218static inline abi_long copy_from_user_timezone(struct timezone *tz,
1219 abi_ulong target_tz_addr)
1220{
1221 struct target_timezone *target_tz;
1222
1223 if (!lock_user_struct(VERIFY_READ, target_tz, target_tz_addr, 1)) {
1224 return -TARGET_EFAULT;
1225 }
1226
1227 __get_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
1228 __get_user(tz->tz_dsttime, &target_tz->tz_dsttime);
1229
1230 unlock_user_struct(target_tz, target_tz_addr, 0);
1231
1232 return 0;
1233}
1234
Nathan Froyd8ec9cf82009-07-22 09:14:36 -07001235#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
1236#include <mqueue.h>
1237
aurel3224e10032009-04-15 16:11:43 +00001238static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr,
1239 abi_ulong target_mq_attr_addr)
1240{
1241 struct target_mq_attr *target_mq_attr;
1242
1243 if (!lock_user_struct(VERIFY_READ, target_mq_attr,
1244 target_mq_attr_addr, 1))
1245 return -TARGET_EFAULT;
1246
1247 __get_user(attr->mq_flags, &target_mq_attr->mq_flags);
1248 __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
1249 __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
1250 __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
1251
1252 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0);
1253
1254 return 0;
1255}
1256
1257static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
1258 const struct mq_attr *attr)
1259{
1260 struct target_mq_attr *target_mq_attr;
1261
1262 if (!lock_user_struct(VERIFY_WRITE, target_mq_attr,
1263 target_mq_attr_addr, 0))
1264 return -TARGET_EFAULT;
1265
1266 __put_user(attr->mq_flags, &target_mq_attr->mq_flags);
1267 __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
1268 __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
1269 __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
1270
1271 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1);
1272
1273 return 0;
1274}
Nathan Froyd8ec9cf82009-07-22 09:14:36 -07001275#endif
bellard31e31b82003-02-18 22:55:36 +00001276
Mike Frysinger055e0902011-06-03 17:01:49 -04001277#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect)
ths0da46a62007-10-20 20:23:07 +00001278/* do_select() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001279static abi_long do_select(int n,
ths26edcf42007-12-09 02:25:24 +00001280 abi_ulong rfd_addr, abi_ulong wfd_addr,
1281 abi_ulong efd_addr, abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +00001282{
1283 fd_set rfds, wfds, efds;
1284 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
Peter Maydell6df9d382016-05-12 18:47:51 +01001285 struct timeval tv;
1286 struct timespec ts, *ts_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00001287 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00001288
Mike Frysinger055e0902011-06-03 17:01:49 -04001289 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
1290 if (ret) {
1291 return ret;
pbrook53a59602006-03-25 19:31:22 +00001292 }
Mike Frysinger055e0902011-06-03 17:01:49 -04001293 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
1294 if (ret) {
1295 return ret;
pbrook53a59602006-03-25 19:31:22 +00001296 }
Mike Frysinger055e0902011-06-03 17:01:49 -04001297 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
1298 if (ret) {
1299 return ret;
pbrook53a59602006-03-25 19:31:22 +00001300 }
ths3b46e622007-09-17 08:09:54 +00001301
ths26edcf42007-12-09 02:25:24 +00001302 if (target_tv_addr) {
ths788f5ec2007-12-09 02:37:05 +00001303 if (copy_from_user_timeval(&tv, target_tv_addr))
1304 return -TARGET_EFAULT;
Peter Maydell6df9d382016-05-12 18:47:51 +01001305 ts.tv_sec = tv.tv_sec;
1306 ts.tv_nsec = tv.tv_usec * 1000;
1307 ts_ptr = &ts;
bellard31e31b82003-02-18 22:55:36 +00001308 } else {
Peter Maydell6df9d382016-05-12 18:47:51 +01001309 ts_ptr = NULL;
bellard31e31b82003-02-18 22:55:36 +00001310 }
ths26edcf42007-12-09 02:25:24 +00001311
Peter Maydell6df9d382016-05-12 18:47:51 +01001312 ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
1313 ts_ptr, NULL));
pbrook53a59602006-03-25 19:31:22 +00001314
ths26edcf42007-12-09 02:25:24 +00001315 if (!is_error(ret)) {
1316 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
1317 return -TARGET_EFAULT;
1318 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
1319 return -TARGET_EFAULT;
1320 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
1321 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00001322
Peter Maydell6df9d382016-05-12 18:47:51 +01001323 if (target_tv_addr) {
1324 tv.tv_sec = ts.tv_sec;
1325 tv.tv_usec = ts.tv_nsec / 1000;
1326 if (copy_to_user_timeval(target_tv_addr, &tv)) {
1327 return -TARGET_EFAULT;
1328 }
1329 }
bellard31e31b82003-02-18 22:55:36 +00001330 }
bellard579a97f2007-11-11 14:26:47 +00001331
bellard31e31b82003-02-18 22:55:36 +00001332 return ret;
1333}
Laurent Vivier5457dc92016-07-08 01:17:27 +02001334
1335#if defined(TARGET_WANT_OLD_SYS_SELECT)
1336static abi_long do_old_select(abi_ulong arg1)
1337{
1338 struct target_sel_arg_struct *sel;
1339 abi_ulong inp, outp, exp, tvp;
1340 long nsel;
1341
1342 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1)) {
1343 return -TARGET_EFAULT;
1344 }
1345
1346 nsel = tswapal(sel->n);
1347 inp = tswapal(sel->inp);
1348 outp = tswapal(sel->outp);
1349 exp = tswapal(sel->exp);
1350 tvp = tswapal(sel->tvp);
1351
1352 unlock_user_struct(sel, arg1, 0);
1353
1354 return do_select(nsel, inp, outp, exp, tvp);
1355}
1356#endif
Mike Frysinger055e0902011-06-03 17:01:49 -04001357#endif
bellard31e31b82003-02-18 22:55:36 +00001358
Riku Voipio099d6b02009-05-05 12:10:04 +03001359static abi_long do_pipe2(int host_pipe[], int flags)
1360{
1361#ifdef CONFIG_PIPE2
1362 return pipe2(host_pipe, flags);
1363#else
1364 return -ENOSYS;
1365#endif
1366}
1367
Richard Hendersonfb41a662010-05-03 10:07:52 -07001368static abi_long do_pipe(void *cpu_env, abi_ulong pipedes,
1369 int flags, int is_pipe2)
Riku Voipio099d6b02009-05-05 12:10:04 +03001370{
1371 int host_pipe[2];
1372 abi_long ret;
1373 ret = flags ? do_pipe2(host_pipe, flags) : pipe(host_pipe);
1374
1375 if (is_error(ret))
1376 return get_errno(ret);
Richard Hendersonfb41a662010-05-03 10:07:52 -07001377
1378 /* Several targets have special calling conventions for the original
1379 pipe syscall, but didn't replicate this into the pipe2 syscall. */
1380 if (!is_pipe2) {
1381#if defined(TARGET_ALPHA)
1382 ((CPUAlphaState *)cpu_env)->ir[IR_A4] = host_pipe[1];
1383 return host_pipe[0];
1384#elif defined(TARGET_MIPS)
1385 ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1];
1386 return host_pipe[0];
1387#elif defined(TARGET_SH4)
takasi-y@ops.dti.ne.jp597c0212010-02-18 00:35:03 +09001388 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
Richard Hendersonfb41a662010-05-03 10:07:52 -07001389 return host_pipe[0];
Peter Maydell82f05b62013-07-06 17:39:48 +01001390#elif defined(TARGET_SPARC)
1391 ((CPUSPARCState*)cpu_env)->regwptr[1] = host_pipe[1];
1392 return host_pipe[0];
takasi-y@ops.dti.ne.jp597c0212010-02-18 00:35:03 +09001393#endif
Richard Hendersonfb41a662010-05-03 10:07:52 -07001394 }
1395
Riku Voipio099d6b02009-05-05 12:10:04 +03001396 if (put_user_s32(host_pipe[0], pipedes)
1397 || put_user_s32(host_pipe[1], pipedes + sizeof(host_pipe[0])))
1398 return -TARGET_EFAULT;
Riku Voipio099d6b02009-05-05 12:10:04 +03001399 return get_errno(ret);
1400}
1401
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001402static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
1403 abi_ulong target_addr,
1404 socklen_t len)
1405{
1406 struct target_ip_mreqn *target_smreqn;
1407
1408 target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
1409 if (!target_smreqn)
1410 return -TARGET_EFAULT;
1411 mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
1412 mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
1413 if (len == sizeof(struct target_ip_mreqn))
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001414 mreqn->imr_ifindex = tswapal(target_smreqn->imr_ifindex);
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001415 unlock_user(target_smreqn, target_addr, 0);
1416
1417 return 0;
1418}
1419
Laurent Vivier7b36f782015-10-28 21:40:44 +01001420static inline abi_long target_to_host_sockaddr(int fd, struct sockaddr *addr,
bellard579a97f2007-11-11 14:26:47 +00001421 abi_ulong target_addr,
1422 socklen_t len)
bellard7854b052003-03-29 17:22:23 +00001423{
aurel32607175e2009-04-15 16:11:59 +00001424 const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
1425 sa_family_t sa_family;
pbrook53a59602006-03-25 19:31:22 +00001426 struct target_sockaddr *target_saddr;
1427
Laurent Vivier7b36f782015-10-28 21:40:44 +01001428 if (fd_trans_target_to_host_addr(fd)) {
1429 return fd_trans_target_to_host_addr(fd)(addr, target_addr, len);
1430 }
1431
bellard579a97f2007-11-11 14:26:47 +00001432 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
1433 if (!target_saddr)
1434 return -TARGET_EFAULT;
aurel32607175e2009-04-15 16:11:59 +00001435
1436 sa_family = tswap16(target_saddr->sa_family);
1437
1438 /* Oops. The caller might send a incomplete sun_path; sun_path
1439 * must be terminated by \0 (see the manual page), but
1440 * unfortunately it is quite common to specify sockaddr_un
1441 * length as "strlen(x->sun_path)" while it should be
1442 * "strlen(...) + 1". We'll fix that here if needed.
1443 * Linux kernel has a similar feature.
1444 */
1445
1446 if (sa_family == AF_UNIX) {
1447 if (len < unix_maxlen && len > 0) {
1448 char *cp = (char*)target_saddr;
1449
1450 if ( cp[len-1] && !cp[len] )
1451 len++;
1452 }
1453 if (len > unix_maxlen)
1454 len = unix_maxlen;
1455 }
1456
pbrook53a59602006-03-25 19:31:22 +00001457 memcpy(addr, target_saddr, len);
aurel32607175e2009-04-15 16:11:59 +00001458 addr->sa_family = sa_family;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02001459 if (sa_family == AF_NETLINK) {
1460 struct sockaddr_nl *nladdr;
1461
1462 nladdr = (struct sockaddr_nl *)addr;
1463 nladdr->nl_pid = tswap32(nladdr->nl_pid);
1464 nladdr->nl_groups = tswap32(nladdr->nl_groups);
1465 } else if (sa_family == AF_PACKET) {
Joakim Tjernlund33a29b52014-07-12 15:47:07 +02001466 struct target_sockaddr_ll *lladdr;
1467
1468 lladdr = (struct target_sockaddr_ll *)addr;
1469 lladdr->sll_ifindex = tswap32(lladdr->sll_ifindex);
1470 lladdr->sll_hatype = tswap16(lladdr->sll_hatype);
1471 }
pbrook53a59602006-03-25 19:31:22 +00001472 unlock_user(target_saddr, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001473
1474 return 0;
bellard7854b052003-03-29 17:22:23 +00001475}
1476
bellard579a97f2007-11-11 14:26:47 +00001477static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
1478 struct sockaddr *addr,
1479 socklen_t len)
bellard7854b052003-03-29 17:22:23 +00001480{
pbrook53a59602006-03-25 19:31:22 +00001481 struct target_sockaddr *target_saddr;
1482
Peter Maydella1e22192016-07-07 15:44:43 +01001483 if (len == 0) {
1484 return 0;
1485 }
Philippe Mathieu-Daudé68607102017-07-26 23:42:18 -03001486 assert(addr);
Peter Maydella1e22192016-07-07 15:44:43 +01001487
bellard579a97f2007-11-11 14:26:47 +00001488 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
1489 if (!target_saddr)
1490 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001491 memcpy(target_saddr, addr, len);
Peter Maydella1e22192016-07-07 15:44:43 +01001492 if (len >= offsetof(struct target_sockaddr, sa_family) +
1493 sizeof(target_saddr->sa_family)) {
1494 target_saddr->sa_family = tswap16(addr->sa_family);
1495 }
1496 if (addr->sa_family == AF_NETLINK && len >= sizeof(struct sockaddr_nl)) {
Laurent Vivier6c5b5642016-05-22 18:56:19 +02001497 struct sockaddr_nl *target_nl = (struct sockaddr_nl *)target_saddr;
1498 target_nl->nl_pid = tswap32(target_nl->nl_pid);
1499 target_nl->nl_groups = tswap32(target_nl->nl_groups);
Laurent Viviera82ea932016-06-27 00:18:22 +02001500 } else if (addr->sa_family == AF_PACKET) {
1501 struct sockaddr_ll *target_ll = (struct sockaddr_ll *)target_saddr;
1502 target_ll->sll_ifindex = tswap32(target_ll->sll_ifindex);
1503 target_ll->sll_hatype = tswap16(target_ll->sll_hatype);
Helge Delleree1ac3a2017-02-18 23:31:30 +01001504 } else if (addr->sa_family == AF_INET6 &&
1505 len >= sizeof(struct target_sockaddr_in6)) {
1506 struct target_sockaddr_in6 *target_in6 =
1507 (struct target_sockaddr_in6 *)target_saddr;
1508 target_in6->sin6_scope_id = tswap16(target_in6->sin6_scope_id);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02001509 }
pbrook53a59602006-03-25 19:31:22 +00001510 unlock_user(target_saddr, target_addr, len);
bellard579a97f2007-11-11 14:26:47 +00001511
1512 return 0;
bellard7854b052003-03-29 17:22:23 +00001513}
1514
bellard5a4a8982007-11-11 17:39:18 +00001515static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
1516 struct target_msghdr *target_msgh)
bellard7854b052003-03-29 17:22:23 +00001517{
1518 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001519 abi_long msg_controllen;
1520 abi_ulong target_cmsg_addr;
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001521 struct target_cmsghdr *target_cmsg, *target_cmsg_start;
bellard7854b052003-03-29 17:22:23 +00001522 socklen_t space = 0;
bellard5a4a8982007-11-11 17:39:18 +00001523
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001524 msg_controllen = tswapal(target_msgh->msg_controllen);
bellard5a4a8982007-11-11 17:39:18 +00001525 if (msg_controllen < sizeof (struct target_cmsghdr))
1526 goto the_end;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001527 target_cmsg_addr = tswapal(target_msgh->msg_control);
bellard5a4a8982007-11-11 17:39:18 +00001528 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001529 target_cmsg_start = target_cmsg;
bellard5a4a8982007-11-11 17:39:18 +00001530 if (!target_cmsg)
1531 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001532
1533 while (cmsg && target_cmsg) {
1534 void *data = CMSG_DATA(cmsg);
1535 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1536
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001537 int len = tswapal(target_cmsg->cmsg_len)
Peter Maydellad762b92017-12-15 13:52:56 +00001538 - sizeof(struct target_cmsghdr);
bellard7854b052003-03-29 17:22:23 +00001539
1540 space += CMSG_SPACE(len);
1541 if (space > msgh->msg_controllen) {
1542 space -= CMSG_SPACE(len);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001543 /* This is a QEMU bug, since we allocated the payload
1544 * area ourselves (unlike overflow in host-to-target
1545 * conversion, which is just the guest giving us a buffer
1546 * that's too small). It can't happen for the payload types
1547 * we currently support; if it becomes an issue in future
1548 * we would need to improve our allocation strategy to
1549 * something more intelligent than "twice the size of the
1550 * target buffer we're reading from".
1551 */
bellard31febb72005-12-18 20:03:27 +00001552 gemu_log("Host cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +00001553 break;
1554 }
1555
Petar Jovanovicdbf4f792013-09-13 19:27:29 +02001556 if (tswap32(target_cmsg->cmsg_level) == TARGET_SOL_SOCKET) {
1557 cmsg->cmsg_level = SOL_SOCKET;
1558 } else {
1559 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
1560 }
bellard7854b052003-03-29 17:22:23 +00001561 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
1562 cmsg->cmsg_len = CMSG_LEN(len);
1563
Alex Suykov30b8b682014-12-23 07:52:58 +02001564 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +00001565 int *fd = (int *)data;
1566 int *target_fd = (int *)target_data;
1567 int i, numfds = len / sizeof(int);
1568
Peter Maydell876e23c2015-05-26 19:46:32 +01001569 for (i = 0; i < numfds; i++) {
1570 __get_user(fd[i], target_fd + i);
1571 }
Alex Suykov30b8b682014-12-23 07:52:58 +02001572 } else if (cmsg->cmsg_level == SOL_SOCKET
1573 && cmsg->cmsg_type == SCM_CREDENTIALS) {
1574 struct ucred *cred = (struct ucred *)data;
1575 struct target_ucred *target_cred =
1576 (struct target_ucred *)target_data;
1577
Peter Maydell876e23c2015-05-26 19:46:32 +01001578 __get_user(cred->pid, &target_cred->pid);
1579 __get_user(cred->uid, &target_cred->uid);
1580 __get_user(cred->gid, &target_cred->gid);
Alex Suykov30b8b682014-12-23 07:52:58 +02001581 } else {
1582 gemu_log("Unsupported ancillary data: %d/%d\n",
1583 cmsg->cmsg_level, cmsg->cmsg_type);
1584 memcpy(data, target_data, len);
bellard7854b052003-03-29 17:22:23 +00001585 }
1586
1587 cmsg = CMSG_NXTHDR(msgh, cmsg);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001588 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg,
1589 target_cmsg_start);
bellard7854b052003-03-29 17:22:23 +00001590 }
bellard5a4a8982007-11-11 17:39:18 +00001591 unlock_user(target_cmsg, target_cmsg_addr, 0);
1592 the_end:
bellard7854b052003-03-29 17:22:23 +00001593 msgh->msg_controllen = space;
bellard5a4a8982007-11-11 17:39:18 +00001594 return 0;
bellard7854b052003-03-29 17:22:23 +00001595}
1596
bellard5a4a8982007-11-11 17:39:18 +00001597static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
1598 struct msghdr *msgh)
bellard7854b052003-03-29 17:22:23 +00001599{
1600 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001601 abi_long msg_controllen;
1602 abi_ulong target_cmsg_addr;
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001603 struct target_cmsghdr *target_cmsg, *target_cmsg_start;
bellard7854b052003-03-29 17:22:23 +00001604 socklen_t space = 0;
1605
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001606 msg_controllen = tswapal(target_msgh->msg_controllen);
bellard5a4a8982007-11-11 17:39:18 +00001607 if (msg_controllen < sizeof (struct target_cmsghdr))
1608 goto the_end;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001609 target_cmsg_addr = tswapal(target_msgh->msg_control);
bellard5a4a8982007-11-11 17:39:18 +00001610 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001611 target_cmsg_start = target_cmsg;
bellard5a4a8982007-11-11 17:39:18 +00001612 if (!target_cmsg)
1613 return -TARGET_EFAULT;
1614
bellard7854b052003-03-29 17:22:23 +00001615 while (cmsg && target_cmsg) {
1616 void *data = CMSG_DATA(cmsg);
1617 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1618
Peter Maydellad762b92017-12-15 13:52:56 +00001619 int len = cmsg->cmsg_len - sizeof(struct cmsghdr);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001620 int tgt_len, tgt_space;
bellard7854b052003-03-29 17:22:23 +00001621
Peter Maydellc2aeb252015-05-26 19:46:31 +01001622 /* We never copy a half-header but may copy half-data;
1623 * this is Linux's behaviour in put_cmsg(). Note that
1624 * truncation here is a guest problem (which we report
1625 * to the guest via the CTRUNC bit), unlike truncation
1626 * in target_to_host_cmsg, which is a QEMU bug.
1627 */
Peter Maydell71749702017-12-15 13:52:55 +00001628 if (msg_controllen < sizeof(struct target_cmsghdr)) {
Peter Maydellc2aeb252015-05-26 19:46:31 +01001629 target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
bellard7854b052003-03-29 17:22:23 +00001630 break;
1631 }
1632
Petar Jovanovicdbf4f792013-09-13 19:27:29 +02001633 if (cmsg->cmsg_level == SOL_SOCKET) {
1634 target_cmsg->cmsg_level = tswap32(TARGET_SOL_SOCKET);
1635 } else {
1636 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
1637 }
bellard7854b052003-03-29 17:22:23 +00001638 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
bellard7854b052003-03-29 17:22:23 +00001639
Peter Maydellc2aeb252015-05-26 19:46:31 +01001640 /* Payload types which need a different size of payload on
1641 * the target must adjust tgt_len here.
1642 */
Peter Maydell309786c2018-05-18 19:47:15 +01001643 tgt_len = len;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001644 switch (cmsg->cmsg_level) {
1645 case SOL_SOCKET:
1646 switch (cmsg->cmsg_type) {
1647 case SO_TIMESTAMP:
1648 tgt_len = sizeof(struct target_timeval);
1649 break;
1650 default:
1651 break;
1652 }
Peter Maydell309786c2018-05-18 19:47:15 +01001653 break;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001654 default:
1655 break;
1656 }
1657
Peter Maydell71749702017-12-15 13:52:55 +00001658 if (msg_controllen < TARGET_CMSG_LEN(tgt_len)) {
Peter Maydellc2aeb252015-05-26 19:46:31 +01001659 target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
Peter Maydell71749702017-12-15 13:52:55 +00001660 tgt_len = msg_controllen - sizeof(struct target_cmsghdr);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001661 }
1662
1663 /* We must now copy-and-convert len bytes of payload
1664 * into tgt_len bytes of destination space. Bear in mind
1665 * that in both source and destination we may be dealing
1666 * with a truncated value!
1667 */
Huw Davies52b65492014-04-17 14:02:47 +01001668 switch (cmsg->cmsg_level) {
1669 case SOL_SOCKET:
1670 switch (cmsg->cmsg_type) {
1671 case SCM_RIGHTS:
1672 {
1673 int *fd = (int *)data;
1674 int *target_fd = (int *)target_data;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001675 int i, numfds = tgt_len / sizeof(int);
bellard7854b052003-03-29 17:22:23 +00001676
Peter Maydell876e23c2015-05-26 19:46:32 +01001677 for (i = 0; i < numfds; i++) {
1678 __put_user(fd[i], target_fd + i);
1679 }
Huw Davies52b65492014-04-17 14:02:47 +01001680 break;
1681 }
1682 case SO_TIMESTAMP:
1683 {
1684 struct timeval *tv = (struct timeval *)data;
1685 struct target_timeval *target_tv =
1686 (struct target_timeval *)target_data;
Jing Huangaebf5bc2012-07-24 14:01:42 +00001687
Peter Maydellc2aeb252015-05-26 19:46:31 +01001688 if (len != sizeof(struct timeval) ||
1689 tgt_len != sizeof(struct target_timeval)) {
Huw Davies52b65492014-04-17 14:02:47 +01001690 goto unimplemented;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001691 }
Huw Davies52b65492014-04-17 14:02:47 +01001692
1693 /* copy struct timeval to target */
Peter Maydell876e23c2015-05-26 19:46:32 +01001694 __put_user(tv->tv_sec, &target_tv->tv_sec);
1695 __put_user(tv->tv_usec, &target_tv->tv_usec);
Huw Davies52b65492014-04-17 14:02:47 +01001696 break;
1697 }
Huw Davies4bc29752014-04-17 14:02:48 +01001698 case SCM_CREDENTIALS:
1699 {
1700 struct ucred *cred = (struct ucred *)data;
1701 struct target_ucred *target_cred =
1702 (struct target_ucred *)target_data;
1703
1704 __put_user(cred->pid, &target_cred->pid);
1705 __put_user(cred->uid, &target_cred->uid);
1706 __put_user(cred->gid, &target_cred->gid);
1707 break;
1708 }
Huw Davies52b65492014-04-17 14:02:47 +01001709 default:
1710 goto unimplemented;
1711 }
1712 break;
1713
Helge Delleree1ac3a2017-02-18 23:31:30 +01001714 case SOL_IP:
1715 switch (cmsg->cmsg_type) {
1716 case IP_TTL:
1717 {
1718 uint32_t *v = (uint32_t *)data;
1719 uint32_t *t_int = (uint32_t *)target_data;
1720
Peter Maydell71749702017-12-15 13:52:55 +00001721 if (len != sizeof(uint32_t) ||
1722 tgt_len != sizeof(uint32_t)) {
1723 goto unimplemented;
1724 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01001725 __put_user(*v, t_int);
1726 break;
1727 }
1728 case IP_RECVERR:
1729 {
1730 struct errhdr_t {
1731 struct sock_extended_err ee;
1732 struct sockaddr_in offender;
1733 };
1734 struct errhdr_t *errh = (struct errhdr_t *)data;
1735 struct errhdr_t *target_errh =
1736 (struct errhdr_t *)target_data;
1737
Peter Maydell71749702017-12-15 13:52:55 +00001738 if (len != sizeof(struct errhdr_t) ||
1739 tgt_len != sizeof(struct errhdr_t)) {
1740 goto unimplemented;
1741 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01001742 __put_user(errh->ee.ee_errno, &target_errh->ee.ee_errno);
1743 __put_user(errh->ee.ee_origin, &target_errh->ee.ee_origin);
1744 __put_user(errh->ee.ee_type, &target_errh->ee.ee_type);
1745 __put_user(errh->ee.ee_code, &target_errh->ee.ee_code);
1746 __put_user(errh->ee.ee_pad, &target_errh->ee.ee_pad);
1747 __put_user(errh->ee.ee_info, &target_errh->ee.ee_info);
1748 __put_user(errh->ee.ee_data, &target_errh->ee.ee_data);
1749 host_to_target_sockaddr((unsigned long) &target_errh->offender,
1750 (void *) &errh->offender, sizeof(errh->offender));
1751 break;
1752 }
1753 default:
1754 goto unimplemented;
1755 }
1756 break;
1757
1758 case SOL_IPV6:
1759 switch (cmsg->cmsg_type) {
1760 case IPV6_HOPLIMIT:
1761 {
1762 uint32_t *v = (uint32_t *)data;
1763 uint32_t *t_int = (uint32_t *)target_data;
1764
Peter Maydell71749702017-12-15 13:52:55 +00001765 if (len != sizeof(uint32_t) ||
1766 tgt_len != sizeof(uint32_t)) {
1767 goto unimplemented;
1768 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01001769 __put_user(*v, t_int);
1770 break;
1771 }
1772 case IPV6_RECVERR:
1773 {
1774 struct errhdr6_t {
1775 struct sock_extended_err ee;
1776 struct sockaddr_in6 offender;
1777 };
1778 struct errhdr6_t *errh = (struct errhdr6_t *)data;
1779 struct errhdr6_t *target_errh =
1780 (struct errhdr6_t *)target_data;
1781
Peter Maydell71749702017-12-15 13:52:55 +00001782 if (len != sizeof(struct errhdr6_t) ||
1783 tgt_len != sizeof(struct errhdr6_t)) {
1784 goto unimplemented;
1785 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01001786 __put_user(errh->ee.ee_errno, &target_errh->ee.ee_errno);
1787 __put_user(errh->ee.ee_origin, &target_errh->ee.ee_origin);
1788 __put_user(errh->ee.ee_type, &target_errh->ee.ee_type);
1789 __put_user(errh->ee.ee_code, &target_errh->ee.ee_code);
1790 __put_user(errh->ee.ee_pad, &target_errh->ee.ee_pad);
1791 __put_user(errh->ee.ee_info, &target_errh->ee.ee_info);
1792 __put_user(errh->ee.ee_data, &target_errh->ee.ee_data);
1793 host_to_target_sockaddr((unsigned long) &target_errh->offender,
1794 (void *) &errh->offender, sizeof(errh->offender));
1795 break;
1796 }
1797 default:
1798 goto unimplemented;
1799 }
1800 break;
1801
Huw Davies52b65492014-04-17 14:02:47 +01001802 default:
1803 unimplemented:
Jing Huangaebf5bc2012-07-24 14:01:42 +00001804 gemu_log("Unsupported ancillary data: %d/%d\n",
1805 cmsg->cmsg_level, cmsg->cmsg_type);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001806 memcpy(target_data, data, MIN(len, tgt_len));
1807 if (tgt_len > len) {
1808 memset(target_data + len, 0, tgt_len - len);
1809 }
bellard7854b052003-03-29 17:22:23 +00001810 }
1811
Peter Maydell71749702017-12-15 13:52:55 +00001812 target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(tgt_len));
1813 tgt_space = TARGET_CMSG_SPACE(tgt_len);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001814 if (msg_controllen < tgt_space) {
1815 tgt_space = msg_controllen;
1816 }
1817 msg_controllen -= tgt_space;
1818 space += tgt_space;
bellard7854b052003-03-29 17:22:23 +00001819 cmsg = CMSG_NXTHDR(msgh, cmsg);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001820 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg,
1821 target_cmsg_start);
bellard7854b052003-03-29 17:22:23 +00001822 }
bellard5a4a8982007-11-11 17:39:18 +00001823 unlock_user(target_cmsg, target_cmsg_addr, space);
1824 the_end:
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001825 target_msgh->msg_controllen = tswapal(space);
bellard5a4a8982007-11-11 17:39:18 +00001826 return 0;
bellard7854b052003-03-29 17:22:23 +00001827}
1828
ths0da46a62007-10-20 20:23:07 +00001829/* do_setsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001830static abi_long do_setsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00001831 abi_ulong optval_addr, socklen_t optlen)
bellard7854b052003-03-29 17:22:23 +00001832{
blueswir1992f48a2007-10-14 16:27:31 +00001833 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +00001834 int val;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001835 struct ip_mreqn *ip_mreq;
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02001836 struct ip_mreq_source *ip_mreq_source;
ths3b46e622007-09-17 08:09:54 +00001837
bellard8853f862004-02-22 14:57:26 +00001838 switch(level) {
1839 case SOL_TCP:
bellard7854b052003-03-29 17:22:23 +00001840 /* TCP options all take an 'int' value. */
bellard7854b052003-03-29 17:22:23 +00001841 if (optlen < sizeof(uint32_t))
ths0da46a62007-10-20 20:23:07 +00001842 return -TARGET_EINVAL;
ths3b46e622007-09-17 08:09:54 +00001843
bellard2f619692007-11-16 10:46:05 +00001844 if (get_user_u32(val, optval_addr))
1845 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001846 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1847 break;
1848 case SOL_IP:
1849 switch(optname) {
bellard2efbe912005-07-23 15:10:20 +00001850 case IP_TOS:
1851 case IP_TTL:
bellard8853f862004-02-22 14:57:26 +00001852 case IP_HDRINCL:
bellard2efbe912005-07-23 15:10:20 +00001853 case IP_ROUTER_ALERT:
1854 case IP_RECVOPTS:
1855 case IP_RETOPTS:
1856 case IP_PKTINFO:
1857 case IP_MTU_DISCOVER:
1858 case IP_RECVERR:
Helge Delleree1ac3a2017-02-18 23:31:30 +01001859 case IP_RECVTTL:
bellard2efbe912005-07-23 15:10:20 +00001860 case IP_RECVTOS:
1861#ifdef IP_FREEBIND
1862 case IP_FREEBIND:
1863#endif
1864 case IP_MULTICAST_TTL:
1865 case IP_MULTICAST_LOOP:
bellard8853f862004-02-22 14:57:26 +00001866 val = 0;
1867 if (optlen >= sizeof(uint32_t)) {
bellard2f619692007-11-16 10:46:05 +00001868 if (get_user_u32(val, optval_addr))
1869 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001870 } else if (optlen >= 1) {
bellard2f619692007-11-16 10:46:05 +00001871 if (get_user_u8(val, optval_addr))
1872 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001873 }
1874 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1875 break;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001876 case IP_ADD_MEMBERSHIP:
1877 case IP_DROP_MEMBERSHIP:
1878 if (optlen < sizeof (struct target_ip_mreq) ||
1879 optlen > sizeof (struct target_ip_mreqn))
1880 return -TARGET_EINVAL;
1881
1882 ip_mreq = (struct ip_mreqn *) alloca(optlen);
1883 target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
1884 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen));
1885 break;
1886
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02001887 case IP_BLOCK_SOURCE:
1888 case IP_UNBLOCK_SOURCE:
1889 case IP_ADD_SOURCE_MEMBERSHIP:
1890 case IP_DROP_SOURCE_MEMBERSHIP:
1891 if (optlen != sizeof (struct target_ip_mreq_source))
1892 return -TARGET_EINVAL;
1893
1894 ip_mreq_source = lock_user(VERIFY_READ, optval_addr, optlen, 1);
1895 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen));
1896 unlock_user (ip_mreq_source, optval_addr, 0);
1897 break;
1898
bellard8853f862004-02-22 14:57:26 +00001899 default:
1900 goto unimplemented;
1901 }
1902 break;
Laurent Vivier0d78b3b2013-08-30 01:46:43 +02001903 case SOL_IPV6:
1904 switch (optname) {
1905 case IPV6_MTU_DISCOVER:
1906 case IPV6_MTU:
1907 case IPV6_V6ONLY:
1908 case IPV6_RECVPKTINFO:
Helge Delleree1ac3a2017-02-18 23:31:30 +01001909 case IPV6_UNICAST_HOPS:
Laurent Vivier21749c42018-06-27 23:21:52 +02001910 case IPV6_MULTICAST_HOPS:
1911 case IPV6_MULTICAST_LOOP:
Helge Delleree1ac3a2017-02-18 23:31:30 +01001912 case IPV6_RECVERR:
1913 case IPV6_RECVHOPLIMIT:
1914 case IPV6_2292HOPLIMIT:
1915 case IPV6_CHECKSUM:
Helge Dellerb9cce6d2019-03-10 12:12:16 +01001916 case IPV6_ADDRFORM:
1917 case IPV6_2292PKTINFO:
1918 case IPV6_RECVTCLASS:
1919 case IPV6_RECVRTHDR:
1920 case IPV6_2292RTHDR:
1921 case IPV6_RECVHOPOPTS:
1922 case IPV6_2292HOPOPTS:
1923 case IPV6_RECVDSTOPTS:
1924 case IPV6_2292DSTOPTS:
1925 case IPV6_TCLASS:
1926#ifdef IPV6_RECVPATHMTU
1927 case IPV6_RECVPATHMTU:
1928#endif
1929#ifdef IPV6_TRANSPARENT
1930 case IPV6_TRANSPARENT:
1931#endif
1932#ifdef IPV6_FREEBIND
1933 case IPV6_FREEBIND:
1934#endif
1935#ifdef IPV6_RECVORIGDSTADDR
1936 case IPV6_RECVORIGDSTADDR:
1937#endif
Laurent Vivier0d78b3b2013-08-30 01:46:43 +02001938 val = 0;
1939 if (optlen < sizeof(uint32_t)) {
1940 return -TARGET_EINVAL;
1941 }
1942 if (get_user_u32(val, optval_addr)) {
1943 return -TARGET_EFAULT;
1944 }
1945 ret = get_errno(setsockopt(sockfd, level, optname,
1946 &val, sizeof(val)));
1947 break;
Helge Delleree1ac3a2017-02-18 23:31:30 +01001948 case IPV6_PKTINFO:
1949 {
1950 struct in6_pktinfo pki;
1951
1952 if (optlen < sizeof(pki)) {
1953 return -TARGET_EINVAL;
1954 }
1955
1956 if (copy_from_user(&pki, optval_addr, sizeof(pki))) {
1957 return -TARGET_EFAULT;
1958 }
1959
1960 pki.ipi6_ifindex = tswap32(pki.ipi6_ifindex);
1961
1962 ret = get_errno(setsockopt(sockfd, level, optname,
1963 &pki, sizeof(pki)));
1964 break;
1965 }
Neng Chen22bf4ee2019-06-19 16:17:10 +02001966 case IPV6_ADD_MEMBERSHIP:
1967 case IPV6_DROP_MEMBERSHIP:
1968 {
1969 struct ipv6_mreq ipv6mreq;
1970
1971 if (optlen < sizeof(ipv6mreq)) {
1972 return -TARGET_EINVAL;
1973 }
1974
1975 if (copy_from_user(&ipv6mreq, optval_addr, sizeof(ipv6mreq))) {
1976 return -TARGET_EFAULT;
1977 }
1978
1979 ipv6mreq.ipv6mr_interface = tswap32(ipv6mreq.ipv6mr_interface);
1980
1981 ret = get_errno(setsockopt(sockfd, level, optname,
1982 &ipv6mreq, sizeof(ipv6mreq)));
1983 break;
1984 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01001985 default:
1986 goto unimplemented;
1987 }
1988 break;
1989 case SOL_ICMPV6:
1990 switch (optname) {
1991 case ICMPV6_FILTER:
1992 {
1993 struct icmp6_filter icmp6f;
1994
1995 if (optlen > sizeof(icmp6f)) {
1996 optlen = sizeof(icmp6f);
1997 }
1998
1999 if (copy_from_user(&icmp6f, optval_addr, optlen)) {
2000 return -TARGET_EFAULT;
2001 }
2002
2003 for (val = 0; val < 8; val++) {
2004 icmp6f.data[val] = tswap32(icmp6f.data[val]);
2005 }
2006
2007 ret = get_errno(setsockopt(sockfd, level, optname,
2008 &icmp6f, optlen));
2009 break;
2010 }
Laurent Vivier0d78b3b2013-08-30 01:46:43 +02002011 default:
2012 goto unimplemented;
2013 }
2014 break;
Jing Huang920394d2012-07-24 13:59:23 +00002015 case SOL_RAW:
2016 switch (optname) {
2017 case ICMP_FILTER:
Helge Delleree1ac3a2017-02-18 23:31:30 +01002018 case IPV6_CHECKSUM:
2019 /* those take an u32 value */
Jing Huang920394d2012-07-24 13:59:23 +00002020 if (optlen < sizeof(uint32_t)) {
2021 return -TARGET_EINVAL;
2022 }
2023
2024 if (get_user_u32(val, optval_addr)) {
2025 return -TARGET_EFAULT;
2026 }
2027 ret = get_errno(setsockopt(sockfd, level, optname,
2028 &val, sizeof(val)));
2029 break;
2030
2031 default:
2032 goto unimplemented;
2033 }
2034 break;
Yunqiang Suf31dddd2019-06-19 16:17:11 +02002035#if defined(SOL_ALG) && defined(ALG_SET_KEY) && defined(ALG_SET_AEAD_AUTHSIZE)
2036 case SOL_ALG:
2037 switch (optname) {
2038 case ALG_SET_KEY:
2039 {
2040 char *alg_key = g_malloc(optlen);
2041
2042 if (!alg_key) {
2043 return -TARGET_ENOMEM;
2044 }
2045 if (copy_from_user(alg_key, optval_addr, optlen)) {
2046 g_free(alg_key);
2047 return -TARGET_EFAULT;
2048 }
2049 ret = get_errno(setsockopt(sockfd, level, optname,
2050 alg_key, optlen));
2051 g_free(alg_key);
2052 break;
2053 }
2054 case ALG_SET_AEAD_AUTHSIZE:
2055 {
2056 ret = get_errno(setsockopt(sockfd, level, optname,
2057 NULL, optlen));
2058 break;
2059 }
2060 default:
2061 goto unimplemented;
2062 }
2063 break;
2064#endif
bellard3532fa72006-06-24 15:06:03 +00002065 case TARGET_SOL_SOCKET:
bellard8853f862004-02-22 14:57:26 +00002066 switch (optname) {
Laurent Vivier1b09aeb2013-01-01 08:24:11 +00002067 case TARGET_SO_RCVTIMEO:
2068 {
2069 struct timeval tv;
2070
2071 optname = SO_RCVTIMEO;
2072
2073set_timeout:
2074 if (optlen != sizeof(struct target_timeval)) {
2075 return -TARGET_EINVAL;
2076 }
2077
2078 if (copy_from_user_timeval(&tv, optval_addr)) {
2079 return -TARGET_EFAULT;
2080 }
2081
2082 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
2083 &tv, sizeof(tv)));
2084 return ret;
2085 }
2086 case TARGET_SO_SNDTIMEO:
2087 optname = SO_SNDTIMEO;
2088 goto set_timeout;
Laurent Vivierf57d4192013-08-30 01:46:41 +02002089 case TARGET_SO_ATTACH_FILTER:
2090 {
2091 struct target_sock_fprog *tfprog;
2092 struct target_sock_filter *tfilter;
2093 struct sock_fprog fprog;
2094 struct sock_filter *filter;
2095 int i;
2096
2097 if (optlen != sizeof(*tfprog)) {
2098 return -TARGET_EINVAL;
2099 }
2100 if (!lock_user_struct(VERIFY_READ, tfprog, optval_addr, 0)) {
2101 return -TARGET_EFAULT;
2102 }
2103 if (!lock_user_struct(VERIFY_READ, tfilter,
2104 tswapal(tfprog->filter), 0)) {
2105 unlock_user_struct(tfprog, optval_addr, 1);
2106 return -TARGET_EFAULT;
2107 }
2108
2109 fprog.len = tswap16(tfprog->len);
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05302110 filter = g_try_new(struct sock_filter, fprog.len);
Laurent Vivierf57d4192013-08-30 01:46:41 +02002111 if (filter == NULL) {
2112 unlock_user_struct(tfilter, tfprog->filter, 1);
2113 unlock_user_struct(tfprog, optval_addr, 1);
2114 return -TARGET_ENOMEM;
2115 }
2116 for (i = 0; i < fprog.len; i++) {
2117 filter[i].code = tswap16(tfilter[i].code);
2118 filter[i].jt = tfilter[i].jt;
2119 filter[i].jf = tfilter[i].jf;
2120 filter[i].k = tswap32(tfilter[i].k);
2121 }
2122 fprog.filter = filter;
2123
2124 ret = get_errno(setsockopt(sockfd, SOL_SOCKET,
2125 SO_ATTACH_FILTER, &fprog, sizeof(fprog)));
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05302126 g_free(filter);
Laurent Vivierf57d4192013-08-30 01:46:41 +02002127
2128 unlock_user_struct(tfilter, tfprog->filter, 1);
2129 unlock_user_struct(tfprog, optval_addr, 1);
2130 return ret;
2131 }
Joakim Tjernlund451aaf62014-07-12 15:47:06 +02002132 case TARGET_SO_BINDTODEVICE:
2133 {
2134 char *dev_ifname, *addr_ifname;
2135
2136 if (optlen > IFNAMSIZ - 1) {
2137 optlen = IFNAMSIZ - 1;
2138 }
2139 dev_ifname = lock_user(VERIFY_READ, optval_addr, optlen, 1);
2140 if (!dev_ifname) {
2141 return -TARGET_EFAULT;
2142 }
2143 optname = SO_BINDTODEVICE;
2144 addr_ifname = alloca(IFNAMSIZ);
2145 memcpy(addr_ifname, dev_ifname, optlen);
2146 addr_ifname[optlen] = 0;
Chen Gangfad6c582016-01-11 13:58:50 +08002147 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
2148 addr_ifname, optlen));
Joakim Tjernlund451aaf62014-07-12 15:47:06 +02002149 unlock_user (dev_ifname, optval_addr, 0);
2150 return ret;
2151 }
Carlo Marcelo Arenas Belón83eb6e52018-08-24 01:56:01 -07002152 case TARGET_SO_LINGER:
2153 {
2154 struct linger lg;
2155 struct target_linger *tlg;
2156
2157 if (optlen != sizeof(struct target_linger)) {
2158 return -TARGET_EINVAL;
2159 }
2160 if (!lock_user_struct(VERIFY_READ, tlg, optval_addr, 1)) {
2161 return -TARGET_EFAULT;
2162 }
2163 __get_user(lg.l_onoff, &tlg->l_onoff);
2164 __get_user(lg.l_linger, &tlg->l_linger);
2165 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, SO_LINGER,
2166 &lg, sizeof(lg)));
2167 unlock_user_struct(tlg, optval_addr, 0);
2168 return ret;
2169 }
bellard8853f862004-02-22 14:57:26 +00002170 /* Options with 'int' argument. */
bellard3532fa72006-06-24 15:06:03 +00002171 case TARGET_SO_DEBUG:
2172 optname = SO_DEBUG;
2173 break;
2174 case TARGET_SO_REUSEADDR:
2175 optname = SO_REUSEADDR;
2176 break;
Yunqiang Su113a9dd2018-10-30 13:55:08 +01002177#ifdef SO_REUSEPORT
2178 case TARGET_SO_REUSEPORT:
2179 optname = SO_REUSEPORT;
2180 break;
2181#endif
bellard3532fa72006-06-24 15:06:03 +00002182 case TARGET_SO_TYPE:
2183 optname = SO_TYPE;
2184 break;
2185 case TARGET_SO_ERROR:
2186 optname = SO_ERROR;
2187 break;
2188 case TARGET_SO_DONTROUTE:
2189 optname = SO_DONTROUTE;
2190 break;
2191 case TARGET_SO_BROADCAST:
2192 optname = SO_BROADCAST;
2193 break;
2194 case TARGET_SO_SNDBUF:
2195 optname = SO_SNDBUF;
2196 break;
Paul Burtond79b6cc2014-06-22 11:25:35 +01002197 case TARGET_SO_SNDBUFFORCE:
2198 optname = SO_SNDBUFFORCE;
2199 break;
bellard3532fa72006-06-24 15:06:03 +00002200 case TARGET_SO_RCVBUF:
2201 optname = SO_RCVBUF;
2202 break;
Paul Burtond79b6cc2014-06-22 11:25:35 +01002203 case TARGET_SO_RCVBUFFORCE:
2204 optname = SO_RCVBUFFORCE;
2205 break;
bellard3532fa72006-06-24 15:06:03 +00002206 case TARGET_SO_KEEPALIVE:
2207 optname = SO_KEEPALIVE;
2208 break;
2209 case TARGET_SO_OOBINLINE:
2210 optname = SO_OOBINLINE;
2211 break;
2212 case TARGET_SO_NO_CHECK:
2213 optname = SO_NO_CHECK;
2214 break;
2215 case TARGET_SO_PRIORITY:
2216 optname = SO_PRIORITY;
2217 break;
bellard5e83e8e2005-03-01 22:32:06 +00002218#ifdef SO_BSDCOMPAT
bellard3532fa72006-06-24 15:06:03 +00002219 case TARGET_SO_BSDCOMPAT:
2220 optname = SO_BSDCOMPAT;
2221 break;
bellard5e83e8e2005-03-01 22:32:06 +00002222#endif
bellard3532fa72006-06-24 15:06:03 +00002223 case TARGET_SO_PASSCRED:
2224 optname = SO_PASSCRED;
2225 break;
Paul Burton82d0fe62014-06-22 11:25:36 +01002226 case TARGET_SO_PASSSEC:
2227 optname = SO_PASSSEC;
2228 break;
bellard3532fa72006-06-24 15:06:03 +00002229 case TARGET_SO_TIMESTAMP:
2230 optname = SO_TIMESTAMP;
2231 break;
2232 case TARGET_SO_RCVLOWAT:
2233 optname = SO_RCVLOWAT;
2234 break;
bellard8853f862004-02-22 14:57:26 +00002235 default:
2236 goto unimplemented;
2237 }
bellard3532fa72006-06-24 15:06:03 +00002238 if (optlen < sizeof(uint32_t))
bellard2f619692007-11-16 10:46:05 +00002239 return -TARGET_EINVAL;
bellard3532fa72006-06-24 15:06:03 +00002240
bellard2f619692007-11-16 10:46:05 +00002241 if (get_user_u32(val, optval_addr))
2242 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00002243 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
bellard8853f862004-02-22 14:57:26 +00002244 break;
bellard7854b052003-03-29 17:22:23 +00002245 default:
bellard8853f862004-02-22 14:57:26 +00002246 unimplemented:
Stefan Weilb2bedb22011-09-12 22:33:01 +02002247 gemu_log("Unsupported setsockopt level=%d optname=%d\n", level, optname);
ths6fa13c12007-12-18 02:41:04 +00002248 ret = -TARGET_ENOPROTOOPT;
bellard7854b052003-03-29 17:22:23 +00002249 }
bellard8853f862004-02-22 14:57:26 +00002250 return ret;
bellard7854b052003-03-29 17:22:23 +00002251}
2252
ths0da46a62007-10-20 20:23:07 +00002253/* do_getsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002254static abi_long do_getsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00002255 abi_ulong optval_addr, abi_ulong optlen)
bellard7854b052003-03-29 17:22:23 +00002256{
blueswir1992f48a2007-10-14 16:27:31 +00002257 abi_long ret;
blueswir1b55266b2008-09-20 08:07:15 +00002258 int len, val;
2259 socklen_t lv;
bellard8853f862004-02-22 14:57:26 +00002260
2261 switch(level) {
bellard3532fa72006-06-24 15:06:03 +00002262 case TARGET_SOL_SOCKET:
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002263 level = SOL_SOCKET;
2264 switch (optname) {
2265 /* These don't just return a single integer */
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002266 case TARGET_SO_RCVTIMEO:
2267 case TARGET_SO_SNDTIMEO:
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002268 case TARGET_SO_PEERNAME:
2269 goto unimplemented;
Akos PASZTORY583359a2011-11-14 15:09:49 +02002270 case TARGET_SO_PEERCRED: {
2271 struct ucred cr;
2272 socklen_t crlen;
2273 struct target_ucred *tcr;
2274
2275 if (get_user_u32(len, optlen)) {
2276 return -TARGET_EFAULT;
2277 }
2278 if (len < 0) {
2279 return -TARGET_EINVAL;
2280 }
2281
2282 crlen = sizeof(cr);
2283 ret = get_errno(getsockopt(sockfd, level, SO_PEERCRED,
2284 &cr, &crlen));
2285 if (ret < 0) {
2286 return ret;
2287 }
2288 if (len > crlen) {
2289 len = crlen;
2290 }
2291 if (!lock_user_struct(VERIFY_WRITE, tcr, optval_addr, 0)) {
2292 return -TARGET_EFAULT;
2293 }
2294 __put_user(cr.pid, &tcr->pid);
2295 __put_user(cr.uid, &tcr->uid);
2296 __put_user(cr.gid, &tcr->gid);
2297 unlock_user_struct(tcr, optval_addr, 1);
2298 if (put_user_u32(len, optlen)) {
2299 return -TARGET_EFAULT;
2300 }
2301 break;
2302 }
Carlo Marcelo Arenas Belón83eb6e52018-08-24 01:56:01 -07002303 case TARGET_SO_LINGER:
2304 {
2305 struct linger lg;
2306 socklen_t lglen;
2307 struct target_linger *tlg;
2308
2309 if (get_user_u32(len, optlen)) {
2310 return -TARGET_EFAULT;
2311 }
2312 if (len < 0) {
2313 return -TARGET_EINVAL;
2314 }
2315
2316 lglen = sizeof(lg);
2317 ret = get_errno(getsockopt(sockfd, level, SO_LINGER,
2318 &lg, &lglen));
2319 if (ret < 0) {
2320 return ret;
2321 }
2322 if (len > lglen) {
2323 len = lglen;
2324 }
2325 if (!lock_user_struct(VERIFY_WRITE, tlg, optval_addr, 0)) {
2326 return -TARGET_EFAULT;
2327 }
2328 __put_user(lg.l_onoff, &tlg->l_onoff);
2329 __put_user(lg.l_linger, &tlg->l_linger);
2330 unlock_user_struct(tlg, optval_addr, 1);
2331 if (put_user_u32(len, optlen)) {
2332 return -TARGET_EFAULT;
2333 }
2334 break;
2335 }
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002336 /* Options with 'int' argument. */
2337 case TARGET_SO_DEBUG:
2338 optname = SO_DEBUG;
2339 goto int_case;
2340 case TARGET_SO_REUSEADDR:
2341 optname = SO_REUSEADDR;
2342 goto int_case;
Yunqiang Su113a9dd2018-10-30 13:55:08 +01002343#ifdef SO_REUSEPORT
2344 case TARGET_SO_REUSEPORT:
2345 optname = SO_REUSEPORT;
2346 goto int_case;
2347#endif
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002348 case TARGET_SO_TYPE:
2349 optname = SO_TYPE;
2350 goto int_case;
2351 case TARGET_SO_ERROR:
2352 optname = SO_ERROR;
2353 goto int_case;
2354 case TARGET_SO_DONTROUTE:
2355 optname = SO_DONTROUTE;
2356 goto int_case;
2357 case TARGET_SO_BROADCAST:
2358 optname = SO_BROADCAST;
2359 goto int_case;
2360 case TARGET_SO_SNDBUF:
2361 optname = SO_SNDBUF;
2362 goto int_case;
2363 case TARGET_SO_RCVBUF:
2364 optname = SO_RCVBUF;
2365 goto int_case;
2366 case TARGET_SO_KEEPALIVE:
2367 optname = SO_KEEPALIVE;
2368 goto int_case;
2369 case TARGET_SO_OOBINLINE:
2370 optname = SO_OOBINLINE;
2371 goto int_case;
2372 case TARGET_SO_NO_CHECK:
2373 optname = SO_NO_CHECK;
2374 goto int_case;
2375 case TARGET_SO_PRIORITY:
2376 optname = SO_PRIORITY;
2377 goto int_case;
2378#ifdef SO_BSDCOMPAT
2379 case TARGET_SO_BSDCOMPAT:
2380 optname = SO_BSDCOMPAT;
2381 goto int_case;
2382#endif
2383 case TARGET_SO_PASSCRED:
2384 optname = SO_PASSCRED;
2385 goto int_case;
2386 case TARGET_SO_TIMESTAMP:
2387 optname = SO_TIMESTAMP;
2388 goto int_case;
2389 case TARGET_SO_RCVLOWAT:
2390 optname = SO_RCVLOWAT;
2391 goto int_case;
Paul Burtonaec1ca42014-06-22 11:25:34 +01002392 case TARGET_SO_ACCEPTCONN:
2393 optname = SO_ACCEPTCONN;
2394 goto int_case;
bellard8853f862004-02-22 14:57:26 +00002395 default:
bellard2efbe912005-07-23 15:10:20 +00002396 goto int_case;
2397 }
2398 break;
2399 case SOL_TCP:
2400 /* TCP options all take an 'int' value. */
2401 int_case:
bellard2f619692007-11-16 10:46:05 +00002402 if (get_user_u32(len, optlen))
2403 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002404 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00002405 return -TARGET_EINVAL;
Mike Frysinger73160d92011-02-07 01:05:49 -05002406 lv = sizeof(lv);
bellard2efbe912005-07-23 15:10:20 +00002407 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2408 if (ret < 0)
2409 return ret;
Paul Burton8289d112014-06-22 11:25:33 +01002410 if (optname == SO_TYPE) {
2411 val = host_to_target_sock_type(val);
2412 }
bellard2efbe912005-07-23 15:10:20 +00002413 if (len > lv)
2414 len = lv;
bellard2f619692007-11-16 10:46:05 +00002415 if (len == 4) {
2416 if (put_user_u32(val, optval_addr))
2417 return -TARGET_EFAULT;
2418 } else {
2419 if (put_user_u8(val, optval_addr))
2420 return -TARGET_EFAULT;
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002421 }
bellard2f619692007-11-16 10:46:05 +00002422 if (put_user_u32(len, optlen))
2423 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002424 break;
2425 case SOL_IP:
2426 switch(optname) {
2427 case IP_TOS:
2428 case IP_TTL:
2429 case IP_HDRINCL:
2430 case IP_ROUTER_ALERT:
2431 case IP_RECVOPTS:
2432 case IP_RETOPTS:
2433 case IP_PKTINFO:
2434 case IP_MTU_DISCOVER:
2435 case IP_RECVERR:
2436 case IP_RECVTOS:
2437#ifdef IP_FREEBIND
2438 case IP_FREEBIND:
2439#endif
2440 case IP_MULTICAST_TTL:
2441 case IP_MULTICAST_LOOP:
bellard2f619692007-11-16 10:46:05 +00002442 if (get_user_u32(len, optlen))
2443 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00002444 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00002445 return -TARGET_EINVAL;
Mike Frysinger73160d92011-02-07 01:05:49 -05002446 lv = sizeof(lv);
bellard8853f862004-02-22 14:57:26 +00002447 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2448 if (ret < 0)
2449 return ret;
bellard2efbe912005-07-23 15:10:20 +00002450 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
bellard2efbe912005-07-23 15:10:20 +00002451 len = 1;
bellard2f619692007-11-16 10:46:05 +00002452 if (put_user_u32(len, optlen)
2453 || put_user_u8(val, optval_addr))
2454 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002455 } else {
bellard2efbe912005-07-23 15:10:20 +00002456 if (len > sizeof(int))
2457 len = sizeof(int);
bellard2f619692007-11-16 10:46:05 +00002458 if (put_user_u32(len, optlen)
2459 || put_user_u32(val, optval_addr))
2460 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002461 }
bellard8853f862004-02-22 14:57:26 +00002462 break;
bellard2efbe912005-07-23 15:10:20 +00002463 default:
thsc02f4992007-12-18 02:39:59 +00002464 ret = -TARGET_ENOPROTOOPT;
2465 break;
bellard8853f862004-02-22 14:57:26 +00002466 }
2467 break;
Tom Deseynbd8ed482018-12-13 14:06:11 +01002468 case SOL_IPV6:
2469 switch (optname) {
2470 case IPV6_MTU_DISCOVER:
2471 case IPV6_MTU:
2472 case IPV6_V6ONLY:
2473 case IPV6_RECVPKTINFO:
2474 case IPV6_UNICAST_HOPS:
2475 case IPV6_MULTICAST_HOPS:
2476 case IPV6_MULTICAST_LOOP:
2477 case IPV6_RECVERR:
2478 case IPV6_RECVHOPLIMIT:
2479 case IPV6_2292HOPLIMIT:
2480 case IPV6_CHECKSUM:
Helge Dellerb9cce6d2019-03-10 12:12:16 +01002481 case IPV6_ADDRFORM:
2482 case IPV6_2292PKTINFO:
2483 case IPV6_RECVTCLASS:
2484 case IPV6_RECVRTHDR:
2485 case IPV6_2292RTHDR:
2486 case IPV6_RECVHOPOPTS:
2487 case IPV6_2292HOPOPTS:
2488 case IPV6_RECVDSTOPTS:
2489 case IPV6_2292DSTOPTS:
2490 case IPV6_TCLASS:
2491#ifdef IPV6_RECVPATHMTU
2492 case IPV6_RECVPATHMTU:
2493#endif
2494#ifdef IPV6_TRANSPARENT
2495 case IPV6_TRANSPARENT:
2496#endif
2497#ifdef IPV6_FREEBIND
2498 case IPV6_FREEBIND:
2499#endif
2500#ifdef IPV6_RECVORIGDSTADDR
2501 case IPV6_RECVORIGDSTADDR:
2502#endif
Tom Deseynbd8ed482018-12-13 14:06:11 +01002503 if (get_user_u32(len, optlen))
2504 return -TARGET_EFAULT;
2505 if (len < 0)
2506 return -TARGET_EINVAL;
2507 lv = sizeof(lv);
2508 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2509 if (ret < 0)
2510 return ret;
2511 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
2512 len = 1;
2513 if (put_user_u32(len, optlen)
2514 || put_user_u8(val, optval_addr))
2515 return -TARGET_EFAULT;
2516 } else {
2517 if (len > sizeof(int))
2518 len = sizeof(int);
2519 if (put_user_u32(len, optlen)
2520 || put_user_u32(val, optval_addr))
2521 return -TARGET_EFAULT;
2522 }
2523 break;
2524 default:
2525 ret = -TARGET_ENOPROTOOPT;
2526 break;
2527 }
2528 break;
bellard8853f862004-02-22 14:57:26 +00002529 default:
2530 unimplemented:
2531 gemu_log("getsockopt level=%d optname=%d not yet supported\n",
2532 level, optname);
thsc02f4992007-12-18 02:39:59 +00002533 ret = -TARGET_EOPNOTSUPP;
bellard8853f862004-02-22 14:57:26 +00002534 break;
2535 }
2536 return ret;
bellard7854b052003-03-29 17:22:23 +00002537}
2538
Max Filippov9ac22512018-04-04 17:30:41 -07002539/* Convert target low/high pair representing file offset into the host
2540 * low/high pair. This function doesn't handle offsets bigger than 64 bits
2541 * as the kernel doesn't handle them either.
2542 */
2543static void target_to_host_low_high(abi_ulong tlow,
2544 abi_ulong thigh,
2545 unsigned long *hlow,
2546 unsigned long *hhigh)
2547{
2548 uint64_t off = tlow |
2549 ((unsigned long long)thigh << TARGET_LONG_BITS / 2) <<
2550 TARGET_LONG_BITS / 2;
2551
2552 *hlow = off;
2553 *hhigh = (off >> HOST_LONG_BITS / 2) >> HOST_LONG_BITS / 2;
2554}
2555
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002556static struct iovec *lock_iovec(int type, abi_ulong target_addr,
Peter Maydelldab32b32016-07-15 14:57:26 +01002557 abi_ulong count, int copy)
pbrook53a59602006-03-25 19:31:22 +00002558{
2559 struct target_iovec *target_vec;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002560 struct iovec *vec;
2561 abi_ulong total_len, max_len;
balrogd732dcb2008-10-28 10:21:03 +00002562 int i;
Peter Maydell501bb4b2014-02-17 18:55:33 +00002563 int err = 0;
Tom Musta29560a62014-08-12 13:53:43 -05002564 bool bad_address = false;
pbrook53a59602006-03-25 19:31:22 +00002565
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002566 if (count == 0) {
2567 errno = 0;
2568 return NULL;
pbrook53a59602006-03-25 19:31:22 +00002569 }
Peter Maydelldab32b32016-07-15 14:57:26 +01002570 if (count > IOV_MAX) {
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002571 errno = EINVAL;
2572 return NULL;
2573 }
2574
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05302575 vec = g_try_new0(struct iovec, count);
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002576 if (vec == NULL) {
2577 errno = ENOMEM;
2578 return NULL;
2579 }
2580
2581 target_vec = lock_user(VERIFY_READ, target_addr,
2582 count * sizeof(struct target_iovec), 1);
2583 if (target_vec == NULL) {
Peter Maydell501bb4b2014-02-17 18:55:33 +00002584 err = EFAULT;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002585 goto fail2;
2586 }
2587
2588 /* ??? If host page size > target page size, this will result in a
2589 value larger than what we can actually support. */
2590 max_len = 0x7fffffff & TARGET_PAGE_MASK;
2591 total_len = 0;
2592
2593 for (i = 0; i < count; i++) {
2594 abi_ulong base = tswapal(target_vec[i].iov_base);
2595 abi_long len = tswapal(target_vec[i].iov_len);
2596
2597 if (len < 0) {
Peter Maydell501bb4b2014-02-17 18:55:33 +00002598 err = EINVAL;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002599 goto fail;
2600 } else if (len == 0) {
2601 /* Zero length pointer is ignored. */
2602 vec[i].iov_base = 0;
2603 } else {
2604 vec[i].iov_base = lock_user(type, base, len, copy);
Tom Musta29560a62014-08-12 13:53:43 -05002605 /* If the first buffer pointer is bad, this is a fault. But
2606 * subsequent bad buffers will result in a partial write; this
2607 * is realized by filling the vector with null pointers and
2608 * zero lengths. */
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002609 if (!vec[i].iov_base) {
Tom Musta29560a62014-08-12 13:53:43 -05002610 if (i == 0) {
2611 err = EFAULT;
2612 goto fail;
2613 } else {
2614 bad_address = true;
2615 }
2616 }
2617 if (bad_address) {
2618 len = 0;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002619 }
2620 if (len > max_len - total_len) {
2621 len = max_len - total_len;
2622 }
2623 }
2624 vec[i].iov_len = len;
2625 total_len += len;
2626 }
2627
2628 unlock_user(target_vec, target_addr, 0);
2629 return vec;
2630
2631 fail:
Chen Gang S7eff5182015-01-23 18:01:09 +08002632 while (--i >= 0) {
2633 if (tswapal(target_vec[i].iov_len) > 0) {
2634 unlock_user(vec[i].iov_base, tswapal(target_vec[i].iov_base), 0);
2635 }
2636 }
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002637 unlock_user(target_vec, target_addr, 0);
Peter Maydell501bb4b2014-02-17 18:55:33 +00002638 fail2:
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05302639 g_free(vec);
Peter Maydell501bb4b2014-02-17 18:55:33 +00002640 errno = err;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002641 return NULL;
pbrook53a59602006-03-25 19:31:22 +00002642}
2643
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002644static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
Peter Maydelldab32b32016-07-15 14:57:26 +01002645 abi_ulong count, int copy)
pbrook53a59602006-03-25 19:31:22 +00002646{
2647 struct target_iovec *target_vec;
pbrook53a59602006-03-25 19:31:22 +00002648 int i;
2649
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002650 target_vec = lock_user(VERIFY_READ, target_addr,
2651 count * sizeof(struct target_iovec), 1);
2652 if (target_vec) {
2653 for (i = 0; i < count; i++) {
2654 abi_ulong base = tswapal(target_vec[i].iov_base);
Chen Gang S71ec7ce2015-01-23 18:07:50 +08002655 abi_long len = tswapal(target_vec[i].iov_len);
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002656 if (len < 0) {
2657 break;
2658 }
balrogd732dcb2008-10-28 10:21:03 +00002659 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
2660 }
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002661 unlock_user(target_vec, target_addr, 0);
pbrook53a59602006-03-25 19:31:22 +00002662 }
bellard579a97f2007-11-11 14:26:47 +00002663
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05302664 g_free(vec);
pbrook53a59602006-03-25 19:31:22 +00002665}
2666
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02002667static inline int target_to_host_sock_type(int *type)
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02002668{
2669 int host_type = 0;
2670 int target_type = *type;
2671
2672 switch (target_type & TARGET_SOCK_TYPE_MASK) {
2673 case TARGET_SOCK_DGRAM:
2674 host_type = SOCK_DGRAM;
2675 break;
2676 case TARGET_SOCK_STREAM:
2677 host_type = SOCK_STREAM;
2678 break;
2679 default:
2680 host_type = target_type & TARGET_SOCK_TYPE_MASK;
2681 break;
2682 }
2683 if (target_type & TARGET_SOCK_CLOEXEC) {
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02002684#if defined(SOCK_CLOEXEC)
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02002685 host_type |= SOCK_CLOEXEC;
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02002686#else
2687 return -TARGET_EINVAL;
2688#endif
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02002689 }
2690 if (target_type & TARGET_SOCK_NONBLOCK) {
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02002691#if defined(SOCK_NONBLOCK)
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02002692 host_type |= SOCK_NONBLOCK;
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02002693#elif !defined(O_NONBLOCK)
2694 return -TARGET_EINVAL;
2695#endif
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02002696 }
2697 *type = host_type;
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02002698 return 0;
2699}
2700
2701/* Try to emulate socket type flags after socket creation. */
2702static int sock_flags_fixup(int fd, int target_type)
2703{
2704#if !defined(SOCK_NONBLOCK) && defined(O_NONBLOCK)
2705 if (target_type & TARGET_SOCK_NONBLOCK) {
2706 int flags = fcntl(fd, F_GETFL);
2707 if (fcntl(fd, F_SETFL, O_NONBLOCK | flags) == -1) {
2708 close(fd);
2709 return -TARGET_EINVAL;
2710 }
2711 }
2712#endif
2713 return fd;
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02002714}
2715
ths0da46a62007-10-20 20:23:07 +00002716/* do_socket() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002717static abi_long do_socket(int domain, int type, int protocol)
bellard3532fa72006-06-24 15:06:03 +00002718{
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02002719 int target_type = type;
2720 int ret;
2721
2722 ret = target_to_host_sock_type(&type);
2723 if (ret) {
2724 return ret;
2725 }
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02002726
Laurent Vivier575b22b2016-06-02 22:14:15 +02002727 if (domain == PF_NETLINK && !(
2728#ifdef CONFIG_RTNETLINK
2729 protocol == NETLINK_ROUTE ||
2730#endif
2731 protocol == NETLINK_KOBJECT_UEVENT ||
2732 protocol == NETLINK_AUDIT)) {
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002733 return -EPFNOSUPPORT;
2734 }
Laurent Vivierff626f22015-10-28 21:40:42 +01002735
2736 if (domain == AF_PACKET ||
2737 (domain == AF_INET && type == SOCK_PACKET)) {
2738 protocol = tswap16(protocol);
2739 }
2740
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02002741 ret = get_errno(socket(domain, type, protocol));
2742 if (ret >= 0) {
2743 ret = sock_flags_fixup(ret, target_type);
Laurent Vivier0cf22722015-10-28 21:40:45 +01002744 if (type == SOCK_PACKET) {
2745 /* Manage an obsolete case :
2746 * if socket type is SOCK_PACKET, bind by name
2747 */
2748 fd_trans_register(ret, &target_packet_trans);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002749 } else if (domain == PF_NETLINK) {
2750 switch (protocol) {
Laurent Vivier575b22b2016-06-02 22:14:15 +02002751#ifdef CONFIG_RTNETLINK
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002752 case NETLINK_ROUTE:
2753 fd_trans_register(ret, &target_netlink_route_trans);
2754 break;
Laurent Vivier575b22b2016-06-02 22:14:15 +02002755#endif
Laurent Vivierb2656202016-05-22 18:56:20 +02002756 case NETLINK_KOBJECT_UEVENT:
2757 /* nothing to do: messages are strings */
2758 break;
Laurent Vivier5ce9bb52016-05-22 18:56:21 +02002759 case NETLINK_AUDIT:
2760 fd_trans_register(ret, &target_netlink_audit_trans);
2761 break;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002762 default:
2763 g_assert_not_reached();
2764 }
Laurent Vivier0cf22722015-10-28 21:40:45 +01002765 }
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02002766 }
2767 return ret;
bellard3532fa72006-06-24 15:06:03 +00002768}
2769
ths0da46a62007-10-20 20:23:07 +00002770/* do_bind() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002771static abi_long do_bind(int sockfd, abi_ulong target_addr,
2772 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00002773{
aurel328f7aeaf2009-01-30 19:47:57 +00002774 void *addr;
Arnaud Patard917507b2009-06-19 10:44:45 +03002775 abi_long ret;
aurel328f7aeaf2009-01-30 19:47:57 +00002776
Blue Swirl38724252010-09-18 05:53:14 +00002777 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00002778 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00002779 }
aurel328f7aeaf2009-01-30 19:47:57 +00002780
aurel32607175e2009-04-15 16:11:59 +00002781 addr = alloca(addrlen+1);
ths3b46e622007-09-17 08:09:54 +00002782
Laurent Vivier7b36f782015-10-28 21:40:44 +01002783 ret = target_to_host_sockaddr(sockfd, addr, target_addr, addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03002784 if (ret)
2785 return ret;
2786
bellard3532fa72006-06-24 15:06:03 +00002787 return get_errno(bind(sockfd, addr, addrlen));
2788}
2789
ths0da46a62007-10-20 20:23:07 +00002790/* do_connect() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002791static abi_long do_connect(int sockfd, abi_ulong target_addr,
2792 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00002793{
aurel328f7aeaf2009-01-30 19:47:57 +00002794 void *addr;
Arnaud Patard917507b2009-06-19 10:44:45 +03002795 abi_long ret;
aurel328f7aeaf2009-01-30 19:47:57 +00002796
Blue Swirl38724252010-09-18 05:53:14 +00002797 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00002798 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00002799 }
aurel328f7aeaf2009-01-30 19:47:57 +00002800
Joakim Tjernlund2dd08df2014-07-11 17:18:03 +02002801 addr = alloca(addrlen+1);
ths3b46e622007-09-17 08:09:54 +00002802
Laurent Vivier7b36f782015-10-28 21:40:44 +01002803 ret = target_to_host_sockaddr(sockfd, addr, target_addr, addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03002804 if (ret)
2805 return ret;
2806
Peter Maydell2a3c7612016-06-06 19:58:03 +01002807 return get_errno(safe_connect(sockfd, addr, addrlen));
bellard3532fa72006-06-24 15:06:03 +00002808}
2809
Alexander Graff19e00d2014-03-02 19:36:42 +00002810/* do_sendrecvmsg_locked() Must return target values and target errnos. */
2811static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
2812 int flags, int send)
bellard3532fa72006-06-24 15:06:03 +00002813{
balrog6de645c2008-10-28 10:26:29 +00002814 abi_long ret, len;
bellard3532fa72006-06-24 15:06:03 +00002815 struct msghdr msg;
Peter Maydelldab32b32016-07-15 14:57:26 +01002816 abi_ulong count;
bellard3532fa72006-06-24 15:06:03 +00002817 struct iovec *vec;
blueswir1992f48a2007-10-14 16:27:31 +00002818 abi_ulong target_vec;
bellard3532fa72006-06-24 15:06:03 +00002819
bellard3532fa72006-06-24 15:06:03 +00002820 if (msgp->msg_name) {
2821 msg.msg_namelen = tswap32(msgp->msg_namelen);
Joakim Tjernlund2dd08df2014-07-11 17:18:03 +02002822 msg.msg_name = alloca(msg.msg_namelen+1);
Laurent Vivier7b36f782015-10-28 21:40:44 +01002823 ret = target_to_host_sockaddr(fd, msg.msg_name,
2824 tswapal(msgp->msg_name),
2825 msg.msg_namelen);
Peter Maydell26a6fc92016-07-15 14:57:28 +01002826 if (ret == -TARGET_EFAULT) {
2827 /* For connected sockets msg_name and msg_namelen must
2828 * be ignored, so returning EFAULT immediately is wrong.
2829 * Instead, pass a bad msg_name to the host kernel, and
2830 * let it decide whether to return EFAULT or not.
2831 */
2832 msg.msg_name = (void *)-1;
2833 } else if (ret) {
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002834 goto out2;
Arnaud Patard917507b2009-06-19 10:44:45 +03002835 }
bellard3532fa72006-06-24 15:06:03 +00002836 } else {
2837 msg.msg_name = NULL;
2838 msg.msg_namelen = 0;
2839 }
Matthias Brauncbb21ee2011-08-12 19:57:41 +02002840 msg.msg_controllen = 2 * tswapal(msgp->msg_controllen);
bellard3532fa72006-06-24 15:06:03 +00002841 msg.msg_control = alloca(msg.msg_controllen);
Jonas Schievink1d3d1b22018-07-12 00:12:44 +02002842 memset(msg.msg_control, 0, msg.msg_controllen);
2843
bellard3532fa72006-06-24 15:06:03 +00002844 msg.msg_flags = tswap32(msgp->msg_flags);
ths3b46e622007-09-17 08:09:54 +00002845
Matthias Brauncbb21ee2011-08-12 19:57:41 +02002846 count = tswapal(msgp->msg_iovlen);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02002847 target_vec = tswapal(msgp->msg_iov);
Peter Maydell97b07972016-07-15 14:57:27 +01002848
2849 if (count > IOV_MAX) {
2850 /* sendrcvmsg returns a different errno for this condition than
2851 * readv/writev, so we must catch it here before lock_iovec() does.
2852 */
2853 ret = -TARGET_EMSGSIZE;
2854 goto out2;
2855 }
2856
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002857 vec = lock_iovec(send ? VERIFY_READ : VERIFY_WRITE,
2858 target_vec, count, send);
2859 if (vec == NULL) {
2860 ret = -host_to_target_errno(errno);
2861 goto out2;
2862 }
bellard3532fa72006-06-24 15:06:03 +00002863 msg.msg_iovlen = count;
2864 msg.msg_iov = vec;
ths3b46e622007-09-17 08:09:54 +00002865
bellard3532fa72006-06-24 15:06:03 +00002866 if (send) {
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002867 if (fd_trans_target_to_host_data(fd)) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02002868 void *host_msg;
2869
2870 host_msg = g_malloc(msg.msg_iov->iov_len);
2871 memcpy(host_msg, msg.msg_iov->iov_base, msg.msg_iov->iov_len);
2872 ret = fd_trans_target_to_host_data(fd)(host_msg,
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002873 msg.msg_iov->iov_len);
Laurent Vivier7d61d892016-06-21 19:51:14 +02002874 if (ret >= 0) {
2875 msg.msg_iov->iov_base = host_msg;
2876 ret = get_errno(safe_sendmsg(fd, &msg, flags));
2877 }
2878 g_free(host_msg);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002879 } else {
2880 ret = target_to_host_cmsg(&msg, msgp);
Laurent Vivier7d61d892016-06-21 19:51:14 +02002881 if (ret == 0) {
2882 ret = get_errno(safe_sendmsg(fd, &msg, flags));
2883 }
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002884 }
bellard3532fa72006-06-24 15:06:03 +00002885 } else {
Peter Maydell66687532016-06-06 19:58:04 +01002886 ret = get_errno(safe_recvmsg(fd, &msg, flags));
balrog6de645c2008-10-28 10:26:29 +00002887 if (!is_error(ret)) {
2888 len = ret;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002889 if (fd_trans_host_to_target_data(fd)) {
2890 ret = fd_trans_host_to_target_data(fd)(msg.msg_iov->iov_base,
Laurent Vivier2a03d3e2018-08-20 19:15:54 +02002891 MIN(msg.msg_iov->iov_len, len));
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002892 } else {
2893 ret = host_to_target_cmsg(msgp, &msg);
2894 }
Jing Huangca619062012-07-24 13:58:02 +00002895 if (!is_error(ret)) {
2896 msgp->msg_namelen = tswap32(msg.msg_namelen);
Andreas Schwab24894f32019-02-12 17:34:35 +01002897 msgp->msg_flags = tswap32(msg.msg_flags);
Peter Maydell26a6fc92016-07-15 14:57:28 +01002898 if (msg.msg_name != NULL && msg.msg_name != (void *)-1) {
Jing Huangca619062012-07-24 13:58:02 +00002899 ret = host_to_target_sockaddr(tswapal(msgp->msg_name),
2900 msg.msg_name, msg.msg_namelen);
2901 if (ret) {
2902 goto out;
2903 }
2904 }
2905
balrog6de645c2008-10-28 10:26:29 +00002906 ret = len;
Jing Huangca619062012-07-24 13:58:02 +00002907 }
balrog6de645c2008-10-28 10:26:29 +00002908 }
bellard3532fa72006-06-24 15:06:03 +00002909 }
Jing Huangca619062012-07-24 13:58:02 +00002910
2911out:
bellard3532fa72006-06-24 15:06:03 +00002912 unlock_iovec(vec, target_vec, count, !send);
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002913out2:
Alexander Graff19e00d2014-03-02 19:36:42 +00002914 return ret;
2915}
2916
2917static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
2918 int flags, int send)
2919{
2920 abi_long ret;
2921 struct target_msghdr *msgp;
2922
2923 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
2924 msgp,
2925 target_msg,
2926 send ? 1 : 0)) {
2927 return -TARGET_EFAULT;
2928 }
2929 ret = do_sendrecvmsg_locked(fd, msgp, flags, send);
bellard579a97f2007-11-11 14:26:47 +00002930 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
bellard3532fa72006-06-24 15:06:03 +00002931 return ret;
2932}
2933
Alexander Graff19e00d2014-03-02 19:36:42 +00002934/* We don't rely on the C library to have sendmmsg/recvmmsg support,
2935 * so it might not have this *mmsg-specific flag either.
2936 */
2937#ifndef MSG_WAITFORONE
2938#define MSG_WAITFORONE 0x10000
2939#endif
2940
2941static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec,
2942 unsigned int vlen, unsigned int flags,
2943 int send)
2944{
2945 struct target_mmsghdr *mmsgp;
2946 abi_long ret = 0;
2947 int i;
2948
2949 if (vlen > UIO_MAXIOV) {
2950 vlen = UIO_MAXIOV;
2951 }
2952
2953 mmsgp = lock_user(VERIFY_WRITE, target_msgvec, sizeof(*mmsgp) * vlen, 1);
2954 if (!mmsgp) {
2955 return -TARGET_EFAULT;
2956 }
2957
2958 for (i = 0; i < vlen; i++) {
2959 ret = do_sendrecvmsg_locked(fd, &mmsgp[i].msg_hdr, flags, send);
2960 if (is_error(ret)) {
2961 break;
2962 }
2963 mmsgp[i].msg_len = tswap32(ret);
2964 /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
2965 if (flags & MSG_WAITFORONE) {
2966 flags |= MSG_DONTWAIT;
2967 }
2968 }
2969
2970 unlock_user(mmsgp, target_msgvec, sizeof(*mmsgp) * i);
2971
2972 /* Return number of datagrams sent if we sent any at all;
2973 * otherwise return the error.
2974 */
2975 if (i) {
2976 return i;
2977 }
2978 return ret;
2979}
Alexander Graff19e00d2014-03-02 19:36:42 +00002980
Peter Maydella94b4982013-02-08 04:35:04 +00002981/* do_accept4() Must return target values and target errnos. */
2982static abi_long do_accept4(int fd, abi_ulong target_addr,
2983 abi_ulong target_addrlen_addr, int flags)
pbrook1be9e1d2006-11-19 15:26:04 +00002984{
Andreas Schwabcd813362019-02-14 12:43:40 +01002985 socklen_t addrlen, ret_addrlen;
bellard2f619692007-11-16 10:46:05 +00002986 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00002987 abi_long ret;
Petar Jovanovicd25295d2014-03-31 17:41:23 +02002988 int host_flags;
2989
2990 host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
pbrook1be9e1d2006-11-19 15:26:04 +00002991
Peter Maydella94b4982013-02-08 04:35:04 +00002992 if (target_addr == 0) {
Peter Maydellff6dc132016-06-06 19:58:13 +01002993 return get_errno(safe_accept4(fd, NULL, NULL, host_flags));
Peter Maydella94b4982013-02-08 04:35:04 +00002994 }
Arnaud Patard917507b2009-06-19 10:44:45 +03002995
2996 /* linux returns EINVAL if addrlen pointer is invalid */
bellard2f619692007-11-16 10:46:05 +00002997 if (get_user_u32(addrlen, target_addrlen_addr))
Arnaud Patard917507b2009-06-19 10:44:45 +03002998 return -TARGET_EINVAL;
bellard2f619692007-11-16 10:46:05 +00002999
Blue Swirl38724252010-09-18 05:53:14 +00003000 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003001 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003002 }
aurel328f7aeaf2009-01-30 19:47:57 +00003003
Arnaud Patard917507b2009-06-19 10:44:45 +03003004 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
3005 return -TARGET_EINVAL;
3006
bellard2f619692007-11-16 10:46:05 +00003007 addr = alloca(addrlen);
3008
Andreas Schwabcd813362019-02-14 12:43:40 +01003009 ret_addrlen = addrlen;
3010 ret = get_errno(safe_accept4(fd, addr, &ret_addrlen, host_flags));
pbrook1be9e1d2006-11-19 15:26:04 +00003011 if (!is_error(ret)) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003012 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3013 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
bellard2f619692007-11-16 10:46:05 +00003014 ret = -TARGET_EFAULT;
Andreas Schwabcd813362019-02-14 12:43:40 +01003015 }
pbrook1be9e1d2006-11-19 15:26:04 +00003016 }
3017 return ret;
3018}
3019
ths0da46a62007-10-20 20:23:07 +00003020/* do_getpeername() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003021static abi_long do_getpeername(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00003022 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00003023{
Andreas Schwabcd813362019-02-14 12:43:40 +01003024 socklen_t addrlen, ret_addrlen;
bellard2f619692007-11-16 10:46:05 +00003025 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00003026 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003027
bellard2f619692007-11-16 10:46:05 +00003028 if (get_user_u32(addrlen, target_addrlen_addr))
3029 return -TARGET_EFAULT;
3030
Blue Swirl38724252010-09-18 05:53:14 +00003031 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003032 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003033 }
aurel328f7aeaf2009-01-30 19:47:57 +00003034
Arnaud Patard917507b2009-06-19 10:44:45 +03003035 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
3036 return -TARGET_EFAULT;
3037
bellard2f619692007-11-16 10:46:05 +00003038 addr = alloca(addrlen);
3039
Andreas Schwabcd813362019-02-14 12:43:40 +01003040 ret_addrlen = addrlen;
3041 ret = get_errno(getpeername(fd, addr, &ret_addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003042 if (!is_error(ret)) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003043 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3044 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
bellard2f619692007-11-16 10:46:05 +00003045 ret = -TARGET_EFAULT;
Andreas Schwabcd813362019-02-14 12:43:40 +01003046 }
pbrook1be9e1d2006-11-19 15:26:04 +00003047 }
3048 return ret;
3049}
3050
ths0da46a62007-10-20 20:23:07 +00003051/* do_getsockname() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003052static abi_long do_getsockname(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00003053 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00003054{
Andreas Schwabcd813362019-02-14 12:43:40 +01003055 socklen_t addrlen, ret_addrlen;
bellard2f619692007-11-16 10:46:05 +00003056 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00003057 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003058
bellard2f619692007-11-16 10:46:05 +00003059 if (get_user_u32(addrlen, target_addrlen_addr))
3060 return -TARGET_EFAULT;
3061
Blue Swirl38724252010-09-18 05:53:14 +00003062 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003063 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003064 }
aurel328f7aeaf2009-01-30 19:47:57 +00003065
Arnaud Patard917507b2009-06-19 10:44:45 +03003066 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
3067 return -TARGET_EFAULT;
3068
bellard2f619692007-11-16 10:46:05 +00003069 addr = alloca(addrlen);
3070
Andreas Schwabcd813362019-02-14 12:43:40 +01003071 ret_addrlen = addrlen;
3072 ret = get_errno(getsockname(fd, addr, &ret_addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003073 if (!is_error(ret)) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003074 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3075 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
bellard2f619692007-11-16 10:46:05 +00003076 ret = -TARGET_EFAULT;
Andreas Schwabcd813362019-02-14 12:43:40 +01003077 }
pbrook1be9e1d2006-11-19 15:26:04 +00003078 }
3079 return ret;
3080}
3081
ths0da46a62007-10-20 20:23:07 +00003082/* do_socketpair() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003083static abi_long do_socketpair(int domain, int type, int protocol,
bellard2f619692007-11-16 10:46:05 +00003084 abi_ulong target_tab_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00003085{
3086 int tab[2];
blueswir1992f48a2007-10-14 16:27:31 +00003087 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003088
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003089 target_to_host_sock_type(&type);
3090
pbrook1be9e1d2006-11-19 15:26:04 +00003091 ret = get_errno(socketpair(domain, type, protocol, tab));
3092 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00003093 if (put_user_s32(tab[0], target_tab_addr)
3094 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
3095 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00003096 }
3097 return ret;
3098}
3099
ths0da46a62007-10-20 20:23:07 +00003100/* do_sendto() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003101static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
3102 abi_ulong target_addr, socklen_t addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00003103{
3104 void *addr;
3105 void *host_msg;
Laurent Vivier7d61d892016-06-21 19:51:14 +02003106 void *copy_msg = NULL;
blueswir1992f48a2007-10-14 16:27:31 +00003107 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003108
Blue Swirl38724252010-09-18 05:53:14 +00003109 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003110 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003111 }
aurel328f7aeaf2009-01-30 19:47:57 +00003112
bellard579a97f2007-11-11 14:26:47 +00003113 host_msg = lock_user(VERIFY_READ, msg, len, 1);
3114 if (!host_msg)
3115 return -TARGET_EFAULT;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003116 if (fd_trans_target_to_host_data(fd)) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003117 copy_msg = host_msg;
3118 host_msg = g_malloc(len);
3119 memcpy(host_msg, copy_msg, len);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003120 ret = fd_trans_target_to_host_data(fd)(host_msg, len);
3121 if (ret < 0) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003122 goto fail;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003123 }
3124 }
pbrook1be9e1d2006-11-19 15:26:04 +00003125 if (target_addr) {
Joakim Tjernlund2dd08df2014-07-11 17:18:03 +02003126 addr = alloca(addrlen+1);
Laurent Vivier7b36f782015-10-28 21:40:44 +01003127 ret = target_to_host_sockaddr(fd, addr, target_addr, addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03003128 if (ret) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003129 goto fail;
Arnaud Patard917507b2009-06-19 10:44:45 +03003130 }
Peter Maydell66687532016-06-06 19:58:04 +01003131 ret = get_errno(safe_sendto(fd, host_msg, len, flags, addr, addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003132 } else {
Peter Maydell66687532016-06-06 19:58:04 +01003133 ret = get_errno(safe_sendto(fd, host_msg, len, flags, NULL, 0));
pbrook1be9e1d2006-11-19 15:26:04 +00003134 }
Laurent Vivier7d61d892016-06-21 19:51:14 +02003135fail:
3136 if (copy_msg) {
3137 g_free(host_msg);
3138 host_msg = copy_msg;
3139 }
pbrook1be9e1d2006-11-19 15:26:04 +00003140 unlock_user(host_msg, msg, 0);
3141 return ret;
3142}
3143
ths0da46a62007-10-20 20:23:07 +00003144/* do_recvfrom() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003145static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
3146 abi_ulong target_addr,
3147 abi_ulong target_addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00003148{
Andreas Schwabcd813362019-02-14 12:43:40 +01003149 socklen_t addrlen, ret_addrlen;
pbrook1be9e1d2006-11-19 15:26:04 +00003150 void *addr;
3151 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00003152 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003153
bellard579a97f2007-11-11 14:26:47 +00003154 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
3155 if (!host_msg)
3156 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00003157 if (target_addr) {
bellard2f619692007-11-16 10:46:05 +00003158 if (get_user_u32(addrlen, target_addrlen)) {
3159 ret = -TARGET_EFAULT;
3160 goto fail;
3161 }
Blue Swirl38724252010-09-18 05:53:14 +00003162 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003163 ret = -TARGET_EINVAL;
3164 goto fail;
3165 }
pbrook1be9e1d2006-11-19 15:26:04 +00003166 addr = alloca(addrlen);
Andreas Schwabcd813362019-02-14 12:43:40 +01003167 ret_addrlen = addrlen;
Peter Maydell66687532016-06-06 19:58:04 +01003168 ret = get_errno(safe_recvfrom(fd, host_msg, len, flags,
Andreas Schwabcd813362019-02-14 12:43:40 +01003169 addr, &ret_addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003170 } else {
3171 addr = NULL; /* To keep compiler quiet. */
Andreas Schwabcd813362019-02-14 12:43:40 +01003172 addrlen = 0; /* To keep compiler quiet. */
Peter Maydell66687532016-06-06 19:58:04 +01003173 ret = get_errno(safe_recvfrom(fd, host_msg, len, flags, NULL, 0));
pbrook1be9e1d2006-11-19 15:26:04 +00003174 }
3175 if (!is_error(ret)) {
Laurent Vivierc35e1f92016-06-21 19:51:15 +02003176 if (fd_trans_host_to_target_data(fd)) {
Laurent Vivier2a03d3e2018-08-20 19:15:54 +02003177 abi_long trans;
3178 trans = fd_trans_host_to_target_data(fd)(host_msg, MIN(ret, len));
3179 if (is_error(trans)) {
3180 ret = trans;
3181 goto fail;
3182 }
Laurent Vivierc35e1f92016-06-21 19:51:15 +02003183 }
pbrook1be9e1d2006-11-19 15:26:04 +00003184 if (target_addr) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003185 host_to_target_sockaddr(target_addr, addr,
3186 MIN(addrlen, ret_addrlen));
3187 if (put_user_u32(ret_addrlen, target_addrlen)) {
bellard2f619692007-11-16 10:46:05 +00003188 ret = -TARGET_EFAULT;
3189 goto fail;
3190 }
pbrook1be9e1d2006-11-19 15:26:04 +00003191 }
3192 unlock_user(host_msg, msg, len);
3193 } else {
bellard2f619692007-11-16 10:46:05 +00003194fail:
pbrook1be9e1d2006-11-19 15:26:04 +00003195 unlock_user(host_msg, msg, 0);
3196 }
3197 return ret;
3198}
3199
j_mayer32407102007-09-26 23:01:49 +00003200#ifdef TARGET_NR_socketcall
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003201/* do_socketcall() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003202static abi_long do_socketcall(int num, abi_ulong vptr)
bellard31e31b82003-02-18 22:55:36 +00003203{
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003204 static const unsigned nargs[] = { /* number of arguments per operation */
3205 [TARGET_SYS_SOCKET] = 3, /* domain, type, protocol */
3206 [TARGET_SYS_BIND] = 3, /* fd, addr, addrlen */
3207 [TARGET_SYS_CONNECT] = 3, /* fd, addr, addrlen */
3208 [TARGET_SYS_LISTEN] = 2, /* fd, backlog */
3209 [TARGET_SYS_ACCEPT] = 3, /* fd, addr, addrlen */
3210 [TARGET_SYS_GETSOCKNAME] = 3, /* fd, addr, addrlen */
3211 [TARGET_SYS_GETPEERNAME] = 3, /* fd, addr, addrlen */
3212 [TARGET_SYS_SOCKETPAIR] = 4, /* domain, type, protocol, tab */
3213 [TARGET_SYS_SEND] = 4, /* fd, msg, len, flags */
3214 [TARGET_SYS_RECV] = 4, /* fd, msg, len, flags */
3215 [TARGET_SYS_SENDTO] = 6, /* fd, msg, len, flags, addr, addrlen */
3216 [TARGET_SYS_RECVFROM] = 6, /* fd, msg, len, flags, addr, addrlen */
3217 [TARGET_SYS_SHUTDOWN] = 2, /* fd, how */
3218 [TARGET_SYS_SETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
3219 [TARGET_SYS_GETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
3220 [TARGET_SYS_SENDMSG] = 3, /* fd, msg, flags */
3221 [TARGET_SYS_RECVMSG] = 3, /* fd, msg, flags */
3222 [TARGET_SYS_ACCEPT4] = 4, /* fd, addr, addrlen, flags */
3223 [TARGET_SYS_RECVMMSG] = 4, /* fd, msgvec, vlen, flags */
3224 [TARGET_SYS_SENDMMSG] = 4, /* fd, msgvec, vlen, flags */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003225 };
3226 abi_long a[6]; /* max 6 args */
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003227 unsigned i;
bellard31e31b82003-02-18 22:55:36 +00003228
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003229 /* check the range of the first argument num */
3230 /* (TARGET_SYS_SENDMMSG is the highest among TARGET_SYS_xxx) */
3231 if (num < 1 || num > TARGET_SYS_SENDMMSG) {
3232 return -TARGET_EINVAL;
3233 }
3234 /* ensure we have space for args */
3235 if (nargs[num] > ARRAY_SIZE(a)) {
3236 return -TARGET_EINVAL;
3237 }
3238 /* collect the arguments in a[] according to nargs[] */
3239 for (i = 0; i < nargs[num]; ++i) {
3240 if (get_user_ual(a[i], vptr + i * sizeof(abi_long)) != 0) {
3241 return -TARGET_EFAULT;
André Hentschelb9d36eb2014-01-06 20:18:52 +01003242 }
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003243 }
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003244 /* now when we have the args, invoke the appropriate underlying function */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003245 switch (num) {
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003246 case TARGET_SYS_SOCKET: /* domain, type, protocol */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003247 return do_socket(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003248 case TARGET_SYS_BIND: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003249 return do_bind(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003250 case TARGET_SYS_CONNECT: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003251 return do_connect(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003252 case TARGET_SYS_LISTEN: /* sockfd, backlog */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003253 return get_errno(listen(a[0], a[1]));
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003254 case TARGET_SYS_ACCEPT: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003255 return do_accept4(a[0], a[1], a[2], 0);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003256 case TARGET_SYS_GETSOCKNAME: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003257 return do_getsockname(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003258 case TARGET_SYS_GETPEERNAME: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003259 return do_getpeername(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003260 case TARGET_SYS_SOCKETPAIR: /* domain, type, protocol, tab */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003261 return do_socketpair(a[0], a[1], a[2], a[3]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003262 case TARGET_SYS_SEND: /* sockfd, msg, len, flags */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003263 return do_sendto(a[0], a[1], a[2], a[3], 0, 0);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003264 case TARGET_SYS_RECV: /* sockfd, msg, len, flags */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003265 return do_recvfrom(a[0], a[1], a[2], a[3], 0, 0);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003266 case TARGET_SYS_SENDTO: /* sockfd, msg, len, flags, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003267 return do_sendto(a[0], a[1], a[2], a[3], a[4], a[5]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003268 case TARGET_SYS_RECVFROM: /* sockfd, msg, len, flags, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003269 return do_recvfrom(a[0], a[1], a[2], a[3], a[4], a[5]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003270 case TARGET_SYS_SHUTDOWN: /* sockfd, how */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003271 return get_errno(shutdown(a[0], a[1]));
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003272 case TARGET_SYS_SETSOCKOPT: /* sockfd, level, optname, optval, optlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003273 return do_setsockopt(a[0], a[1], a[2], a[3], a[4]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003274 case TARGET_SYS_GETSOCKOPT: /* sockfd, level, optname, optval, optlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003275 return do_getsockopt(a[0], a[1], a[2], a[3], a[4]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003276 case TARGET_SYS_SENDMSG: /* sockfd, msg, flags */
3277 return do_sendrecvmsg(a[0], a[1], a[2], 1);
3278 case TARGET_SYS_RECVMSG: /* sockfd, msg, flags */
3279 return do_sendrecvmsg(a[0], a[1], a[2], 0);
3280 case TARGET_SYS_ACCEPT4: /* sockfd, addr, addrlen, flags */
3281 return do_accept4(a[0], a[1], a[2], a[3]);
3282 case TARGET_SYS_RECVMMSG: /* sockfd, msgvec, vlen, flags */
3283 return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0);
3284 case TARGET_SYS_SENDMMSG: /* sockfd, msgvec, vlen, flags */
3285 return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 1);
bellard31e31b82003-02-18 22:55:36 +00003286 default:
3287 gemu_log("Unsupported socketcall: %d\n", num);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003288 return -TARGET_EINVAL;
bellard31e31b82003-02-18 22:55:36 +00003289 }
bellard31e31b82003-02-18 22:55:36 +00003290}
j_mayer32407102007-09-26 23:01:49 +00003291#endif
bellard31e31b82003-02-18 22:55:36 +00003292
bellard8853f862004-02-22 14:57:26 +00003293#define N_SHM_REGIONS 32
3294
3295static struct shm_region {
Peter Maydellb6e17872016-02-09 15:57:11 +00003296 abi_ulong start;
3297 abi_ulong size;
3298 bool in_use;
bellard8853f862004-02-22 14:57:26 +00003299} shm_regions[N_SHM_REGIONS];
3300
Peter Maydell005eb2a2016-07-15 16:50:47 +01003301#ifndef TARGET_SEMID64_DS
3302/* asm-generic version of this struct */
3303struct target_semid64_ds
ths3eb6b042007-06-03 14:26:27 +00003304{
3305 struct target_ipc_perm sem_perm;
blueswir1992f48a2007-10-14 16:27:31 +00003306 abi_ulong sem_otime;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003307#if TARGET_ABI_BITS == 32
blueswir1992f48a2007-10-14 16:27:31 +00003308 abi_ulong __unused1;
Tom Musta03527342014-08-12 13:53:32 -05003309#endif
blueswir1992f48a2007-10-14 16:27:31 +00003310 abi_ulong sem_ctime;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003311#if TARGET_ABI_BITS == 32
blueswir1992f48a2007-10-14 16:27:31 +00003312 abi_ulong __unused2;
Tom Musta03527342014-08-12 13:53:32 -05003313#endif
blueswir1992f48a2007-10-14 16:27:31 +00003314 abi_ulong sem_nsems;
3315 abi_ulong __unused3;
3316 abi_ulong __unused4;
ths3eb6b042007-06-03 14:26:27 +00003317};
Peter Maydell005eb2a2016-07-15 16:50:47 +01003318#endif
ths3eb6b042007-06-03 14:26:27 +00003319
bellard579a97f2007-11-11 14:26:47 +00003320static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
3321 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00003322{
3323 struct target_ipc_perm *target_ip;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003324 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003325
bellard579a97f2007-11-11 14:26:47 +00003326 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
3327 return -TARGET_EFAULT;
Michael S. Tsirkine8bbe362009-09-30 18:56:44 +00003328 target_ip = &(target_sd->sem_perm);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003329 host_ip->__key = tswap32(target_ip->__key);
3330 host_ip->uid = tswap32(target_ip->uid);
3331 host_ip->gid = tswap32(target_ip->gid);
3332 host_ip->cuid = tswap32(target_ip->cuid);
3333 host_ip->cgid = tswap32(target_ip->cgid);
3334#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
3335 host_ip->mode = tswap32(target_ip->mode);
3336#else
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003337 host_ip->mode = tswap16(target_ip->mode);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003338#endif
3339#if defined(TARGET_PPC)
3340 host_ip->__seq = tswap32(target_ip->__seq);
3341#else
3342 host_ip->__seq = tswap16(target_ip->__seq);
3343#endif
ths3eb6b042007-06-03 14:26:27 +00003344 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00003345 return 0;
ths3eb6b042007-06-03 14:26:27 +00003346}
3347
bellard579a97f2007-11-11 14:26:47 +00003348static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
3349 struct ipc_perm *host_ip)
ths3eb6b042007-06-03 14:26:27 +00003350{
3351 struct target_ipc_perm *target_ip;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003352 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003353
bellard579a97f2007-11-11 14:26:47 +00003354 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3355 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00003356 target_ip = &(target_sd->sem_perm);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003357 target_ip->__key = tswap32(host_ip->__key);
3358 target_ip->uid = tswap32(host_ip->uid);
3359 target_ip->gid = tswap32(host_ip->gid);
3360 target_ip->cuid = tswap32(host_ip->cuid);
3361 target_ip->cgid = tswap32(host_ip->cgid);
3362#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
3363 target_ip->mode = tswap32(host_ip->mode);
3364#else
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003365 target_ip->mode = tswap16(host_ip->mode);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003366#endif
3367#if defined(TARGET_PPC)
3368 target_ip->__seq = tswap32(host_ip->__seq);
3369#else
3370 target_ip->__seq = tswap16(host_ip->__seq);
3371#endif
ths3eb6b042007-06-03 14:26:27 +00003372 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00003373 return 0;
ths3eb6b042007-06-03 14:26:27 +00003374}
3375
bellard579a97f2007-11-11 14:26:47 +00003376static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
3377 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00003378{
Peter Maydell005eb2a2016-07-15 16:50:47 +01003379 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003380
bellard579a97f2007-11-11 14:26:47 +00003381 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
3382 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00003383 if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
3384 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003385 host_sd->sem_nsems = tswapal(target_sd->sem_nsems);
3386 host_sd->sem_otime = tswapal(target_sd->sem_otime);
3387 host_sd->sem_ctime = tswapal(target_sd->sem_ctime);
ths3eb6b042007-06-03 14:26:27 +00003388 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00003389 return 0;
ths3eb6b042007-06-03 14:26:27 +00003390}
3391
bellard579a97f2007-11-11 14:26:47 +00003392static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
3393 struct semid_ds *host_sd)
ths3eb6b042007-06-03 14:26:27 +00003394{
Peter Maydell005eb2a2016-07-15 16:50:47 +01003395 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003396
bellard579a97f2007-11-11 14:26:47 +00003397 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3398 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00003399 if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
Dong Xu Wang3a931132011-11-29 16:52:38 +08003400 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003401 target_sd->sem_nsems = tswapal(host_sd->sem_nsems);
3402 target_sd->sem_otime = tswapal(host_sd->sem_otime);
3403 target_sd->sem_ctime = tswapal(host_sd->sem_ctime);
ths3eb6b042007-06-03 14:26:27 +00003404 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00003405 return 0;
ths3eb6b042007-06-03 14:26:27 +00003406}
3407
aurel32e5289082009-04-18 16:16:12 +00003408struct target_seminfo {
3409 int semmap;
3410 int semmni;
3411 int semmns;
3412 int semmnu;
3413 int semmsl;
3414 int semopm;
3415 int semume;
3416 int semusz;
3417 int semvmx;
3418 int semaem;
3419};
3420
3421static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
3422 struct seminfo *host_seminfo)
3423{
3424 struct target_seminfo *target_seminfo;
3425 if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
3426 return -TARGET_EFAULT;
3427 __put_user(host_seminfo->semmap, &target_seminfo->semmap);
3428 __put_user(host_seminfo->semmni, &target_seminfo->semmni);
3429 __put_user(host_seminfo->semmns, &target_seminfo->semmns);
3430 __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
3431 __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
3432 __put_user(host_seminfo->semopm, &target_seminfo->semopm);
3433 __put_user(host_seminfo->semume, &target_seminfo->semume);
3434 __put_user(host_seminfo->semusz, &target_seminfo->semusz);
3435 __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
3436 __put_user(host_seminfo->semaem, &target_seminfo->semaem);
3437 unlock_user_struct(target_seminfo, target_addr, 1);
3438 return 0;
3439}
3440
thsfa294812007-02-02 22:05:00 +00003441union semun {
3442 int val;
ths3eb6b042007-06-03 14:26:27 +00003443 struct semid_ds *buf;
thsfa294812007-02-02 22:05:00 +00003444 unsigned short *array;
aurel32e5289082009-04-18 16:16:12 +00003445 struct seminfo *__buf;
thsfa294812007-02-02 22:05:00 +00003446};
3447
ths3eb6b042007-06-03 14:26:27 +00003448union target_semun {
3449 int val;
aurel32e5289082009-04-18 16:16:12 +00003450 abi_ulong buf;
3451 abi_ulong array;
3452 abi_ulong __buf;
ths3eb6b042007-06-03 14:26:27 +00003453};
3454
aurel32e5289082009-04-18 16:16:12 +00003455static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
3456 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00003457{
aurel32e5289082009-04-18 16:16:12 +00003458 int nsems;
3459 unsigned short *array;
3460 union semun semun;
3461 struct semid_ds semid_ds;
3462 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00003463
aurel32e5289082009-04-18 16:16:12 +00003464 semun.buf = &semid_ds;
3465
3466 ret = semctl(semid, 0, IPC_STAT, semun);
3467 if (ret == -1)
3468 return get_errno(ret);
3469
3470 nsems = semid_ds.sem_nsems;
3471
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303472 *host_array = g_try_new(unsigned short, nsems);
Peter Maydell69d4c702014-02-17 18:55:34 +00003473 if (!*host_array) {
3474 return -TARGET_ENOMEM;
3475 }
aurel32e5289082009-04-18 16:16:12 +00003476 array = lock_user(VERIFY_READ, target_addr,
3477 nsems*sizeof(unsigned short), 1);
Peter Maydell69d4c702014-02-17 18:55:34 +00003478 if (!array) {
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303479 g_free(*host_array);
aurel32e5289082009-04-18 16:16:12 +00003480 return -TARGET_EFAULT;
Peter Maydell69d4c702014-02-17 18:55:34 +00003481 }
aurel32e5289082009-04-18 16:16:12 +00003482
3483 for(i=0; i<nsems; i++) {
3484 __get_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00003485 }
aurel32e5289082009-04-18 16:16:12 +00003486 unlock_user(array, target_addr, 0);
3487
bellard579a97f2007-11-11 14:26:47 +00003488 return 0;
ths3eb6b042007-06-03 14:26:27 +00003489}
3490
aurel32e5289082009-04-18 16:16:12 +00003491static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
3492 unsigned short **host_array)
ths3eb6b042007-06-03 14:26:27 +00003493{
aurel32e5289082009-04-18 16:16:12 +00003494 int nsems;
3495 unsigned short *array;
3496 union semun semun;
3497 struct semid_ds semid_ds;
3498 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00003499
aurel32e5289082009-04-18 16:16:12 +00003500 semun.buf = &semid_ds;
3501
3502 ret = semctl(semid, 0, IPC_STAT, semun);
3503 if (ret == -1)
3504 return get_errno(ret);
3505
3506 nsems = semid_ds.sem_nsems;
3507
3508 array = lock_user(VERIFY_WRITE, target_addr,
3509 nsems*sizeof(unsigned short), 0);
3510 if (!array)
3511 return -TARGET_EFAULT;
3512
3513 for(i=0; i<nsems; i++) {
3514 __put_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00003515 }
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303516 g_free(*host_array);
aurel32e5289082009-04-18 16:16:12 +00003517 unlock_user(array, target_addr, 1);
3518
bellard579a97f2007-11-11 14:26:47 +00003519 return 0;
ths3eb6b042007-06-03 14:26:27 +00003520}
3521
aurel32e5289082009-04-18 16:16:12 +00003522static inline abi_long do_semctl(int semid, int semnum, int cmd,
Stefan Weild1c002b2015-02-08 15:40:58 +01003523 abi_ulong target_arg)
ths3eb6b042007-06-03 14:26:27 +00003524{
Stefan Weild1c002b2015-02-08 15:40:58 +01003525 union target_semun target_su = { .buf = target_arg };
ths3eb6b042007-06-03 14:26:27 +00003526 union semun arg;
3527 struct semid_ds dsarg;
vibi sreenivasan7b8118e2009-06-19 13:34:39 +05303528 unsigned short *array = NULL;
aurel32e5289082009-04-18 16:16:12 +00003529 struct seminfo seminfo;
3530 abi_long ret = -TARGET_EINVAL;
3531 abi_long err;
3532 cmd &= 0xff;
ths3eb6b042007-06-03 14:26:27 +00003533
3534 switch( cmd ) {
3535 case GETVAL:
ths3eb6b042007-06-03 14:26:27 +00003536 case SETVAL:
Tom Musta5464bae2014-08-12 13:53:34 -05003537 /* In 64 bit cross-endian situations, we will erroneously pick up
3538 * the wrong half of the union for the "val" element. To rectify
3539 * this, the entire 8-byte structure is byteswapped, followed by
3540 * a swap of the 4 byte val field. In other cases, the data is
3541 * already in proper host byte order. */
3542 if (sizeof(target_su.val) != (sizeof(target_su.buf))) {
3543 target_su.buf = tswapal(target_su.buf);
3544 arg.val = tswap32(target_su.val);
3545 } else {
3546 arg.val = target_su.val;
3547 }
aurel32e5289082009-04-18 16:16:12 +00003548 ret = get_errno(semctl(semid, semnum, cmd, arg));
ths3eb6b042007-06-03 14:26:27 +00003549 break;
3550 case GETALL:
ths3eb6b042007-06-03 14:26:27 +00003551 case SETALL:
aurel32e5289082009-04-18 16:16:12 +00003552 err = target_to_host_semarray(semid, &array, target_su.array);
3553 if (err)
3554 return err;
3555 arg.array = array;
3556 ret = get_errno(semctl(semid, semnum, cmd, arg));
3557 err = host_to_target_semarray(semid, target_su.array, &array);
3558 if (err)
3559 return err;
ths3eb6b042007-06-03 14:26:27 +00003560 break;
3561 case IPC_STAT:
ths3eb6b042007-06-03 14:26:27 +00003562 case IPC_SET:
aurel32e5289082009-04-18 16:16:12 +00003563 case SEM_STAT:
3564 err = target_to_host_semid_ds(&dsarg, target_su.buf);
3565 if (err)
3566 return err;
3567 arg.buf = &dsarg;
3568 ret = get_errno(semctl(semid, semnum, cmd, arg));
3569 err = host_to_target_semid_ds(target_su.buf, &dsarg);
3570 if (err)
3571 return err;
ths3eb6b042007-06-03 14:26:27 +00003572 break;
aurel32e5289082009-04-18 16:16:12 +00003573 case IPC_INFO:
3574 case SEM_INFO:
3575 arg.__buf = &seminfo;
3576 ret = get_errno(semctl(semid, semnum, cmd, arg));
3577 err = host_to_target_seminfo(target_su.__buf, &seminfo);
3578 if (err)
3579 return err;
3580 break;
3581 case IPC_RMID:
3582 case GETPID:
3583 case GETNCNT:
3584 case GETZCNT:
3585 ret = get_errno(semctl(semid, semnum, cmd, NULL));
3586 break;
ths3eb6b042007-06-03 14:26:27 +00003587 }
3588
3589 return ret;
3590}
3591
aurel32e5289082009-04-18 16:16:12 +00003592struct target_sembuf {
3593 unsigned short sem_num;
3594 short sem_op;
3595 short sem_flg;
3596};
3597
3598static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
3599 abi_ulong target_addr,
3600 unsigned nsops)
3601{
3602 struct target_sembuf *target_sembuf;
3603 int i;
3604
3605 target_sembuf = lock_user(VERIFY_READ, target_addr,
3606 nsops*sizeof(struct target_sembuf), 1);
3607 if (!target_sembuf)
3608 return -TARGET_EFAULT;
3609
3610 for(i=0; i<nsops; i++) {
3611 __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
3612 __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
3613 __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
3614 }
3615
3616 unlock_user(target_sembuf, target_addr, 0);
3617
3618 return 0;
3619}
3620
3621static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops)
3622{
3623 struct sembuf sops[nsops];
Laurent Vivier524fa342019-05-29 10:48:04 +02003624 abi_long ret;
aurel32e5289082009-04-18 16:16:12 +00003625
3626 if (target_to_host_sembuf(sops, ptr, nsops))
3627 return -TARGET_EFAULT;
3628
Laurent Vivier524fa342019-05-29 10:48:04 +02003629 ret = -TARGET_ENOSYS;
3630#ifdef __NR_semtimedop
3631 ret = get_errno(safe_semtimedop(semid, sops, nsops, NULL));
3632#endif
3633#ifdef __NR_ipc
3634 if (ret == -TARGET_ENOSYS) {
3635 ret = get_errno(safe_ipc(IPCOP_semtimedop, semid, nsops, 0, sops, 0));
3636 }
3637#endif
3638 return ret;
aurel32e5289082009-04-18 16:16:12 +00003639}
3640
ths1bc012f2007-06-03 14:27:49 +00003641struct target_msqid_ds
3642{
aurel321c54ff92008-10-13 21:08:44 +00003643 struct target_ipc_perm msg_perm;
3644 abi_ulong msg_stime;
3645#if TARGET_ABI_BITS == 32
3646 abi_ulong __unused1;
3647#endif
3648 abi_ulong msg_rtime;
3649#if TARGET_ABI_BITS == 32
3650 abi_ulong __unused2;
3651#endif
3652 abi_ulong msg_ctime;
3653#if TARGET_ABI_BITS == 32
3654 abi_ulong __unused3;
3655#endif
3656 abi_ulong __msg_cbytes;
3657 abi_ulong msg_qnum;
3658 abi_ulong msg_qbytes;
3659 abi_ulong msg_lspid;
3660 abi_ulong msg_lrpid;
3661 abi_ulong __unused4;
3662 abi_ulong __unused5;
ths1bc012f2007-06-03 14:27:49 +00003663};
3664
bellard579a97f2007-11-11 14:26:47 +00003665static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
3666 abi_ulong target_addr)
ths1bc012f2007-06-03 14:27:49 +00003667{
3668 struct target_msqid_ds *target_md;
3669
bellard579a97f2007-11-11 14:26:47 +00003670 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
3671 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00003672 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
3673 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003674 host_md->msg_stime = tswapal(target_md->msg_stime);
3675 host_md->msg_rtime = tswapal(target_md->msg_rtime);
3676 host_md->msg_ctime = tswapal(target_md->msg_ctime);
3677 host_md->__msg_cbytes = tswapal(target_md->__msg_cbytes);
3678 host_md->msg_qnum = tswapal(target_md->msg_qnum);
3679 host_md->msg_qbytes = tswapal(target_md->msg_qbytes);
3680 host_md->msg_lspid = tswapal(target_md->msg_lspid);
3681 host_md->msg_lrpid = tswapal(target_md->msg_lrpid);
ths1bc012f2007-06-03 14:27:49 +00003682 unlock_user_struct(target_md, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00003683 return 0;
ths1bc012f2007-06-03 14:27:49 +00003684}
3685
bellard579a97f2007-11-11 14:26:47 +00003686static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
3687 struct msqid_ds *host_md)
ths1bc012f2007-06-03 14:27:49 +00003688{
3689 struct target_msqid_ds *target_md;
3690
bellard579a97f2007-11-11 14:26:47 +00003691 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
3692 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00003693 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
3694 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003695 target_md->msg_stime = tswapal(host_md->msg_stime);
3696 target_md->msg_rtime = tswapal(host_md->msg_rtime);
3697 target_md->msg_ctime = tswapal(host_md->msg_ctime);
3698 target_md->__msg_cbytes = tswapal(host_md->__msg_cbytes);
3699 target_md->msg_qnum = tswapal(host_md->msg_qnum);
3700 target_md->msg_qbytes = tswapal(host_md->msg_qbytes);
3701 target_md->msg_lspid = tswapal(host_md->msg_lspid);
3702 target_md->msg_lrpid = tswapal(host_md->msg_lrpid);
ths1bc012f2007-06-03 14:27:49 +00003703 unlock_user_struct(target_md, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00003704 return 0;
ths1bc012f2007-06-03 14:27:49 +00003705}
3706
aurel321c54ff92008-10-13 21:08:44 +00003707struct target_msginfo {
3708 int msgpool;
3709 int msgmap;
3710 int msgmax;
3711 int msgmnb;
3712 int msgmni;
3713 int msgssz;
3714 int msgtql;
3715 unsigned short int msgseg;
3716};
3717
3718static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
3719 struct msginfo *host_msginfo)
3720{
3721 struct target_msginfo *target_msginfo;
3722 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
3723 return -TARGET_EFAULT;
3724 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
3725 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
3726 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
3727 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
3728 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
3729 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
3730 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
3731 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
3732 unlock_user_struct(target_msginfo, target_addr, 1);
aurel3200b229a2008-10-24 13:12:52 +00003733 return 0;
aurel321c54ff92008-10-13 21:08:44 +00003734}
3735
3736static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
ths1bc012f2007-06-03 14:27:49 +00003737{
3738 struct msqid_ds dsarg;
aurel321c54ff92008-10-13 21:08:44 +00003739 struct msginfo msginfo;
3740 abi_long ret = -TARGET_EINVAL;
3741
3742 cmd &= 0xff;
3743
3744 switch (cmd) {
ths1bc012f2007-06-03 14:27:49 +00003745 case IPC_STAT:
3746 case IPC_SET:
aurel321c54ff92008-10-13 21:08:44 +00003747 case MSG_STAT:
3748 if (target_to_host_msqid_ds(&dsarg,ptr))
3749 return -TARGET_EFAULT;
3750 ret = get_errno(msgctl(msgid, cmd, &dsarg));
3751 if (host_to_target_msqid_ds(ptr,&dsarg))
3752 return -TARGET_EFAULT;
3753 break;
3754 case IPC_RMID:
3755 ret = get_errno(msgctl(msgid, cmd, NULL));
3756 break;
3757 case IPC_INFO:
3758 case MSG_INFO:
3759 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
3760 if (host_to_target_msginfo(ptr, &msginfo))
3761 return -TARGET_EFAULT;
3762 break;
ths1bc012f2007-06-03 14:27:49 +00003763 }
aurel321c54ff92008-10-13 21:08:44 +00003764
ths1bc012f2007-06-03 14:27:49 +00003765 return ret;
3766}
3767
3768struct target_msgbuf {
aurel321c54ff92008-10-13 21:08:44 +00003769 abi_long mtype;
3770 char mtext[1];
ths1bc012f2007-06-03 14:27:49 +00003771};
3772
blueswir1992f48a2007-10-14 16:27:31 +00003773static inline abi_long do_msgsnd(int msqid, abi_long msgp,
Tom Mustaedcc5f92014-08-12 13:53:37 -05003774 ssize_t msgsz, int msgflg)
ths1bc012f2007-06-03 14:27:49 +00003775{
3776 struct target_msgbuf *target_mb;
3777 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00003778 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00003779
Tom Mustaedcc5f92014-08-12 13:53:37 -05003780 if (msgsz < 0) {
3781 return -TARGET_EINVAL;
3782 }
3783
bellard579a97f2007-11-11 14:26:47 +00003784 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
3785 return -TARGET_EFAULT;
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303786 host_mb = g_try_malloc(msgsz + sizeof(long));
zhanghailiang29e03fc2014-08-14 15:29:18 +08003787 if (!host_mb) {
3788 unlock_user_struct(target_mb, msgp, 0);
3789 return -TARGET_ENOMEM;
3790 }
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003791 host_mb->mtype = (abi_long) tswapal(target_mb->mtype);
aurel321c54ff92008-10-13 21:08:44 +00003792 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
Laurent Vivier524fa342019-05-29 10:48:04 +02003793 ret = -TARGET_ENOSYS;
3794#ifdef __NR_msgsnd
Peter Maydell89f9fe42016-06-06 19:58:05 +01003795 ret = get_errno(safe_msgsnd(msqid, host_mb, msgsz, msgflg));
Laurent Vivier524fa342019-05-29 10:48:04 +02003796#endif
3797#ifdef __NR_ipc
3798 if (ret == -TARGET_ENOSYS) {
3799 ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg,
3800 host_mb, 0));
3801 }
3802#endif
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303803 g_free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00003804 unlock_user_struct(target_mb, msgp, 0);
3805
3806 return ret;
3807}
3808
blueswir1992f48a2007-10-14 16:27:31 +00003809static inline abi_long do_msgrcv(int msqid, abi_long msgp,
Peter Maydell99874f62016-05-20 19:00:56 +01003810 ssize_t msgsz, abi_long msgtyp,
blueswir1992f48a2007-10-14 16:27:31 +00003811 int msgflg)
ths1bc012f2007-06-03 14:27:49 +00003812{
3813 struct target_msgbuf *target_mb;
bellard579a97f2007-11-11 14:26:47 +00003814 char *target_mtext;
ths1bc012f2007-06-03 14:27:49 +00003815 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00003816 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00003817
Peter Maydell99874f62016-05-20 19:00:56 +01003818 if (msgsz < 0) {
3819 return -TARGET_EINVAL;
3820 }
3821
bellard579a97f2007-11-11 14:26:47 +00003822 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
3823 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00003824
Peter Maydell415d8472016-05-20 19:00:57 +01003825 host_mb = g_try_malloc(msgsz + sizeof(long));
3826 if (!host_mb) {
3827 ret = -TARGET_ENOMEM;
3828 goto end;
3829 }
Laurent Vivier524fa342019-05-29 10:48:04 +02003830 ret = -TARGET_ENOSYS;
3831#ifdef __NR_msgrcv
Peter Maydell89f9fe42016-06-06 19:58:05 +01003832 ret = get_errno(safe_msgrcv(msqid, host_mb, msgsz, msgtyp, msgflg));
Laurent Vivier524fa342019-05-29 10:48:04 +02003833#endif
3834#ifdef __NR_ipc
3835 if (ret == -TARGET_ENOSYS) {
3836 ret = get_errno(safe_ipc(IPCOP_CALL(1, IPCOP_msgrcv), msqid, msgsz,
3837 msgflg, host_mb, msgtyp));
3838 }
3839#endif
aurel321c54ff92008-10-13 21:08:44 +00003840
bellard579a97f2007-11-11 14:26:47 +00003841 if (ret > 0) {
3842 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
3843 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
3844 if (!target_mtext) {
3845 ret = -TARGET_EFAULT;
3846 goto end;
3847 }
aurel321c54ff92008-10-13 21:08:44 +00003848 memcpy(target_mb->mtext, host_mb->mtext, ret);
bellard579a97f2007-11-11 14:26:47 +00003849 unlock_user(target_mtext, target_mtext_addr, ret);
3850 }
aurel321c54ff92008-10-13 21:08:44 +00003851
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003852 target_mb->mtype = tswapal(host_mb->mtype);
ths1bc012f2007-06-03 14:27:49 +00003853
bellard579a97f2007-11-11 14:26:47 +00003854end:
3855 if (target_mb)
3856 unlock_user_struct(target_mb, msgp, 1);
Jim Meyering0d07fe42012-08-22 13:55:53 +02003857 g_free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00003858 return ret;
3859}
3860
Riku Voipio88a8c982009-04-03 10:42:00 +03003861static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
3862 abi_ulong target_addr)
3863{
3864 struct target_shmid_ds *target_sd;
3865
3866 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
3867 return -TARGET_EFAULT;
3868 if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
3869 return -TARGET_EFAULT;
3870 __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
3871 __get_user(host_sd->shm_atime, &target_sd->shm_atime);
3872 __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
3873 __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
3874 __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
3875 __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
3876 __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
3877 unlock_user_struct(target_sd, target_addr, 0);
3878 return 0;
3879}
3880
3881static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
3882 struct shmid_ds *host_sd)
3883{
3884 struct target_shmid_ds *target_sd;
3885
3886 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3887 return -TARGET_EFAULT;
3888 if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
3889 return -TARGET_EFAULT;
3890 __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
3891 __put_user(host_sd->shm_atime, &target_sd->shm_atime);
3892 __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
3893 __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
3894 __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
3895 __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
3896 __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
3897 unlock_user_struct(target_sd, target_addr, 1);
3898 return 0;
3899}
3900
3901struct target_shminfo {
3902 abi_ulong shmmax;
3903 abi_ulong shmmin;
3904 abi_ulong shmmni;
3905 abi_ulong shmseg;
3906 abi_ulong shmall;
3907};
3908
3909static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
3910 struct shminfo *host_shminfo)
3911{
3912 struct target_shminfo *target_shminfo;
3913 if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
3914 return -TARGET_EFAULT;
3915 __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
3916 __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
3917 __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
3918 __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
3919 __put_user(host_shminfo->shmall, &target_shminfo->shmall);
3920 unlock_user_struct(target_shminfo, target_addr, 1);
3921 return 0;
3922}
3923
3924struct target_shm_info {
3925 int used_ids;
3926 abi_ulong shm_tot;
3927 abi_ulong shm_rss;
3928 abi_ulong shm_swp;
3929 abi_ulong swap_attempts;
3930 abi_ulong swap_successes;
3931};
3932
3933static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
3934 struct shm_info *host_shm_info)
3935{
3936 struct target_shm_info *target_shm_info;
3937 if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
3938 return -TARGET_EFAULT;
3939 __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
3940 __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
3941 __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
3942 __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
3943 __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
3944 __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
3945 unlock_user_struct(target_shm_info, target_addr, 1);
3946 return 0;
3947}
3948
3949static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
3950{
3951 struct shmid_ds dsarg;
3952 struct shminfo shminfo;
3953 struct shm_info shm_info;
3954 abi_long ret = -TARGET_EINVAL;
3955
3956 cmd &= 0xff;
3957
3958 switch(cmd) {
3959 case IPC_STAT:
3960 case IPC_SET:
3961 case SHM_STAT:
3962 if (target_to_host_shmid_ds(&dsarg, buf))
3963 return -TARGET_EFAULT;
3964 ret = get_errno(shmctl(shmid, cmd, &dsarg));
3965 if (host_to_target_shmid_ds(buf, &dsarg))
3966 return -TARGET_EFAULT;
3967 break;
3968 case IPC_INFO:
3969 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
3970 if (host_to_target_shminfo(buf, &shminfo))
3971 return -TARGET_EFAULT;
3972 break;
3973 case SHM_INFO:
3974 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
3975 if (host_to_target_shm_info(buf, &shm_info))
3976 return -TARGET_EFAULT;
3977 break;
3978 case IPC_RMID:
3979 case SHM_LOCK:
3980 case SHM_UNLOCK:
3981 ret = get_errno(shmctl(shmid, cmd, NULL));
3982 break;
3983 }
3984
3985 return ret;
3986}
3987
Peter Maydellee8e7612016-07-11 16:48:11 +01003988#ifndef TARGET_FORCE_SHMLBA
3989/* For most architectures, SHMLBA is the same as the page size;
3990 * some architectures have larger values, in which case they should
3991 * define TARGET_FORCE_SHMLBA and provide a target_shmlba() function.
3992 * This corresponds to the kernel arch code defining __ARCH_FORCE_SHMLBA
3993 * and defining its own value for SHMLBA.
3994 *
3995 * The kernel also permits SHMLBA to be set by the architecture to a
3996 * value larger than the page size without setting __ARCH_FORCE_SHMLBA;
3997 * this means that addresses are rounded to the large size if
3998 * SHM_RND is set but addresses not aligned to that size are not rejected
3999 * as long as they are at least page-aligned. Since the only architecture
4000 * which uses this is ia64 this code doesn't provide for that oddity.
4001 */
4002static inline abi_ulong target_shmlba(CPUArchState *cpu_env)
4003{
4004 return TARGET_PAGE_SIZE;
4005}
4006#endif
4007
4008static inline abi_ulong do_shmat(CPUArchState *cpu_env,
4009 int shmid, abi_ulong shmaddr, int shmflg)
Riku Voipio88a8c982009-04-03 10:42:00 +03004010{
4011 abi_long raddr;
4012 void *host_raddr;
4013 struct shmid_ds shm_info;
4014 int i,ret;
Peter Maydellee8e7612016-07-11 16:48:11 +01004015 abi_ulong shmlba;
Riku Voipio88a8c982009-04-03 10:42:00 +03004016
4017 /* find out the length of the shared memory segment */
4018 ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
4019 if (is_error(ret)) {
4020 /* can't get length, bail out */
4021 return ret;
4022 }
4023
Peter Maydellee8e7612016-07-11 16:48:11 +01004024 shmlba = target_shmlba(cpu_env);
4025
4026 if (shmaddr & (shmlba - 1)) {
4027 if (shmflg & SHM_RND) {
4028 shmaddr &= ~(shmlba - 1);
4029 } else {
4030 return -TARGET_EINVAL;
4031 }
4032 }
Max Filippovebf9a362018-03-07 13:50:10 -08004033 if (!guest_range_valid(shmaddr, shm_info.shm_segsz)) {
4034 return -TARGET_EINVAL;
4035 }
Peter Maydellee8e7612016-07-11 16:48:11 +01004036
Riku Voipio88a8c982009-04-03 10:42:00 +03004037 mmap_lock();
4038
4039 if (shmaddr)
4040 host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg);
4041 else {
4042 abi_ulong mmap_start;
4043
Richard Henderson30ab9ef2019-05-19 13:19:52 -07004044 /* In order to use the host shmat, we need to honor host SHMLBA. */
4045 mmap_start = mmap_find_vma(0, shm_info.shm_segsz, MAX(SHMLBA, shmlba));
Riku Voipio88a8c982009-04-03 10:42:00 +03004046
4047 if (mmap_start == -1) {
4048 errno = ENOMEM;
4049 host_raddr = (void *)-1;
4050 } else
4051 host_raddr = shmat(shmid, g2h(mmap_start), shmflg | SHM_REMAP);
4052 }
4053
4054 if (host_raddr == (void *)-1) {
4055 mmap_unlock();
4056 return get_errno((long)host_raddr);
4057 }
4058 raddr=h2g((unsigned long)host_raddr);
4059
4060 page_set_flags(raddr, raddr + shm_info.shm_segsz,
4061 PAGE_VALID | PAGE_READ |
4062 ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE));
4063
4064 for (i = 0; i < N_SHM_REGIONS; i++) {
Peter Maydellb6e17872016-02-09 15:57:11 +00004065 if (!shm_regions[i].in_use) {
4066 shm_regions[i].in_use = true;
Riku Voipio88a8c982009-04-03 10:42:00 +03004067 shm_regions[i].start = raddr;
4068 shm_regions[i].size = shm_info.shm_segsz;
4069 break;
4070 }
4071 }
4072
4073 mmap_unlock();
4074 return raddr;
4075
4076}
4077
4078static inline abi_long do_shmdt(abi_ulong shmaddr)
4079{
4080 int i;
Max Filippov3c5f6a52018-02-28 14:16:04 -08004081 abi_long rv;
4082
4083 mmap_lock();
Riku Voipio88a8c982009-04-03 10:42:00 +03004084
4085 for (i = 0; i < N_SHM_REGIONS; ++i) {
Peter Maydellb6e17872016-02-09 15:57:11 +00004086 if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
4087 shm_regions[i].in_use = false;
takasi-y@ops.dti.ne.jpe00ac242010-04-11 02:09:57 +09004088 page_set_flags(shmaddr, shmaddr + shm_regions[i].size, 0);
Riku Voipio88a8c982009-04-03 10:42:00 +03004089 break;
4090 }
4091 }
Max Filippov3c5f6a52018-02-28 14:16:04 -08004092 rv = get_errno(shmdt(g2h(shmaddr)));
Riku Voipio88a8c982009-04-03 10:42:00 +03004093
Max Filippov3c5f6a52018-02-28 14:16:04 -08004094 mmap_unlock();
4095
4096 return rv;
Riku Voipio88a8c982009-04-03 10:42:00 +03004097}
4098
aurel321c54ff92008-10-13 21:08:44 +00004099#ifdef TARGET_NR_ipc
pbrook53a59602006-03-25 19:31:22 +00004100/* ??? This only works with linear mappings. */
ths0da46a62007-10-20 20:23:07 +00004101/* do_ipc() must return target values and target errnos. */
Peter Maydellee8e7612016-07-11 16:48:11 +01004102static abi_long do_ipc(CPUArchState *cpu_env,
4103 unsigned int call, abi_long first,
Tom Musta37ed0952014-08-12 13:53:35 -05004104 abi_long second, abi_long third,
blueswir1992f48a2007-10-14 16:27:31 +00004105 abi_long ptr, abi_long fifth)
bellard8853f862004-02-22 14:57:26 +00004106{
4107 int version;
blueswir1992f48a2007-10-14 16:27:31 +00004108 abi_long ret = 0;
bellard8853f862004-02-22 14:57:26 +00004109
4110 version = call >> 16;
4111 call &= 0xffff;
4112
4113 switch (call) {
thsfa294812007-02-02 22:05:00 +00004114 case IPCOP_semop:
aurel32e5289082009-04-18 16:16:12 +00004115 ret = do_semop(first, ptr, second);
thsfa294812007-02-02 22:05:00 +00004116 break;
4117
4118 case IPCOP_semget:
4119 ret = get_errno(semget(first, second, third));
4120 break;
4121
Tom Musta5d2fa8e2014-08-12 13:53:33 -05004122 case IPCOP_semctl: {
4123 /* The semun argument to semctl is passed by value, so dereference the
4124 * ptr argument. */
4125 abi_ulong atptr;
Tom Musta37ed0952014-08-12 13:53:35 -05004126 get_user_ual(atptr, ptr);
Stefan Weild1c002b2015-02-08 15:40:58 +01004127 ret = do_semctl(first, second, third, atptr);
thsfa294812007-02-02 22:05:00 +00004128 break;
Tom Musta5d2fa8e2014-08-12 13:53:33 -05004129 }
thsd96372e2007-02-02 22:05:44 +00004130
aurel321c54ff92008-10-13 21:08:44 +00004131 case IPCOP_msgget:
4132 ret = get_errno(msgget(first, second));
4133 break;
thsd96372e2007-02-02 22:05:44 +00004134
aurel321c54ff92008-10-13 21:08:44 +00004135 case IPCOP_msgsnd:
4136 ret = do_msgsnd(first, ptr, second, third);
4137 break;
thsd96372e2007-02-02 22:05:44 +00004138
aurel321c54ff92008-10-13 21:08:44 +00004139 case IPCOP_msgctl:
4140 ret = do_msgctl(first, second, ptr);
4141 break;
thsd96372e2007-02-02 22:05:44 +00004142
aurel321c54ff92008-10-13 21:08:44 +00004143 case IPCOP_msgrcv:
4144 switch (version) {
4145 case 0:
4146 {
4147 struct target_ipc_kludge {
4148 abi_long msgp;
4149 abi_long msgtyp;
4150 } *tmp;
thsd96372e2007-02-02 22:05:44 +00004151
aurel321c54ff92008-10-13 21:08:44 +00004152 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
4153 ret = -TARGET_EFAULT;
4154 break;
ths1bc012f2007-06-03 14:27:49 +00004155 }
aurel321c54ff92008-10-13 21:08:44 +00004156
Laurent Vivier79dd77d2012-12-20 11:00:11 +00004157 ret = do_msgrcv(first, tswapal(tmp->msgp), second, tswapal(tmp->msgtyp), third);
aurel321c54ff92008-10-13 21:08:44 +00004158
4159 unlock_user_struct(tmp, ptr, 0);
4160 break;
4161 }
4162 default:
4163 ret = do_msgrcv(first, ptr, second, fifth, third);
4164 }
4165 break;
thsd96372e2007-02-02 22:05:44 +00004166
bellard8853f862004-02-22 14:57:26 +00004167 case IPCOP_shmat:
Riku Voipio88a8c982009-04-03 10:42:00 +03004168 switch (version) {
4169 default:
bellard5a4a8982007-11-11 17:39:18 +00004170 {
4171 abi_ulong raddr;
Peter Maydellee8e7612016-07-11 16:48:11 +01004172 raddr = do_shmat(cpu_env, first, ptr, second);
Riku Voipio88a8c982009-04-03 10:42:00 +03004173 if (is_error(raddr))
4174 return get_errno(raddr);
bellard2f619692007-11-16 10:46:05 +00004175 if (put_user_ual(raddr, third))
bellard5a4a8982007-11-11 17:39:18 +00004176 return -TARGET_EFAULT;
Riku Voipio88a8c982009-04-03 10:42:00 +03004177 break;
4178 }
4179 case 1:
4180 ret = -TARGET_EINVAL;
4181 break;
bellard5a4a8982007-11-11 17:39:18 +00004182 }
bellard8853f862004-02-22 14:57:26 +00004183 break;
4184 case IPCOP_shmdt:
Riku Voipio88a8c982009-04-03 10:42:00 +03004185 ret = do_shmdt(ptr);
bellard8853f862004-02-22 14:57:26 +00004186 break;
4187
4188 case IPCOP_shmget:
4189 /* IPC_* flag values are the same on all linux platforms */
4190 ret = get_errno(shmget(first, second, third));
4191 break;
4192
4193 /* IPC_* and SHM_* command values are the same on all linux platforms */
4194 case IPCOP_shmctl:
Petar Jovanovica2926782013-10-30 14:46:32 +01004195 ret = do_shmctl(first, second, ptr);
bellard8853f862004-02-22 14:57:26 +00004196 break;
4197 default:
j_mayer32407102007-09-26 23:01:49 +00004198 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00004199 ret = -TARGET_ENOSYS;
bellard8853f862004-02-22 14:57:26 +00004200 break;
4201 }
4202 return ret;
4203}
j_mayer32407102007-09-26 23:01:49 +00004204#endif
bellard8853f862004-02-22 14:57:26 +00004205
bellard31e31b82003-02-18 22:55:36 +00004206/* kernel structure types definitions */
bellard31e31b82003-02-18 22:55:36 +00004207
Blue Swirl001faf32009-05-13 17:53:17 +00004208#define STRUCT(name, ...) STRUCT_ ## name,
bellard31e31b82003-02-18 22:55:36 +00004209#define STRUCT_SPECIAL(name) STRUCT_ ## name,
4210enum {
4211#include "syscall_types.h"
Alexander Graf8be656b2015-05-06 23:47:32 +02004212STRUCT_MAX
bellard31e31b82003-02-18 22:55:36 +00004213};
4214#undef STRUCT
4215#undef STRUCT_SPECIAL
4216
Blue Swirl001faf32009-05-13 17:53:17 +00004217#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
bellard31e31b82003-02-18 22:55:36 +00004218#define STRUCT_SPECIAL(name)
4219#include "syscall_types.h"
4220#undef STRUCT
4221#undef STRUCT_SPECIAL
4222
Peter Maydelld2ef05b2011-01-06 15:04:17 +00004223typedef struct IOCTLEntry IOCTLEntry;
4224
4225typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004226 int fd, int cmd, abi_long arg);
Peter Maydelld2ef05b2011-01-06 15:04:17 +00004227
4228struct IOCTLEntry {
Ed Swierk9c6bf9c2014-12-16 12:55:31 -08004229 int target_cmd;
bellard2ab83ea2003-06-15 19:56:46 +00004230 unsigned int host_cmd;
bellard31e31b82003-02-18 22:55:36 +00004231 const char *name;
4232 int access;
Peter Maydelld2ef05b2011-01-06 15:04:17 +00004233 do_ioctl_fn *do_ioctl;
bellard1a9353d2003-03-16 20:28:50 +00004234 const argtype arg_type[5];
Peter Maydelld2ef05b2011-01-06 15:04:17 +00004235};
bellard31e31b82003-02-18 22:55:36 +00004236
4237#define IOC_R 0x0001
4238#define IOC_W 0x0002
4239#define IOC_RW (IOC_R | IOC_W)
4240
4241#define MAX_STRUCT_SIZE 4096
4242
Peter Maydelldace20d2011-01-10 13:11:24 +00004243#ifdef CONFIG_FIEMAP
Peter Maydell285da2b2011-01-06 15:04:18 +00004244/* So fiemap access checks don't overflow on 32 bit systems.
4245 * This is very slightly smaller than the limit imposed by
4246 * the underlying kernel.
4247 */
4248#define FIEMAP_MAX_EXTENTS ((UINT_MAX - sizeof(struct fiemap)) \
4249 / sizeof(struct fiemap_extent))
4250
4251static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004252 int fd, int cmd, abi_long arg)
Peter Maydell285da2b2011-01-06 15:04:18 +00004253{
4254 /* The parameter for this ioctl is a struct fiemap followed
4255 * by an array of struct fiemap_extent whose size is set
4256 * in fiemap->fm_extent_count. The array is filled in by the
4257 * ioctl.
4258 */
4259 int target_size_in, target_size_out;
4260 struct fiemap *fm;
4261 const argtype *arg_type = ie->arg_type;
4262 const argtype extent_arg_type[] = { MK_STRUCT(STRUCT_fiemap_extent) };
4263 void *argptr, *p;
4264 abi_long ret;
4265 int i, extent_size = thunk_type_size(extent_arg_type, 0);
4266 uint32_t outbufsz;
4267 int free_fm = 0;
4268
4269 assert(arg_type[0] == TYPE_PTR);
4270 assert(ie->access == IOC_RW);
4271 arg_type++;
4272 target_size_in = thunk_type_size(arg_type, 0);
4273 argptr = lock_user(VERIFY_READ, arg, target_size_in, 1);
4274 if (!argptr) {
4275 return -TARGET_EFAULT;
4276 }
4277 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4278 unlock_user(argptr, arg, 0);
4279 fm = (struct fiemap *)buf_temp;
4280 if (fm->fm_extent_count > FIEMAP_MAX_EXTENTS) {
4281 return -TARGET_EINVAL;
4282 }
4283
4284 outbufsz = sizeof (*fm) +
4285 (sizeof(struct fiemap_extent) * fm->fm_extent_count);
4286
4287 if (outbufsz > MAX_STRUCT_SIZE) {
4288 /* We can't fit all the extents into the fixed size buffer.
4289 * Allocate one that is large enough and use it instead.
4290 */
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304291 fm = g_try_malloc(outbufsz);
Peter Maydell285da2b2011-01-06 15:04:18 +00004292 if (!fm) {
4293 return -TARGET_ENOMEM;
4294 }
4295 memcpy(fm, buf_temp, sizeof(struct fiemap));
4296 free_fm = 1;
4297 }
Peter Maydell49ca6f32016-06-06 19:58:14 +01004298 ret = get_errno(safe_ioctl(fd, ie->host_cmd, fm));
Peter Maydell285da2b2011-01-06 15:04:18 +00004299 if (!is_error(ret)) {
4300 target_size_out = target_size_in;
4301 /* An extent_count of 0 means we were only counting the extents
4302 * so there are no structs to copy
4303 */
4304 if (fm->fm_extent_count != 0) {
4305 target_size_out += fm->fm_mapped_extents * extent_size;
4306 }
4307 argptr = lock_user(VERIFY_WRITE, arg, target_size_out, 0);
4308 if (!argptr) {
4309 ret = -TARGET_EFAULT;
4310 } else {
4311 /* Convert the struct fiemap */
4312 thunk_convert(argptr, fm, arg_type, THUNK_TARGET);
4313 if (fm->fm_extent_count != 0) {
4314 p = argptr + target_size_in;
4315 /* ...and then all the struct fiemap_extents */
4316 for (i = 0; i < fm->fm_mapped_extents; i++) {
4317 thunk_convert(p, &fm->fm_extents[i], extent_arg_type,
4318 THUNK_TARGET);
4319 p += extent_size;
4320 }
4321 }
4322 unlock_user(argptr, arg, target_size_out);
4323 }
4324 }
4325 if (free_fm) {
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304326 g_free(fm);
Peter Maydell285da2b2011-01-06 15:04:18 +00004327 }
4328 return ret;
4329}
Peter Maydelldace20d2011-01-10 13:11:24 +00004330#endif
Peter Maydell285da2b2011-01-06 15:04:18 +00004331
Laurent Vivier059c2f22011-03-30 00:12:12 +02004332static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004333 int fd, int cmd, abi_long arg)
Laurent Vivier059c2f22011-03-30 00:12:12 +02004334{
4335 const argtype *arg_type = ie->arg_type;
4336 int target_size;
4337 void *argptr;
4338 int ret;
4339 struct ifconf *host_ifconf;
4340 uint32_t outbufsz;
4341 const argtype ifreq_arg_type[] = { MK_STRUCT(STRUCT_sockaddr_ifreq) };
4342 int target_ifreq_size;
4343 int nb_ifreq;
4344 int free_buf = 0;
4345 int i;
4346 int target_ifc_len;
4347 abi_long target_ifc_buf;
4348 int host_ifc_len;
4349 char *host_ifc_buf;
4350
4351 assert(arg_type[0] == TYPE_PTR);
4352 assert(ie->access == IOC_RW);
4353
4354 arg_type++;
4355 target_size = thunk_type_size(arg_type, 0);
4356
4357 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4358 if (!argptr)
4359 return -TARGET_EFAULT;
4360 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4361 unlock_user(argptr, arg, 0);
4362
4363 host_ifconf = (struct ifconf *)(unsigned long)buf_temp;
Laurent Vivier059c2f22011-03-30 00:12:12 +02004364 target_ifc_buf = (abi_long)(unsigned long)host_ifconf->ifc_buf;
Laurent Vivier059c2f22011-03-30 00:12:12 +02004365 target_ifreq_size = thunk_type_size(ifreq_arg_type, 0);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004366
Kan Li22e4a2672018-10-24 20:13:03 +00004367 if (target_ifc_buf != 0) {
4368 target_ifc_len = host_ifconf->ifc_len;
4369 nb_ifreq = target_ifc_len / target_ifreq_size;
4370 host_ifc_len = nb_ifreq * sizeof(struct ifreq);
4371
4372 outbufsz = sizeof(*host_ifconf) + host_ifc_len;
4373 if (outbufsz > MAX_STRUCT_SIZE) {
4374 /*
4375 * We can't fit all the extents into the fixed size buffer.
4376 * Allocate one that is large enough and use it instead.
4377 */
4378 host_ifconf = malloc(outbufsz);
4379 if (!host_ifconf) {
4380 return -TARGET_ENOMEM;
4381 }
4382 memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf));
4383 free_buf = 1;
Laurent Vivier059c2f22011-03-30 00:12:12 +02004384 }
Kan Li22e4a2672018-10-24 20:13:03 +00004385 host_ifc_buf = (char *)host_ifconf + sizeof(*host_ifconf);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004386
Kan Li22e4a2672018-10-24 20:13:03 +00004387 host_ifconf->ifc_len = host_ifc_len;
4388 } else {
4389 host_ifc_buf = NULL;
4390 }
Laurent Vivier059c2f22011-03-30 00:12:12 +02004391 host_ifconf->ifc_buf = host_ifc_buf;
4392
Peter Maydell49ca6f32016-06-06 19:58:14 +01004393 ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_ifconf));
Laurent Vivier059c2f22011-03-30 00:12:12 +02004394 if (!is_error(ret)) {
4395 /* convert host ifc_len to target ifc_len */
4396
4397 nb_ifreq = host_ifconf->ifc_len / sizeof(struct ifreq);
4398 target_ifc_len = nb_ifreq * target_ifreq_size;
4399 host_ifconf->ifc_len = target_ifc_len;
4400
4401 /* restore target ifc_buf */
4402
4403 host_ifconf->ifc_buf = (char *)(unsigned long)target_ifc_buf;
4404
4405 /* copy struct ifconf to target user */
4406
4407 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
4408 if (!argptr)
4409 return -TARGET_EFAULT;
4410 thunk_convert(argptr, host_ifconf, arg_type, THUNK_TARGET);
4411 unlock_user(argptr, arg, target_size);
4412
Kan Li22e4a2672018-10-24 20:13:03 +00004413 if (target_ifc_buf != 0) {
4414 /* copy ifreq[] to target user */
4415 argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0);
4416 for (i = 0; i < nb_ifreq ; i++) {
4417 thunk_convert(argptr + i * target_ifreq_size,
4418 host_ifc_buf + i * sizeof(struct ifreq),
4419 ifreq_arg_type, THUNK_TARGET);
4420 }
4421 unlock_user(argptr, target_ifc_buf, target_ifc_len);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004422 }
Laurent Vivier059c2f22011-03-30 00:12:12 +02004423 }
4424
4425 if (free_buf) {
4426 free(host_ifconf);
4427 }
4428
4429 return ret;
4430}
4431
Cortland Tölvaa1333672018-10-08 09:35:21 -07004432#if defined(CONFIG_USBFS)
4433#if HOST_LONG_BITS > 64
4434#error USBDEVFS thunks do not support >64 bit hosts yet.
4435#endif
4436struct live_urb {
4437 uint64_t target_urb_adr;
4438 uint64_t target_buf_adr;
4439 char *target_buf_ptr;
4440 struct usbdevfs_urb host_urb;
4441};
4442
4443static GHashTable *usbdevfs_urb_hashtable(void)
4444{
4445 static GHashTable *urb_hashtable;
4446
4447 if (!urb_hashtable) {
4448 urb_hashtable = g_hash_table_new(g_int64_hash, g_int64_equal);
4449 }
4450 return urb_hashtable;
4451}
4452
4453static void urb_hashtable_insert(struct live_urb *urb)
4454{
4455 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
4456 g_hash_table_insert(urb_hashtable, urb, urb);
4457}
4458
4459static struct live_urb *urb_hashtable_lookup(uint64_t target_urb_adr)
4460{
4461 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
4462 return g_hash_table_lookup(urb_hashtable, &target_urb_adr);
4463}
4464
4465static void urb_hashtable_remove(struct live_urb *urb)
4466{
4467 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
4468 g_hash_table_remove(urb_hashtable, urb);
4469}
4470
4471static abi_long
4472do_ioctl_usbdevfs_reapurb(const IOCTLEntry *ie, uint8_t *buf_temp,
4473 int fd, int cmd, abi_long arg)
4474{
4475 const argtype usbfsurb_arg_type[] = { MK_STRUCT(STRUCT_usbdevfs_urb) };
4476 const argtype ptrvoid_arg_type[] = { TYPE_PTRVOID, 0, 0 };
4477 struct live_urb *lurb;
4478 void *argptr;
4479 uint64_t hurb;
4480 int target_size;
4481 uintptr_t target_urb_adr;
4482 abi_long ret;
4483
4484 target_size = thunk_type_size(usbfsurb_arg_type, THUNK_TARGET);
4485
4486 memset(buf_temp, 0, sizeof(uint64_t));
4487 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
4488 if (is_error(ret)) {
4489 return ret;
4490 }
4491
4492 memcpy(&hurb, buf_temp, sizeof(uint64_t));
4493 lurb = (void *)((uintptr_t)hurb - offsetof(struct live_urb, host_urb));
4494 if (!lurb->target_urb_adr) {
4495 return -TARGET_EFAULT;
4496 }
4497 urb_hashtable_remove(lurb);
4498 unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr,
4499 lurb->host_urb.buffer_length);
4500 lurb->target_buf_ptr = NULL;
4501
4502 /* restore the guest buffer pointer */
4503 lurb->host_urb.buffer = (void *)(uintptr_t)lurb->target_buf_adr;
4504
4505 /* update the guest urb struct */
4506 argptr = lock_user(VERIFY_WRITE, lurb->target_urb_adr, target_size, 0);
4507 if (!argptr) {
4508 g_free(lurb);
4509 return -TARGET_EFAULT;
4510 }
4511 thunk_convert(argptr, &lurb->host_urb, usbfsurb_arg_type, THUNK_TARGET);
4512 unlock_user(argptr, lurb->target_urb_adr, target_size);
4513
4514 target_size = thunk_type_size(ptrvoid_arg_type, THUNK_TARGET);
4515 /* write back the urb handle */
4516 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
4517 if (!argptr) {
4518 g_free(lurb);
4519 return -TARGET_EFAULT;
4520 }
4521
4522 /* GHashTable uses 64-bit keys but thunk_convert expects uintptr_t */
4523 target_urb_adr = lurb->target_urb_adr;
4524 thunk_convert(argptr, &target_urb_adr, ptrvoid_arg_type, THUNK_TARGET);
4525 unlock_user(argptr, arg, target_size);
4526
4527 g_free(lurb);
4528 return ret;
4529}
4530
4531static abi_long
4532do_ioctl_usbdevfs_discardurb(const IOCTLEntry *ie,
4533 uint8_t *buf_temp __attribute__((unused)),
4534 int fd, int cmd, abi_long arg)
4535{
4536 struct live_urb *lurb;
4537
4538 /* map target address back to host URB with metadata. */
4539 lurb = urb_hashtable_lookup(arg);
4540 if (!lurb) {
4541 return -TARGET_EFAULT;
4542 }
4543 return get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
4544}
4545
4546static abi_long
4547do_ioctl_usbdevfs_submiturb(const IOCTLEntry *ie, uint8_t *buf_temp,
4548 int fd, int cmd, abi_long arg)
4549{
4550 const argtype *arg_type = ie->arg_type;
4551 int target_size;
4552 abi_long ret;
4553 void *argptr;
4554 int rw_dir;
4555 struct live_urb *lurb;
4556
4557 /*
4558 * each submitted URB needs to map to a unique ID for the
4559 * kernel, and that unique ID needs to be a pointer to
4560 * host memory. hence, we need to malloc for each URB.
4561 * isochronous transfers have a variable length struct.
4562 */
4563 arg_type++;
4564 target_size = thunk_type_size(arg_type, THUNK_TARGET);
4565
4566 /* construct host copy of urb and metadata */
4567 lurb = g_try_malloc0(sizeof(struct live_urb));
4568 if (!lurb) {
4569 return -TARGET_ENOMEM;
4570 }
4571
4572 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4573 if (!argptr) {
4574 g_free(lurb);
4575 return -TARGET_EFAULT;
4576 }
4577 thunk_convert(&lurb->host_urb, argptr, arg_type, THUNK_HOST);
4578 unlock_user(argptr, arg, 0);
4579
4580 lurb->target_urb_adr = arg;
4581 lurb->target_buf_adr = (uintptr_t)lurb->host_urb.buffer;
4582
4583 /* buffer space used depends on endpoint type so lock the entire buffer */
4584 /* control type urbs should check the buffer contents for true direction */
4585 rw_dir = lurb->host_urb.endpoint & USB_DIR_IN ? VERIFY_WRITE : VERIFY_READ;
4586 lurb->target_buf_ptr = lock_user(rw_dir, lurb->target_buf_adr,
4587 lurb->host_urb.buffer_length, 1);
4588 if (lurb->target_buf_ptr == NULL) {
4589 g_free(lurb);
4590 return -TARGET_EFAULT;
4591 }
4592
4593 /* update buffer pointer in host copy */
4594 lurb->host_urb.buffer = lurb->target_buf_ptr;
4595
4596 ret = get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
4597 if (is_error(ret)) {
4598 unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr, 0);
4599 g_free(lurb);
4600 } else {
4601 urb_hashtable_insert(lurb);
4602 }
4603
4604 return ret;
4605}
4606#endif /* CONFIG_USBFS */
4607
Alexander Graf56e904e2012-01-31 18:42:06 +01004608static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004609 int cmd, abi_long arg)
Alexander Graf56e904e2012-01-31 18:42:06 +01004610{
4611 void *argptr;
4612 struct dm_ioctl *host_dm;
4613 abi_long guest_data;
4614 uint32_t guest_data_size;
4615 int target_size;
4616 const argtype *arg_type = ie->arg_type;
4617 abi_long ret;
4618 void *big_buf = NULL;
4619 char *host_data;
4620
4621 arg_type++;
4622 target_size = thunk_type_size(arg_type, 0);
4623 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4624 if (!argptr) {
4625 ret = -TARGET_EFAULT;
4626 goto out;
4627 }
4628 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4629 unlock_user(argptr, arg, 0);
4630
4631 /* buf_temp is too small, so fetch things into a bigger buffer */
4632 big_buf = g_malloc0(((struct dm_ioctl*)buf_temp)->data_size * 2);
4633 memcpy(big_buf, buf_temp, target_size);
4634 buf_temp = big_buf;
4635 host_dm = big_buf;
4636
4637 guest_data = arg + host_dm->data_start;
4638 if ((guest_data - arg) < 0) {
Peter Maydellf9757b12016-07-12 13:02:14 +01004639 ret = -TARGET_EINVAL;
Alexander Graf56e904e2012-01-31 18:42:06 +01004640 goto out;
4641 }
4642 guest_data_size = host_dm->data_size - host_dm->data_start;
4643 host_data = (char*)host_dm + host_dm->data_start;
4644
4645 argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1);
Peter Maydell32112152016-07-12 13:02:13 +01004646 if (!argptr) {
4647 ret = -TARGET_EFAULT;
4648 goto out;
4649 }
4650
Alexander Graf56e904e2012-01-31 18:42:06 +01004651 switch (ie->host_cmd) {
4652 case DM_REMOVE_ALL:
4653 case DM_LIST_DEVICES:
4654 case DM_DEV_CREATE:
4655 case DM_DEV_REMOVE:
4656 case DM_DEV_SUSPEND:
4657 case DM_DEV_STATUS:
4658 case DM_DEV_WAIT:
4659 case DM_TABLE_STATUS:
4660 case DM_TABLE_CLEAR:
4661 case DM_TABLE_DEPS:
4662 case DM_LIST_VERSIONS:
4663 /* no input data */
4664 break;
4665 case DM_DEV_RENAME:
4666 case DM_DEV_SET_GEOMETRY:
4667 /* data contains only strings */
4668 memcpy(host_data, argptr, guest_data_size);
4669 break;
4670 case DM_TARGET_MSG:
4671 memcpy(host_data, argptr, guest_data_size);
4672 *(uint64_t*)host_data = tswap64(*(uint64_t*)argptr);
4673 break;
4674 case DM_TABLE_LOAD:
4675 {
4676 void *gspec = argptr;
4677 void *cur_data = host_data;
4678 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
4679 int spec_size = thunk_type_size(arg_type, 0);
4680 int i;
4681
4682 for (i = 0; i < host_dm->target_count; i++) {
4683 struct dm_target_spec *spec = cur_data;
4684 uint32_t next;
4685 int slen;
4686
4687 thunk_convert(spec, gspec, arg_type, THUNK_HOST);
4688 slen = strlen((char*)gspec + spec_size) + 1;
4689 next = spec->next;
4690 spec->next = sizeof(*spec) + slen;
4691 strcpy((char*)&spec[1], gspec + spec_size);
4692 gspec += next;
4693 cur_data += spec->next;
4694 }
4695 break;
4696 }
4697 default:
4698 ret = -TARGET_EINVAL;
Chen Gang Sdec04732015-01-25 08:00:42 +08004699 unlock_user(argptr, guest_data, 0);
Alexander Graf56e904e2012-01-31 18:42:06 +01004700 goto out;
4701 }
4702 unlock_user(argptr, guest_data, 0);
4703
Peter Maydell49ca6f32016-06-06 19:58:14 +01004704 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
Alexander Graf56e904e2012-01-31 18:42:06 +01004705 if (!is_error(ret)) {
4706 guest_data = arg + host_dm->data_start;
4707 guest_data_size = host_dm->data_size - host_dm->data_start;
4708 argptr = lock_user(VERIFY_WRITE, guest_data, guest_data_size, 0);
4709 switch (ie->host_cmd) {
4710 case DM_REMOVE_ALL:
4711 case DM_DEV_CREATE:
4712 case DM_DEV_REMOVE:
4713 case DM_DEV_RENAME:
4714 case DM_DEV_SUSPEND:
4715 case DM_DEV_STATUS:
4716 case DM_TABLE_LOAD:
4717 case DM_TABLE_CLEAR:
4718 case DM_TARGET_MSG:
4719 case DM_DEV_SET_GEOMETRY:
4720 /* no return data */
4721 break;
4722 case DM_LIST_DEVICES:
4723 {
4724 struct dm_name_list *nl = (void*)host_dm + host_dm->data_start;
4725 uint32_t remaining_data = guest_data_size;
4726 void *cur_data = argptr;
4727 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
4728 int nl_size = 12; /* can't use thunk_size due to alignment */
4729
4730 while (1) {
4731 uint32_t next = nl->next;
4732 if (next) {
4733 nl->next = nl_size + (strlen(nl->name) + 1);
4734 }
4735 if (remaining_data < nl->next) {
4736 host_dm->flags |= DM_BUFFER_FULL_FLAG;
4737 break;
4738 }
4739 thunk_convert(cur_data, nl, arg_type, THUNK_TARGET);
4740 strcpy(cur_data + nl_size, nl->name);
4741 cur_data += nl->next;
4742 remaining_data -= nl->next;
4743 if (!next) {
4744 break;
4745 }
4746 nl = (void*)nl + next;
4747 }
4748 break;
4749 }
4750 case DM_DEV_WAIT:
4751 case DM_TABLE_STATUS:
4752 {
4753 struct dm_target_spec *spec = (void*)host_dm + host_dm->data_start;
4754 void *cur_data = argptr;
4755 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
4756 int spec_size = thunk_type_size(arg_type, 0);
4757 int i;
4758
4759 for (i = 0; i < host_dm->target_count; i++) {
4760 uint32_t next = spec->next;
4761 int slen = strlen((char*)&spec[1]) + 1;
4762 spec->next = (cur_data - argptr) + spec_size + slen;
4763 if (guest_data_size < spec->next) {
4764 host_dm->flags |= DM_BUFFER_FULL_FLAG;
4765 break;
4766 }
4767 thunk_convert(cur_data, spec, arg_type, THUNK_TARGET);
4768 strcpy(cur_data + spec_size, (char*)&spec[1]);
4769 cur_data = argptr + spec->next;
4770 spec = (void*)host_dm + host_dm->data_start + next;
4771 }
4772 break;
4773 }
4774 case DM_TABLE_DEPS:
4775 {
4776 void *hdata = (void*)host_dm + host_dm->data_start;
4777 int count = *(uint32_t*)hdata;
4778 uint64_t *hdev = hdata + 8;
4779 uint64_t *gdev = argptr + 8;
4780 int i;
4781
4782 *(uint32_t*)argptr = tswap32(count);
4783 for (i = 0; i < count; i++) {
4784 *gdev = tswap64(*hdev);
4785 gdev++;
4786 hdev++;
4787 }
4788 break;
4789 }
4790 case DM_LIST_VERSIONS:
4791 {
4792 struct dm_target_versions *vers = (void*)host_dm + host_dm->data_start;
4793 uint32_t remaining_data = guest_data_size;
4794 void *cur_data = argptr;
4795 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_versions) };
4796 int vers_size = thunk_type_size(arg_type, 0);
4797
4798 while (1) {
4799 uint32_t next = vers->next;
4800 if (next) {
4801 vers->next = vers_size + (strlen(vers->name) + 1);
4802 }
4803 if (remaining_data < vers->next) {
4804 host_dm->flags |= DM_BUFFER_FULL_FLAG;
4805 break;
4806 }
4807 thunk_convert(cur_data, vers, arg_type, THUNK_TARGET);
4808 strcpy(cur_data + vers_size, vers->name);
4809 cur_data += vers->next;
4810 remaining_data -= vers->next;
4811 if (!next) {
4812 break;
4813 }
4814 vers = (void*)vers + next;
4815 }
4816 break;
4817 }
4818 default:
Chen Gang Sdec04732015-01-25 08:00:42 +08004819 unlock_user(argptr, guest_data, 0);
Alexander Graf56e904e2012-01-31 18:42:06 +01004820 ret = -TARGET_EINVAL;
4821 goto out;
4822 }
4823 unlock_user(argptr, guest_data, guest_data_size);
4824
4825 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
4826 if (!argptr) {
4827 ret = -TARGET_EFAULT;
4828 goto out;
4829 }
4830 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
4831 unlock_user(argptr, arg, target_size);
4832 }
4833out:
Stefan Weilad11ad72012-09-04 22:14:19 +02004834 g_free(big_buf);
Alexander Graf56e904e2012-01-31 18:42:06 +01004835 return ret;
4836}
4837
Alexander Grafa59b5e32014-08-22 13:15:50 +02004838static abi_long do_ioctl_blkpg(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004839 int cmd, abi_long arg)
Alexander Grafa59b5e32014-08-22 13:15:50 +02004840{
4841 void *argptr;
4842 int target_size;
4843 const argtype *arg_type = ie->arg_type;
4844 const argtype part_arg_type[] = { MK_STRUCT(STRUCT_blkpg_partition) };
4845 abi_long ret;
4846
4847 struct blkpg_ioctl_arg *host_blkpg = (void*)buf_temp;
4848 struct blkpg_partition host_part;
4849
4850 /* Read and convert blkpg */
4851 arg_type++;
4852 target_size = thunk_type_size(arg_type, 0);
4853 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4854 if (!argptr) {
4855 ret = -TARGET_EFAULT;
4856 goto out;
4857 }
4858 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4859 unlock_user(argptr, arg, 0);
4860
4861 switch (host_blkpg->op) {
4862 case BLKPG_ADD_PARTITION:
4863 case BLKPG_DEL_PARTITION:
4864 /* payload is struct blkpg_partition */
4865 break;
4866 default:
4867 /* Unknown opcode */
4868 ret = -TARGET_EINVAL;
4869 goto out;
4870 }
4871
4872 /* Read and convert blkpg->data */
4873 arg = (abi_long)(uintptr_t)host_blkpg->data;
4874 target_size = thunk_type_size(part_arg_type, 0);
4875 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4876 if (!argptr) {
4877 ret = -TARGET_EFAULT;
4878 goto out;
4879 }
4880 thunk_convert(&host_part, argptr, part_arg_type, THUNK_HOST);
4881 unlock_user(argptr, arg, 0);
4882
4883 /* Swizzle the data pointer to our local copy and call! */
4884 host_blkpg->data = &host_part;
Peter Maydell49ca6f32016-06-06 19:58:14 +01004885 ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_blkpg));
Alexander Grafa59b5e32014-08-22 13:15:50 +02004886
4887out:
4888 return ret;
4889}
4890
Laurent Vivier7ff7b662013-07-02 14:04:12 +01004891static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004892 int fd, int cmd, abi_long arg)
Laurent Vivier7ff7b662013-07-02 14:04:12 +01004893{
4894 const argtype *arg_type = ie->arg_type;
4895 const StructEntry *se;
4896 const argtype *field_types;
4897 const int *dst_offsets, *src_offsets;
4898 int target_size;
4899 void *argptr;
Marc-André Lureaub78c5222019-03-05 16:15:00 +01004900 abi_ulong *target_rt_dev_ptr = NULL;
4901 unsigned long *host_rt_dev_ptr = NULL;
Laurent Vivier7ff7b662013-07-02 14:04:12 +01004902 abi_long ret;
4903 int i;
4904
4905 assert(ie->access == IOC_W);
4906 assert(*arg_type == TYPE_PTR);
4907 arg_type++;
4908 assert(*arg_type == TYPE_STRUCT);
4909 target_size = thunk_type_size(arg_type, 0);
4910 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4911 if (!argptr) {
4912 return -TARGET_EFAULT;
4913 }
4914 arg_type++;
4915 assert(*arg_type == (int)STRUCT_rtentry);
4916 se = struct_entries + *arg_type++;
4917 assert(se->convert[0] == NULL);
4918 /* convert struct here to be able to catch rt_dev string */
4919 field_types = se->field_types;
4920 dst_offsets = se->field_offsets[THUNK_HOST];
4921 src_offsets = se->field_offsets[THUNK_TARGET];
4922 for (i = 0; i < se->nb_fields; i++) {
4923 if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) {
4924 assert(*field_types == TYPE_PTRVOID);
4925 target_rt_dev_ptr = (abi_ulong *)(argptr + src_offsets[i]);
4926 host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]);
4927 if (*target_rt_dev_ptr != 0) {
4928 *host_rt_dev_ptr = (unsigned long)lock_user_string(
4929 tswapal(*target_rt_dev_ptr));
4930 if (!*host_rt_dev_ptr) {
4931 unlock_user(argptr, arg, 0);
4932 return -TARGET_EFAULT;
4933 }
4934 } else {
4935 *host_rt_dev_ptr = 0;
4936 }
4937 field_types++;
4938 continue;
4939 }
4940 field_types = thunk_convert(buf_temp + dst_offsets[i],
4941 argptr + src_offsets[i],
4942 field_types, THUNK_HOST);
4943 }
4944 unlock_user(argptr, arg, 0);
4945
Peter Maydell49ca6f32016-06-06 19:58:14 +01004946 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
Marc-André Lureaub78c5222019-03-05 16:15:00 +01004947
4948 assert(host_rt_dev_ptr != NULL);
4949 assert(target_rt_dev_ptr != NULL);
Laurent Vivier7ff7b662013-07-02 14:04:12 +01004950 if (*host_rt_dev_ptr != 0) {
4951 unlock_user((void *)*host_rt_dev_ptr,
4952 *target_rt_dev_ptr, 0);
4953 }
4954 return ret;
4955}
4956
Paul Burtonca56f5b2014-06-22 11:25:47 +01004957static abi_long do_ioctl_kdsigaccept(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004958 int fd, int cmd, abi_long arg)
Paul Burtonca56f5b2014-06-22 11:25:47 +01004959{
4960 int sig = target_to_host_signal(arg);
Peter Maydell49ca6f32016-06-06 19:58:14 +01004961 return get_errno(safe_ioctl(fd, ie->host_cmd, sig));
Paul Burtonca56f5b2014-06-22 11:25:47 +01004962}
4963
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02004964static abi_long do_ioctl_SIOCGSTAMP(const IOCTLEntry *ie, uint8_t *buf_temp,
4965 int fd, int cmd, abi_long arg)
4966{
4967 struct timeval tv;
4968 abi_long ret;
4969
4970 ret = get_errno(safe_ioctl(fd, SIOCGSTAMP, &tv));
4971 if (is_error(ret)) {
4972 return ret;
4973 }
4974
4975 if (cmd == (int)TARGET_SIOCGSTAMP_OLD) {
4976 if (copy_to_user_timeval(arg, &tv)) {
4977 return -TARGET_EFAULT;
4978 }
4979 } else {
4980 if (copy_to_user_timeval64(arg, &tv)) {
4981 return -TARGET_EFAULT;
4982 }
4983 }
4984
4985 return ret;
4986}
4987
4988static abi_long do_ioctl_SIOCGSTAMPNS(const IOCTLEntry *ie, uint8_t *buf_temp,
4989 int fd, int cmd, abi_long arg)
4990{
4991 struct timespec ts;
4992 abi_long ret;
4993
4994 ret = get_errno(safe_ioctl(fd, SIOCGSTAMPNS, &ts));
4995 if (is_error(ret)) {
4996 return ret;
4997 }
4998
4999 if (cmd == (int)TARGET_SIOCGSTAMPNS_OLD) {
5000 if (host_to_target_timespec(arg, &ts)) {
5001 return -TARGET_EFAULT;
5002 }
5003 } else{
5004 if (host_to_target_timespec64(arg, &ts)) {
5005 return -TARGET_EFAULT;
5006 }
5007 }
5008
5009 return ret;
5010}
5011
Andreas Schwab2b74f622018-01-29 11:47:06 +01005012#ifdef TIOCGPTPEER
5013static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry *ie, uint8_t *buf_temp,
5014 int fd, int cmd, abi_long arg)
5015{
5016 int flags = target_to_host_bitmask(arg, fcntl_flags_tbl);
5017 return get_errno(safe_ioctl(fd, ie->host_cmd, flags));
5018}
5019#endif
5020
blueswir19f106a72008-10-05 10:52:52 +00005021static IOCTLEntry ioctl_entries[] = {
Blue Swirl001faf32009-05-13 17:53:17 +00005022#define IOCTL(cmd, access, ...) \
Peter Maydelld2ef05b2011-01-06 15:04:17 +00005023 { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
5024#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
5025 { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
Helge Deller8cb762f2016-12-06 16:24:03 +01005026#define IOCTL_IGNORE(cmd) \
5027 { TARGET_ ## cmd, 0, #cmd },
bellard31e31b82003-02-18 22:55:36 +00005028#include "ioctls.h"
5029 { 0, 0, },
5030};
5031
pbrook53a59602006-03-25 19:31:22 +00005032/* ??? Implement proper locking for ioctls. */
ths0da46a62007-10-20 20:23:07 +00005033/* do_ioctl() Must return target values and target errnos. */
Laurent Vivier45c874e2015-06-16 00:35:28 +02005034static abi_long do_ioctl(int fd, int cmd, abi_long arg)
bellard31e31b82003-02-18 22:55:36 +00005035{
5036 const IOCTLEntry *ie;
5037 const argtype *arg_type;
blueswir1992f48a2007-10-14 16:27:31 +00005038 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00005039 uint8_t buf_temp[MAX_STRUCT_SIZE];
pbrook53a59602006-03-25 19:31:22 +00005040 int target_size;
5041 void *argptr;
bellard31e31b82003-02-18 22:55:36 +00005042
5043 ie = ioctl_entries;
5044 for(;;) {
5045 if (ie->target_cmd == 0) {
j_mayer32407102007-09-26 23:01:49 +00005046 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
ths0da46a62007-10-20 20:23:07 +00005047 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00005048 }
5049 if (ie->target_cmd == cmd)
5050 break;
5051 ie++;
5052 }
5053 arg_type = ie->arg_type;
Peter Maydelld2ef05b2011-01-06 15:04:17 +00005054 if (ie->do_ioctl) {
5055 return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
Helge Deller8cb762f2016-12-06 16:24:03 +01005056 } else if (!ie->host_cmd) {
5057 /* Some architectures define BSD ioctls in their headers
5058 that are not implemented in Linux. */
5059 return -TARGET_ENOSYS;
Peter Maydelld2ef05b2011-01-06 15:04:17 +00005060 }
5061
bellard31e31b82003-02-18 22:55:36 +00005062 switch(arg_type[0]) {
5063 case TYPE_NULL:
5064 /* no argument */
Peter Maydell49ca6f32016-06-06 19:58:14 +01005065 ret = get_errno(safe_ioctl(fd, ie->host_cmd));
bellard31e31b82003-02-18 22:55:36 +00005066 break;
5067 case TYPE_PTRVOID:
5068 case TYPE_INT:
Peter Maydell49ca6f32016-06-06 19:58:14 +01005069 ret = get_errno(safe_ioctl(fd, ie->host_cmd, arg));
bellard31e31b82003-02-18 22:55:36 +00005070 break;
5071 case TYPE_PTR:
5072 arg_type++;
pbrook53a59602006-03-25 19:31:22 +00005073 target_size = thunk_type_size(arg_type, 0);
bellard31e31b82003-02-18 22:55:36 +00005074 switch(ie->access) {
5075 case IOC_R:
Peter Maydell49ca6f32016-06-06 19:58:14 +01005076 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
bellard31e31b82003-02-18 22:55:36 +00005077 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005078 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5079 if (!argptr)
5080 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005081 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5082 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00005083 }
5084 break;
5085 case IOC_W:
bellard579a97f2007-11-11 14:26:47 +00005086 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5087 if (!argptr)
5088 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005089 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5090 unlock_user(argptr, arg, 0);
Peter Maydell49ca6f32016-06-06 19:58:14 +01005091 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
bellard31e31b82003-02-18 22:55:36 +00005092 break;
5093 default:
5094 case IOC_RW:
bellard579a97f2007-11-11 14:26:47 +00005095 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5096 if (!argptr)
5097 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005098 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5099 unlock_user(argptr, arg, 0);
Peter Maydell49ca6f32016-06-06 19:58:14 +01005100 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
bellard31e31b82003-02-18 22:55:36 +00005101 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005102 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5103 if (!argptr)
5104 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005105 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5106 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00005107 }
5108 break;
5109 }
5110 break;
5111 default:
j_mayer32407102007-09-26 23:01:49 +00005112 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
5113 (long)cmd, arg_type[0]);
ths0da46a62007-10-20 20:23:07 +00005114 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00005115 break;
5116 }
5117 return ret;
5118}
5119
blueswir1b39bc502008-10-05 10:51:10 +00005120static const bitmask_transtbl iflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00005121 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
5122 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
5123 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
5124 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
5125 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
5126 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
5127 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
5128 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
5129 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
5130 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
5131 { TARGET_IXON, TARGET_IXON, IXON, IXON },
5132 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
5133 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
5134 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
5135 { 0, 0, 0, 0 }
5136};
5137
blueswir1b39bc502008-10-05 10:51:10 +00005138static const bitmask_transtbl oflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00005139 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
5140 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
5141 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
5142 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
5143 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
5144 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
5145 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
5146 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
5147 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
5148 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
5149 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
5150 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
5151 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
5152 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
5153 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
5154 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
5155 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
5156 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
5157 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
5158 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
5159 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
5160 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
5161 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
5162 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
5163 { 0, 0, 0, 0 }
5164};
5165
blueswir1b39bc502008-10-05 10:51:10 +00005166static const bitmask_transtbl cflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00005167 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
5168 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
5169 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
5170 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
5171 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
5172 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
5173 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
5174 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
5175 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
5176 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
5177 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
5178 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
5179 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
5180 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
5181 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
5182 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
5183 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
5184 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
5185 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
5186 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
5187 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
5188 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
5189 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
5190 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
5191 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
5192 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
5193 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
5194 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
5195 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
5196 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
5197 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
5198 { 0, 0, 0, 0 }
5199};
5200
blueswir1b39bc502008-10-05 10:51:10 +00005201static const bitmask_transtbl lflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00005202 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
5203 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
5204 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
5205 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
5206 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
5207 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
5208 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
5209 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
5210 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
5211 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
5212 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
5213 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
5214 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
5215 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
5216 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
5217 { 0, 0, 0, 0 }
5218};
5219
5220static void target_to_host_termios (void *dst, const void *src)
5221{
5222 struct host_termios *host = dst;
5223 const struct target_termios *target = src;
ths3b46e622007-09-17 08:09:54 +00005224
ths5fafdf22007-09-16 21:08:06 +00005225 host->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00005226 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00005227 host->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00005228 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00005229 host->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00005230 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00005231 host->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00005232 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
5233 host->c_line = target->c_line;
ths3b46e622007-09-17 08:09:54 +00005234
Arnaud Patard44607122009-04-21 17:39:08 +03005235 memset(host->c_cc, 0, sizeof(host->c_cc));
ths5fafdf22007-09-16 21:08:06 +00005236 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
5237 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
ths3b46e622007-09-17 08:09:54 +00005238 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
ths5fafdf22007-09-16 21:08:06 +00005239 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
ths3b46e622007-09-17 08:09:54 +00005240 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
ths5fafdf22007-09-16 21:08:06 +00005241 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
ths3b46e622007-09-17 08:09:54 +00005242 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
ths5fafdf22007-09-16 21:08:06 +00005243 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
ths3b46e622007-09-17 08:09:54 +00005244 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
ths5fafdf22007-09-16 21:08:06 +00005245 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
5246 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
ths3b46e622007-09-17 08:09:54 +00005247 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
5248 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
5249 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
5250 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
5251 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
ths5fafdf22007-09-16 21:08:06 +00005252 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
bellard31e31b82003-02-18 22:55:36 +00005253}
ths3b46e622007-09-17 08:09:54 +00005254
bellard31e31b82003-02-18 22:55:36 +00005255static void host_to_target_termios (void *dst, const void *src)
5256{
5257 struct target_termios *target = dst;
5258 const struct host_termios *host = src;
5259
ths5fafdf22007-09-16 21:08:06 +00005260 target->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00005261 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00005262 target->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00005263 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00005264 target->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00005265 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00005266 target->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00005267 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
5268 target->c_line = host->c_line;
ths3b46e622007-09-17 08:09:54 +00005269
Arnaud Patard44607122009-04-21 17:39:08 +03005270 memset(target->c_cc, 0, sizeof(target->c_cc));
bellard31e31b82003-02-18 22:55:36 +00005271 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
5272 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
5273 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
5274 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
5275 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
5276 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
5277 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
5278 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
5279 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
5280 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
5281 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
5282 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
5283 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
5284 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
5285 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
5286 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
5287 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
5288}
5289
blueswir18e853dc2008-10-05 10:49:32 +00005290static const StructEntry struct_termios_def = {
bellard31e31b82003-02-18 22:55:36 +00005291 .convert = { host_to_target_termios, target_to_host_termios },
5292 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
5293 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
5294};
5295
bellard5286db72003-06-05 00:57:30 +00005296static bitmask_transtbl mmap_flags_tbl[] = {
Helge Deller541e1692017-10-31 13:53:58 +01005297 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
5298 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
5299 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
5300 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS,
5301 MAP_ANONYMOUS, MAP_ANONYMOUS },
5302 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN,
5303 MAP_GROWSDOWN, MAP_GROWSDOWN },
5304 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE,
5305 MAP_DENYWRITE, MAP_DENYWRITE },
5306 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE,
5307 MAP_EXECUTABLE, MAP_EXECUTABLE },
5308 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
5309 { TARGET_MAP_NORESERVE, TARGET_MAP_NORESERVE,
5310 MAP_NORESERVE, MAP_NORESERVE },
5311 { TARGET_MAP_HUGETLB, TARGET_MAP_HUGETLB, MAP_HUGETLB, MAP_HUGETLB },
5312 /* MAP_STACK had been ignored by the kernel for quite some time.
5313 Recognize it for the target insofar as we do not want to pass
5314 it through to the host. */
5315 { TARGET_MAP_STACK, TARGET_MAP_STACK, 0, 0 },
5316 { 0, 0, 0, 0 }
bellard5286db72003-06-05 00:57:30 +00005317};
5318
bellard2ab83ea2003-06-15 19:56:46 +00005319#if defined(TARGET_I386)
bellard6dbad632003-03-16 18:05:05 +00005320
5321/* NOTE: there is really one LDT for all the threads */
blueswir1b1d8e522008-10-26 13:43:07 +00005322static uint8_t *ldt_table;
bellard6dbad632003-03-16 18:05:05 +00005323
bellard03acab62007-11-11 14:57:14 +00005324static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00005325{
5326 int size;
pbrook53a59602006-03-25 19:31:22 +00005327 void *p;
bellard6dbad632003-03-16 18:05:05 +00005328
5329 if (!ldt_table)
5330 return 0;
5331 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
5332 if (size > bytecount)
5333 size = bytecount;
bellard579a97f2007-11-11 14:26:47 +00005334 p = lock_user(VERIFY_WRITE, ptr, size, 0);
5335 if (!p)
bellard03acab62007-11-11 14:57:14 +00005336 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00005337 /* ??? Should this by byteswapped? */
pbrook53a59602006-03-25 19:31:22 +00005338 memcpy(p, ldt_table, size);
5339 unlock_user(p, ptr, size);
bellard6dbad632003-03-16 18:05:05 +00005340 return size;
5341}
5342
5343/* XXX: add locking support */
bellard03acab62007-11-11 14:57:14 +00005344static abi_long write_ldt(CPUX86State *env,
5345 abi_ulong ptr, unsigned long bytecount, int oldmode)
bellard6dbad632003-03-16 18:05:05 +00005346{
5347 struct target_modify_ldt_ldt_s ldt_info;
pbrook53a59602006-03-25 19:31:22 +00005348 struct target_modify_ldt_ldt_s *target_ldt_info;
bellard6dbad632003-03-16 18:05:05 +00005349 int seg_32bit, contents, read_exec_only, limit_in_pages;
bellard8d18e892007-11-14 15:18:40 +00005350 int seg_not_present, useable, lm;
bellard6dbad632003-03-16 18:05:05 +00005351 uint32_t *lp, entry_1, entry_2;
5352
5353 if (bytecount != sizeof(ldt_info))
bellard03acab62007-11-11 14:57:14 +00005354 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +00005355 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
bellard03acab62007-11-11 14:57:14 +00005356 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005357 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02005358 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
pbrook53a59602006-03-25 19:31:22 +00005359 ldt_info.limit = tswap32(target_ldt_info->limit);
5360 ldt_info.flags = tswap32(target_ldt_info->flags);
5361 unlock_user_struct(target_ldt_info, ptr, 0);
ths3b46e622007-09-17 08:09:54 +00005362
bellard6dbad632003-03-16 18:05:05 +00005363 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
bellard03acab62007-11-11 14:57:14 +00005364 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00005365 seg_32bit = ldt_info.flags & 1;
5366 contents = (ldt_info.flags >> 1) & 3;
5367 read_exec_only = (ldt_info.flags >> 3) & 1;
5368 limit_in_pages = (ldt_info.flags >> 4) & 1;
5369 seg_not_present = (ldt_info.flags >> 5) & 1;
5370 useable = (ldt_info.flags >> 6) & 1;
bellard8d18e892007-11-14 15:18:40 +00005371#ifdef TARGET_ABI32
5372 lm = 0;
5373#else
5374 lm = (ldt_info.flags >> 7) & 1;
5375#endif
bellard6dbad632003-03-16 18:05:05 +00005376 if (contents == 3) {
5377 if (oldmode)
bellard03acab62007-11-11 14:57:14 +00005378 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00005379 if (seg_not_present == 0)
bellard03acab62007-11-11 14:57:14 +00005380 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00005381 }
5382 /* allocate the LDT */
5383 if (!ldt_table) {
balroge4415702008-11-10 02:55:33 +00005384 env->ldt.base = target_mmap(0,
5385 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
5386 PROT_READ|PROT_WRITE,
5387 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
5388 if (env->ldt.base == -1)
bellard03acab62007-11-11 14:57:14 +00005389 return -TARGET_ENOMEM;
balroge4415702008-11-10 02:55:33 +00005390 memset(g2h(env->ldt.base), 0,
5391 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
bellard6dbad632003-03-16 18:05:05 +00005392 env->ldt.limit = 0xffff;
balroge4415702008-11-10 02:55:33 +00005393 ldt_table = g2h(env->ldt.base);
bellard6dbad632003-03-16 18:05:05 +00005394 }
5395
5396 /* NOTE: same code as Linux kernel */
5397 /* Allow LDTs to be cleared by the user. */
5398 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
5399 if (oldmode ||
5400 (contents == 0 &&
5401 read_exec_only == 1 &&
5402 seg_32bit == 0 &&
5403 limit_in_pages == 0 &&
5404 seg_not_present == 1 &&
5405 useable == 0 )) {
5406 entry_1 = 0;
5407 entry_2 = 0;
5408 goto install;
5409 }
5410 }
ths3b46e622007-09-17 08:09:54 +00005411
bellard6dbad632003-03-16 18:05:05 +00005412 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
5413 (ldt_info.limit & 0x0ffff);
5414 entry_2 = (ldt_info.base_addr & 0xff000000) |
5415 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
5416 (ldt_info.limit & 0xf0000) |
5417 ((read_exec_only ^ 1) << 9) |
5418 (contents << 10) |
5419 ((seg_not_present ^ 1) << 15) |
5420 (seg_32bit << 22) |
5421 (limit_in_pages << 23) |
bellard8d18e892007-11-14 15:18:40 +00005422 (lm << 21) |
bellard6dbad632003-03-16 18:05:05 +00005423 0x7000;
5424 if (!oldmode)
5425 entry_2 |= (useable << 20);
bellard14ae3ba2003-05-27 23:25:06 +00005426
bellard6dbad632003-03-16 18:05:05 +00005427 /* Install the new entry ... */
5428install:
5429 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
5430 lp[0] = tswap32(entry_1);
5431 lp[1] = tswap32(entry_2);
5432 return 0;
5433}
5434
5435/* specific and weird i386 syscalls */
blueswir18fcd3692008-08-17 20:26:25 +00005436static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
5437 unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00005438{
bellard03acab62007-11-11 14:57:14 +00005439 abi_long ret;
ths3b46e622007-09-17 08:09:54 +00005440
bellard6dbad632003-03-16 18:05:05 +00005441 switch (func) {
5442 case 0:
5443 ret = read_ldt(ptr, bytecount);
5444 break;
5445 case 1:
5446 ret = write_ldt(env, ptr, bytecount, 1);
5447 break;
5448 case 0x11:
5449 ret = write_ldt(env, ptr, bytecount, 0);
5450 break;
bellard03acab62007-11-11 14:57:14 +00005451 default:
5452 ret = -TARGET_ENOSYS;
5453 break;
bellard6dbad632003-03-16 18:05:05 +00005454 }
5455 return ret;
5456}
bellard1b6b0292003-03-22 17:31:38 +00005457
blueswir14583f582008-08-24 10:35:55 +00005458#if defined(TARGET_I386) && defined(TARGET_ABI32)
Alexander Grafbc22eb42013-07-16 18:44:58 +01005459abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00005460{
5461 uint64_t *gdt_table = g2h(env->gdt.base);
5462 struct target_modify_ldt_ldt_s ldt_info;
5463 struct target_modify_ldt_ldt_s *target_ldt_info;
5464 int seg_32bit, contents, read_exec_only, limit_in_pages;
5465 int seg_not_present, useable, lm;
5466 uint32_t *lp, entry_1, entry_2;
5467 int i;
5468
5469 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
5470 if (!target_ldt_info)
5471 return -TARGET_EFAULT;
5472 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02005473 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
bellard8d18e892007-11-14 15:18:40 +00005474 ldt_info.limit = tswap32(target_ldt_info->limit);
5475 ldt_info.flags = tswap32(target_ldt_info->flags);
5476 if (ldt_info.entry_number == -1) {
5477 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
5478 if (gdt_table[i] == 0) {
5479 ldt_info.entry_number = i;
5480 target_ldt_info->entry_number = tswap32(i);
5481 break;
5482 }
5483 }
5484 }
5485 unlock_user_struct(target_ldt_info, ptr, 1);
5486
5487 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
5488 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
5489 return -TARGET_EINVAL;
5490 seg_32bit = ldt_info.flags & 1;
5491 contents = (ldt_info.flags >> 1) & 3;
5492 read_exec_only = (ldt_info.flags >> 3) & 1;
5493 limit_in_pages = (ldt_info.flags >> 4) & 1;
5494 seg_not_present = (ldt_info.flags >> 5) & 1;
5495 useable = (ldt_info.flags >> 6) & 1;
5496#ifdef TARGET_ABI32
5497 lm = 0;
5498#else
5499 lm = (ldt_info.flags >> 7) & 1;
5500#endif
5501
5502 if (contents == 3) {
5503 if (seg_not_present == 0)
5504 return -TARGET_EINVAL;
5505 }
5506
5507 /* NOTE: same code as Linux kernel */
5508 /* Allow LDTs to be cleared by the user. */
5509 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
5510 if ((contents == 0 &&
5511 read_exec_only == 1 &&
5512 seg_32bit == 0 &&
5513 limit_in_pages == 0 &&
5514 seg_not_present == 1 &&
5515 useable == 0 )) {
5516 entry_1 = 0;
5517 entry_2 = 0;
5518 goto install;
5519 }
5520 }
5521
5522 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
5523 (ldt_info.limit & 0x0ffff);
5524 entry_2 = (ldt_info.base_addr & 0xff000000) |
5525 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
5526 (ldt_info.limit & 0xf0000) |
5527 ((read_exec_only ^ 1) << 9) |
5528 (contents << 10) |
5529 ((seg_not_present ^ 1) << 15) |
5530 (seg_32bit << 22) |
5531 (limit_in_pages << 23) |
5532 (useable << 20) |
5533 (lm << 21) |
5534 0x7000;
5535
5536 /* Install the new entry ... */
5537install:
5538 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
5539 lp[0] = tswap32(entry_1);
5540 lp[1] = tswap32(entry_2);
5541 return 0;
5542}
5543
blueswir18fcd3692008-08-17 20:26:25 +00005544static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00005545{
5546 struct target_modify_ldt_ldt_s *target_ldt_info;
5547 uint64_t *gdt_table = g2h(env->gdt.base);
5548 uint32_t base_addr, limit, flags;
5549 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
5550 int seg_not_present, useable, lm;
5551 uint32_t *lp, entry_1, entry_2;
5552
5553 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
5554 if (!target_ldt_info)
5555 return -TARGET_EFAULT;
5556 idx = tswap32(target_ldt_info->entry_number);
5557 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
5558 idx > TARGET_GDT_ENTRY_TLS_MAX) {
5559 unlock_user_struct(target_ldt_info, ptr, 1);
5560 return -TARGET_EINVAL;
5561 }
5562 lp = (uint32_t *)(gdt_table + idx);
5563 entry_1 = tswap32(lp[0]);
5564 entry_2 = tswap32(lp[1]);
5565
5566 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
5567 contents = (entry_2 >> 10) & 3;
5568 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
5569 seg_32bit = (entry_2 >> 22) & 1;
5570 limit_in_pages = (entry_2 >> 23) & 1;
5571 useable = (entry_2 >> 20) & 1;
5572#ifdef TARGET_ABI32
5573 lm = 0;
5574#else
5575 lm = (entry_2 >> 21) & 1;
5576#endif
5577 flags = (seg_32bit << 0) | (contents << 1) |
5578 (read_exec_only << 3) | (limit_in_pages << 4) |
5579 (seg_not_present << 5) | (useable << 6) | (lm << 7);
5580 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
5581 base_addr = (entry_1 >> 16) |
5582 (entry_2 & 0xff000000) |
5583 ((entry_2 & 0xff) << 16);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02005584 target_ldt_info->base_addr = tswapal(base_addr);
bellard8d18e892007-11-14 15:18:40 +00005585 target_ldt_info->limit = tswap32(limit);
5586 target_ldt_info->flags = tswap32(flags);
5587 unlock_user_struct(target_ldt_info, ptr, 1);
5588 return 0;
5589}
blueswir14583f582008-08-24 10:35:55 +00005590#endif /* TARGET_I386 && TARGET_ABI32 */
bellard8d18e892007-11-14 15:18:40 +00005591
bellardd2fd1af2007-11-14 18:08:56 +00005592#ifndef TARGET_ABI32
Peter Maydell2667e712013-07-16 18:44:59 +01005593abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
bellardd2fd1af2007-11-14 18:08:56 +00005594{
Juan Quintela1add8692011-06-16 17:37:09 +01005595 abi_long ret = 0;
bellardd2fd1af2007-11-14 18:08:56 +00005596 abi_ulong val;
5597 int idx;
Juan Quintela1add8692011-06-16 17:37:09 +01005598
bellardd2fd1af2007-11-14 18:08:56 +00005599 switch(code) {
5600 case TARGET_ARCH_SET_GS:
5601 case TARGET_ARCH_SET_FS:
5602 if (code == TARGET_ARCH_SET_GS)
5603 idx = R_GS;
5604 else
5605 idx = R_FS;
5606 cpu_x86_load_seg(env, idx, 0);
5607 env->segs[idx].base = addr;
5608 break;
5609 case TARGET_ARCH_GET_GS:
5610 case TARGET_ARCH_GET_FS:
5611 if (code == TARGET_ARCH_GET_GS)
5612 idx = R_GS;
5613 else
5614 idx = R_FS;
5615 val = env->segs[idx].base;
5616 if (put_user(val, addr, abi_ulong))
Juan Quintela1add8692011-06-16 17:37:09 +01005617 ret = -TARGET_EFAULT;
bellardd2fd1af2007-11-14 18:08:56 +00005618 break;
5619 default:
5620 ret = -TARGET_EINVAL;
5621 break;
5622 }
Juan Quintela1add8692011-06-16 17:37:09 +01005623 return ret;
bellardd2fd1af2007-11-14 18:08:56 +00005624}
5625#endif
5626
bellard2ab83ea2003-06-15 19:56:46 +00005627#endif /* defined(TARGET_I386) */
5628
Riku Voipio05098a92011-03-04 15:27:29 +02005629#define NEW_STACK_SIZE 0x40000
pbrookd865bab2008-06-07 22:12:17 +00005630
pbrookd865bab2008-06-07 22:12:17 +00005631
5632static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
5633typedef struct {
Andreas Färber9349b4f2012-03-14 01:38:32 +01005634 CPUArchState *env;
pbrookd865bab2008-06-07 22:12:17 +00005635 pthread_mutex_t mutex;
5636 pthread_cond_t cond;
5637 pthread_t thread;
5638 uint32_t tid;
5639 abi_ulong child_tidptr;
5640 abi_ulong parent_tidptr;
5641 sigset_t sigmask;
5642} new_thread_info;
5643
5644static void *clone_func(void *arg)
5645{
5646 new_thread_info *info = arg;
Andreas Färber9349b4f2012-03-14 01:38:32 +01005647 CPUArchState *env;
Andreas Färber0d342822012-12-17 07:12:13 +01005648 CPUState *cpu;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03005649 TaskState *ts;
pbrookd865bab2008-06-07 22:12:17 +00005650
Emilio G. Cota70903762015-08-23 20:23:41 -04005651 rcu_register_thread();
Emilio G. Cota3468b592017-07-19 18:57:58 -04005652 tcg_register_thread();
pbrookd865bab2008-06-07 22:12:17 +00005653 env = info->env;
Richard Henderson29a0af62019-03-22 16:07:18 -07005654 cpu = env_cpu(env);
Andreas Färbera2247f82013-06-09 19:47:04 +02005655 thread_cpu = cpu;
Andreas Färber0429a972013-08-26 18:14:44 +02005656 ts = (TaskState *)cpu->opaque;
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +00005657 info->tid = sys_gettid();
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03005658 task_settid(ts);
pbrookd865bab2008-06-07 22:12:17 +00005659 if (info->child_tidptr)
5660 put_user_u32(info->tid, info->child_tidptr);
5661 if (info->parent_tidptr)
5662 put_user_u32(info->tid, info->parent_tidptr);
Richard Henderson5ebdd772019-03-14 13:10:53 -07005663 qemu_guest_random_seed_thread_part2(cpu->random_seed);
pbrookd865bab2008-06-07 22:12:17 +00005664 /* Enable signals. */
5665 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
5666 /* Signal to the parent that we're ready. */
5667 pthread_mutex_lock(&info->mutex);
5668 pthread_cond_broadcast(&info->cond);
5669 pthread_mutex_unlock(&info->mutex);
Emilio G. Cotaa4dd3d52017-10-18 18:01:41 -04005670 /* Wait until the parent has finished initializing the tls state. */
pbrookd865bab2008-06-07 22:12:17 +00005671 pthread_mutex_lock(&clone_lock);
5672 pthread_mutex_unlock(&clone_lock);
5673 cpu_loop(env);
5674 /* never exits */
5675 return NULL;
5676}
bellard1b6b0292003-03-22 17:31:38 +00005677
ths0da46a62007-10-20 20:23:07 +00005678/* do_fork() Must return host values and target errnos (unlike most
5679 do_*() functions). */
Andreas Färber9349b4f2012-03-14 01:38:32 +01005680static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
pbrookd865bab2008-06-07 22:12:17 +00005681 abi_ulong parent_tidptr, target_ulong newtls,
5682 abi_ulong child_tidptr)
bellard1b6b0292003-03-22 17:31:38 +00005683{
Richard Henderson29a0af62019-03-22 16:07:18 -07005684 CPUState *cpu = env_cpu(env);
bellard1b6b0292003-03-22 17:31:38 +00005685 int ret;
bellard5cd43932003-03-29 16:54:36 +00005686 TaskState *ts;
Andreas Färber0429a972013-08-26 18:14:44 +02005687 CPUState *new_cpu;
Andreas Färber9349b4f2012-03-14 01:38:32 +01005688 CPUArchState *new_env;
pbrookd865bab2008-06-07 22:12:17 +00005689 sigset_t sigmask;
ths3b46e622007-09-17 08:09:54 +00005690
Peter Maydell5ea2fc82016-08-02 18:41:27 +01005691 flags &= ~CLONE_IGNORED_FLAGS;
5692
balrog436d1242008-09-21 02:39:45 +00005693 /* Emulate vfork() with fork() */
5694 if (flags & CLONE_VFORK)
5695 flags &= ~(CLONE_VFORK | CLONE_VM);
5696
bellard1b6b0292003-03-22 17:31:38 +00005697 if (flags & CLONE_VM) {
Andreas Färber0429a972013-08-26 18:14:44 +02005698 TaskState *parent_ts = (TaskState *)cpu->opaque;
pbrookd865bab2008-06-07 22:12:17 +00005699 new_thread_info info;
5700 pthread_attr_t attr;
Peter Maydell24cb36a2013-07-16 18:45:00 +01005701
Peter Maydell5ea2fc82016-08-02 18:41:27 +01005702 if (((flags & CLONE_THREAD_FLAGS) != CLONE_THREAD_FLAGS) ||
5703 (flags & CLONE_INVALID_THREAD_FLAGS)) {
5704 return -TARGET_EINVAL;
5705 }
5706
Markus Armbrusterc78d65e2015-09-14 13:53:03 +02005707 ts = g_new0(TaskState, 1);
pbrook624f7972008-05-31 16:11:38 +00005708 init_task_state(ts);
Max Filippov73a988d2018-03-30 06:19:58 -07005709
5710 /* Grab a mutex so that thread setup appears atomic. */
5711 pthread_mutex_lock(&clone_lock);
5712
bellard1b6b0292003-03-22 17:31:38 +00005713 /* we create a new CPU instance. */
thsc5be9f02007-02-28 20:20:53 +00005714 new_env = cpu_copy(env);
pbrook6e68e072008-05-30 17:22:15 +00005715 /* Init regs that differ from the parent. */
5716 cpu_clone_regs(new_env, newsp);
Richard Henderson29a0af62019-03-22 16:07:18 -07005717 new_cpu = env_cpu(new_env);
Andreas Färber0429a972013-08-26 18:14:44 +02005718 new_cpu->opaque = ts;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03005719 ts->bprm = parent_ts->bprm;
5720 ts->info = parent_ts->info;
Peter Maydell3d3efba2016-05-27 15:51:49 +01005721 ts->signal_mask = parent_ts->signal_mask;
pbrookd865bab2008-06-07 22:12:17 +00005722
Peter Maydell7cfbd382016-08-02 18:41:26 +01005723 if (flags & CLONE_CHILD_CLEARTID) {
pbrookc2764712009-03-07 15:24:59 +00005724 ts->child_tidptr = child_tidptr;
5725 }
5726
Peter Maydell7cfbd382016-08-02 18:41:26 +01005727 if (flags & CLONE_SETTLS) {
pbrookd865bab2008-06-07 22:12:17 +00005728 cpu_set_tls (new_env, newtls);
Peter Maydell7cfbd382016-08-02 18:41:26 +01005729 }
pbrookd865bab2008-06-07 22:12:17 +00005730
pbrookd865bab2008-06-07 22:12:17 +00005731 memset(&info, 0, sizeof(info));
5732 pthread_mutex_init(&info.mutex, NULL);
5733 pthread_mutex_lock(&info.mutex);
5734 pthread_cond_init(&info.cond, NULL);
5735 info.env = new_env;
Peter Maydell7cfbd382016-08-02 18:41:26 +01005736 if (flags & CLONE_CHILD_SETTID) {
pbrookd865bab2008-06-07 22:12:17 +00005737 info.child_tidptr = child_tidptr;
Peter Maydell7cfbd382016-08-02 18:41:26 +01005738 }
5739 if (flags & CLONE_PARENT_SETTID) {
pbrookd865bab2008-06-07 22:12:17 +00005740 info.parent_tidptr = parent_tidptr;
Peter Maydell7cfbd382016-08-02 18:41:26 +01005741 }
pbrookd865bab2008-06-07 22:12:17 +00005742
5743 ret = pthread_attr_init(&attr);
Nathan Froyd48e15fc2010-10-29 07:48:57 -07005744 ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE);
5745 ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pbrookd865bab2008-06-07 22:12:17 +00005746 /* It is not safe to deliver signals until the child has finished
5747 initializing, so temporarily block all signals. */
5748 sigfillset(&sigmask);
5749 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
Richard Henderson5ebdd772019-03-14 13:10:53 -07005750 cpu->random_seed = qemu_guest_random_seed_thread_part1();
pbrookd865bab2008-06-07 22:12:17 +00005751
Alex Bennéeb67cb682016-10-05 11:13:04 -07005752 /* If this is our first additional thread, we need to ensure we
5753 * generate code for parallel execution and flush old translations.
5754 */
5755 if (!parallel_cpus) {
5756 parallel_cpus = true;
5757 tb_flush(cpu);
5758 }
5759
pbrookd865bab2008-06-07 22:12:17 +00005760 ret = pthread_create(&info.thread, &attr, clone_func, &info);
pbrookc2764712009-03-07 15:24:59 +00005761 /* TODO: Free new CPU state if thread creation failed. */
pbrookd865bab2008-06-07 22:12:17 +00005762
5763 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
5764 pthread_attr_destroy(&attr);
5765 if (ret == 0) {
5766 /* Wait for the child to initialize. */
5767 pthread_cond_wait(&info.cond, &info.mutex);
5768 ret = info.tid;
pbrookd865bab2008-06-07 22:12:17 +00005769 } else {
5770 ret = -1;
5771 }
5772 pthread_mutex_unlock(&info.mutex);
5773 pthread_cond_destroy(&info.cond);
5774 pthread_mutex_destroy(&info.mutex);
5775 pthread_mutex_unlock(&clone_lock);
bellard1b6b0292003-03-22 17:31:38 +00005776 } else {
5777 /* if no CLONE_VM, we consider it is a fork */
Peter Maydell5ea2fc82016-08-02 18:41:27 +01005778 if (flags & CLONE_INVALID_FORK_FLAGS) {
5779 return -TARGET_EINVAL;
5780 }
5781
5782 /* We can't support custom termination signals */
5783 if ((flags & CSIGNAL) != TARGET_SIGCHLD) {
Timothy E Baldwin93b4eff2015-08-31 00:26:21 +01005784 return -TARGET_EINVAL;
5785 }
Timothy E Baldwin7d92d342016-05-27 15:51:58 +01005786
5787 if (block_signals()) {
5788 return -TARGET_ERESTARTSYS;
5789 }
5790
pbrookd865bab2008-06-07 22:12:17 +00005791 fork_start();
bellard1b6b0292003-03-22 17:31:38 +00005792 ret = fork();
pbrookd865bab2008-06-07 22:12:17 +00005793 if (ret == 0) {
aurel322b1319c2008-12-18 22:44:04 +00005794 /* Child Process. */
pbrookd865bab2008-06-07 22:12:17 +00005795 cpu_clone_regs(env, newsp);
5796 fork_end(1);
aurel322b1319c2008-12-18 22:44:04 +00005797 /* There is a race condition here. The parent process could
5798 theoretically read the TID in the child process before the child
5799 tid is set. This would require using either ptrace
5800 (not implemented) or having *_tidptr to point at a shared memory
5801 mapping. We can't repeat the spinlock hack used above because
5802 the child process gets its own copy of the lock. */
pbrookd865bab2008-06-07 22:12:17 +00005803 if (flags & CLONE_CHILD_SETTID)
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +00005804 put_user_u32(sys_gettid(), child_tidptr);
pbrookd865bab2008-06-07 22:12:17 +00005805 if (flags & CLONE_PARENT_SETTID)
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +00005806 put_user_u32(sys_gettid(), parent_tidptr);
Andreas Färber0429a972013-08-26 18:14:44 +02005807 ts = (TaskState *)cpu->opaque;
pbrookd865bab2008-06-07 22:12:17 +00005808 if (flags & CLONE_SETTLS)
5809 cpu_set_tls (env, newtls);
pbrookc2764712009-03-07 15:24:59 +00005810 if (flags & CLONE_CHILD_CLEARTID)
5811 ts->child_tidptr = child_tidptr;
pbrookd865bab2008-06-07 22:12:17 +00005812 } else {
5813 fork_end(0);
5814 }
bellard1b6b0292003-03-22 17:31:38 +00005815 }
5816 return ret;
5817}
5818
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02005819/* warning : doesn't handle linux specific flags... */
5820static int target_to_host_fcntl_cmd(int cmd)
5821{
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05005822 int ret;
5823
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02005824 switch(cmd) {
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05005825 case TARGET_F_DUPFD:
5826 case TARGET_F_GETFD:
5827 case TARGET_F_SETFD:
5828 case TARGET_F_GETFL:
5829 case TARGET_F_SETFL:
5830 ret = cmd;
5831 break;
5832 case TARGET_F_GETLK:
5833 ret = F_GETLK64;
5834 break;
5835 case TARGET_F_SETLK:
5836 ret = F_SETLK64;
5837 break;
5838 case TARGET_F_SETLKW:
5839 ret = F_SETLKW64;
5840 break;
5841 case TARGET_F_GETOWN:
5842 ret = F_GETOWN;
5843 break;
5844 case TARGET_F_SETOWN:
5845 ret = F_SETOWN;
5846 break;
5847 case TARGET_F_GETSIG:
5848 ret = F_GETSIG;
5849 break;
5850 case TARGET_F_SETSIG:
5851 ret = F_SETSIG;
5852 break;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02005853#if TARGET_ABI_BITS == 32
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05005854 case TARGET_F_GETLK64:
5855 ret = F_GETLK64;
5856 break;
5857 case TARGET_F_SETLK64:
5858 ret = F_SETLK64;
5859 break;
5860 case TARGET_F_SETLKW64:
5861 ret = F_SETLKW64;
5862 break;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02005863#endif
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05005864 case TARGET_F_SETLEASE:
5865 ret = F_SETLEASE;
5866 break;
5867 case TARGET_F_GETLEASE:
5868 ret = F_GETLEASE;
5869 break;
malcfbd5de92009-09-06 06:31:59 +04005870#ifdef F_DUPFD_CLOEXEC
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05005871 case TARGET_F_DUPFD_CLOEXEC:
5872 ret = F_DUPFD_CLOEXEC;
5873 break;
malcfbd5de92009-09-06 06:31:59 +04005874#endif
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05005875 case TARGET_F_NOTIFY:
5876 ret = F_NOTIFY;
5877 break;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01005878#ifdef F_GETOWN_EX
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05005879 case TARGET_F_GETOWN_EX:
5880 ret = F_GETOWN_EX;
5881 break;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01005882#endif
5883#ifdef F_SETOWN_EX
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05005884 case TARGET_F_SETOWN_EX:
5885 ret = F_SETOWN_EX;
5886 break;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01005887#endif
Peter Maydellddf31aa2016-06-30 17:33:49 +01005888#ifdef F_SETPIPE_SZ
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05005889 case TARGET_F_SETPIPE_SZ:
5890 ret = F_SETPIPE_SZ;
5891 break;
5892 case TARGET_F_GETPIPE_SZ:
5893 ret = F_GETPIPE_SZ;
5894 break;
Peter Maydellddf31aa2016-06-30 17:33:49 +01005895#endif
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05005896 default:
5897 ret = -TARGET_EINVAL;
5898 break;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02005899 }
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05005900
5901#if defined(__powerpc64__)
5902 /* On PPC64, glibc headers has the F_*LK* defined to 12, 13 and 14 and
5903 * is not supported by kernel. The glibc fcntl call actually adjusts
5904 * them to 5, 6 and 7 before making the syscall(). Since we make the
5905 * syscall directly, adjust to what is supported by the kernel.
5906 */
5907 if (ret >= F_GETLK64 && ret <= F_SETLKW64) {
5908 ret -= F_GETLK64 - 5;
5909 }
5910#endif
5911
5912 return ret;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02005913}
5914
Laurent Vivierae68ad92018-05-10 01:11:21 +02005915#define FLOCK_TRANSTBL \
5916 switch (type) { \
5917 TRANSTBL_CONVERT(F_RDLCK); \
5918 TRANSTBL_CONVERT(F_WRLCK); \
5919 TRANSTBL_CONVERT(F_UNLCK); \
5920 TRANSTBL_CONVERT(F_EXLCK); \
5921 TRANSTBL_CONVERT(F_SHLCK); \
5922 }
5923
5924static int target_to_host_flock(int type)
5925{
5926#define TRANSTBL_CONVERT(a) case TARGET_##a: return a
5927 FLOCK_TRANSTBL
5928#undef TRANSTBL_CONVERT
5929 return -TARGET_EINVAL;
5930}
5931
5932static int host_to_target_flock(int type)
5933{
5934#define TRANSTBL_CONVERT(a) case a: return TARGET_##a
5935 FLOCK_TRANSTBL
5936#undef TRANSTBL_CONVERT
5937 /* if we don't know how to convert the value coming
5938 * from the host we copy to the target field as-is
5939 */
5940 return type;
5941}
Laurent Vivier2ba7f732013-01-10 21:42:48 +01005942
Peter Maydell213d3e92016-06-13 11:22:05 +01005943static inline abi_long copy_from_user_flock(struct flock64 *fl,
5944 abi_ulong target_flock_addr)
5945{
5946 struct target_flock *target_fl;
Laurent Vivierae68ad92018-05-10 01:11:21 +02005947 int l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01005948
5949 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
5950 return -TARGET_EFAULT;
5951 }
5952
5953 __get_user(l_type, &target_fl->l_type);
Laurent Vivierae68ad92018-05-10 01:11:21 +02005954 l_type = target_to_host_flock(l_type);
5955 if (l_type < 0) {
5956 return l_type;
5957 }
5958 fl->l_type = l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01005959 __get_user(fl->l_whence, &target_fl->l_whence);
5960 __get_user(fl->l_start, &target_fl->l_start);
5961 __get_user(fl->l_len, &target_fl->l_len);
5962 __get_user(fl->l_pid, &target_fl->l_pid);
5963 unlock_user_struct(target_fl, target_flock_addr, 0);
5964 return 0;
5965}
5966
5967static inline abi_long copy_to_user_flock(abi_ulong target_flock_addr,
5968 const struct flock64 *fl)
5969{
5970 struct target_flock *target_fl;
5971 short l_type;
5972
5973 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
5974 return -TARGET_EFAULT;
5975 }
5976
Laurent Vivierae68ad92018-05-10 01:11:21 +02005977 l_type = host_to_target_flock(fl->l_type);
Peter Maydell213d3e92016-06-13 11:22:05 +01005978 __put_user(l_type, &target_fl->l_type);
5979 __put_user(fl->l_whence, &target_fl->l_whence);
5980 __put_user(fl->l_start, &target_fl->l_start);
5981 __put_user(fl->l_len, &target_fl->l_len);
5982 __put_user(fl->l_pid, &target_fl->l_pid);
5983 unlock_user_struct(target_fl, target_flock_addr, 1);
5984 return 0;
5985}
5986
5987typedef abi_long from_flock64_fn(struct flock64 *fl, abi_ulong target_addr);
5988typedef abi_long to_flock64_fn(abi_ulong target_addr, const struct flock64 *fl);
5989
5990#if defined(TARGET_ARM) && TARGET_ABI_BITS == 32
Laurent Vivier7f254c52018-05-02 23:57:30 +02005991static inline abi_long copy_from_user_oabi_flock64(struct flock64 *fl,
Peter Maydell213d3e92016-06-13 11:22:05 +01005992 abi_ulong target_flock_addr)
5993{
Laurent Vivier7f254c52018-05-02 23:57:30 +02005994 struct target_oabi_flock64 *target_fl;
Laurent Vivierae68ad92018-05-10 01:11:21 +02005995 int l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01005996
5997 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
5998 return -TARGET_EFAULT;
5999 }
6000
6001 __get_user(l_type, &target_fl->l_type);
Laurent Vivierae68ad92018-05-10 01:11:21 +02006002 l_type = target_to_host_flock(l_type);
6003 if (l_type < 0) {
6004 return l_type;
6005 }
6006 fl->l_type = l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006007 __get_user(fl->l_whence, &target_fl->l_whence);
6008 __get_user(fl->l_start, &target_fl->l_start);
6009 __get_user(fl->l_len, &target_fl->l_len);
6010 __get_user(fl->l_pid, &target_fl->l_pid);
6011 unlock_user_struct(target_fl, target_flock_addr, 0);
6012 return 0;
6013}
6014
Laurent Vivier7f254c52018-05-02 23:57:30 +02006015static inline abi_long copy_to_user_oabi_flock64(abi_ulong target_flock_addr,
Peter Maydell213d3e92016-06-13 11:22:05 +01006016 const struct flock64 *fl)
6017{
Laurent Vivier7f254c52018-05-02 23:57:30 +02006018 struct target_oabi_flock64 *target_fl;
Peter Maydell213d3e92016-06-13 11:22:05 +01006019 short l_type;
6020
6021 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
6022 return -TARGET_EFAULT;
6023 }
6024
Laurent Vivierae68ad92018-05-10 01:11:21 +02006025 l_type = host_to_target_flock(fl->l_type);
Peter Maydell213d3e92016-06-13 11:22:05 +01006026 __put_user(l_type, &target_fl->l_type);
6027 __put_user(fl->l_whence, &target_fl->l_whence);
6028 __put_user(fl->l_start, &target_fl->l_start);
6029 __put_user(fl->l_len, &target_fl->l_len);
6030 __put_user(fl->l_pid, &target_fl->l_pid);
6031 unlock_user_struct(target_fl, target_flock_addr, 1);
6032 return 0;
6033}
6034#endif
6035
6036static inline abi_long copy_from_user_flock64(struct flock64 *fl,
6037 abi_ulong target_flock_addr)
6038{
6039 struct target_flock64 *target_fl;
Laurent Vivierae68ad92018-05-10 01:11:21 +02006040 int l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006041
6042 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
6043 return -TARGET_EFAULT;
6044 }
6045
6046 __get_user(l_type, &target_fl->l_type);
Laurent Vivierae68ad92018-05-10 01:11:21 +02006047 l_type = target_to_host_flock(l_type);
6048 if (l_type < 0) {
6049 return l_type;
6050 }
6051 fl->l_type = l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006052 __get_user(fl->l_whence, &target_fl->l_whence);
6053 __get_user(fl->l_start, &target_fl->l_start);
6054 __get_user(fl->l_len, &target_fl->l_len);
6055 __get_user(fl->l_pid, &target_fl->l_pid);
6056 unlock_user_struct(target_fl, target_flock_addr, 0);
6057 return 0;
6058}
6059
6060static inline abi_long copy_to_user_flock64(abi_ulong target_flock_addr,
6061 const struct flock64 *fl)
6062{
6063 struct target_flock64 *target_fl;
6064 short l_type;
6065
6066 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
6067 return -TARGET_EFAULT;
6068 }
6069
Laurent Vivierae68ad92018-05-10 01:11:21 +02006070 l_type = host_to_target_flock(fl->l_type);
Peter Maydell213d3e92016-06-13 11:22:05 +01006071 __put_user(l_type, &target_fl->l_type);
6072 __put_user(fl->l_whence, &target_fl->l_whence);
6073 __put_user(fl->l_start, &target_fl->l_start);
6074 __put_user(fl->l_len, &target_fl->l_len);
6075 __put_user(fl->l_pid, &target_fl->l_pid);
6076 unlock_user_struct(target_fl, target_flock_addr, 1);
6077 return 0;
6078}
6079
blueswir1992f48a2007-10-14 16:27:31 +00006080static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
bellard7775e9e2003-05-14 22:46:48 +00006081{
ths43f238d2007-01-05 20:55:49 +00006082 struct flock64 fl64;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006083#ifdef F_GETOWN_EX
6084 struct f_owner_ex fox;
6085 struct target_f_owner_ex *target_fox;
6086#endif
blueswir1992f48a2007-10-14 16:27:31 +00006087 abi_long ret;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006088 int host_cmd = target_to_host_fcntl_cmd(cmd);
6089
6090 if (host_cmd == -TARGET_EINVAL)
6091 return host_cmd;
pbrook53a59602006-03-25 19:31:22 +00006092
bellard7775e9e2003-05-14 22:46:48 +00006093 switch(cmd) {
6094 case TARGET_F_GETLK:
Peter Maydell213d3e92016-06-13 11:22:05 +01006095 ret = copy_from_user_flock(&fl64, arg);
6096 if (ret) {
6097 return ret;
6098 }
Peter Maydell435da5e2016-06-13 11:22:05 +01006099 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00006100 if (ret == 0) {
Peter Maydell213d3e92016-06-13 11:22:05 +01006101 ret = copy_to_user_flock(arg, &fl64);
bellard7775e9e2003-05-14 22:46:48 +00006102 }
6103 break;
ths3b46e622007-09-17 08:09:54 +00006104
bellard7775e9e2003-05-14 22:46:48 +00006105 case TARGET_F_SETLK:
6106 case TARGET_F_SETLKW:
Peter Maydell213d3e92016-06-13 11:22:05 +01006107 ret = copy_from_user_flock(&fl64, arg);
6108 if (ret) {
6109 return ret;
6110 }
Peter Maydell435da5e2016-06-13 11:22:05 +01006111 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00006112 break;
ths3b46e622007-09-17 08:09:54 +00006113
bellard7775e9e2003-05-14 22:46:48 +00006114 case TARGET_F_GETLK64:
Peter Maydell213d3e92016-06-13 11:22:05 +01006115 ret = copy_from_user_flock64(&fl64, arg);
6116 if (ret) {
6117 return ret;
6118 }
Peter Maydell435da5e2016-06-13 11:22:05 +01006119 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
ths43f238d2007-01-05 20:55:49 +00006120 if (ret == 0) {
Peter Maydell213d3e92016-06-13 11:22:05 +01006121 ret = copy_to_user_flock64(arg, &fl64);
ths43f238d2007-01-05 20:55:49 +00006122 }
bellard9ee1fa22007-11-11 15:11:19 +00006123 break;
bellard7775e9e2003-05-14 22:46:48 +00006124 case TARGET_F_SETLK64:
6125 case TARGET_F_SETLKW64:
Peter Maydell213d3e92016-06-13 11:22:05 +01006126 ret = copy_from_user_flock64(&fl64, arg);
6127 if (ret) {
6128 return ret;
6129 }
Peter Maydell435da5e2016-06-13 11:22:05 +01006130 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00006131 break;
6132
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006133 case TARGET_F_GETFL:
Peter Maydell435da5e2016-06-13 11:22:05 +01006134 ret = get_errno(safe_fcntl(fd, host_cmd, arg));
bellard9ee1fa22007-11-11 15:11:19 +00006135 if (ret >= 0) {
6136 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
6137 }
bellardffa65c32004-01-04 23:57:22 +00006138 break;
6139
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006140 case TARGET_F_SETFL:
Peter Maydell435da5e2016-06-13 11:22:05 +01006141 ret = get_errno(safe_fcntl(fd, host_cmd,
6142 target_to_host_bitmask(arg,
6143 fcntl_flags_tbl)));
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006144 break;
6145
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006146#ifdef F_GETOWN_EX
6147 case TARGET_F_GETOWN_EX:
Peter Maydell435da5e2016-06-13 11:22:05 +01006148 ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006149 if (ret >= 0) {
6150 if (!lock_user_struct(VERIFY_WRITE, target_fox, arg, 0))
6151 return -TARGET_EFAULT;
6152 target_fox->type = tswap32(fox.type);
6153 target_fox->pid = tswap32(fox.pid);
6154 unlock_user_struct(target_fox, arg, 1);
6155 }
6156 break;
6157#endif
6158
6159#ifdef F_SETOWN_EX
6160 case TARGET_F_SETOWN_EX:
6161 if (!lock_user_struct(VERIFY_READ, target_fox, arg, 1))
6162 return -TARGET_EFAULT;
6163 fox.type = tswap32(target_fox->type);
6164 fox.pid = tswap32(target_fox->pid);
6165 unlock_user_struct(target_fox, arg, 0);
Peter Maydell435da5e2016-06-13 11:22:05 +01006166 ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006167 break;
6168#endif
6169
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006170 case TARGET_F_SETOWN:
6171 case TARGET_F_GETOWN:
6172 case TARGET_F_SETSIG:
6173 case TARGET_F_GETSIG:
Ulrich Hecht7e22e542009-07-24 19:10:27 +02006174 case TARGET_F_SETLEASE:
6175 case TARGET_F_GETLEASE:
Peter Maydell7e3b92e2016-06-20 15:50:37 +01006176 case TARGET_F_SETPIPE_SZ:
6177 case TARGET_F_GETPIPE_SZ:
Peter Maydell435da5e2016-06-13 11:22:05 +01006178 ret = get_errno(safe_fcntl(fd, host_cmd, arg));
bellardffa65c32004-01-04 23:57:22 +00006179 break;
6180
bellard7775e9e2003-05-14 22:46:48 +00006181 default:
Peter Maydell435da5e2016-06-13 11:22:05 +01006182 ret = get_errno(safe_fcntl(fd, cmd, arg));
bellard7775e9e2003-05-14 22:46:48 +00006183 break;
6184 }
6185 return ret;
6186}
6187
bellard67867302003-11-23 17:05:30 +00006188#ifdef USE_UID16
bellard7775e9e2003-05-14 22:46:48 +00006189
bellard67867302003-11-23 17:05:30 +00006190static inline int high2lowuid(int uid)
6191{
6192 if (uid > 65535)
6193 return 65534;
6194 else
6195 return uid;
6196}
6197
6198static inline int high2lowgid(int gid)
6199{
6200 if (gid > 65535)
6201 return 65534;
6202 else
6203 return gid;
6204}
6205
6206static inline int low2highuid(int uid)
6207{
6208 if ((int16_t)uid == -1)
6209 return -1;
6210 else
6211 return uid;
6212}
6213
6214static inline int low2highgid(int gid)
6215{
6216 if ((int16_t)gid == -1)
6217 return -1;
6218 else
6219 return gid;
6220}
Riku Voipio0c866a72011-04-18 15:23:06 +03006221static inline int tswapid(int id)
6222{
6223 return tswap16(id);
6224}
Peter Maydell76ca3102014-03-02 19:36:41 +00006225
6226#define put_user_id(x, gaddr) put_user_u16(x, gaddr)
6227
Riku Voipio0c866a72011-04-18 15:23:06 +03006228#else /* !USE_UID16 */
6229static inline int high2lowuid(int uid)
6230{
6231 return uid;
6232}
6233static inline int high2lowgid(int gid)
6234{
6235 return gid;
6236}
6237static inline int low2highuid(int uid)
6238{
6239 return uid;
6240}
6241static inline int low2highgid(int gid)
6242{
6243 return gid;
6244}
6245static inline int tswapid(int id)
6246{
6247 return tswap32(id);
6248}
Peter Maydell76ca3102014-03-02 19:36:41 +00006249
6250#define put_user_id(x, gaddr) put_user_u32(x, gaddr)
6251
bellard67867302003-11-23 17:05:30 +00006252#endif /* USE_UID16 */
bellard1b6b0292003-03-22 17:31:38 +00006253
Peter Maydellfd6f7792016-03-01 16:33:02 +00006254/* We must do direct syscalls for setting UID/GID, because we want to
6255 * implement the Linux system call semantics of "change only for this thread",
6256 * not the libc/POSIX semantics of "change for all threads in process".
6257 * (See http://ewontfix.com/17/ for more details.)
6258 * We use the 32-bit version of the syscalls if present; if it is not
6259 * then either the host architecture supports 32-bit UIDs natively with
6260 * the standard syscall, or the 16-bit UID is the best we can do.
6261 */
6262#ifdef __NR_setuid32
6263#define __NR_sys_setuid __NR_setuid32
6264#else
6265#define __NR_sys_setuid __NR_setuid
6266#endif
6267#ifdef __NR_setgid32
6268#define __NR_sys_setgid __NR_setgid32
6269#else
6270#define __NR_sys_setgid __NR_setgid
6271#endif
6272#ifdef __NR_setresuid32
6273#define __NR_sys_setresuid __NR_setresuid32
6274#else
6275#define __NR_sys_setresuid __NR_setresuid
6276#endif
6277#ifdef __NR_setresgid32
6278#define __NR_sys_setresgid __NR_setresgid32
6279#else
6280#define __NR_sys_setresgid __NR_setresgid
6281#endif
6282
6283_syscall1(int, sys_setuid, uid_t, uid)
6284_syscall1(int, sys_setgid, gid_t, gid)
6285_syscall3(int, sys_setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
6286_syscall3(int, sys_setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
6287
bellard31e31b82003-02-18 22:55:36 +00006288void syscall_init(void)
6289{
bellard2ab83ea2003-06-15 19:56:46 +00006290 IOCTLEntry *ie;
6291 const argtype *arg_type;
6292 int size;
thsb92c47c2007-11-01 00:07:38 +00006293 int i;
bellard2ab83ea2003-06-15 19:56:46 +00006294
Alexander Graf8be656b2015-05-06 23:47:32 +02006295 thunk_init(STRUCT_MAX);
6296
Blue Swirl001faf32009-05-13 17:53:17 +00006297#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
ths5fafdf22007-09-16 21:08:06 +00006298#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
bellard31e31b82003-02-18 22:55:36 +00006299#include "syscall_types.h"
6300#undef STRUCT
6301#undef STRUCT_SPECIAL
bellard2ab83ea2003-06-15 19:56:46 +00006302
Peter Maydelldd6e9572012-07-23 08:07:22 +00006303 /* Build target_to_host_errno_table[] table from
6304 * host_to_target_errno_table[]. */
6305 for (i = 0; i < ERRNO_TABLE_SIZE; i++) {
6306 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
6307 }
6308
bellard2ab83ea2003-06-15 19:56:46 +00006309 /* we patch the ioctl size if necessary. We rely on the fact that
6310 no ioctl has all the bits at '1' in the size field */
6311 ie = ioctl_entries;
6312 while (ie->target_cmd != 0) {
6313 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
6314 TARGET_IOC_SIZEMASK) {
6315 arg_type = ie->arg_type;
6316 if (arg_type[0] != TYPE_PTR) {
ths5fafdf22007-09-16 21:08:06 +00006317 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00006318 ie->target_cmd);
6319 exit(1);
6320 }
6321 arg_type++;
6322 size = thunk_type_size(arg_type, 0);
ths5fafdf22007-09-16 21:08:06 +00006323 ie->target_cmd = (ie->target_cmd &
bellard2ab83ea2003-06-15 19:56:46 +00006324 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
6325 (size << TARGET_IOC_SIZESHIFT);
6326 }
thsb92c47c2007-11-01 00:07:38 +00006327
bellard2ab83ea2003-06-15 19:56:46 +00006328 /* automatic consistency check if same arch */
balrog872ea0c2008-09-21 02:31:19 +00006329#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
6330 (defined(__x86_64__) && defined(TARGET_X86_64))
6331 if (unlikely(ie->target_cmd != ie->host_cmd)) {
6332 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
6333 ie->name, ie->target_cmd, ie->host_cmd);
bellard2ab83ea2003-06-15 19:56:46 +00006334 }
6335#endif
6336 ie++;
6337 }
bellard31e31b82003-02-18 22:55:36 +00006338}
bellardc573ff62004-01-04 15:51:36 +00006339
blueswir1992f48a2007-10-14 16:27:31 +00006340#if TARGET_ABI_BITS == 32
pbrookce4defa2006-02-09 16:49:55 +00006341static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
6342{
thsaf325d32008-06-10 15:29:15 +00006343#ifdef TARGET_WORDS_BIGENDIAN
pbrookce4defa2006-02-09 16:49:55 +00006344 return ((uint64_t)word0 << 32) | word1;
6345#else
6346 return ((uint64_t)word1 << 32) | word0;
6347#endif
6348}
blueswir1992f48a2007-10-14 16:27:31 +00006349#else /* TARGET_ABI_BITS == 32 */
j_mayer32407102007-09-26 23:01:49 +00006350static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
6351{
6352 return word0;
6353}
blueswir1992f48a2007-10-14 16:27:31 +00006354#endif /* TARGET_ABI_BITS != 32 */
pbrookce4defa2006-02-09 16:49:55 +00006355
6356#ifdef TARGET_NR_truncate64
blueswir1992f48a2007-10-14 16:27:31 +00006357static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
6358 abi_long arg2,
6359 abi_long arg3,
6360 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00006361{
James Clarke8bf8e9d2017-09-15 20:33:13 +01006362 if (regpairs_aligned(cpu_env, TARGET_NR_truncate64)) {
pbrookce4defa2006-02-09 16:49:55 +00006363 arg2 = arg3;
6364 arg3 = arg4;
Riku Voipio48e515d2011-07-12 15:40:51 +03006365 }
pbrookce4defa2006-02-09 16:49:55 +00006366 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
6367}
6368#endif
6369
6370#ifdef TARGET_NR_ftruncate64
blueswir1992f48a2007-10-14 16:27:31 +00006371static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
6372 abi_long arg2,
6373 abi_long arg3,
6374 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00006375{
James Clarke8bf8e9d2017-09-15 20:33:13 +01006376 if (regpairs_aligned(cpu_env, TARGET_NR_ftruncate64)) {
pbrookce4defa2006-02-09 16:49:55 +00006377 arg2 = arg3;
6378 arg3 = arg4;
Riku Voipio48e515d2011-07-12 15:40:51 +03006379 }
pbrookce4defa2006-02-09 16:49:55 +00006380 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
6381}
6382#endif
6383
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11006384static inline abi_long target_to_host_itimerspec(struct itimerspec *host_itspec,
6385 abi_ulong target_addr)
6386{
6387 struct target_itimerspec *target_itspec;
6388
6389 if (!lock_user_struct(VERIFY_READ, target_itspec, target_addr, 1)) {
6390 return -TARGET_EFAULT;
6391 }
6392
6393 host_itspec->it_interval.tv_sec =
6394 tswapal(target_itspec->it_interval.tv_sec);
6395 host_itspec->it_interval.tv_nsec =
6396 tswapal(target_itspec->it_interval.tv_nsec);
6397 host_itspec->it_value.tv_sec = tswapal(target_itspec->it_value.tv_sec);
6398 host_itspec->it_value.tv_nsec = tswapal(target_itspec->it_value.tv_nsec);
6399
6400 unlock_user_struct(target_itspec, target_addr, 1);
6401 return 0;
6402}
6403
6404static inline abi_long host_to_target_itimerspec(abi_ulong target_addr,
6405 struct itimerspec *host_its)
6406{
6407 struct target_itimerspec *target_itspec;
6408
6409 if (!lock_user_struct(VERIFY_WRITE, target_itspec, target_addr, 0)) {
6410 return -TARGET_EFAULT;
6411 }
6412
6413 target_itspec->it_interval.tv_sec = tswapal(host_its->it_interval.tv_sec);
6414 target_itspec->it_interval.tv_nsec = tswapal(host_its->it_interval.tv_nsec);
6415
6416 target_itspec->it_value.tv_sec = tswapal(host_its->it_value.tv_sec);
6417 target_itspec->it_value.tv_nsec = tswapal(host_its->it_value.tv_nsec);
6418
6419 unlock_user_struct(target_itspec, target_addr, 0);
6420 return 0;
6421}
6422
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +02006423static inline abi_long target_to_host_timex(struct timex *host_tx,
6424 abi_long target_addr)
6425{
6426 struct target_timex *target_tx;
6427
6428 if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) {
6429 return -TARGET_EFAULT;
6430 }
6431
6432 __get_user(host_tx->modes, &target_tx->modes);
6433 __get_user(host_tx->offset, &target_tx->offset);
6434 __get_user(host_tx->freq, &target_tx->freq);
6435 __get_user(host_tx->maxerror, &target_tx->maxerror);
6436 __get_user(host_tx->esterror, &target_tx->esterror);
6437 __get_user(host_tx->status, &target_tx->status);
6438 __get_user(host_tx->constant, &target_tx->constant);
6439 __get_user(host_tx->precision, &target_tx->precision);
6440 __get_user(host_tx->tolerance, &target_tx->tolerance);
6441 __get_user(host_tx->time.tv_sec, &target_tx->time.tv_sec);
6442 __get_user(host_tx->time.tv_usec, &target_tx->time.tv_usec);
6443 __get_user(host_tx->tick, &target_tx->tick);
6444 __get_user(host_tx->ppsfreq, &target_tx->ppsfreq);
6445 __get_user(host_tx->jitter, &target_tx->jitter);
6446 __get_user(host_tx->shift, &target_tx->shift);
6447 __get_user(host_tx->stabil, &target_tx->stabil);
6448 __get_user(host_tx->jitcnt, &target_tx->jitcnt);
6449 __get_user(host_tx->calcnt, &target_tx->calcnt);
6450 __get_user(host_tx->errcnt, &target_tx->errcnt);
6451 __get_user(host_tx->stbcnt, &target_tx->stbcnt);
6452 __get_user(host_tx->tai, &target_tx->tai);
6453
6454 unlock_user_struct(target_tx, target_addr, 0);
6455 return 0;
6456}
6457
6458static inline abi_long host_to_target_timex(abi_long target_addr,
6459 struct timex *host_tx)
6460{
6461 struct target_timex *target_tx;
6462
6463 if (!lock_user_struct(VERIFY_WRITE, target_tx, target_addr, 0)) {
6464 return -TARGET_EFAULT;
6465 }
6466
6467 __put_user(host_tx->modes, &target_tx->modes);
6468 __put_user(host_tx->offset, &target_tx->offset);
6469 __put_user(host_tx->freq, &target_tx->freq);
6470 __put_user(host_tx->maxerror, &target_tx->maxerror);
6471 __put_user(host_tx->esterror, &target_tx->esterror);
6472 __put_user(host_tx->status, &target_tx->status);
6473 __put_user(host_tx->constant, &target_tx->constant);
6474 __put_user(host_tx->precision, &target_tx->precision);
6475 __put_user(host_tx->tolerance, &target_tx->tolerance);
6476 __put_user(host_tx->time.tv_sec, &target_tx->time.tv_sec);
6477 __put_user(host_tx->time.tv_usec, &target_tx->time.tv_usec);
6478 __put_user(host_tx->tick, &target_tx->tick);
6479 __put_user(host_tx->ppsfreq, &target_tx->ppsfreq);
6480 __put_user(host_tx->jitter, &target_tx->jitter);
6481 __put_user(host_tx->shift, &target_tx->shift);
6482 __put_user(host_tx->stabil, &target_tx->stabil);
6483 __put_user(host_tx->jitcnt, &target_tx->jitcnt);
6484 __put_user(host_tx->calcnt, &target_tx->calcnt);
6485 __put_user(host_tx->errcnt, &target_tx->errcnt);
6486 __put_user(host_tx->stbcnt, &target_tx->stbcnt);
6487 __put_user(host_tx->tai, &target_tx->tai);
6488
6489 unlock_user_struct(target_tx, target_addr, 1);
6490 return 0;
6491}
6492
6493
Peter Maydellc0659762014-08-09 15:42:32 +01006494static inline abi_long target_to_host_sigevent(struct sigevent *host_sevp,
6495 abi_ulong target_addr)
6496{
6497 struct target_sigevent *target_sevp;
6498
6499 if (!lock_user_struct(VERIFY_READ, target_sevp, target_addr, 1)) {
6500 return -TARGET_EFAULT;
6501 }
6502
6503 /* This union is awkward on 64 bit systems because it has a 32 bit
6504 * integer and a pointer in it; we follow the conversion approach
6505 * used for handling sigval types in signal.c so the guest should get
6506 * the correct value back even if we did a 64 bit byteswap and it's
6507 * using the 32 bit integer.
6508 */
6509 host_sevp->sigev_value.sival_ptr =
6510 (void *)(uintptr_t)tswapal(target_sevp->sigev_value.sival_ptr);
6511 host_sevp->sigev_signo =
6512 target_to_host_signal(tswap32(target_sevp->sigev_signo));
6513 host_sevp->sigev_notify = tswap32(target_sevp->sigev_notify);
6514 host_sevp->_sigev_un._tid = tswap32(target_sevp->_sigev_un._tid);
6515
6516 unlock_user_struct(target_sevp, target_addr, 1);
6517 return 0;
6518}
6519
Tom Musta6f6a4032014-08-12 13:53:42 -05006520#if defined(TARGET_NR_mlockall)
6521static inline int target_to_host_mlockall_arg(int arg)
6522{
6523 int result = 0;
6524
6525 if (arg & TARGET_MLOCKALL_MCL_CURRENT) {
6526 result |= MCL_CURRENT;
6527 }
6528 if (arg & TARGET_MLOCKALL_MCL_FUTURE) {
6529 result |= MCL_FUTURE;
6530 }
6531 return result;
6532}
6533#endif
6534
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02006535#if (defined(TARGET_NR_stat64) || defined(TARGET_NR_lstat64) || \
6536 defined(TARGET_NR_fstat64) || defined(TARGET_NR_fstatat64) || \
6537 defined(TARGET_NR_newfstatat))
balrog6a24a772008-09-20 02:23:36 +00006538static inline abi_long host_to_target_stat64(void *cpu_env,
6539 abi_ulong target_addr,
6540 struct stat *host_st)
6541{
Alexander Graf09701192013-09-03 20:12:15 +01006542#if defined(TARGET_ARM) && defined(TARGET_ABI32)
balrog6a24a772008-09-20 02:23:36 +00006543 if (((CPUARMState *)cpu_env)->eabi) {
6544 struct target_eabi_stat64 *target_st;
6545
6546 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
6547 return -TARGET_EFAULT;
6548 memset(target_st, 0, sizeof(struct target_eabi_stat64));
6549 __put_user(host_st->st_dev, &target_st->st_dev);
6550 __put_user(host_st->st_ino, &target_st->st_ino);
6551#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
6552 __put_user(host_st->st_ino, &target_st->__st_ino);
6553#endif
6554 __put_user(host_st->st_mode, &target_st->st_mode);
6555 __put_user(host_st->st_nlink, &target_st->st_nlink);
6556 __put_user(host_st->st_uid, &target_st->st_uid);
6557 __put_user(host_st->st_gid, &target_st->st_gid);
6558 __put_user(host_st->st_rdev, &target_st->st_rdev);
6559 __put_user(host_st->st_size, &target_st->st_size);
6560 __put_user(host_st->st_blksize, &target_st->st_blksize);
6561 __put_user(host_st->st_blocks, &target_st->st_blocks);
6562 __put_user(host_st->st_atime, &target_st->target_st_atime);
6563 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
6564 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
Chen-Yu Tsai5f992db2019-05-23 00:21:47 +08006565#if _POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700
6566 __put_user(host_st->st_atim.tv_nsec, &target_st->target_st_atime_nsec);
6567 __put_user(host_st->st_mtim.tv_nsec, &target_st->target_st_mtime_nsec);
6568 __put_user(host_st->st_ctim.tv_nsec, &target_st->target_st_ctime_nsec);
6569#endif
balrog6a24a772008-09-20 02:23:36 +00006570 unlock_user_struct(target_st, target_addr, 1);
6571 } else
6572#endif
6573 {
Stefan Weil20d155b2013-10-30 22:52:24 +01006574#if defined(TARGET_HAS_STRUCT_STAT64)
balrog6a24a772008-09-20 02:23:36 +00006575 struct target_stat64 *target_st;
Stefan Weil20d155b2013-10-30 22:52:24 +01006576#else
6577 struct target_stat *target_st;
aurel329d33b762009-04-08 23:07:05 +00006578#endif
balrog6a24a772008-09-20 02:23:36 +00006579
6580 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
6581 return -TARGET_EFAULT;
aurel329d33b762009-04-08 23:07:05 +00006582 memset(target_st, 0, sizeof(*target_st));
balrog6a24a772008-09-20 02:23:36 +00006583 __put_user(host_st->st_dev, &target_st->st_dev);
6584 __put_user(host_st->st_ino, &target_st->st_ino);
6585#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
6586 __put_user(host_st->st_ino, &target_st->__st_ino);
6587#endif
6588 __put_user(host_st->st_mode, &target_st->st_mode);
6589 __put_user(host_st->st_nlink, &target_st->st_nlink);
6590 __put_user(host_st->st_uid, &target_st->st_uid);
6591 __put_user(host_st->st_gid, &target_st->st_gid);
6592 __put_user(host_st->st_rdev, &target_st->st_rdev);
6593 /* XXX: better use of kernel struct */
6594 __put_user(host_st->st_size, &target_st->st_size);
6595 __put_user(host_st->st_blksize, &target_st->st_blksize);
6596 __put_user(host_st->st_blocks, &target_st->st_blocks);
6597 __put_user(host_st->st_atime, &target_st->target_st_atime);
6598 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
6599 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
Chen-Yu Tsai5f992db2019-05-23 00:21:47 +08006600#if _POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700
6601 __put_user(host_st->st_atim.tv_nsec, &target_st->target_st_atime_nsec);
6602 __put_user(host_st->st_mtim.tv_nsec, &target_st->target_st_mtime_nsec);
6603 __put_user(host_st->st_ctim.tv_nsec, &target_st->target_st_ctime_nsec);
6604#endif
balrog6a24a772008-09-20 02:23:36 +00006605 unlock_user_struct(target_st, target_addr, 1);
6606 }
6607
6608 return 0;
6609}
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02006610#endif
balrog6a24a772008-09-20 02:23:36 +00006611
Aleksandar Rikaloefa92182019-06-28 12:43:34 +02006612#if defined(TARGET_NR_statx) && defined(__NR_statx)
6613static inline abi_long host_to_target_statx(struct target_statx *host_stx,
6614 abi_ulong target_addr)
6615{
6616 struct target_statx *target_stx;
6617
6618 if (!lock_user_struct(VERIFY_WRITE, target_stx, target_addr, 0)) {
6619 return -TARGET_EFAULT;
6620 }
6621 memset(target_stx, 0, sizeof(*target_stx));
6622
6623 __put_user(host_stx->stx_mask, &target_stx->stx_mask);
6624 __put_user(host_stx->stx_blksize, &target_stx->stx_blksize);
6625 __put_user(host_stx->stx_attributes, &target_stx->stx_attributes);
6626 __put_user(host_stx->stx_nlink, &target_stx->stx_nlink);
6627 __put_user(host_stx->stx_uid, &target_stx->stx_uid);
6628 __put_user(host_stx->stx_gid, &target_stx->stx_gid);
6629 __put_user(host_stx->stx_mode, &target_stx->stx_mode);
6630 __put_user(host_stx->stx_ino, &target_stx->stx_ino);
6631 __put_user(host_stx->stx_size, &target_stx->stx_size);
6632 __put_user(host_stx->stx_blocks, &target_stx->stx_blocks);
6633 __put_user(host_stx->stx_attributes_mask, &target_stx->stx_attributes_mask);
6634 __put_user(host_stx->stx_atime.tv_sec, &target_stx->stx_atime.tv_sec);
6635 __put_user(host_stx->stx_atime.tv_nsec, &target_stx->stx_atime.tv_nsec);
6636 __put_user(host_stx->stx_btime.tv_sec, &target_stx->stx_atime.tv_sec);
6637 __put_user(host_stx->stx_btime.tv_nsec, &target_stx->stx_atime.tv_nsec);
6638 __put_user(host_stx->stx_ctime.tv_sec, &target_stx->stx_atime.tv_sec);
6639 __put_user(host_stx->stx_ctime.tv_nsec, &target_stx->stx_atime.tv_nsec);
6640 __put_user(host_stx->stx_mtime.tv_sec, &target_stx->stx_atime.tv_sec);
6641 __put_user(host_stx->stx_mtime.tv_nsec, &target_stx->stx_atime.tv_nsec);
6642 __put_user(host_stx->stx_rdev_major, &target_stx->stx_rdev_major);
6643 __put_user(host_stx->stx_rdev_minor, &target_stx->stx_rdev_minor);
6644 __put_user(host_stx->stx_dev_major, &target_stx->stx_dev_major);
6645 __put_user(host_stx->stx_dev_minor, &target_stx->stx_dev_minor);
6646
6647 unlock_user_struct(target_stx, target_addr, 1);
6648
6649 return 0;
6650}
6651#endif
6652
6653
pbrookbd0c5662008-05-29 14:34:11 +00006654/* ??? Using host futex calls even when target atomic operations
6655 are not really atomic probably breaks things. However implementing
6656 futexes locally would make futexes shared between multiple processes
6657 tricky. However they're probably useless because guest atomic
6658 operations won't work either. */
blueswir18fcd3692008-08-17 20:26:25 +00006659static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
6660 target_ulong uaddr2, int val3)
pbrookbd0c5662008-05-29 14:34:11 +00006661{
6662 struct timespec ts, *pts;
Nathan Froyda16aae02009-08-03 08:43:29 -07006663 int base_op;
pbrookbd0c5662008-05-29 14:34:11 +00006664
6665 /* ??? We assume FUTEX_* constants are the same on both host
6666 and target. */
Martin Mohringa29ccd62009-05-04 21:34:56 +03006667#ifdef FUTEX_CMD_MASK
Nathan Froyda16aae02009-08-03 08:43:29 -07006668 base_op = op & FUTEX_CMD_MASK;
Martin Mohringa29ccd62009-05-04 21:34:56 +03006669#else
Nathan Froyda16aae02009-08-03 08:43:29 -07006670 base_op = op;
Martin Mohringa29ccd62009-05-04 21:34:56 +03006671#endif
Nathan Froyda16aae02009-08-03 08:43:29 -07006672 switch (base_op) {
pbrookbd0c5662008-05-29 14:34:11 +00006673 case FUTEX_WAIT:
John Rigbycce246e2013-02-23 16:14:07 -07006674 case FUTEX_WAIT_BITSET:
pbrookbd0c5662008-05-29 14:34:11 +00006675 if (timeout) {
6676 pts = &ts;
6677 target_to_host_timespec(pts, timeout);
6678 } else {
6679 pts = NULL;
6680 }
Peter Maydelld509eeb2016-05-12 18:47:52 +01006681 return get_errno(safe_futex(g2h(uaddr), op, tswap32(val),
John Rigbycce246e2013-02-23 16:14:07 -07006682 pts, NULL, val3));
pbrookbd0c5662008-05-29 14:34:11 +00006683 case FUTEX_WAKE:
Peter Maydelld509eeb2016-05-12 18:47:52 +01006684 return get_errno(safe_futex(g2h(uaddr), op, val, NULL, NULL, 0));
pbrookbd0c5662008-05-29 14:34:11 +00006685 case FUTEX_FD:
Peter Maydelld509eeb2016-05-12 18:47:52 +01006686 return get_errno(safe_futex(g2h(uaddr), op, val, NULL, NULL, 0));
pbrookbd0c5662008-05-29 14:34:11 +00006687 case FUTEX_REQUEUE:
pbrookbd0c5662008-05-29 14:34:11 +00006688 case FUTEX_CMP_REQUEUE:
Nathan Froyda16aae02009-08-03 08:43:29 -07006689 case FUTEX_WAKE_OP:
6690 /* For FUTEX_REQUEUE, FUTEX_CMP_REQUEUE, and FUTEX_WAKE_OP, the
6691 TIMEOUT parameter is interpreted as a uint32_t by the kernel.
6692 But the prototype takes a `struct timespec *'; insert casts
6693 to satisfy the compiler. We do not need to tswap TIMEOUT
6694 since it's not compared to guest memory. */
6695 pts = (struct timespec *)(uintptr_t) timeout;
Peter Maydelld509eeb2016-05-12 18:47:52 +01006696 return get_errno(safe_futex(g2h(uaddr), op, val, pts,
6697 g2h(uaddr2),
6698 (base_op == FUTEX_CMP_REQUEUE
6699 ? tswap32(val3)
6700 : val3)));
pbrookbd0c5662008-05-29 14:34:11 +00006701 default:
6702 return -TARGET_ENOSYS;
6703 }
6704}
Laurent Vivier0f0426f2015-09-01 22:27:33 +02006705#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
6706static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname,
6707 abi_long handle, abi_long mount_id,
6708 abi_long flags)
6709{
6710 struct file_handle *target_fh;
6711 struct file_handle *fh;
6712 int mid = 0;
6713 abi_long ret;
6714 char *name;
6715 unsigned int size, total_size;
6716
6717 if (get_user_s32(size, handle)) {
6718 return -TARGET_EFAULT;
6719 }
6720
6721 name = lock_user_string(pathname);
6722 if (!name) {
6723 return -TARGET_EFAULT;
6724 }
6725
6726 total_size = sizeof(struct file_handle) + size;
6727 target_fh = lock_user(VERIFY_WRITE, handle, total_size, 0);
6728 if (!target_fh) {
6729 unlock_user(name, pathname, 0);
6730 return -TARGET_EFAULT;
6731 }
6732
6733 fh = g_malloc0(total_size);
6734 fh->handle_bytes = size;
6735
6736 ret = get_errno(name_to_handle_at(dirfd, path(name), fh, &mid, flags));
6737 unlock_user(name, pathname, 0);
6738
6739 /* man name_to_handle_at(2):
6740 * Other than the use of the handle_bytes field, the caller should treat
6741 * the file_handle structure as an opaque data type
6742 */
6743
6744 memcpy(target_fh, fh, total_size);
6745 target_fh->handle_bytes = tswap32(fh->handle_bytes);
6746 target_fh->handle_type = tswap32(fh->handle_type);
6747 g_free(fh);
6748 unlock_user(target_fh, handle, total_size);
6749
6750 if (put_user_s32(mid, mount_id)) {
6751 return -TARGET_EFAULT;
6752 }
6753
6754 return ret;
6755
6756}
6757#endif
6758
6759#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
6760static abi_long do_open_by_handle_at(abi_long mount_fd, abi_long handle,
6761 abi_long flags)
6762{
6763 struct file_handle *target_fh;
6764 struct file_handle *fh;
6765 unsigned int size, total_size;
6766 abi_long ret;
6767
6768 if (get_user_s32(size, handle)) {
6769 return -TARGET_EFAULT;
6770 }
6771
6772 total_size = sizeof(struct file_handle) + size;
6773 target_fh = lock_user(VERIFY_READ, handle, total_size, 1);
6774 if (!target_fh) {
6775 return -TARGET_EFAULT;
6776 }
6777
Thomas Huthe9d49d52015-10-09 17:56:38 +02006778 fh = g_memdup(target_fh, total_size);
Laurent Vivier0f0426f2015-09-01 22:27:33 +02006779 fh->handle_bytes = size;
6780 fh->handle_type = tswap32(target_fh->handle_type);
6781
6782 ret = get_errno(open_by_handle_at(mount_fd, fh,
6783 target_to_host_bitmask(flags, fcntl_flags_tbl)));
6784
6785 g_free(fh);
6786
6787 unlock_user(target_fh, handle, total_size);
6788
6789 return ret;
6790}
6791#endif
pbrookbd0c5662008-05-29 14:34:11 +00006792
Laurent Viviere36800c2015-10-02 14:48:09 +02006793#if defined(TARGET_NR_signalfd) || defined(TARGET_NR_signalfd4)
6794
Laurent Viviere36800c2015-10-02 14:48:09 +02006795static abi_long do_signalfd4(int fd, abi_long mask, int flags)
6796{
6797 int host_flags;
6798 target_sigset_t *target_mask;
6799 sigset_t host_mask;
6800 abi_long ret;
6801
6802 if (flags & ~(TARGET_O_NONBLOCK | TARGET_O_CLOEXEC)) {
6803 return -TARGET_EINVAL;
6804 }
6805 if (!lock_user_struct(VERIFY_READ, target_mask, mask, 1)) {
6806 return -TARGET_EFAULT;
6807 }
6808
6809 target_to_host_sigset(&host_mask, target_mask);
6810
6811 host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
6812
6813 ret = get_errno(signalfd(fd, &host_mask, host_flags));
6814 if (ret >= 0) {
6815 fd_trans_register(ret, &target_signalfd_trans);
6816 }
6817
6818 unlock_user_struct(target_mask, mask, 0);
6819
6820 return ret;
6821}
6822#endif
6823
pbrook1d9d8b52009-04-16 15:17:02 +00006824/* Map host to target signal numbers for the wait family of syscalls.
6825 Assume all other status bits are the same. */
Richard Hendersona05c6402012-09-15 11:34:20 -07006826int host_to_target_waitstatus(int status)
pbrook1d9d8b52009-04-16 15:17:02 +00006827{
6828 if (WIFSIGNALED(status)) {
6829 return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
6830 }
6831 if (WIFSTOPPED(status)) {
6832 return (host_to_target_signal(WSTOPSIG(status)) << 8)
6833 | (status & 0xff);
6834 }
6835 return status;
6836}
6837
Wim Vander Schelden76b94242014-06-18 11:02:39 +02006838static int open_self_cmdline(void *cpu_env, int fd)
6839{
Richard Henderson29a0af62019-03-22 16:07:18 -07006840 CPUState *cpu = env_cpu((CPUArchState *)cpu_env);
Andreas Schwab58de8b92017-03-20 12:31:55 +01006841 struct linux_binprm *bprm = ((TaskState *)cpu->opaque)->bprm;
6842 int i;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02006843
Andreas Schwab58de8b92017-03-20 12:31:55 +01006844 for (i = 0; i < bprm->argc; i++) {
6845 size_t len = strlen(bprm->argv[i]) + 1;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02006846
Andreas Schwab58de8b92017-03-20 12:31:55 +01006847 if (write(fd, bprm->argv[i], len) != len) {
Wim Vander Schelden76b94242014-06-18 11:02:39 +02006848 return -1;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02006849 }
6850 }
6851
Andreas Schwab58de8b92017-03-20 12:31:55 +01006852 return 0;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02006853}
6854
Alexander Graf36c08d42011-11-02 20:23:24 +01006855static int open_self_maps(void *cpu_env, int fd)
6856{
Richard Henderson29a0af62019-03-22 16:07:18 -07006857 CPUState *cpu = env_cpu((CPUArchState *)cpu_env);
Andreas Färber0429a972013-08-26 18:14:44 +02006858 TaskState *ts = cpu->opaque;
Alexander Graf1a49ef22012-05-01 16:30:28 +01006859 FILE *fp;
6860 char *line = NULL;
6861 size_t len = 0;
6862 ssize_t read;
Alexander Graf36c08d42011-11-02 20:23:24 +01006863
Alexander Graf1a49ef22012-05-01 16:30:28 +01006864 fp = fopen("/proc/self/maps", "r");
6865 if (fp == NULL) {
Peter Maydella3ca7bb2016-05-12 18:47:26 +01006866 return -1;
Alexander Graf1a49ef22012-05-01 16:30:28 +01006867 }
6868
6869 while ((read = getline(&line, &len, fp)) != -1) {
6870 int fields, dev_maj, dev_min, inode;
6871 uint64_t min, max, offset;
6872 char flag_r, flag_w, flag_x, flag_p;
6873 char path[512] = "";
6874 fields = sscanf(line, "%"PRIx64"-%"PRIx64" %c%c%c%c %"PRIx64" %x:%x %d"
6875 " %512s", &min, &max, &flag_r, &flag_w, &flag_x,
6876 &flag_p, &offset, &dev_maj, &dev_min, &inode, path);
6877
6878 if ((fields < 10) || (fields > 11)) {
6879 continue;
6880 }
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04006881 if (h2g_valid(min)) {
6882 int flags = page_get_flags(h2g(min));
Max Filippovebf9a362018-03-07 13:50:10 -08006883 max = h2g_valid(max - 1) ? max : (uintptr_t)g2h(GUEST_ADDR_MAX) + 1;
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04006884 if (page_check_range(h2g(min), max - min, flags) == -1) {
6885 continue;
6886 }
6887 if (h2g(min) == ts->info->stack_limit) {
6888 pstrcpy(path, sizeof(path), " [stack]");
6889 }
Laurent Vivier3e23de12018-08-14 19:12:17 +02006890 dprintf(fd, TARGET_ABI_FMT_ptr "-" TARGET_ABI_FMT_ptr
Christophe Lyone24fed42013-04-02 14:03:38 +02006891 " %c%c%c%c %08" PRIx64 " %02x:%02x %d %s%s\n",
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04006892 h2g(min), h2g(max - 1) + 1, flag_r, flag_w,
Alexander Graf1a49ef22012-05-01 16:30:28 +01006893 flag_x, flag_p, offset, dev_maj, dev_min, inode,
Christophe Lyone24fed42013-04-02 14:03:38 +02006894 path[0] ? " " : "", path);
Alexander Graf1a49ef22012-05-01 16:30:28 +01006895 }
6896 }
6897
6898 free(line);
6899 fclose(fp);
6900
Alexander Graf36c08d42011-11-02 20:23:24 +01006901 return 0;
6902}
6903
Alexander Graf480b8e72011-11-02 20:23:25 +01006904static int open_self_stat(void *cpu_env, int fd)
6905{
Richard Henderson29a0af62019-03-22 16:07:18 -07006906 CPUState *cpu = env_cpu((CPUArchState *)cpu_env);
Andreas Färber0429a972013-08-26 18:14:44 +02006907 TaskState *ts = cpu->opaque;
Alexander Graf480b8e72011-11-02 20:23:25 +01006908 abi_ulong start_stack = ts->info->start_stack;
6909 int i;
6910
6911 for (i = 0; i < 44; i++) {
6912 char buf[128];
6913 int len;
6914 uint64_t val = 0;
6915
Fabio Erculianie0e65be2012-01-03 09:38:34 +00006916 if (i == 0) {
6917 /* pid */
6918 val = getpid();
6919 snprintf(buf, sizeof(buf), "%"PRId64 " ", val);
6920 } else if (i == 1) {
6921 /* app name */
6922 snprintf(buf, sizeof(buf), "(%s) ", ts->bprm->argv[0]);
6923 } else if (i == 27) {
6924 /* stack bottom */
6925 val = start_stack;
6926 snprintf(buf, sizeof(buf), "%"PRId64 " ", val);
6927 } else {
6928 /* for the rest, there is MasterCard */
6929 snprintf(buf, sizeof(buf), "0%c", i == 43 ? '\n' : ' ');
Alexander Graf480b8e72011-11-02 20:23:25 +01006930 }
Fabio Erculianie0e65be2012-01-03 09:38:34 +00006931
Alexander Graf480b8e72011-11-02 20:23:25 +01006932 len = strlen(buf);
6933 if (write(fd, buf, len) != len) {
6934 return -1;
6935 }
6936 }
6937
6938 return 0;
6939}
6940
Alexander Graf257450e2011-11-02 20:23:26 +01006941static int open_self_auxv(void *cpu_env, int fd)
6942{
Richard Henderson29a0af62019-03-22 16:07:18 -07006943 CPUState *cpu = env_cpu((CPUArchState *)cpu_env);
Andreas Färber0429a972013-08-26 18:14:44 +02006944 TaskState *ts = cpu->opaque;
Alexander Graf257450e2011-11-02 20:23:26 +01006945 abi_ulong auxv = ts->info->saved_auxv;
6946 abi_ulong len = ts->info->auxv_len;
6947 char *ptr;
6948
6949 /*
6950 * Auxiliary vector is stored in target process stack.
6951 * read in whole auxv vector and copy it to file
6952 */
6953 ptr = lock_user(VERIFY_READ, auxv, len, 0);
6954 if (ptr != NULL) {
6955 while (len > 0) {
6956 ssize_t r;
6957 r = write(fd, ptr, len);
6958 if (r <= 0) {
6959 break;
6960 }
6961 len -= r;
6962 ptr += r;
6963 }
6964 lseek(fd, 0, SEEK_SET);
6965 unlock_user(ptr, auxv, len);
6966 }
6967
6968 return 0;
6969}
6970
Andreas Schwab463d8e72013-07-02 14:04:12 +01006971static int is_proc_myself(const char *filename, const char *entry)
6972{
6973 if (!strncmp(filename, "/proc/", strlen("/proc/"))) {
6974 filename += strlen("/proc/");
6975 if (!strncmp(filename, "self/", strlen("self/"))) {
6976 filename += strlen("self/");
6977 } else if (*filename >= '1' && *filename <= '9') {
6978 char myself[80];
6979 snprintf(myself, sizeof(myself), "%d/", getpid());
6980 if (!strncmp(filename, myself, strlen(myself))) {
6981 filename += strlen(myself);
6982 } else {
6983 return 0;
6984 }
6985 } else {
6986 return 0;
6987 }
6988 if (!strcmp(filename, entry)) {
6989 return 1;
6990 }
6991 }
6992 return 0;
6993}
6994
Laurent Vivierfff69382019-05-17 15:31:48 +02006995#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) || \
Laurent Vivier4ab67132019-05-17 15:31:49 +02006996 defined(TARGET_SPARC) || defined(TARGET_M68K)
Laurent Vivierde6b9932013-08-30 01:46:40 +02006997static int is_proc(const char *filename, const char *entry)
6998{
6999 return strcmp(filename, entry) == 0;
7000}
Laurent Vivierfff69382019-05-17 15:31:48 +02007001#endif
Laurent Vivierde6b9932013-08-30 01:46:40 +02007002
Laurent Vivierfff69382019-05-17 15:31:48 +02007003#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
Laurent Vivierde6b9932013-08-30 01:46:40 +02007004static int open_net_route(void *cpu_env, int fd)
7005{
7006 FILE *fp;
7007 char *line = NULL;
7008 size_t len = 0;
7009 ssize_t read;
7010
7011 fp = fopen("/proc/net/route", "r");
7012 if (fp == NULL) {
Peter Maydella3ca7bb2016-05-12 18:47:26 +01007013 return -1;
Laurent Vivierde6b9932013-08-30 01:46:40 +02007014 }
7015
7016 /* read header */
7017
7018 read = getline(&line, &len, fp);
7019 dprintf(fd, "%s", line);
7020
7021 /* read routes */
7022
7023 while ((read = getline(&line, &len, fp)) != -1) {
7024 char iface[16];
7025 uint32_t dest, gw, mask;
7026 unsigned int flags, refcnt, use, metric, mtu, window, irtt;
Peter Maydell9d0bd0c2019-02-05 17:42:07 +00007027 int fields;
7028
7029 fields = sscanf(line,
7030 "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
7031 iface, &dest, &gw, &flags, &refcnt, &use, &metric,
7032 &mask, &mtu, &window, &irtt);
7033 if (fields != 11) {
7034 continue;
7035 }
Laurent Vivierde6b9932013-08-30 01:46:40 +02007036 dprintf(fd, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
7037 iface, tswap32(dest), tswap32(gw), flags, refcnt, use,
7038 metric, tswap32(mask), mtu, window, irtt);
7039 }
7040
7041 free(line);
7042 fclose(fp);
7043
7044 return 0;
7045}
7046#endif
7047
Laurent Vivierfff69382019-05-17 15:31:48 +02007048#if defined(TARGET_SPARC)
7049static int open_cpuinfo(void *cpu_env, int fd)
7050{
7051 dprintf(fd, "type\t\t: sun4u\n");
7052 return 0;
7053}
7054#endif
7055
Laurent Vivier4ab67132019-05-17 15:31:49 +02007056#if defined(TARGET_M68K)
7057static int open_hardware(void *cpu_env, int fd)
7058{
7059 dprintf(fd, "Model:\t\tqemu-m68k\n");
7060 return 0;
7061}
7062#endif
7063
Riku Voipio0b2effd2014-08-06 10:36:37 +03007064static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags, mode_t mode)
Alexander Graf3be14d02011-11-02 20:23:23 +01007065{
7066 struct fake_open {
7067 const char *filename;
7068 int (*fill)(void *cpu_env, int fd);
Laurent Vivierde6b9932013-08-30 01:46:40 +02007069 int (*cmp)(const char *s1, const char *s2);
Alexander Graf3be14d02011-11-02 20:23:23 +01007070 };
7071 const struct fake_open *fake_open;
7072 static const struct fake_open fakes[] = {
Laurent Vivierde6b9932013-08-30 01:46:40 +02007073 { "maps", open_self_maps, is_proc_myself },
7074 { "stat", open_self_stat, is_proc_myself },
7075 { "auxv", open_self_auxv, is_proc_myself },
Wim Vander Schelden76b94242014-06-18 11:02:39 +02007076 { "cmdline", open_self_cmdline, is_proc_myself },
Laurent Vivierde6b9932013-08-30 01:46:40 +02007077#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
7078 { "/proc/net/route", open_net_route, is_proc },
7079#endif
Laurent Vivierfff69382019-05-17 15:31:48 +02007080#if defined(TARGET_SPARC)
7081 { "/proc/cpuinfo", open_cpuinfo, is_proc },
7082#endif
Laurent Vivier4ab67132019-05-17 15:31:49 +02007083#if defined(TARGET_M68K)
7084 { "/proc/hardware", open_hardware, is_proc },
7085#endif
Laurent Vivierde6b9932013-08-30 01:46:40 +02007086 { NULL, NULL, NULL }
Alexander Graf3be14d02011-11-02 20:23:23 +01007087 };
7088
Maxim Ostapenkoaa07f5e2014-05-02 11:17:07 +03007089 if (is_proc_myself(pathname, "exe")) {
7090 int execfd = qemu_getauxval(AT_EXECFD);
Timothy E Baldwinc10a0732016-05-12 18:47:48 +01007091 return execfd ? execfd : safe_openat(dirfd, exec_path, flags, mode);
Maxim Ostapenkoaa07f5e2014-05-02 11:17:07 +03007092 }
7093
Alexander Graf3be14d02011-11-02 20:23:23 +01007094 for (fake_open = fakes; fake_open->filename; fake_open++) {
Laurent Vivierde6b9932013-08-30 01:46:40 +02007095 if (fake_open->cmp(pathname, fake_open->filename)) {
Alexander Graf3be14d02011-11-02 20:23:23 +01007096 break;
7097 }
7098 }
7099
7100 if (fake_open->filename) {
7101 const char *tmpdir;
7102 char filename[PATH_MAX];
7103 int fd, r;
7104
7105 /* create temporary file to map stat to */
7106 tmpdir = getenv("TMPDIR");
7107 if (!tmpdir)
7108 tmpdir = "/tmp";
7109 snprintf(filename, sizeof(filename), "%s/qemu-open.XXXXXX", tmpdir);
7110 fd = mkstemp(filename);
7111 if (fd < 0) {
7112 return fd;
7113 }
7114 unlink(filename);
7115
7116 if ((r = fake_open->fill(cpu_env, fd))) {
Peter Maydella3ca7bb2016-05-12 18:47:26 +01007117 int e = errno;
Alexander Graf3be14d02011-11-02 20:23:23 +01007118 close(fd);
Peter Maydella3ca7bb2016-05-12 18:47:26 +01007119 errno = e;
Alexander Graf3be14d02011-11-02 20:23:23 +01007120 return r;
7121 }
7122 lseek(fd, 0, SEEK_SET);
7123
7124 return fd;
7125 }
7126
Timothy E Baldwinc10a0732016-05-12 18:47:48 +01007127 return safe_openat(dirfd, path(pathname), flags, mode);
Alexander Graf3be14d02011-11-02 20:23:23 +01007128}
7129
Alexander Grafaecc8862014-11-10 21:33:03 +01007130#define TIMER_MAGIC 0x0caf0000
7131#define TIMER_MAGIC_MASK 0xffff0000
7132
7133/* Convert QEMU provided timer ID back to internal 16bit index format */
7134static target_timer_t get_timer_id(abi_long arg)
7135{
7136 target_timer_t timerid = arg;
7137
7138 if ((timerid & TIMER_MAGIC_MASK) != TIMER_MAGIC) {
7139 return -TARGET_EINVAL;
7140 }
7141
7142 timerid &= 0xffff;
7143
7144 if (timerid >= ARRAY_SIZE(g_posix_timers)) {
7145 return -TARGET_EINVAL;
7146 }
7147
7148 return timerid;
7149}
7150
Samuel Thibault2e0a8712018-01-09 21:16:43 +01007151static int target_to_host_cpu_mask(unsigned long *host_mask,
7152 size_t host_size,
7153 abi_ulong target_addr,
7154 size_t target_size)
7155{
7156 unsigned target_bits = sizeof(abi_ulong) * 8;
7157 unsigned host_bits = sizeof(*host_mask) * 8;
7158 abi_ulong *target_mask;
7159 unsigned i, j;
7160
7161 assert(host_size >= target_size);
7162
7163 target_mask = lock_user(VERIFY_READ, target_addr, target_size, 1);
7164 if (!target_mask) {
7165 return -TARGET_EFAULT;
7166 }
7167 memset(host_mask, 0, host_size);
7168
7169 for (i = 0 ; i < target_size / sizeof(abi_ulong); i++) {
7170 unsigned bit = i * target_bits;
7171 abi_ulong val;
7172
7173 __get_user(val, &target_mask[i]);
7174 for (j = 0; j < target_bits; j++, bit++) {
7175 if (val & (1UL << j)) {
7176 host_mask[bit / host_bits] |= 1UL << (bit % host_bits);
7177 }
7178 }
7179 }
7180
7181 unlock_user(target_mask, target_addr, 0);
7182 return 0;
7183}
7184
7185static int host_to_target_cpu_mask(const unsigned long *host_mask,
7186 size_t host_size,
7187 abi_ulong target_addr,
7188 size_t target_size)
7189{
7190 unsigned target_bits = sizeof(abi_ulong) * 8;
7191 unsigned host_bits = sizeof(*host_mask) * 8;
7192 abi_ulong *target_mask;
7193 unsigned i, j;
7194
7195 assert(host_size >= target_size);
7196
7197 target_mask = lock_user(VERIFY_WRITE, target_addr, target_size, 0);
7198 if (!target_mask) {
7199 return -TARGET_EFAULT;
7200 }
7201
7202 for (i = 0 ; i < target_size / sizeof(abi_ulong); i++) {
7203 unsigned bit = i * target_bits;
7204 abi_ulong val = 0;
7205
7206 for (j = 0; j < target_bits; j++, bit++) {
7207 if (host_mask[bit / host_bits] & (1UL << (bit % host_bits))) {
7208 val |= 1UL << j;
7209 }
7210 }
7211 __put_user(val, &target_mask[i]);
7212 }
7213
7214 unlock_user(target_mask, target_addr, target_size);
7215 return 0;
7216}
7217
Richard Hendersondc1ce182018-08-18 12:01:04 -07007218/* This is an internal helper for do_syscall so that it is easier
7219 * to have a single return point, so that actions, such as logging
7220 * of syscall results, can be performed.
7221 * All errnos that do_syscall() returns must be -TARGET_<errcode>.
7222 */
7223static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
7224 abi_long arg2, abi_long arg3, abi_long arg4,
7225 abi_long arg5, abi_long arg6, abi_long arg7,
7226 abi_long arg8)
bellard31e31b82003-02-18 22:55:36 +00007227{
Richard Henderson29a0af62019-03-22 16:07:18 -07007228 CPUState *cpu = env_cpu(cpu_env);
blueswir1992f48a2007-10-14 16:27:31 +00007229 abi_long ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02007230#if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) \
7231 || defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64) \
Aleksandar Rikaloefa92182019-06-28 12:43:34 +02007232 || defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64) \
7233 || defined(TARGET_NR_statx)
bellard31e31b82003-02-18 22:55:36 +00007234 struct stat st;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02007235#endif
7236#if defined(TARGET_NR_statfs) || defined(TARGET_NR_statfs64) \
7237 || defined(TARGET_NR_fstatfs)
bellard56c8f682005-11-28 22:28:41 +00007238 struct statfs stfs;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02007239#endif
pbrook53a59602006-03-25 19:31:22 +00007240 void *p;
ths3b46e622007-09-17 08:09:54 +00007241
bellard31e31b82003-02-18 22:55:36 +00007242 switch(num) {
7243 case TARGET_NR_exit:
Andreas Färber9b056fc2013-06-24 23:53:10 +02007244 /* In old applications this may be used to implement _exit(2).
7245 However in threaded applictions it is used for thread termination,
7246 and _exit_group is used for application termination.
7247 Do thread termination if we have more then one thread. */
Timothy E Baldwina0995882016-05-27 15:51:56 +01007248
7249 if (block_signals()) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007250 return -TARGET_ERESTARTSYS;
Timothy E Baldwina0995882016-05-27 15:51:56 +01007251 }
7252
Alex Bennéedd1f6342016-09-30 22:31:01 +01007253 cpu_list_lock();
7254
Andreas Färberbdc44642013-06-24 23:50:24 +02007255 if (CPU_NEXT(first_cpu)) {
Andreas Färber9b056fc2013-06-24 23:53:10 +02007256 TaskState *ts;
pbrookc2764712009-03-07 15:24:59 +00007257
Andreas Färber9b056fc2013-06-24 23:53:10 +02007258 /* Remove the CPU from the list. */
Emilio G. Cota068a5ea2018-08-19 05:13:35 -04007259 QTAILQ_REMOVE_RCU(&cpus, cpu, node);
Alex Bennéedd1f6342016-09-30 22:31:01 +01007260
Andreas Färber9b056fc2013-06-24 23:53:10 +02007261 cpu_list_unlock();
Alex Bennéedd1f6342016-09-30 22:31:01 +01007262
Andreas Färber0429a972013-08-26 18:14:44 +02007263 ts = cpu->opaque;
Andreas Färber9b056fc2013-06-24 23:53:10 +02007264 if (ts->child_tidptr) {
7265 put_user_u32(0, ts->child_tidptr);
7266 sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
7267 NULL, NULL, 0);
7268 }
Andreas Färbera2247f82013-06-09 19:47:04 +02007269 thread_cpu = NULL;
Andreas Färber0429a972013-08-26 18:14:44 +02007270 object_unref(OBJECT(cpu));
Andreas Färber9b056fc2013-06-24 23:53:10 +02007271 g_free(ts);
Emilio G. Cota70903762015-08-23 20:23:41 -04007272 rcu_unregister_thread();
Andreas Färber9b056fc2013-06-24 23:53:10 +02007273 pthread_exit(NULL);
7274 }
Alex Bennéedd1f6342016-09-30 22:31:01 +01007275
7276 cpu_list_unlock();
Alex Bennée708b6a62018-06-22 17:09:10 +01007277 preexit_cleanup(cpu_env, arg1);
pbrookc2764712009-03-07 15:24:59 +00007278 _exit(arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007279 return 0; /* avoid warning */
bellard31e31b82003-02-18 22:55:36 +00007280 case TARGET_NR_read:
Andreas Schwabba584f12019-03-05 17:45:05 +01007281 if (arg2 == 0 && arg3 == 0) {
7282 return get_errno(safe_read(arg1, 0, 0));
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007283 } else {
aurel3238d840e2009-01-30 19:48:17 +00007284 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007285 return -TARGET_EFAULT;
Timothy E Baldwin50afd022016-05-12 18:47:47 +01007286 ret = get_errno(safe_read(arg1, p, arg3));
Laurent Viviere36800c2015-10-02 14:48:09 +02007287 if (ret >= 0 &&
Laurent Vivier5d4d3662015-10-28 21:40:43 +01007288 fd_trans_host_to_target_data(arg1)) {
7289 ret = fd_trans_host_to_target_data(arg1)(p, ret);
Laurent Viviere36800c2015-10-02 14:48:09 +02007290 }
aurel3238d840e2009-01-30 19:48:17 +00007291 unlock_user(p, arg2, ret);
7292 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007293 return ret;
bellard31e31b82003-02-18 22:55:36 +00007294 case TARGET_NR_write:
Tony Garnock-Jones58cfa6c2018-09-08 19:22:05 +01007295 if (arg2 == 0 && arg3 == 0) {
7296 return get_errno(safe_write(arg1, 0, 0));
7297 }
bellard579a97f2007-11-11 14:26:47 +00007298 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007299 return -TARGET_EFAULT;
Laurent Vivier04b9bcf2017-03-01 10:37:47 +01007300 if (fd_trans_target_to_host_data(arg1)) {
7301 void *copy = g_malloc(arg3);
7302 memcpy(copy, p, arg3);
7303 ret = fd_trans_target_to_host_data(arg1)(copy, arg3);
7304 if (ret >= 0) {
7305 ret = get_errno(safe_write(arg1, copy, ret));
7306 }
7307 g_free(copy);
7308 } else {
7309 ret = get_errno(safe_write(arg1, p, arg3));
7310 }
pbrook53a59602006-03-25 19:31:22 +00007311 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007312 return ret;
7313
Chen Gang704eff62015-08-21 05:37:33 +08007314#ifdef TARGET_NR_open
bellard31e31b82003-02-18 22:55:36 +00007315 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00007316 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007317 return -TARGET_EFAULT;
Riku Voipio0b2effd2014-08-06 10:36:37 +03007318 ret = get_errno(do_openat(cpu_env, AT_FDCWD, p,
7319 target_to_host_bitmask(arg2, fcntl_flags_tbl),
7320 arg3));
Laurent Viviere36800c2015-10-02 14:48:09 +02007321 fd_trans_unregister(ret);
pbrook53a59602006-03-25 19:31:22 +00007322 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007323 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007324#endif
ths82424832007-09-24 09:21:55 +00007325 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00007326 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007327 return -TARGET_EFAULT;
Riku Voipio0b2effd2014-08-06 10:36:37 +03007328 ret = get_errno(do_openat(cpu_env, arg1, p,
7329 target_to_host_bitmask(arg3, fcntl_flags_tbl),
7330 arg4));
Laurent Viviere36800c2015-10-02 14:48:09 +02007331 fd_trans_unregister(ret);
bellard579a97f2007-11-11 14:26:47 +00007332 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007333 return ret;
Laurent Vivier0f0426f2015-09-01 22:27:33 +02007334#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
7335 case TARGET_NR_name_to_handle_at:
7336 ret = do_name_to_handle_at(arg1, arg2, arg3, arg4, arg5);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007337 return ret;
Laurent Vivier0f0426f2015-09-01 22:27:33 +02007338#endif
7339#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
7340 case TARGET_NR_open_by_handle_at:
7341 ret = do_open_by_handle_at(arg1, arg2, arg3);
Laurent Viviere36800c2015-10-02 14:48:09 +02007342 fd_trans_unregister(ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007343 return ret;
Laurent Vivier0f0426f2015-09-01 22:27:33 +02007344#endif
bellard31e31b82003-02-18 22:55:36 +00007345 case TARGET_NR_close:
Laurent Viviere36800c2015-10-02 14:48:09 +02007346 fd_trans_unregister(arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007347 return get_errno(close(arg1));
7348
bellard31e31b82003-02-18 22:55:36 +00007349 case TARGET_NR_brk:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007350 return do_brk(arg1);
Chen Gang704eff62015-08-21 05:37:33 +08007351#ifdef TARGET_NR_fork
bellard31e31b82003-02-18 22:55:36 +00007352 case TARGET_NR_fork:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007353 return get_errno(do_fork(cpu_env, TARGET_SIGCHLD, 0, 0, 0, 0));
Chen Gang704eff62015-08-21 05:37:33 +08007354#endif
thse5febef2007-04-01 18:31:35 +00007355#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00007356 case TARGET_NR_waitpid:
7357 {
pbrook53a59602006-03-25 19:31:22 +00007358 int status;
Timothy E Baldwin4af80a32016-05-12 18:47:49 +01007359 ret = get_errno(safe_wait4(arg1, &status, arg3, 0));
Alexander Graf53795572011-11-24 00:44:43 +01007360 if (!is_error(ret) && arg2 && ret
pbrook1d9d8b52009-04-16 15:17:02 +00007361 && put_user_s32(host_to_target_waitstatus(status), arg2))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007362 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00007363 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007364 return ret;
thse5febef2007-04-01 18:31:35 +00007365#endif
pbrookf0cbb612008-05-30 18:20:05 +00007366#ifdef TARGET_NR_waitid
7367 case TARGET_NR_waitid:
7368 {
7369 siginfo_t info;
7370 info.si_pid = 0;
Timothy E Baldwin4af80a32016-05-12 18:47:49 +01007371 ret = get_errno(safe_waitid(arg1, arg2, &info, arg4, NULL));
pbrookf0cbb612008-05-30 18:20:05 +00007372 if (!is_error(ret) && arg3 && info.si_pid != 0) {
Anthony Liguoric227f092009-10-01 16:12:16 -05007373 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007374 return -TARGET_EFAULT;
pbrookf0cbb612008-05-30 18:20:05 +00007375 host_to_target_siginfo(p, &info);
Anthony Liguoric227f092009-10-01 16:12:16 -05007376 unlock_user(p, arg3, sizeof(target_siginfo_t));
pbrookf0cbb612008-05-30 18:20:05 +00007377 }
7378 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007379 return ret;
pbrookf0cbb612008-05-30 18:20:05 +00007380#endif
j_mayer7a3148a2007-04-05 07:13:51 +00007381#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00007382 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00007383 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007384 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007385 ret = get_errno(creat(p, arg2));
Laurent Viviere36800c2015-10-02 14:48:09 +02007386 fd_trans_unregister(ret);
pbrook53a59602006-03-25 19:31:22 +00007387 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007388 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00007389#endif
Chen Gang704eff62015-08-21 05:37:33 +08007390#ifdef TARGET_NR_link
bellard31e31b82003-02-18 22:55:36 +00007391 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00007392 {
7393 void * p2;
7394 p = lock_user_string(arg1);
7395 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00007396 if (!p || !p2)
7397 ret = -TARGET_EFAULT;
7398 else
7399 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00007400 unlock_user(p2, arg2, 0);
7401 unlock_user(p, arg1, 0);
7402 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007403 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007404#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01007405#if defined(TARGET_NR_linkat)
ths64f0ce42007-09-24 09:25:06 +00007406 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00007407 {
7408 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00007409 if (!arg2 || !arg4)
Richard Henderson2852aaf2018-08-18 12:01:06 -07007410 return -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00007411 p = lock_user_string(arg2);
7412 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00007413 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00007414 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00007415 else
Peter Maydellc0d472b2013-06-12 16:20:21 +01007416 ret = get_errno(linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00007417 unlock_user(p, arg2, 0);
7418 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00007419 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007420 return ret;
ths64f0ce42007-09-24 09:25:06 +00007421#endif
Chen Gang704eff62015-08-21 05:37:33 +08007422#ifdef TARGET_NR_unlink
bellard31e31b82003-02-18 22:55:36 +00007423 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00007424 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007425 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007426 ret = get_errno(unlink(p));
7427 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007428 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007429#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01007430#if defined(TARGET_NR_unlinkat)
ths8170f562007-09-24 09:24:11 +00007431 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00007432 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007433 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01007434 ret = get_errno(unlinkat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00007435 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007436 return ret;
balrogb7d35e62007-12-12 00:40:24 +00007437#endif
bellard31e31b82003-02-18 22:55:36 +00007438 case TARGET_NR_execve:
bellard7854b052003-03-29 17:22:23 +00007439 {
7440 char **argp, **envp;
bellardf7341ff2003-03-30 21:00:25 +00007441 int argc, envc;
blueswir1992f48a2007-10-14 16:27:31 +00007442 abi_ulong gp;
7443 abi_ulong guest_argp;
7444 abi_ulong guest_envp;
7445 abi_ulong addr;
bellard7854b052003-03-29 17:22:23 +00007446 char **q;
Ulrich Hechta6f79cc2012-01-31 12:43:16 +01007447 int total_size = 0;
bellard7854b052003-03-29 17:22:23 +00007448
bellardf7341ff2003-03-30 21:00:25 +00007449 argc = 0;
pbrook53a59602006-03-25 19:31:22 +00007450 guest_argp = arg2;
pbrookda94d262008-05-30 18:24:00 +00007451 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00007452 if (get_user_ual(addr, gp))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007453 return -TARGET_EFAULT;
ths03aa1972007-12-02 06:28:08 +00007454 if (!addr)
bellard2f619692007-11-16 10:46:05 +00007455 break;
bellard7854b052003-03-29 17:22:23 +00007456 argc++;
bellard2f619692007-11-16 10:46:05 +00007457 }
bellardf7341ff2003-03-30 21:00:25 +00007458 envc = 0;
pbrook53a59602006-03-25 19:31:22 +00007459 guest_envp = arg3;
pbrookda94d262008-05-30 18:24:00 +00007460 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00007461 if (get_user_ual(addr, gp))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007462 return -TARGET_EFAULT;
ths03aa1972007-12-02 06:28:08 +00007463 if (!addr)
bellard2f619692007-11-16 10:46:05 +00007464 break;
bellard7854b052003-03-29 17:22:23 +00007465 envc++;
bellard2f619692007-11-16 10:46:05 +00007466 }
bellard7854b052003-03-29 17:22:23 +00007467
Prasad J Panditb936cb52017-03-07 12:51:47 +05307468 argp = g_new0(char *, argc + 1);
7469 envp = g_new0(char *, envc + 1);
bellard7854b052003-03-29 17:22:23 +00007470
pbrookda94d262008-05-30 18:24:00 +00007471 for (gp = guest_argp, q = argp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00007472 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00007473 if (get_user_ual(addr, gp))
7474 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00007475 if (!addr)
7476 break;
bellard2f619692007-11-16 10:46:05 +00007477 if (!(*q = lock_user_string(addr)))
7478 goto execve_efault;
Ulrich Hechta6f79cc2012-01-31 12:43:16 +01007479 total_size += strlen(*q) + 1;
pbrook53a59602006-03-25 19:31:22 +00007480 }
bellardf7341ff2003-03-30 21:00:25 +00007481 *q = NULL;
7482
pbrookda94d262008-05-30 18:24:00 +00007483 for (gp = guest_envp, q = envp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00007484 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00007485 if (get_user_ual(addr, gp))
7486 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00007487 if (!addr)
7488 break;
bellard2f619692007-11-16 10:46:05 +00007489 if (!(*q = lock_user_string(addr)))
7490 goto execve_efault;
Ulrich Hechta6f79cc2012-01-31 12:43:16 +01007491 total_size += strlen(*q) + 1;
pbrook53a59602006-03-25 19:31:22 +00007492 }
bellardf7341ff2003-03-30 21:00:25 +00007493 *q = NULL;
bellard7854b052003-03-29 17:22:23 +00007494
bellard2f619692007-11-16 10:46:05 +00007495 if (!(p = lock_user_string(arg1)))
7496 goto execve_efault;
Timothy E Baldwinffdcbe22016-05-12 18:47:50 +01007497 /* Although execve() is not an interruptible syscall it is
7498 * a special case where we must use the safe_syscall wrapper:
7499 * if we allow a signal to happen before we make the host
7500 * syscall then we will 'lose' it, because at the point of
7501 * execve the process leaves QEMU's control. So we use the
7502 * safe syscall wrapper to ensure that we either take the
7503 * signal as a guest signal, or else it does not happen
7504 * before the execve completes and makes it the other
7505 * program's problem.
7506 */
7507 ret = get_errno(safe_execve(p, argp, envp));
pbrook53a59602006-03-25 19:31:22 +00007508 unlock_user(p, arg1, 0);
7509
bellard2f619692007-11-16 10:46:05 +00007510 goto execve_end;
7511
7512 execve_efault:
7513 ret = -TARGET_EFAULT;
7514
7515 execve_end:
pbrook53a59602006-03-25 19:31:22 +00007516 for (gp = guest_argp, q = argp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00007517 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00007518 if (get_user_ual(addr, gp)
7519 || !addr)
7520 break;
pbrook53a59602006-03-25 19:31:22 +00007521 unlock_user(*q, addr, 0);
7522 }
7523 for (gp = guest_envp, q = envp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00007524 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00007525 if (get_user_ual(addr, gp)
7526 || !addr)
7527 break;
pbrook53a59602006-03-25 19:31:22 +00007528 unlock_user(*q, addr, 0);
7529 }
Prasad J Panditb936cb52017-03-07 12:51:47 +05307530
7531 g_free(argp);
7532 g_free(envp);
bellard7854b052003-03-29 17:22:23 +00007533 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007534 return ret;
bellard31e31b82003-02-18 22:55:36 +00007535 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00007536 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007537 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007538 ret = get_errno(chdir(p));
7539 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007540 return ret;
bellarda315a142005-01-30 22:59:18 +00007541#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00007542 case TARGET_NR_time:
7543 {
pbrook53a59602006-03-25 19:31:22 +00007544 time_t host_time;
7545 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00007546 if (!is_error(ret)
7547 && arg1
7548 && put_user_sal(host_time, arg1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007549 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00007550 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007551 return ret;
bellarda315a142005-01-30 22:59:18 +00007552#endif
Chen Gang704eff62015-08-21 05:37:33 +08007553#ifdef TARGET_NR_mknod
bellard31e31b82003-02-18 22:55:36 +00007554 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00007555 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007556 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007557 ret = get_errno(mknod(p, arg2, arg3));
7558 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007559 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007560#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01007561#if defined(TARGET_NR_mknodat)
ths75ac37a2007-09-24 09:23:05 +00007562 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00007563 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007564 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01007565 ret = get_errno(mknodat(arg1, p, arg3, arg4));
bellard579a97f2007-11-11 14:26:47 +00007566 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007567 return ret;
ths75ac37a2007-09-24 09:23:05 +00007568#endif
Chen Gang704eff62015-08-21 05:37:33 +08007569#ifdef TARGET_NR_chmod
bellard31e31b82003-02-18 22:55:36 +00007570 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00007571 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007572 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007573 ret = get_errno(chmod(p, arg2));
7574 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007575 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007576#endif
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02007577#ifdef TARGET_NR_lseek
bellard31e31b82003-02-18 22:55:36 +00007578 case TARGET_NR_lseek:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007579 return get_errno(lseek(arg1, arg2, arg3));
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02007580#endif
Richard Henderson92317332010-05-03 10:07:53 -07007581#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA)
7582 /* Alpha specific */
j_mayer7a3148a2007-04-05 07:13:51 +00007583 case TARGET_NR_getxpid:
Richard Henderson92317332010-05-03 10:07:53 -07007584 ((CPUAlphaState *)cpu_env)->ir[IR_A4] = getppid();
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007585 return get_errno(getpid());
Richard Henderson92317332010-05-03 10:07:53 -07007586#endif
7587#ifdef TARGET_NR_getpid
7588 case TARGET_NR_getpid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007589 return get_errno(getpid());
Richard Henderson92317332010-05-03 10:07:53 -07007590#endif
bellard31e31b82003-02-18 22:55:36 +00007591 case TARGET_NR_mount:
Paul Burton356d7712014-06-22 11:25:37 +01007592 {
7593 /* need to look at the data field */
7594 void *p2, *p3;
7595
7596 if (arg1) {
7597 p = lock_user_string(arg1);
7598 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07007599 return -TARGET_EFAULT;
Paul Burton356d7712014-06-22 11:25:37 +01007600 }
7601 } else {
7602 p = NULL;
7603 }
7604
7605 p2 = lock_user_string(arg2);
7606 if (!p2) {
7607 if (arg1) {
7608 unlock_user(p, arg1, 0);
7609 }
Richard Henderson2852aaf2018-08-18 12:01:06 -07007610 return -TARGET_EFAULT;
Paul Burton356d7712014-06-22 11:25:37 +01007611 }
7612
7613 if (arg3) {
7614 p3 = lock_user_string(arg3);
7615 if (!p3) {
7616 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00007617 unlock_user(p, arg1, 0);
Paul Burton356d7712014-06-22 11:25:37 +01007618 }
7619 unlock_user(p2, arg2, 0);
Richard Henderson2852aaf2018-08-18 12:01:06 -07007620 return -TARGET_EFAULT;
Paul Burton356d7712014-06-22 11:25:37 +01007621 }
7622 } else {
7623 p3 = NULL;
7624 }
7625
7626 /* FIXME - arg5 should be locked, but it isn't clear how to
7627 * do that since it's not guaranteed to be a NULL-terminated
7628 * string.
7629 */
7630 if (!arg5) {
7631 ret = mount(p, p2, p3, (unsigned long)arg4, NULL);
7632 } else {
7633 ret = mount(p, p2, p3, (unsigned long)arg4, g2h(arg5));
7634 }
7635 ret = get_errno(ret);
7636
7637 if (arg1) {
7638 unlock_user(p, arg1, 0);
7639 }
7640 unlock_user(p2, arg2, 0);
7641 if (arg3) {
7642 unlock_user(p3, arg3, 0);
7643 }
7644 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007645 return ret;
thse5febef2007-04-01 18:31:35 +00007646#ifdef TARGET_NR_umount
bellard31e31b82003-02-18 22:55:36 +00007647 case TARGET_NR_umount:
bellard579a97f2007-11-11 14:26:47 +00007648 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007649 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007650 ret = get_errno(umount(p));
7651 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007652 return ret;
thse5febef2007-04-01 18:31:35 +00007653#endif
j_mayer7a3148a2007-04-05 07:13:51 +00007654#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00007655 case TARGET_NR_stime:
7656 {
pbrook53a59602006-03-25 19:31:22 +00007657 time_t host_time;
bellard2f619692007-11-16 10:46:05 +00007658 if (get_user_sal(host_time, arg1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007659 return -TARGET_EFAULT;
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007660 return get_errno(stime(&host_time));
bellard31e31b82003-02-18 22:55:36 +00007661 }
j_mayer7a3148a2007-04-05 07:13:51 +00007662#endif
j_mayer7a3148a2007-04-05 07:13:51 +00007663#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00007664 case TARGET_NR_alarm:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007665 return alarm(arg1);
j_mayer7a3148a2007-04-05 07:13:51 +00007666#endif
j_mayer7a3148a2007-04-05 07:13:51 +00007667#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00007668 case TARGET_NR_pause:
Timothy E Baldwinf59ec602016-05-27 15:51:55 +01007669 if (!block_signals()) {
7670 sigsuspend(&((TaskState *)cpu->opaque)->signal_mask);
7671 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007672 return -TARGET_EINTR;
j_mayer7a3148a2007-04-05 07:13:51 +00007673#endif
thse5febef2007-04-01 18:31:35 +00007674#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00007675 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00007676 {
pbrook53a59602006-03-25 19:31:22 +00007677 struct utimbuf tbuf, *host_tbuf;
7678 struct target_utimbuf *target_tbuf;
7679 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00007680 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007681 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02007682 tbuf.actime = tswapal(target_tbuf->actime);
7683 tbuf.modtime = tswapal(target_tbuf->modtime);
pbrook53a59602006-03-25 19:31:22 +00007684 unlock_user_struct(target_tbuf, arg2, 0);
7685 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00007686 } else {
pbrook53a59602006-03-25 19:31:22 +00007687 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00007688 }
bellard579a97f2007-11-11 14:26:47 +00007689 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007690 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007691 ret = get_errno(utime(p, host_tbuf));
7692 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00007693 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007694 return ret;
thse5febef2007-04-01 18:31:35 +00007695#endif
Chen Gang704eff62015-08-21 05:37:33 +08007696#ifdef TARGET_NR_utimes
bellard978a66f2004-12-06 22:58:05 +00007697 case TARGET_NR_utimes:
7698 {
bellard978a66f2004-12-06 22:58:05 +00007699 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00007700 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00007701 if (copy_from_user_timeval(&tv[0], arg2)
7702 || copy_from_user_timeval(&tv[1],
7703 arg2 + sizeof(struct target_timeval)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007704 return -TARGET_EFAULT;
bellard978a66f2004-12-06 22:58:05 +00007705 tvp = tv;
7706 } else {
7707 tvp = NULL;
7708 }
bellard579a97f2007-11-11 14:26:47 +00007709 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007710 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007711 ret = get_errno(utimes(p, tvp));
7712 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00007713 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007714 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007715#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01007716#if defined(TARGET_NR_futimesat)
balrogac8a6552008-09-20 02:25:39 +00007717 case TARGET_NR_futimesat:
7718 {
7719 struct timeval *tvp, tv[2];
7720 if (arg3) {
7721 if (copy_from_user_timeval(&tv[0], arg3)
7722 || copy_from_user_timeval(&tv[1],
7723 arg3 + sizeof(struct target_timeval)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007724 return -TARGET_EFAULT;
balrogac8a6552008-09-20 02:25:39 +00007725 tvp = tv;
7726 } else {
7727 tvp = NULL;
7728 }
Richard Henderson2852aaf2018-08-18 12:01:06 -07007729 if (!(p = lock_user_string(arg2))) {
7730 return -TARGET_EFAULT;
7731 }
Peter Maydellc0d472b2013-06-12 16:20:21 +01007732 ret = get_errno(futimesat(arg1, path(p), tvp));
balrogac8a6552008-09-20 02:25:39 +00007733 unlock_user(p, arg2, 0);
7734 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007735 return ret;
balrogac8a6552008-09-20 02:25:39 +00007736#endif
Chen Gang704eff62015-08-21 05:37:33 +08007737#ifdef TARGET_NR_access
bellard31e31b82003-02-18 22:55:36 +00007738 case TARGET_NR_access:
Richard Henderson2852aaf2018-08-18 12:01:06 -07007739 if (!(p = lock_user_string(arg1))) {
7740 return -TARGET_EFAULT;
7741 }
Ulrich Hecht719f9082009-07-03 17:09:29 +02007742 ret = get_errno(access(path(p), arg2));
pbrook53a59602006-03-25 19:31:22 +00007743 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007744 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007745#endif
ths92a34c12007-09-24 09:27:49 +00007746#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
7747 case TARGET_NR_faccessat:
Richard Henderson2852aaf2018-08-18 12:01:06 -07007748 if (!(p = lock_user_string(arg2))) {
7749 return -TARGET_EFAULT;
7750 }
Peter Maydellc0d472b2013-06-12 16:20:21 +01007751 ret = get_errno(faccessat(arg1, p, arg3, 0));
bellard579a97f2007-11-11 14:26:47 +00007752 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007753 return ret;
ths92a34c12007-09-24 09:27:49 +00007754#endif
j_mayer7a3148a2007-04-05 07:13:51 +00007755#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00007756 case TARGET_NR_nice:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007757 return get_errno(nice(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +00007758#endif
bellard31e31b82003-02-18 22:55:36 +00007759 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00007760 sync();
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007761 return 0;
Aleksandar Markovic5a03cd02016-10-10 13:23:30 +02007762#if defined(TARGET_NR_syncfs) && defined(CONFIG_SYNCFS)
7763 case TARGET_NR_syncfs:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007764 return get_errno(syncfs(arg1));
Aleksandar Markovic5a03cd02016-10-10 13:23:30 +02007765#endif
bellard31e31b82003-02-18 22:55:36 +00007766 case TARGET_NR_kill:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007767 return get_errno(safe_kill(arg1, target_to_host_signal(arg2)));
Chen Gang704eff62015-08-21 05:37:33 +08007768#ifdef TARGET_NR_rename
bellard31e31b82003-02-18 22:55:36 +00007769 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00007770 {
7771 void *p2;
7772 p = lock_user_string(arg1);
7773 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00007774 if (!p || !p2)
7775 ret = -TARGET_EFAULT;
7776 else
7777 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00007778 unlock_user(p2, arg2, 0);
7779 unlock_user(p, arg1, 0);
7780 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007781 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007782#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01007783#if defined(TARGET_NR_renameat)
ths722183f2007-09-24 09:24:37 +00007784 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00007785 {
bellard579a97f2007-11-11 14:26:47 +00007786 void *p2;
ths722183f2007-09-24 09:24:37 +00007787 p = lock_user_string(arg2);
7788 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00007789 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00007790 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00007791 else
Peter Maydellc0d472b2013-06-12 16:20:21 +01007792 ret = get_errno(renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00007793 unlock_user(p2, arg4, 0);
7794 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00007795 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007796 return ret;
ths722183f2007-09-24 09:24:37 +00007797#endif
Andreas Schwab95d03072018-01-23 11:53:31 +01007798#if defined(TARGET_NR_renameat2)
7799 case TARGET_NR_renameat2:
7800 {
7801 void *p2;
7802 p = lock_user_string(arg2);
7803 p2 = lock_user_string(arg4);
7804 if (!p || !p2) {
7805 ret = -TARGET_EFAULT;
7806 } else {
7807 ret = get_errno(sys_renameat2(arg1, p, arg3, p2, arg5));
7808 }
7809 unlock_user(p2, arg4, 0);
7810 unlock_user(p, arg2, 0);
7811 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007812 return ret;
Andreas Schwab95d03072018-01-23 11:53:31 +01007813#endif
Chen Gang704eff62015-08-21 05:37:33 +08007814#ifdef TARGET_NR_mkdir
bellard31e31b82003-02-18 22:55:36 +00007815 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00007816 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007817 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007818 ret = get_errno(mkdir(p, arg2));
7819 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007820 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007821#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01007822#if defined(TARGET_NR_mkdirat)
ths4472ad02007-09-24 09:22:32 +00007823 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00007824 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007825 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01007826 ret = get_errno(mkdirat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00007827 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007828 return ret;
ths4472ad02007-09-24 09:22:32 +00007829#endif
Chen Gang704eff62015-08-21 05:37:33 +08007830#ifdef TARGET_NR_rmdir
bellard31e31b82003-02-18 22:55:36 +00007831 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00007832 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007833 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007834 ret = get_errno(rmdir(p));
7835 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007836 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007837#endif
bellard31e31b82003-02-18 22:55:36 +00007838 case TARGET_NR_dup:
7839 ret = get_errno(dup(arg1));
Laurent Viviere36800c2015-10-02 14:48:09 +02007840 if (ret >= 0) {
7841 fd_trans_dup(arg1, ret);
7842 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007843 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007844#ifdef TARGET_NR_pipe
bellard31e31b82003-02-18 22:55:36 +00007845 case TARGET_NR_pipe:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007846 return do_pipe(cpu_env, arg1, 0, 0);
Chen Gang704eff62015-08-21 05:37:33 +08007847#endif
Riku Voipio099d6b02009-05-05 12:10:04 +03007848#ifdef TARGET_NR_pipe2
7849 case TARGET_NR_pipe2:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007850 return do_pipe(cpu_env, arg1,
7851 target_to_host_bitmask(arg2, fcntl_flags_tbl), 1);
Riku Voipio099d6b02009-05-05 12:10:04 +03007852#endif
bellard31e31b82003-02-18 22:55:36 +00007853 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00007854 {
pbrook53a59602006-03-25 19:31:22 +00007855 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00007856 struct tms tms;
7857 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00007858 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00007859 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
7860 if (!tmsp)
Richard Henderson2852aaf2018-08-18 12:01:06 -07007861 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02007862 tmsp->tms_utime = tswapal(host_to_target_clock_t(tms.tms_utime));
7863 tmsp->tms_stime = tswapal(host_to_target_clock_t(tms.tms_stime));
7864 tmsp->tms_cutime = tswapal(host_to_target_clock_t(tms.tms_cutime));
7865 tmsp->tms_cstime = tswapal(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00007866 }
bellardc596ed12003-07-13 17:32:31 +00007867 if (!is_error(ret))
7868 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00007869 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007870 return ret;
bellard31e31b82003-02-18 22:55:36 +00007871 case TARGET_NR_acct:
aurel3238d840e2009-01-30 19:48:17 +00007872 if (arg1 == 0) {
7873 ret = get_errno(acct(NULL));
7874 } else {
Richard Henderson2852aaf2018-08-18 12:01:06 -07007875 if (!(p = lock_user_string(arg1))) {
7876 return -TARGET_EFAULT;
7877 }
aurel3238d840e2009-01-30 19:48:17 +00007878 ret = get_errno(acct(path(p)));
7879 unlock_user(p, arg1, 0);
7880 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007881 return ret;
Richard Henderson8070e7b2013-07-24 09:50:00 -10007882#ifdef TARGET_NR_umount2
bellard31e31b82003-02-18 22:55:36 +00007883 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00007884 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007885 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007886 ret = get_errno(umount2(p, arg2));
7887 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007888 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00007889#endif
bellard31e31b82003-02-18 22:55:36 +00007890 case TARGET_NR_ioctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007891 return do_ioctl(arg1, arg2, arg3);
Michael Clark47ae93c2018-03-03 01:31:11 +13007892#ifdef TARGET_NR_fcntl
bellard31e31b82003-02-18 22:55:36 +00007893 case TARGET_NR_fcntl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007894 return do_fcntl(arg1, arg2, arg3);
Michael Clark47ae93c2018-03-03 01:31:11 +13007895#endif
bellard31e31b82003-02-18 22:55:36 +00007896 case TARGET_NR_setpgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007897 return get_errno(setpgid(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00007898 case TARGET_NR_umask:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007899 return get_errno(umask(arg1));
bellard31e31b82003-02-18 22:55:36 +00007900 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00007901 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007902 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007903 ret = get_errno(chroot(p));
7904 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007905 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007906#ifdef TARGET_NR_dup2
bellard31e31b82003-02-18 22:55:36 +00007907 case TARGET_NR_dup2:
7908 ret = get_errno(dup2(arg1, arg2));
Laurent Viviere36800c2015-10-02 14:48:09 +02007909 if (ret >= 0) {
7910 fd_trans_dup(arg1, arg2);
7911 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007912 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007913#endif
Ulrich Hechtd0927932009-09-17 20:22:14 +03007914#if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3)
7915 case TARGET_NR_dup3:
Peter Maydell10fa9932017-12-15 15:18:00 +00007916 {
7917 int host_flags;
7918
7919 if ((arg3 & ~TARGET_O_CLOEXEC) != 0) {
7920 return -EINVAL;
7921 }
7922 host_flags = target_to_host_bitmask(arg3, fcntl_flags_tbl);
7923 ret = get_errno(dup3(arg1, arg2, host_flags));
Laurent Viviere36800c2015-10-02 14:48:09 +02007924 if (ret >= 0) {
7925 fd_trans_dup(arg1, arg2);
7926 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007927 return ret;
Peter Maydell10fa9932017-12-15 15:18:00 +00007928 }
Ulrich Hechtd0927932009-09-17 20:22:14 +03007929#endif
j_mayer7a3148a2007-04-05 07:13:51 +00007930#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00007931 case TARGET_NR_getppid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007932 return get_errno(getppid());
j_mayer7a3148a2007-04-05 07:13:51 +00007933#endif
Chen Gang704eff62015-08-21 05:37:33 +08007934#ifdef TARGET_NR_getpgrp
bellard31e31b82003-02-18 22:55:36 +00007935 case TARGET_NR_getpgrp:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007936 return get_errno(getpgrp());
Chen Gang704eff62015-08-21 05:37:33 +08007937#endif
bellard31e31b82003-02-18 22:55:36 +00007938 case TARGET_NR_setsid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007939 return get_errno(setsid());
thse5febef2007-04-01 18:31:35 +00007940#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00007941 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00007942 {
Richard Henderson6049f4f2009-12-27 18:30:03 -08007943#if defined(TARGET_ALPHA)
7944 struct target_sigaction act, oact, *pact = 0;
pbrook53a59602006-03-25 19:31:22 +00007945 struct target_old_sigaction *old_act;
pbrook53a59602006-03-25 19:31:22 +00007946 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00007947 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007948 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +00007949 act._sa_handler = old_act->_sa_handler;
7950 target_siginitset(&act.sa_mask, old_act->sa_mask);
7951 act.sa_flags = old_act->sa_flags;
Richard Henderson6049f4f2009-12-27 18:30:03 -08007952 act.sa_restorer = 0;
pbrook53a59602006-03-25 19:31:22 +00007953 unlock_user_struct(old_act, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00007954 pact = &act;
bellard66fb9762003-03-23 01:06:05 +00007955 }
7956 ret = get_errno(do_sigaction(arg1, pact, &oact));
pbrook53a59602006-03-25 19:31:22 +00007957 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00007958 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007959 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007960 old_act->_sa_handler = oact._sa_handler;
7961 old_act->sa_mask = oact.sa_mask.sig[0];
7962 old_act->sa_flags = oact.sa_flags;
pbrook53a59602006-03-25 19:31:22 +00007963 unlock_user_struct(old_act, arg3, 1);
bellard66fb9762003-03-23 01:06:05 +00007964 }
Richard Henderson6049f4f2009-12-27 18:30:03 -08007965#elif defined(TARGET_MIPS)
bellard106ec872006-06-27 21:08:10 +00007966 struct target_sigaction act, oact, *pact, *old_act;
7967
7968 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00007969 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007970 return -TARGET_EFAULT;
bellard106ec872006-06-27 21:08:10 +00007971 act._sa_handler = old_act->_sa_handler;
7972 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
7973 act.sa_flags = old_act->sa_flags;
7974 unlock_user_struct(old_act, arg2, 0);
7975 pact = &act;
7976 } else {
7977 pact = NULL;
7978 }
7979
7980 ret = get_errno(do_sigaction(arg1, pact, &oact));
7981
7982 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00007983 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007984 return -TARGET_EFAULT;
bellard106ec872006-06-27 21:08:10 +00007985 old_act->_sa_handler = oact._sa_handler;
7986 old_act->sa_flags = oact.sa_flags;
7987 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
7988 old_act->sa_mask.sig[1] = 0;
7989 old_act->sa_mask.sig[2] = 0;
7990 old_act->sa_mask.sig[3] = 0;
7991 unlock_user_struct(old_act, arg3, 1);
7992 }
Richard Henderson6049f4f2009-12-27 18:30:03 -08007993#else
7994 struct target_old_sigaction *old_act;
7995 struct target_sigaction act, oact, *pact;
7996 if (arg2) {
7997 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007998 return -TARGET_EFAULT;
Richard Henderson6049f4f2009-12-27 18:30:03 -08007999 act._sa_handler = old_act->_sa_handler;
8000 target_siginitset(&act.sa_mask, old_act->sa_mask);
8001 act.sa_flags = old_act->sa_flags;
8002 act.sa_restorer = old_act->sa_restorer;
Laurent Vivier5de154e2018-04-02 12:24:52 +02008003#ifdef TARGET_ARCH_HAS_KA_RESTORER
8004 act.ka_restorer = 0;
8005#endif
Richard Henderson6049f4f2009-12-27 18:30:03 -08008006 unlock_user_struct(old_act, arg2, 0);
8007 pact = &act;
8008 } else {
8009 pact = NULL;
8010 }
8011 ret = get_errno(do_sigaction(arg1, pact, &oact));
8012 if (!is_error(ret) && arg3) {
8013 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008014 return -TARGET_EFAULT;
Richard Henderson6049f4f2009-12-27 18:30:03 -08008015 old_act->_sa_handler = oact._sa_handler;
8016 old_act->sa_mask = oact.sa_mask.sig[0];
8017 old_act->sa_flags = oact.sa_flags;
8018 old_act->sa_restorer = oact.sa_restorer;
8019 unlock_user_struct(old_act, arg3, 1);
8020 }
ths388bb212007-05-13 13:58:00 +00008021#endif
bellard31e31b82003-02-18 22:55:36 +00008022 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008023 return ret;
thse5febef2007-04-01 18:31:35 +00008024#endif
bellard66fb9762003-03-23 01:06:05 +00008025 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00008026 {
Richard Henderson6049f4f2009-12-27 18:30:03 -08008027#if defined(TARGET_ALPHA)
Peter Maydell78bfef72017-11-06 18:33:26 +00008028 /* For Alpha and SPARC this is a 5 argument syscall, with
8029 * a 'restorer' parameter which must be copied into the
8030 * sa_restorer field of the sigaction struct.
8031 * For Alpha that 'restorer' is arg5; for SPARC it is arg4,
8032 * and arg5 is the sigsetsize.
8033 * Alpha also has a separate rt_sigaction struct that it uses
8034 * here; SPARC uses the usual sigaction struct.
8035 */
Richard Henderson6049f4f2009-12-27 18:30:03 -08008036 struct target_rt_sigaction *rt_act;
Peter Maydell78bfef72017-11-06 18:33:26 +00008037 struct target_sigaction act, oact, *pact = 0;
Peter Maydellc8157012016-06-30 14:23:24 +01008038
8039 if (arg4 != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008040 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01008041 }
Richard Henderson6049f4f2009-12-27 18:30:03 -08008042 if (arg2) {
8043 if (!lock_user_struct(VERIFY_READ, rt_act, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008044 return -TARGET_EFAULT;
Richard Henderson6049f4f2009-12-27 18:30:03 -08008045 act._sa_handler = rt_act->_sa_handler;
8046 act.sa_mask = rt_act->sa_mask;
8047 act.sa_flags = rt_act->sa_flags;
8048 act.sa_restorer = arg5;
8049 unlock_user_struct(rt_act, arg2, 0);
8050 pact = &act;
8051 }
8052 ret = get_errno(do_sigaction(arg1, pact, &oact));
8053 if (!is_error(ret) && arg3) {
8054 if (!lock_user_struct(VERIFY_WRITE, rt_act, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008055 return -TARGET_EFAULT;
Richard Henderson6049f4f2009-12-27 18:30:03 -08008056 rt_act->_sa_handler = oact._sa_handler;
8057 rt_act->sa_mask = oact.sa_mask;
8058 rt_act->sa_flags = oact.sa_flags;
8059 unlock_user_struct(rt_act, arg3, 1);
8060 }
8061#else
Peter Maydell78bfef72017-11-06 18:33:26 +00008062#ifdef TARGET_SPARC
8063 target_ulong restorer = arg4;
8064 target_ulong sigsetsize = arg5;
8065#else
8066 target_ulong sigsetsize = arg4;
8067#endif
pbrook53a59602006-03-25 19:31:22 +00008068 struct target_sigaction *act;
8069 struct target_sigaction *oact;
8070
Peter Maydell78bfef72017-11-06 18:33:26 +00008071 if (sigsetsize != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008072 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01008073 }
bellard579a97f2007-11-11 14:26:47 +00008074 if (arg2) {
Peter Maydell78bfef72017-11-06 18:33:26 +00008075 if (!lock_user_struct(VERIFY_READ, act, arg2, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008076 return -TARGET_EFAULT;
Peter Maydell78bfef72017-11-06 18:33:26 +00008077 }
Laurent Vivier5de154e2018-04-02 12:24:52 +02008078#ifdef TARGET_ARCH_HAS_KA_RESTORER
8079 act->ka_restorer = restorer;
Peter Maydell78bfef72017-11-06 18:33:26 +00008080#endif
8081 } else {
pbrook53a59602006-03-25 19:31:22 +00008082 act = NULL;
Peter Maydell78bfef72017-11-06 18:33:26 +00008083 }
bellard579a97f2007-11-11 14:26:47 +00008084 if (arg3) {
8085 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
8086 ret = -TARGET_EFAULT;
8087 goto rt_sigaction_fail;
8088 }
8089 } else
pbrook53a59602006-03-25 19:31:22 +00008090 oact = NULL;
8091 ret = get_errno(do_sigaction(arg1, act, oact));
bellard579a97f2007-11-11 14:26:47 +00008092 rt_sigaction_fail:
8093 if (act)
pbrook53a59602006-03-25 19:31:22 +00008094 unlock_user_struct(act, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +00008095 if (oact)
pbrook53a59602006-03-25 19:31:22 +00008096 unlock_user_struct(oact, arg3, 1);
Richard Henderson6049f4f2009-12-27 18:30:03 -08008097#endif
pbrook53a59602006-03-25 19:31:22 +00008098 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008099 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00008100#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00008101 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00008102 {
8103 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00008104 abi_ulong target_set;
Peter Maydell3d3efba2016-05-27 15:51:49 +01008105 ret = do_sigprocmask(0, NULL, &cur_set);
8106 if (!ret) {
8107 host_to_target_old_sigset(&target_set, &cur_set);
8108 ret = target_set;
8109 }
bellard66fb9762003-03-23 01:06:05 +00008110 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008111 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00008112#endif
8113#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00008114 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00008115 {
Miloš Stojanovića8617d82017-05-15 16:59:43 +02008116 sigset_t set, oset;
blueswir1992f48a2007-10-14 16:27:31 +00008117 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00008118 target_to_host_old_sigset(&set, &target_set);
Peter Maydell3d3efba2016-05-27 15:51:49 +01008119 ret = do_sigprocmask(SIG_SETMASK, &set, &oset);
8120 if (!ret) {
8121 host_to_target_old_sigset(&target_set, &oset);
8122 ret = target_set;
8123 }
bellard66fb9762003-03-23 01:06:05 +00008124 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008125 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00008126#endif
thse5febef2007-04-01 18:31:35 +00008127#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00008128 case TARGET_NR_sigprocmask:
8129 {
Richard Hendersona5b3b132010-05-03 10:07:55 -07008130#if defined(TARGET_ALPHA)
8131 sigset_t set, oldset;
8132 abi_ulong mask;
8133 int how;
8134
8135 switch (arg1) {
8136 case TARGET_SIG_BLOCK:
8137 how = SIG_BLOCK;
8138 break;
8139 case TARGET_SIG_UNBLOCK:
8140 how = SIG_UNBLOCK;
8141 break;
8142 case TARGET_SIG_SETMASK:
8143 how = SIG_SETMASK;
8144 break;
8145 default:
Richard Henderson259841c2018-08-18 12:01:09 -07008146 return -TARGET_EINVAL;
Richard Hendersona5b3b132010-05-03 10:07:55 -07008147 }
8148 mask = arg2;
8149 target_to_host_old_sigset(&set, &mask);
8150
Peter Maydell3d3efba2016-05-27 15:51:49 +01008151 ret = do_sigprocmask(how, &set, &oldset);
Richard Hendersona5b3b132010-05-03 10:07:55 -07008152 if (!is_error(ret)) {
8153 host_to_target_old_sigset(&mask, &oldset);
8154 ret = mask;
Richard Henderson0229f5a2012-06-07 15:02:49 -07008155 ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0; /* force no error */
Richard Hendersona5b3b132010-05-03 10:07:55 -07008156 }
8157#else
bellard66fb9762003-03-23 01:06:05 +00008158 sigset_t set, oldset, *set_ptr;
Richard Hendersona5b3b132010-05-03 10:07:55 -07008159 int how;
ths3b46e622007-09-17 08:09:54 +00008160
pbrook53a59602006-03-25 19:31:22 +00008161 if (arg2) {
Richard Hendersona5b3b132010-05-03 10:07:55 -07008162 switch (arg1) {
bellard66fb9762003-03-23 01:06:05 +00008163 case TARGET_SIG_BLOCK:
8164 how = SIG_BLOCK;
8165 break;
8166 case TARGET_SIG_UNBLOCK:
8167 how = SIG_UNBLOCK;
8168 break;
8169 case TARGET_SIG_SETMASK:
8170 how = SIG_SETMASK;
8171 break;
8172 default:
Richard Henderson259841c2018-08-18 12:01:09 -07008173 return -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00008174 }
Anthony Liguoric227f092009-10-01 16:12:16 -05008175 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008176 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008177 target_to_host_old_sigset(&set, p);
8178 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00008179 set_ptr = &set;
8180 } else {
8181 how = 0;
8182 set_ptr = NULL;
8183 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01008184 ret = do_sigprocmask(how, set_ptr, &oldset);
pbrook53a59602006-03-25 19:31:22 +00008185 if (!is_error(ret) && arg3) {
Anthony Liguoric227f092009-10-01 16:12:16 -05008186 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008187 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008188 host_to_target_old_sigset(p, &oldset);
Anthony Liguoric227f092009-10-01 16:12:16 -05008189 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00008190 }
Richard Hendersona5b3b132010-05-03 10:07:55 -07008191#endif
bellard66fb9762003-03-23 01:06:05 +00008192 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008193 return ret;
thse5febef2007-04-01 18:31:35 +00008194#endif
bellard66fb9762003-03-23 01:06:05 +00008195 case TARGET_NR_rt_sigprocmask:
8196 {
8197 int how = arg1;
8198 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00008199
Peter Maydellc8157012016-06-30 14:23:24 +01008200 if (arg4 != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008201 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01008202 }
8203
pbrook53a59602006-03-25 19:31:22 +00008204 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00008205 switch(how) {
8206 case TARGET_SIG_BLOCK:
8207 how = SIG_BLOCK;
8208 break;
8209 case TARGET_SIG_UNBLOCK:
8210 how = SIG_UNBLOCK;
8211 break;
8212 case TARGET_SIG_SETMASK:
8213 how = SIG_SETMASK;
8214 break;
8215 default:
Richard Henderson259841c2018-08-18 12:01:09 -07008216 return -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00008217 }
Anthony Liguoric227f092009-10-01 16:12:16 -05008218 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008219 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008220 target_to_host_sigset(&set, p);
8221 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00008222 set_ptr = &set;
8223 } else {
8224 how = 0;
8225 set_ptr = NULL;
8226 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01008227 ret = do_sigprocmask(how, set_ptr, &oldset);
pbrook53a59602006-03-25 19:31:22 +00008228 if (!is_error(ret) && arg3) {
Anthony Liguoric227f092009-10-01 16:12:16 -05008229 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008230 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008231 host_to_target_sigset(p, &oldset);
Anthony Liguoric227f092009-10-01 16:12:16 -05008232 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00008233 }
8234 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008235 return ret;
thse5febef2007-04-01 18:31:35 +00008236#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00008237 case TARGET_NR_sigpending:
8238 {
8239 sigset_t set;
8240 ret = get_errno(sigpending(&set));
8241 if (!is_error(ret)) {
Anthony Liguoric227f092009-10-01 16:12:16 -05008242 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008243 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008244 host_to_target_old_sigset(p, &set);
Anthony Liguoric227f092009-10-01 16:12:16 -05008245 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00008246 }
8247 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008248 return ret;
thse5febef2007-04-01 18:31:35 +00008249#endif
bellard66fb9762003-03-23 01:06:05 +00008250 case TARGET_NR_rt_sigpending:
8251 {
8252 sigset_t set;
Peter Maydellc8157012016-06-30 14:23:24 +01008253
8254 /* Yes, this check is >, not != like most. We follow the kernel's
8255 * logic and it does it like this because it implements
8256 * NR_sigpending through the same code path, and in that case
8257 * the old_sigset_t is smaller in size.
8258 */
8259 if (arg2 > sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008260 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01008261 }
8262
bellard66fb9762003-03-23 01:06:05 +00008263 ret = get_errno(sigpending(&set));
8264 if (!is_error(ret)) {
Anthony Liguoric227f092009-10-01 16:12:16 -05008265 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008266 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008267 host_to_target_sigset(p, &set);
Anthony Liguoric227f092009-10-01 16:12:16 -05008268 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00008269 }
8270 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008271 return ret;
thse5febef2007-04-01 18:31:35 +00008272#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00008273 case TARGET_NR_sigsuspend:
8274 {
Peter Maydell3d3efba2016-05-27 15:51:49 +01008275 TaskState *ts = cpu->opaque;
Richard Hendersonf43ce122010-05-03 10:07:54 -07008276#if defined(TARGET_ALPHA)
8277 abi_ulong mask = arg1;
Peter Maydell3d3efba2016-05-27 15:51:49 +01008278 target_to_host_old_sigset(&ts->sigsuspend_mask, &mask);
Richard Hendersonf43ce122010-05-03 10:07:54 -07008279#else
Anthony Liguoric227f092009-10-01 16:12:16 -05008280 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008281 return -TARGET_EFAULT;
Peter Maydell3d3efba2016-05-27 15:51:49 +01008282 target_to_host_old_sigset(&ts->sigsuspend_mask, p);
pbrook53a59602006-03-25 19:31:22 +00008283 unlock_user(p, arg1, 0);
Richard Hendersonf43ce122010-05-03 10:07:54 -07008284#endif
Peter Maydell3d3efba2016-05-27 15:51:49 +01008285 ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
8286 SIGSET_T_SIZE));
8287 if (ret != -TARGET_ERESTARTSYS) {
8288 ts->in_sigsuspend = 1;
8289 }
bellard66fb9762003-03-23 01:06:05 +00008290 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008291 return ret;
thse5febef2007-04-01 18:31:35 +00008292#endif
bellard66fb9762003-03-23 01:06:05 +00008293 case TARGET_NR_rt_sigsuspend:
8294 {
Peter Maydell3d3efba2016-05-27 15:51:49 +01008295 TaskState *ts = cpu->opaque;
Peter Maydellc8157012016-06-30 14:23:24 +01008296
8297 if (arg2 != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008298 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01008299 }
Anthony Liguoric227f092009-10-01 16:12:16 -05008300 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008301 return -TARGET_EFAULT;
Peter Maydell3d3efba2016-05-27 15:51:49 +01008302 target_to_host_sigset(&ts->sigsuspend_mask, p);
pbrook53a59602006-03-25 19:31:22 +00008303 unlock_user(p, arg1, 0);
Peter Maydell3d3efba2016-05-27 15:51:49 +01008304 ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
8305 SIGSET_T_SIZE));
8306 if (ret != -TARGET_ERESTARTSYS) {
8307 ts->in_sigsuspend = 1;
8308 }
bellard66fb9762003-03-23 01:06:05 +00008309 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008310 return ret;
bellard66fb9762003-03-23 01:06:05 +00008311 case TARGET_NR_rt_sigtimedwait:
8312 {
bellard66fb9762003-03-23 01:06:05 +00008313 sigset_t set;
8314 struct timespec uts, *puts;
8315 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00008316
Peter Maydellc8157012016-06-30 14:23:24 +01008317 if (arg4 != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008318 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01008319 }
8320
Anthony Liguoric227f092009-10-01 16:12:16 -05008321 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008322 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008323 target_to_host_sigset(&set, p);
8324 unlock_user(p, arg1, 0);
8325 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00008326 puts = &uts;
pbrook53a59602006-03-25 19:31:22 +00008327 target_to_host_timespec(puts, arg3);
bellard66fb9762003-03-23 01:06:05 +00008328 } else {
8329 puts = NULL;
8330 }
Peter Maydellb3f82332016-06-06 19:58:08 +01008331 ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts,
8332 SIGSET_T_SIZE));
Petar Jovanovic974a1962014-03-03 15:07:41 +01008333 if (!is_error(ret)) {
8334 if (arg2) {
8335 p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t),
8336 0);
8337 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008338 return -TARGET_EFAULT;
Petar Jovanovic974a1962014-03-03 15:07:41 +01008339 }
8340 host_to_target_siginfo(p, &uinfo);
8341 unlock_user(p, arg2, sizeof(target_siginfo_t));
8342 }
8343 ret = host_to_target_signal(ret);
bellard66fb9762003-03-23 01:06:05 +00008344 }
8345 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008346 return ret;
bellard66fb9762003-03-23 01:06:05 +00008347 case TARGET_NR_rt_sigqueueinfo:
8348 {
8349 siginfo_t uinfo;
Peter Maydell4debae62016-06-20 15:50:36 +01008350
8351 p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
8352 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008353 return -TARGET_EFAULT;
Peter Maydell4debae62016-06-20 15:50:36 +01008354 }
pbrook53a59602006-03-25 19:31:22 +00008355 target_to_host_siginfo(&uinfo, p);
Miloš Stojanovićd8b6d892017-05-15 16:59:44 +02008356 unlock_user(p, arg3, 0);
bellard66fb9762003-03-23 01:06:05 +00008357 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
8358 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008359 return ret;
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +02008360 case TARGET_NR_rt_tgsigqueueinfo:
8361 {
8362 siginfo_t uinfo;
8363
8364 p = lock_user(VERIFY_READ, arg4, sizeof(target_siginfo_t), 1);
8365 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008366 return -TARGET_EFAULT;
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +02008367 }
8368 target_to_host_siginfo(&uinfo, p);
8369 unlock_user(p, arg4, 0);
8370 ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, arg3, &uinfo));
8371 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008372 return ret;
thse5febef2007-04-01 18:31:35 +00008373#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00008374 case TARGET_NR_sigreturn:
Peter Maydell3d3efba2016-05-27 15:51:49 +01008375 if (block_signals()) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008376 return -TARGET_ERESTARTSYS;
Peter Maydell3d3efba2016-05-27 15:51:49 +01008377 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008378 return do_sigreturn(cpu_env);
thse5febef2007-04-01 18:31:35 +00008379#endif
bellard66fb9762003-03-23 01:06:05 +00008380 case TARGET_NR_rt_sigreturn:
Peter Maydell3d3efba2016-05-27 15:51:49 +01008381 if (block_signals()) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008382 return -TARGET_ERESTARTSYS;
Peter Maydell3d3efba2016-05-27 15:51:49 +01008383 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008384 return do_rt_sigreturn(cpu_env);
bellard31e31b82003-02-18 22:55:36 +00008385 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00008386 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008387 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008388 ret = get_errno(sethostname(p, arg2));
8389 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008390 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008391#ifdef TARGET_NR_setrlimit
bellard31e31b82003-02-18 22:55:36 +00008392 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +00008393 {
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03008394 int resource = target_to_host_resource(arg1);
pbrook53a59602006-03-25 19:31:22 +00008395 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00008396 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +00008397 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008398 return -TARGET_EFAULT;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09008399 rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
8400 rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00008401 unlock_user_struct(target_rlim, arg2, 0);
Max Filippov5dfa88f2018-09-17 11:13:14 -07008402 /*
8403 * If we just passed through resource limit settings for memory then
8404 * they would also apply to QEMU's own allocations, and QEMU will
8405 * crash or hang or die if its allocations fail. Ideally we would
8406 * track the guest allocations in QEMU and apply the limits ourselves.
8407 * For now, just tell the guest the call succeeded but don't actually
8408 * limit anything.
8409 */
8410 if (resource != RLIMIT_AS &&
8411 resource != RLIMIT_DATA &&
8412 resource != RLIMIT_STACK) {
8413 return get_errno(setrlimit(resource, &rlim));
8414 } else {
8415 return 0;
8416 }
bellard9de5e442003-03-23 16:49:39 +00008417 }
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008418#endif
8419#ifdef TARGET_NR_getrlimit
bellard31e31b82003-02-18 22:55:36 +00008420 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00008421 {
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03008422 int resource = target_to_host_resource(arg1);
pbrook53a59602006-03-25 19:31:22 +00008423 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00008424 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00008425
bellard9de5e442003-03-23 16:49:39 +00008426 ret = get_errno(getrlimit(resource, &rlim));
8427 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00008428 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008429 return -TARGET_EFAULT;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09008430 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
8431 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00008432 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00008433 }
8434 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008435 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008436#endif
bellard31e31b82003-02-18 22:55:36 +00008437 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00008438 {
8439 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00008440 ret = get_errno(getrusage(arg1, &rusage));
8441 if (!is_error(ret)) {
Petar Jovanovica39fb272014-04-08 19:24:30 +02008442 ret = host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00008443 }
8444 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008445 return ret;
bellard31e31b82003-02-18 22:55:36 +00008446 case TARGET_NR_gettimeofday:
8447 {
bellard31e31b82003-02-18 22:55:36 +00008448 struct timeval tv;
8449 ret = get_errno(gettimeofday(&tv, NULL));
8450 if (!is_error(ret)) {
ths788f5ec2007-12-09 02:37:05 +00008451 if (copy_to_user_timeval(arg1, &tv))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008452 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00008453 }
8454 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008455 return ret;
bellard31e31b82003-02-18 22:55:36 +00008456 case TARGET_NR_settimeofday:
8457 {
Paul Burtonb67d8032014-06-22 11:25:41 +01008458 struct timeval tv, *ptv = NULL;
Paul Burtonef4467e2014-06-22 11:25:40 +01008459 struct timezone tz, *ptz = NULL;
8460
Paul Burtonb67d8032014-06-22 11:25:41 +01008461 if (arg1) {
8462 if (copy_from_user_timeval(&tv, arg1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008463 return -TARGET_EFAULT;
Paul Burtonb67d8032014-06-22 11:25:41 +01008464 }
8465 ptv = &tv;
8466 }
Paul Burtonef4467e2014-06-22 11:25:40 +01008467
8468 if (arg2) {
8469 if (copy_from_user_timezone(&tz, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008470 return -TARGET_EFAULT;
Paul Burtonef4467e2014-06-22 11:25:40 +01008471 }
8472 ptz = &tz;
8473 }
8474
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008475 return get_errno(settimeofday(ptv, ptz));
bellard31e31b82003-02-18 22:55:36 +00008476 }
Laurent Vivier9468a5d2013-01-10 22:30:50 +01008477#if defined(TARGET_NR_select)
bellard31e31b82003-02-18 22:55:36 +00008478 case TARGET_NR_select:
Laurent Vivier5457dc92016-07-08 01:17:27 +02008479#if defined(TARGET_WANT_NI_OLD_SELECT)
8480 /* some architectures used to have old_select here
8481 * but now ENOSYS it.
8482 */
8483 ret = -TARGET_ENOSYS;
8484#elif defined(TARGET_WANT_OLD_SYS_SELECT)
8485 ret = do_old_select(arg1);
Laurent Vivier9468a5d2013-01-10 22:30:50 +01008486#else
Laurent Vivier5457dc92016-07-08 01:17:27 +02008487 ret = do_select(arg1, arg2, arg3, arg4, arg5);
Laurent Vivier9468a5d2013-01-10 22:30:50 +01008488#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008489 return ret;
bellard048f6b42005-11-26 18:47:20 +00008490#endif
Riku Voipio9e423822010-05-07 12:28:05 +00008491#ifdef TARGET_NR_pselect6
8492 case TARGET_NR_pselect6:
Mike Frysinger055e0902011-06-03 17:01:49 -04008493 {
8494 abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr;
8495 fd_set rfds, wfds, efds;
8496 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
8497 struct timespec ts, *ts_ptr;
8498
8499 /*
8500 * The 6th arg is actually two args smashed together,
8501 * so we cannot use the C library.
8502 */
8503 sigset_t set;
8504 struct {
8505 sigset_t *set;
8506 size_t size;
8507 } sig, *sig_ptr;
8508
8509 abi_ulong arg_sigset, arg_sigsize, *arg7;
8510 target_sigset_t *target_sigset;
8511
8512 n = arg1;
8513 rfd_addr = arg2;
8514 wfd_addr = arg3;
8515 efd_addr = arg4;
8516 ts_addr = arg5;
8517
8518 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
8519 if (ret) {
Richard Henderson259841c2018-08-18 12:01:09 -07008520 return ret;
Mike Frysinger055e0902011-06-03 17:01:49 -04008521 }
8522 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
8523 if (ret) {
Richard Henderson259841c2018-08-18 12:01:09 -07008524 return ret;
Mike Frysinger055e0902011-06-03 17:01:49 -04008525 }
8526 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
8527 if (ret) {
Richard Henderson259841c2018-08-18 12:01:09 -07008528 return ret;
Mike Frysinger055e0902011-06-03 17:01:49 -04008529 }
8530
8531 /*
8532 * This takes a timespec, and not a timeval, so we cannot
8533 * use the do_select() helper ...
8534 */
8535 if (ts_addr) {
8536 if (target_to_host_timespec(&ts, ts_addr)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008537 return -TARGET_EFAULT;
Mike Frysinger055e0902011-06-03 17:01:49 -04008538 }
8539 ts_ptr = &ts;
8540 } else {
8541 ts_ptr = NULL;
8542 }
8543
8544 /* Extract the two packed args for the sigset */
8545 if (arg6) {
8546 sig_ptr = &sig;
Peter Maydellb28a1f32016-05-27 15:51:47 +01008547 sig.size = SIGSET_T_SIZE;
Mike Frysinger055e0902011-06-03 17:01:49 -04008548
8549 arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1);
8550 if (!arg7) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008551 return -TARGET_EFAULT;
Mike Frysinger055e0902011-06-03 17:01:49 -04008552 }
Matthias Brauncbb21ee2011-08-12 19:57:41 +02008553 arg_sigset = tswapal(arg7[0]);
8554 arg_sigsize = tswapal(arg7[1]);
Mike Frysinger055e0902011-06-03 17:01:49 -04008555 unlock_user(arg7, arg6, 0);
8556
8557 if (arg_sigset) {
8558 sig.set = &set;
Peter Maydell8f04eeb2011-06-28 12:21:57 +01008559 if (arg_sigsize != sizeof(*target_sigset)) {
8560 /* Like the kernel, we enforce correct size sigsets */
Richard Henderson259841c2018-08-18 12:01:09 -07008561 return -TARGET_EINVAL;
Peter Maydell8f04eeb2011-06-28 12:21:57 +01008562 }
Mike Frysinger055e0902011-06-03 17:01:49 -04008563 target_sigset = lock_user(VERIFY_READ, arg_sigset,
8564 sizeof(*target_sigset), 1);
8565 if (!target_sigset) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008566 return -TARGET_EFAULT;
Mike Frysinger055e0902011-06-03 17:01:49 -04008567 }
8568 target_to_host_sigset(&set, target_sigset);
8569 unlock_user(target_sigset, arg_sigset, 0);
8570 } else {
8571 sig.set = NULL;
8572 }
8573 } else {
8574 sig_ptr = NULL;
8575 }
8576
Peter Maydell6df9d382016-05-12 18:47:51 +01008577 ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
8578 ts_ptr, sig_ptr));
Mike Frysinger055e0902011-06-03 17:01:49 -04008579
8580 if (!is_error(ret)) {
8581 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008582 return -TARGET_EFAULT;
Mike Frysinger055e0902011-06-03 17:01:49 -04008583 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008584 return -TARGET_EFAULT;
Mike Frysinger055e0902011-06-03 17:01:49 -04008585 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008586 return -TARGET_EFAULT;
Mike Frysinger055e0902011-06-03 17:01:49 -04008587
8588 if (ts_addr && host_to_target_timespec(ts_addr, &ts))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008589 return -TARGET_EFAULT;
Mike Frysinger055e0902011-06-03 17:01:49 -04008590 }
8591 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008592 return ret;
Riku Voipio9e423822010-05-07 12:28:05 +00008593#endif
Chen Gang704eff62015-08-21 05:37:33 +08008594#ifdef TARGET_NR_symlink
bellard31e31b82003-02-18 22:55:36 +00008595 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00008596 {
8597 void *p2;
8598 p = lock_user_string(arg1);
8599 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00008600 if (!p || !p2)
8601 ret = -TARGET_EFAULT;
8602 else
8603 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00008604 unlock_user(p2, arg2, 0);
8605 unlock_user(p, arg1, 0);
8606 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008607 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008608#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01008609#if defined(TARGET_NR_symlinkat)
thsf0b62432007-09-24 09:25:40 +00008610 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00008611 {
bellard579a97f2007-11-11 14:26:47 +00008612 void *p2;
thsf0b62432007-09-24 09:25:40 +00008613 p = lock_user_string(arg1);
8614 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00008615 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00008616 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00008617 else
Peter Maydellc0d472b2013-06-12 16:20:21 +01008618 ret = get_errno(symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00008619 unlock_user(p2, arg3, 0);
8620 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00008621 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008622 return ret;
thsf0b62432007-09-24 09:25:40 +00008623#endif
Chen Gang704eff62015-08-21 05:37:33 +08008624#ifdef TARGET_NR_readlink
bellard31e31b82003-02-18 22:55:36 +00008625 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00008626 {
Andreas Schwab463d8e72013-07-02 14:04:12 +01008627 void *p2;
pbrook53a59602006-03-25 19:31:22 +00008628 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00008629 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
Andreas Schwab463d8e72013-07-02 14:04:12 +01008630 if (!p || !p2) {
bellard579a97f2007-11-11 14:26:47 +00008631 ret = -TARGET_EFAULT;
Mike Frysingerf17f4982014-08-08 09:40:25 +09008632 } else if (!arg3) {
8633 /* Short circuit this for the magic exe check. */
8634 ret = -TARGET_EINVAL;
Andreas Schwab463d8e72013-07-02 14:04:12 +01008635 } else if (is_proc_myself((const char *)p, "exe")) {
8636 char real[PATH_MAX], *temp;
8637 temp = realpath(exec_path, real);
Mike Frysingerf17f4982014-08-08 09:40:25 +09008638 /* Return value is # of bytes that we wrote to the buffer. */
8639 if (temp == NULL) {
8640 ret = get_errno(-1);
8641 } else {
8642 /* Don't worry about sign mismatch as earlier mapping
8643 * logic would have thrown a bad address error. */
8644 ret = MIN(strlen(real), arg3);
8645 /* We cannot NUL terminate the string. */
8646 memcpy(p2, real, ret);
8647 }
Andreas Schwab463d8e72013-07-02 14:04:12 +01008648 } else {
8649 ret = get_errno(readlink(path(p), p2, arg3));
aurel32d088d662009-01-30 20:09:01 +00008650 }
pbrook53a59602006-03-25 19:31:22 +00008651 unlock_user(p2, arg2, ret);
8652 unlock_user(p, arg1, 0);
8653 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008654 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008655#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01008656#if defined(TARGET_NR_readlinkat)
ths5e0ccb12007-09-24 09:26:10 +00008657 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +00008658 {
bellard579a97f2007-11-11 14:26:47 +00008659 void *p2;
ths5e0ccb12007-09-24 09:26:10 +00008660 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00008661 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
Andreas Schwab463d8e72013-07-02 14:04:12 +01008662 if (!p || !p2) {
8663 ret = -TARGET_EFAULT;
8664 } else if (is_proc_myself((const char *)p, "exe")) {
8665 char real[PATH_MAX], *temp;
8666 temp = realpath(exec_path, real);
8667 ret = temp == NULL ? get_errno(-1) : strlen(real) ;
8668 snprintf((char *)p2, arg4, "%s", real);
8669 } else {
Peter Maydellc0d472b2013-06-12 16:20:21 +01008670 ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
Andreas Schwab463d8e72013-07-02 14:04:12 +01008671 }
bellard579a97f2007-11-11 14:26:47 +00008672 unlock_user(p2, arg3, ret);
8673 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +00008674 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008675 return ret;
ths5e0ccb12007-09-24 09:26:10 +00008676#endif
thse5febef2007-04-01 18:31:35 +00008677#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +00008678 case TARGET_NR_swapon:
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(swapon(p, arg2));
8682 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008683 return ret;
thse5febef2007-04-01 18:31:35 +00008684#endif
bellard31e31b82003-02-18 22:55:36 +00008685 case TARGET_NR_reboot:
Laurent Vivierc07ecc62013-01-07 11:40:06 +00008686 if (arg3 == LINUX_REBOOT_CMD_RESTART2) {
8687 /* arg4 must be ignored in all other cases */
8688 p = lock_user_string(arg4);
8689 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008690 return -TARGET_EFAULT;
Laurent Vivierc07ecc62013-01-07 11:40:06 +00008691 }
8692 ret = get_errno(reboot(arg1, arg2, arg3, p));
8693 unlock_user(p, arg4, 0);
8694 } else {
8695 ret = get_errno(reboot(arg1, arg2, arg3, NULL));
8696 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008697 return ret;
thse5febef2007-04-01 18:31:35 +00008698#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +00008699 case TARGET_NR_mmap:
Alexander Graf09701192013-09-03 20:12:15 +01008700#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
8701 (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
Ulrich Hechta4c075f2009-07-24 16:57:31 +02008702 defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \
8703 || defined(TARGET_S390X)
bellard31e31b82003-02-18 22:55:36 +00008704 {
blueswir1992f48a2007-10-14 16:27:31 +00008705 abi_ulong *v;
8706 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +00008707 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008708 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02008709 v1 = tswapal(v[0]);
8710 v2 = tswapal(v[1]);
8711 v3 = tswapal(v[2]);
8712 v4 = tswapal(v[3]);
8713 v5 = tswapal(v[4]);
8714 v6 = tswapal(v[5]);
pbrook53a59602006-03-25 19:31:22 +00008715 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +00008716 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +00008717 target_to_host_bitmask(v4, mmap_flags_tbl),
8718 v5, v6));
bellard31e31b82003-02-18 22:55:36 +00008719 }
bellard31e31b82003-02-18 22:55:36 +00008720#else
ths5fafdf22007-09-16 21:08:06 +00008721 ret = get_errno(target_mmap(arg1, arg2, arg3,
8722 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +00008723 arg5,
8724 arg6));
bellard31e31b82003-02-18 22:55:36 +00008725#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008726 return ret;
thse5febef2007-04-01 18:31:35 +00008727#endif
bellarda315a142005-01-30 22:59:18 +00008728#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +00008729 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +00008730#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +00008731#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +00008732#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008733 ret = target_mmap(arg1, arg2, arg3,
8734 target_to_host_bitmask(arg4, mmap_flags_tbl),
8735 arg5, arg6 << MMAP_SHIFT);
8736 return get_errno(ret);
bellarda315a142005-01-30 22:59:18 +00008737#endif
bellard31e31b82003-02-18 22:55:36 +00008738 case TARGET_NR_munmap:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008739 return get_errno(target_munmap(arg1, arg2));
bellard9de5e442003-03-23 16:49:39 +00008740 case TARGET_NR_mprotect:
Paul Brook97374d32010-06-16 13:03:51 +01008741 {
Andreas Färber0429a972013-08-26 18:14:44 +02008742 TaskState *ts = cpu->opaque;
Paul Brook97374d32010-06-16 13:03:51 +01008743 /* Special hack to detect libc making the stack executable. */
8744 if ((arg3 & PROT_GROWSDOWN)
8745 && arg1 >= ts->info->stack_limit
8746 && arg1 <= ts->info->start_stack) {
8747 arg3 &= ~PROT_GROWSDOWN;
8748 arg2 = arg2 + arg1 - ts->info->stack_limit;
8749 arg1 = ts->info->stack_limit;
8750 }
8751 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008752 return get_errno(target_mprotect(arg1, arg2, arg3));
thse5febef2007-04-01 18:31:35 +00008753#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +00008754 case TARGET_NR_mremap:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008755 return get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
thse5febef2007-04-01 18:31:35 +00008756#endif
pbrook53a59602006-03-25 19:31:22 +00008757 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +00008758#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +00008759 case TARGET_NR_msync:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008760 return get_errno(msync(g2h(arg1), arg2, arg3));
thse5febef2007-04-01 18:31:35 +00008761#endif
8762#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +00008763 case TARGET_NR_mlock:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008764 return get_errno(mlock(g2h(arg1), arg2));
thse5febef2007-04-01 18:31:35 +00008765#endif
8766#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +00008767 case TARGET_NR_munlock:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008768 return get_errno(munlock(g2h(arg1), arg2));
thse5febef2007-04-01 18:31:35 +00008769#endif
8770#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +00008771 case TARGET_NR_mlockall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008772 return get_errno(mlockall(target_to_host_mlockall_arg(arg1)));
thse5febef2007-04-01 18:31:35 +00008773#endif
8774#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +00008775 case TARGET_NR_munlockall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008776 return get_errno(munlockall());
thse5febef2007-04-01 18:31:35 +00008777#endif
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008778#ifdef TARGET_NR_truncate
bellard31e31b82003-02-18 22:55:36 +00008779 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +00008780 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008781 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008782 ret = get_errno(truncate(p, arg2));
8783 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008784 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008785#endif
8786#ifdef TARGET_NR_ftruncate
bellard31e31b82003-02-18 22:55:36 +00008787 case TARGET_NR_ftruncate:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008788 return get_errno(ftruncate(arg1, arg2));
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008789#endif
bellard31e31b82003-02-18 22:55:36 +00008790 case TARGET_NR_fchmod:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008791 return get_errno(fchmod(arg1, arg2));
Peter Maydellc0d472b2013-06-12 16:20:21 +01008792#if defined(TARGET_NR_fchmodat)
ths814d7972007-09-24 09:26:51 +00008793 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +00008794 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008795 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01008796 ret = get_errno(fchmodat(arg1, p, arg3, 0));
bellard579a97f2007-11-11 14:26:47 +00008797 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008798 return ret;
ths814d7972007-09-24 09:26:51 +00008799#endif
bellard31e31b82003-02-18 22:55:36 +00008800 case TARGET_NR_getpriority:
Richard Henderson95c09822012-06-07 15:14:50 -07008801 /* Note that negative values are valid for getpriority, so we must
8802 differentiate based on errno settings. */
8803 errno = 0;
8804 ret = getpriority(arg1, arg2);
8805 if (ret == -1 && errno != 0) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008806 return -host_to_target_errno(errno);
Richard Henderson95c09822012-06-07 15:14:50 -07008807 }
8808#ifdef TARGET_ALPHA
8809 /* Return value is the unbiased priority. Signal no error. */
8810 ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0;
8811#else
8812 /* Return value is a biased priority to avoid negative numbers. */
8813 ret = 20 - ret;
8814#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008815 return ret;
bellard31e31b82003-02-18 22:55:36 +00008816 case TARGET_NR_setpriority:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008817 return get_errno(setpriority(arg1, arg2, arg3));
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008818#ifdef TARGET_NR_statfs
bellard31e31b82003-02-18 22:55:36 +00008819 case TARGET_NR_statfs:
Richard Henderson2852aaf2018-08-18 12:01:06 -07008820 if (!(p = lock_user_string(arg1))) {
8821 return -TARGET_EFAULT;
8822 }
pbrook53a59602006-03-25 19:31:22 +00008823 ret = get_errno(statfs(path(p), &stfs));
8824 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00008825 convert_statfs:
8826 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00008827 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +00008828
bellard579a97f2007-11-11 14:26:47 +00008829 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008830 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00008831 __put_user(stfs.f_type, &target_stfs->f_type);
8832 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
8833 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
8834 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
8835 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
8836 __put_user(stfs.f_files, &target_stfs->f_files);
8837 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
8838 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
8839 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
8840 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
Alexander Graf229d3372012-09-19 04:39:53 +02008841 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
Shea Levyd4247ec2018-03-01 06:15:00 -05008842#ifdef _STATFS_F_FLAGS
8843 __put_user(stfs.f_flags, &target_stfs->f_flags);
8844#else
8845 __put_user(0, &target_stfs->f_flags);
8846#endif
Alexander Graf229d3372012-09-19 04:39:53 +02008847 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
pbrook53a59602006-03-25 19:31:22 +00008848 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00008849 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008850 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008851#endif
8852#ifdef TARGET_NR_fstatfs
bellard31e31b82003-02-18 22:55:36 +00008853 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +00008854 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +00008855 goto convert_statfs;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008856#endif
bellard56c8f682005-11-28 22:28:41 +00008857#ifdef TARGET_NR_statfs64
8858 case TARGET_NR_statfs64:
Richard Henderson2852aaf2018-08-18 12:01:06 -07008859 if (!(p = lock_user_string(arg1))) {
8860 return -TARGET_EFAULT;
8861 }
pbrook53a59602006-03-25 19:31:22 +00008862 ret = get_errno(statfs(path(p), &stfs));
8863 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +00008864 convert_statfs64:
8865 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00008866 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +00008867
bellard579a97f2007-11-11 14:26:47 +00008868 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008869 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00008870 __put_user(stfs.f_type, &target_stfs->f_type);
8871 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
8872 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
8873 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
8874 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
8875 __put_user(stfs.f_files, &target_stfs->f_files);
8876 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
8877 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
8878 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
8879 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
Alexander Graf229d3372012-09-19 04:39:53 +02008880 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
8881 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
bellard579a97f2007-11-11 14:26:47 +00008882 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +00008883 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008884 return ret;
bellard56c8f682005-11-28 22:28:41 +00008885 case TARGET_NR_fstatfs64:
8886 ret = get_errno(fstatfs(arg1, &stfs));
8887 goto convert_statfs64;
8888#endif
thse5febef2007-04-01 18:31:35 +00008889#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +00008890 case TARGET_NR_socketcall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008891 return do_socketcall(arg1, arg2);
thse5febef2007-04-01 18:31:35 +00008892#endif
bellard3532fa72006-06-24 15:06:03 +00008893#ifdef TARGET_NR_accept
8894 case TARGET_NR_accept:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008895 return do_accept4(arg1, arg2, arg3, 0);
Peter Maydella94b4982013-02-08 04:35:04 +00008896#endif
8897#ifdef TARGET_NR_accept4
8898 case TARGET_NR_accept4:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008899 return do_accept4(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00008900#endif
8901#ifdef TARGET_NR_bind
8902 case TARGET_NR_bind:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008903 return do_bind(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00008904#endif
8905#ifdef TARGET_NR_connect
8906 case TARGET_NR_connect:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008907 return do_connect(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00008908#endif
8909#ifdef TARGET_NR_getpeername
8910 case TARGET_NR_getpeername:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008911 return do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00008912#endif
8913#ifdef TARGET_NR_getsockname
8914 case TARGET_NR_getsockname:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008915 return do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00008916#endif
8917#ifdef TARGET_NR_getsockopt
8918 case TARGET_NR_getsockopt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008919 return do_getsockopt(arg1, arg2, arg3, arg4, arg5);
bellard3532fa72006-06-24 15:06:03 +00008920#endif
8921#ifdef TARGET_NR_listen
8922 case TARGET_NR_listen:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008923 return get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00008924#endif
8925#ifdef TARGET_NR_recv
8926 case TARGET_NR_recv:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008927 return do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00008928#endif
8929#ifdef TARGET_NR_recvfrom
8930 case TARGET_NR_recvfrom:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008931 return do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00008932#endif
8933#ifdef TARGET_NR_recvmsg
8934 case TARGET_NR_recvmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008935 return do_sendrecvmsg(arg1, arg2, arg3, 0);
bellard3532fa72006-06-24 15:06:03 +00008936#endif
8937#ifdef TARGET_NR_send
8938 case TARGET_NR_send:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008939 return do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00008940#endif
8941#ifdef TARGET_NR_sendmsg
8942 case TARGET_NR_sendmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008943 return do_sendrecvmsg(arg1, arg2, arg3, 1);
bellard3532fa72006-06-24 15:06:03 +00008944#endif
Alexander Graff19e00d2014-03-02 19:36:42 +00008945#ifdef TARGET_NR_sendmmsg
8946 case TARGET_NR_sendmmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008947 return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1);
Alexander Graff19e00d2014-03-02 19:36:42 +00008948 case TARGET_NR_recvmmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008949 return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0);
Alexander Graff19e00d2014-03-02 19:36:42 +00008950#endif
bellard3532fa72006-06-24 15:06:03 +00008951#ifdef TARGET_NR_sendto
8952 case TARGET_NR_sendto:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008953 return do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00008954#endif
8955#ifdef TARGET_NR_shutdown
8956 case TARGET_NR_shutdown:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008957 return get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00008958#endif
Laurent Vivierf894efd2016-02-21 10:56:23 +01008959#if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
8960 case TARGET_NR_getrandom:
8961 p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
8962 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008963 return -TARGET_EFAULT;
Laurent Vivierf894efd2016-02-21 10:56:23 +01008964 }
8965 ret = get_errno(getrandom(p, arg2, arg3));
8966 unlock_user(p, arg1, ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008967 return ret;
Laurent Vivierf894efd2016-02-21 10:56:23 +01008968#endif
bellard3532fa72006-06-24 15:06:03 +00008969#ifdef TARGET_NR_socket
8970 case TARGET_NR_socket:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008971 return do_socket(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00008972#endif
8973#ifdef TARGET_NR_socketpair
8974 case TARGET_NR_socketpair:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008975 return do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00008976#endif
8977#ifdef TARGET_NR_setsockopt
8978 case TARGET_NR_setsockopt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008979 return do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
bellard3532fa72006-06-24 15:06:03 +00008980#endif
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02008981#if defined(TARGET_NR_syslog)
bellard31e31b82003-02-18 22:55:36 +00008982 case TARGET_NR_syslog:
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02008983 {
8984 int len = arg2;
ths7494b0f2007-02-11 18:26:53 +00008985
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02008986 switch (arg1) {
8987 case TARGET_SYSLOG_ACTION_CLOSE: /* Close log */
8988 case TARGET_SYSLOG_ACTION_OPEN: /* Open log */
8989 case TARGET_SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
8990 case TARGET_SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging */
8991 case TARGET_SYSLOG_ACTION_CONSOLE_ON: /* Enable logging */
8992 case TARGET_SYSLOG_ACTION_CONSOLE_LEVEL: /* Set messages level */
8993 case TARGET_SYSLOG_ACTION_SIZE_UNREAD: /* Number of chars */
8994 case TARGET_SYSLOG_ACTION_SIZE_BUFFER: /* Size of the buffer */
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008995 return get_errno(sys_syslog((int)arg1, NULL, (int)arg3));
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02008996 case TARGET_SYSLOG_ACTION_READ: /* Read from log */
8997 case TARGET_SYSLOG_ACTION_READ_CLEAR: /* Read/clear msgs */
8998 case TARGET_SYSLOG_ACTION_READ_ALL: /* Read last messages */
8999 {
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02009000 if (len < 0) {
Richard Henderson259841c2018-08-18 12:01:09 -07009001 return -TARGET_EINVAL;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02009002 }
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02009003 if (len == 0) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009004 return 0;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02009005 }
9006 p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
9007 if (!p) {
Richard Henderson259841c2018-08-18 12:01:09 -07009008 return -TARGET_EFAULT;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02009009 }
9010 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
9011 unlock_user(p, arg2, arg3);
9012 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009013 return ret;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02009014 default:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009015 return -TARGET_EINVAL;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02009016 }
9017 }
9018 break;
9019#endif
bellard31e31b82003-02-18 22:55:36 +00009020 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +00009021 {
bellard66fb9762003-03-23 01:06:05 +00009022 struct itimerval value, ovalue, *pvalue;
9023
pbrook53a59602006-03-25 19:31:22 +00009024 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00009025 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +00009026 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
9027 || copy_from_user_timeval(&pvalue->it_value,
9028 arg2 + sizeof(struct target_timeval)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009029 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +00009030 } else {
9031 pvalue = NULL;
9032 }
9033 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +00009034 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +00009035 if (copy_to_user_timeval(arg3,
9036 &ovalue.it_interval)
9037 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
9038 &ovalue.it_value))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009039 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +00009040 }
9041 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009042 return ret;
bellard31e31b82003-02-18 22:55:36 +00009043 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +00009044 {
bellard66fb9762003-03-23 01:06:05 +00009045 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +00009046
bellard66fb9762003-03-23 01:06:05 +00009047 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +00009048 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +00009049 if (copy_to_user_timeval(arg2,
9050 &value.it_interval)
9051 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
9052 &value.it_value))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009053 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +00009054 }
9055 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009056 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009057#ifdef TARGET_NR_stat
bellard31e31b82003-02-18 22:55:36 +00009058 case TARGET_NR_stat:
Richard Henderson2852aaf2018-08-18 12:01:06 -07009059 if (!(p = lock_user_string(arg1))) {
9060 return -TARGET_EFAULT;
9061 }
pbrook53a59602006-03-25 19:31:22 +00009062 ret = get_errno(stat(path(p), &st));
9063 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00009064 goto do_stat;
Chen Gang704eff62015-08-21 05:37:33 +08009065#endif
9066#ifdef TARGET_NR_lstat
bellard31e31b82003-02-18 22:55:36 +00009067 case TARGET_NR_lstat:
Richard Henderson2852aaf2018-08-18 12:01:06 -07009068 if (!(p = lock_user_string(arg1))) {
9069 return -TARGET_EFAULT;
9070 }
pbrook53a59602006-03-25 19:31:22 +00009071 ret = get_errno(lstat(path(p), &st));
9072 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00009073 goto do_stat;
Chen Gang704eff62015-08-21 05:37:33 +08009074#endif
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009075#ifdef TARGET_NR_fstat
bellard31e31b82003-02-18 22:55:36 +00009076 case TARGET_NR_fstat:
9077 {
9078 ret = get_errno(fstat(arg1, &st));
Chen Gang704eff62015-08-21 05:37:33 +08009079#if defined(TARGET_NR_stat) || defined(TARGET_NR_lstat)
bellard31e31b82003-02-18 22:55:36 +00009080 do_stat:
Chen Gang704eff62015-08-21 05:37:33 +08009081#endif
bellard31e31b82003-02-18 22:55:36 +00009082 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00009083 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +00009084
bellard579a97f2007-11-11 14:26:47 +00009085 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009086 return -TARGET_EFAULT;
Ulrich Hecht12727912009-07-24 19:10:32 +02009087 memset(target_st, 0, sizeof(*target_st));
bellardd2fd1af2007-11-14 18:08:56 +00009088 __put_user(st.st_dev, &target_st->st_dev);
9089 __put_user(st.st_ino, &target_st->st_ino);
9090 __put_user(st.st_mode, &target_st->st_mode);
9091 __put_user(st.st_uid, &target_st->st_uid);
9092 __put_user(st.st_gid, &target_st->st_gid);
9093 __put_user(st.st_nlink, &target_st->st_nlink);
9094 __put_user(st.st_rdev, &target_st->st_rdev);
9095 __put_user(st.st_size, &target_st->st_size);
9096 __put_user(st.st_blksize, &target_st->st_blksize);
9097 __put_user(st.st_blocks, &target_st->st_blocks);
9098 __put_user(st.st_atime, &target_st->target_st_atime);
9099 __put_user(st.st_mtime, &target_st->target_st_mtime);
9100 __put_user(st.st_ctime, &target_st->target_st_ctime);
Chen-Yu Tsai5f992db2019-05-23 00:21:47 +08009101#if (_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) && \
9102 defined(TARGET_STAT_HAVE_NSEC)
9103 __put_user(st.st_atim.tv_nsec,
9104 &target_st->target_st_atime_nsec);
9105 __put_user(st.st_mtim.tv_nsec,
9106 &target_st->target_st_mtime_nsec);
9107 __put_user(st.st_ctim.tv_nsec,
9108 &target_st->target_st_ctime_nsec);
9109#endif
pbrook53a59602006-03-25 19:31:22 +00009110 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00009111 }
9112 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009113 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009114#endif
bellard31e31b82003-02-18 22:55:36 +00009115 case TARGET_NR_vhangup:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009116 return get_errno(vhangup());
bellard42ad6ae2005-01-03 22:48:11 +00009117#ifdef TARGET_NR_syscall
9118 case TARGET_NR_syscall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009119 return do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5,
9120 arg6, arg7, arg8, 0);
bellard42ad6ae2005-01-03 22:48:11 +00009121#endif
bellard31e31b82003-02-18 22:55:36 +00009122 case TARGET_NR_wait4:
9123 {
9124 int status;
blueswir1992f48a2007-10-14 16:27:31 +00009125 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +00009126 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00009127 abi_ulong target_rusage = arg4;
Petar Jovanovica39fb272014-04-08 19:24:30 +02009128 abi_long rusage_err;
bellard31e31b82003-02-18 22:55:36 +00009129 if (target_rusage)
9130 rusage_ptr = &rusage;
9131 else
9132 rusage_ptr = NULL;
Timothy E Baldwin4af80a32016-05-12 18:47:49 +01009133 ret = get_errno(safe_wait4(arg1, &status, arg3, rusage_ptr));
bellard31e31b82003-02-18 22:55:36 +00009134 if (!is_error(ret)) {
Alexander Graf53795572011-11-24 00:44:43 +01009135 if (status_ptr && ret) {
pbrook1d9d8b52009-04-16 15:17:02 +00009136 status = host_to_target_waitstatus(status);
bellard2f619692007-11-16 10:46:05 +00009137 if (put_user_s32(status, status_ptr))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009138 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00009139 }
Petar Jovanovica39fb272014-04-08 19:24:30 +02009140 if (target_rusage) {
9141 rusage_err = host_to_target_rusage(target_rusage, &rusage);
9142 if (rusage_err) {
9143 ret = rusage_err;
9144 }
9145 }
bellard31e31b82003-02-18 22:55:36 +00009146 }
9147 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009148 return ret;
thse5febef2007-04-01 18:31:35 +00009149#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +00009150 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +00009151 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009152 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009153 ret = get_errno(swapoff(p));
9154 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009155 return ret;
thse5febef2007-04-01 18:31:35 +00009156#endif
bellard31e31b82003-02-18 22:55:36 +00009157 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +00009158 {
pbrook53a59602006-03-25 19:31:22 +00009159 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +00009160 struct sysinfo value;
9161 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +00009162 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +00009163 {
bellard579a97f2007-11-11 14:26:47 +00009164 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009165 return -TARGET_EFAULT;
bellarda5448a72004-06-19 16:59:03 +00009166 __put_user(value.uptime, &target_value->uptime);
9167 __put_user(value.loads[0], &target_value->loads[0]);
9168 __put_user(value.loads[1], &target_value->loads[1]);
9169 __put_user(value.loads[2], &target_value->loads[2]);
9170 __put_user(value.totalram, &target_value->totalram);
9171 __put_user(value.freeram, &target_value->freeram);
9172 __put_user(value.sharedram, &target_value->sharedram);
9173 __put_user(value.bufferram, &target_value->bufferram);
9174 __put_user(value.totalswap, &target_value->totalswap);
9175 __put_user(value.freeswap, &target_value->freeswap);
9176 __put_user(value.procs, &target_value->procs);
9177 __put_user(value.totalhigh, &target_value->totalhigh);
9178 __put_user(value.freehigh, &target_value->freehigh);
9179 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +00009180 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +00009181 }
9182 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009183 return ret;
thse5febef2007-04-01 18:31:35 +00009184#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +00009185 case TARGET_NR_ipc:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009186 return do_ipc(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
thse5febef2007-04-01 18:31:35 +00009187#endif
aurel32e5289082009-04-18 16:16:12 +00009188#ifdef TARGET_NR_semget
9189 case TARGET_NR_semget:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009190 return get_errno(semget(arg1, arg2, arg3));
aurel32e5289082009-04-18 16:16:12 +00009191#endif
9192#ifdef TARGET_NR_semop
9193 case TARGET_NR_semop:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009194 return do_semop(arg1, arg2, arg3);
aurel32e5289082009-04-18 16:16:12 +00009195#endif
9196#ifdef TARGET_NR_semctl
9197 case TARGET_NR_semctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009198 return do_semctl(arg1, arg2, arg3, arg4);
aurel32e5289082009-04-18 16:16:12 +00009199#endif
aurel32eeb438c2008-10-13 21:08:55 +00009200#ifdef TARGET_NR_msgctl
9201 case TARGET_NR_msgctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009202 return do_msgctl(arg1, arg2, arg3);
aurel32eeb438c2008-10-13 21:08:55 +00009203#endif
9204#ifdef TARGET_NR_msgget
9205 case TARGET_NR_msgget:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009206 return get_errno(msgget(arg1, arg2));
aurel32eeb438c2008-10-13 21:08:55 +00009207#endif
9208#ifdef TARGET_NR_msgrcv
9209 case TARGET_NR_msgrcv:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009210 return do_msgrcv(arg1, arg2, arg3, arg4, arg5);
aurel32eeb438c2008-10-13 21:08:55 +00009211#endif
9212#ifdef TARGET_NR_msgsnd
9213 case TARGET_NR_msgsnd:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009214 return do_msgsnd(arg1, arg2, arg3, arg4);
aurel32eeb438c2008-10-13 21:08:55 +00009215#endif
Riku Voipio88a8c982009-04-03 10:42:00 +03009216#ifdef TARGET_NR_shmget
9217 case TARGET_NR_shmget:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009218 return get_errno(shmget(arg1, arg2, arg3));
Riku Voipio88a8c982009-04-03 10:42:00 +03009219#endif
9220#ifdef TARGET_NR_shmctl
9221 case TARGET_NR_shmctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009222 return do_shmctl(arg1, arg2, arg3);
Riku Voipio88a8c982009-04-03 10:42:00 +03009223#endif
9224#ifdef TARGET_NR_shmat
9225 case TARGET_NR_shmat:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009226 return do_shmat(cpu_env, arg1, arg2, arg3);
Riku Voipio88a8c982009-04-03 10:42:00 +03009227#endif
9228#ifdef TARGET_NR_shmdt
9229 case TARGET_NR_shmdt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009230 return do_shmdt(arg1);
Riku Voipio88a8c982009-04-03 10:42:00 +03009231#endif
bellard31e31b82003-02-18 22:55:36 +00009232 case TARGET_NR_fsync:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009233 return get_errno(fsync(arg1));
bellard31e31b82003-02-18 22:55:36 +00009234 case TARGET_NR_clone:
Peter Maydell4ce62432013-07-16 18:44:57 +01009235 /* Linux manages to have three different orderings for its
9236 * arguments to clone(); the BACKWARDS and BACKWARDS2 defines
9237 * match the kernel's CONFIG_CLONE_* settings.
9238 * Microblaze is further special in that it uses a sixth
9239 * implicit argument to clone for the TLS pointer.
9240 */
9241#if defined(TARGET_MICROBLAZE)
Edgar E. Iglesiasa5b3bdc2012-04-26 14:17:41 +02009242 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5));
Peter Maydell4ce62432013-07-16 18:44:57 +01009243#elif defined(TARGET_CLONE_BACKWARDS)
9244 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
9245#elif defined(TARGET_CLONE_BACKWARDS2)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02009246 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
aurel320b6d3ae2008-09-15 07:43:43 +00009247#else
Peter Maydell4ce62432013-07-16 18:44:57 +01009248 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
aurel320b6d3ae2008-09-15 07:43:43 +00009249#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009250 return ret;
bellardec86b0f2003-04-11 00:15:04 +00009251#ifdef __NR_exit_group
9252 /* new thread calls */
9253 case TARGET_NR_exit_group:
Alex Bennée708b6a62018-06-22 17:09:10 +01009254 preexit_cleanup(cpu_env, arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009255 return get_errno(exit_group(arg1));
bellardec86b0f2003-04-11 00:15:04 +00009256#endif
bellard31e31b82003-02-18 22:55:36 +00009257 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +00009258 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009259 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009260 ret = get_errno(setdomainname(p, arg2));
9261 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009262 return ret;
bellard31e31b82003-02-18 22:55:36 +00009263 case TARGET_NR_uname:
9264 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +00009265 {
9266 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +00009267
bellard579a97f2007-11-11 14:26:47 +00009268 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009269 return -TARGET_EFAULT;
bellard29e619b2004-09-13 21:41:04 +00009270 ret = get_errno(sys_uname(buf));
9271 if (!is_error(ret)) {
Peter Maydell332c9782016-07-12 13:02:16 +01009272 /* Overwrite the native machine name with whatever is being
bellard29e619b2004-09-13 21:41:04 +00009273 emulated. */
Philippe Mathieu-Daudé871f95c2017-07-24 15:27:47 -03009274 g_strlcpy(buf->machine, cpu_to_uname_machine(cpu_env),
9275 sizeof(buf->machine));
pbrookc5937222006-05-14 11:30:38 +00009276 /* Allow the user to override the reported release. */
Peter Maydell332c9782016-07-12 13:02:16 +01009277 if (qemu_uname_release && *qemu_uname_release) {
9278 g_strlcpy(buf->release, qemu_uname_release,
9279 sizeof(buf->release));
9280 }
bellard29e619b2004-09-13 21:41:04 +00009281 }
pbrook53a59602006-03-25 19:31:22 +00009282 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +00009283 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009284 return ret;
bellard6dbad632003-03-16 18:05:05 +00009285#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +00009286 case TARGET_NR_modify_ldt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009287 return do_modify_ldt(cpu_env, arg1, arg2, arg3);
j_mayer84409dd2007-04-06 08:56:50 +00009288#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +00009289 case TARGET_NR_vm86:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009290 return do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +00009291#endif
j_mayer84409dd2007-04-06 08:56:50 +00009292#endif
bellard31e31b82003-02-18 22:55:36 +00009293 case TARGET_NR_adjtimex:
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +02009294 {
9295 struct timex host_buf;
9296
9297 if (target_to_host_timex(&host_buf, arg1) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009298 return -TARGET_EFAULT;
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +02009299 }
9300 ret = get_errno(adjtimex(&host_buf));
9301 if (!is_error(ret)) {
9302 if (host_to_target_timex(arg1, &host_buf) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009303 return -TARGET_EFAULT;
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +02009304 }
9305 }
9306 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009307 return ret;
Aleksandar Markovic38860a02016-10-10 13:23:29 +02009308#if defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME)
9309 case TARGET_NR_clock_adjtime:
9310 {
9311 struct timex htx, *phtx = &htx;
9312
9313 if (target_to_host_timex(phtx, arg2) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009314 return -TARGET_EFAULT;
Aleksandar Markovic38860a02016-10-10 13:23:29 +02009315 }
9316 ret = get_errno(clock_adjtime(arg1, phtx));
9317 if (!is_error(ret) && phtx) {
9318 if (host_to_target_timex(arg2, phtx) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009319 return -TARGET_EFAULT;
Aleksandar Markovic38860a02016-10-10 13:23:29 +02009320 }
9321 }
9322 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009323 return ret;
Aleksandar Markovic38860a02016-10-10 13:23:29 +02009324#endif
bellard31e31b82003-02-18 22:55:36 +00009325 case TARGET_NR_getpgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009326 return get_errno(getpgid(arg1));
bellard31e31b82003-02-18 22:55:36 +00009327 case TARGET_NR_fchdir:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009328 return get_errno(fchdir(arg1));
bellard31e31b82003-02-18 22:55:36 +00009329 case TARGET_NR_personality:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009330 return get_errno(personality(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +00009331#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009332 case TARGET_NR__llseek:
9333 {
9334 int64_t res;
Peter Maydell0c1592d2011-02-22 13:02:26 +00009335#if !defined(__NR_llseek)
Peter Maydell9fea2732016-08-11 18:59:39 +01009336 res = lseek(arg1, ((uint64_t)arg2 << 32) | (abi_ulong)arg3, arg5);
Peter Maydell0c1592d2011-02-22 13:02:26 +00009337 if (res == -1) {
9338 ret = get_errno(res);
9339 } else {
9340 ret = 0;
9341 }
9342#else
bellard31e31b82003-02-18 22:55:36 +00009343 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard4f2ac232004-04-26 19:44:02 +00009344#endif
Peter Maydell0c1592d2011-02-22 13:02:26 +00009345 if ((ret == 0) && put_user_s64(res, arg4)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009346 return -TARGET_EFAULT;
Peter Maydell0c1592d2011-02-22 13:02:26 +00009347 }
bellard31e31b82003-02-18 22:55:36 +00009348 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009349 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00009350#endif
Chen Gang704eff62015-08-21 05:37:33 +08009351#ifdef TARGET_NR_getdents
bellard31e31b82003-02-18 22:55:36 +00009352 case TARGET_NR_getdents:
Peter Maydell2b3f64c2018-04-19 13:57:40 +01009353#ifdef EMULATE_GETDENTS_WITH_GETDENTS
Ulrich Hechtd83c8732009-07-24 19:10:28 +02009354#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
bellard4add45b2003-06-05 01:52:59 +00009355 {
pbrook53a59602006-03-25 19:31:22 +00009356 struct target_dirent *target_dirp;
aurel326556a832008-10-13 21:08:17 +00009357 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00009358 abi_long count = arg3;
bellard4add45b2003-06-05 01:52:59 +00009359
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05309360 dirp = g_try_malloc(count);
9361 if (!dirp) {
Richard Henderson259841c2018-08-18 12:01:09 -07009362 return -TARGET_ENOMEM;
ths0da46a62007-10-20 20:23:07 +00009363 }
ths3b46e622007-09-17 08:09:54 +00009364
bellard4add45b2003-06-05 01:52:59 +00009365 ret = get_errno(sys_getdents(arg1, dirp, count));
9366 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00009367 struct linux_dirent *de;
bellard4add45b2003-06-05 01:52:59 +00009368 struct target_dirent *tde;
9369 int len = ret;
9370 int reclen, treclen;
9371 int count1, tnamelen;
9372
9373 count1 = 0;
9374 de = dirp;
bellard579a97f2007-11-11 14:26:47 +00009375 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009376 return -TARGET_EFAULT;
bellard4add45b2003-06-05 01:52:59 +00009377 tde = target_dirp;
9378 while (len > 0) {
9379 reclen = de->d_reclen;
Dmitry V. Levin333858b2012-08-21 02:13:12 +04009380 tnamelen = reclen - offsetof(struct linux_dirent, d_name);
9381 assert(tnamelen >= 0);
9382 treclen = tnamelen + offsetof(struct target_dirent, d_name);
9383 assert(count1 + treclen <= count);
bellard4add45b2003-06-05 01:52:59 +00009384 tde->d_reclen = tswap16(treclen);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02009385 tde->d_ino = tswapal(de->d_ino);
9386 tde->d_off = tswapal(de->d_off);
Dmitry V. Levin333858b2012-08-21 02:13:12 +04009387 memcpy(tde->d_name, de->d_name, tnamelen);
aurel326556a832008-10-13 21:08:17 +00009388 de = (struct linux_dirent *)((char *)de + reclen);
bellard4add45b2003-06-05 01:52:59 +00009389 len -= reclen;
j_mayer1c5bf3b2007-04-14 12:17:59 +00009390 tde = (struct target_dirent *)((char *)tde + treclen);
bellard4add45b2003-06-05 01:52:59 +00009391 count1 += treclen;
9392 }
9393 ret = count1;
bellard579a97f2007-11-11 14:26:47 +00009394 unlock_user(target_dirp, arg2, ret);
bellard4add45b2003-06-05 01:52:59 +00009395 }
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05309396 g_free(dirp);
bellard4add45b2003-06-05 01:52:59 +00009397 }
9398#else
bellard31e31b82003-02-18 22:55:36 +00009399 {
aurel326556a832008-10-13 21:08:17 +00009400 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00009401 abi_long count = arg3;
bellarddab2ed92003-03-22 15:23:14 +00009402
bellard579a97f2007-11-11 14:26:47 +00009403 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009404 return -TARGET_EFAULT;
bellard72f03902003-02-18 23:33:18 +00009405 ret = get_errno(sys_getdents(arg1, dirp, count));
bellard31e31b82003-02-18 22:55:36 +00009406 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00009407 struct linux_dirent *de;
bellard31e31b82003-02-18 22:55:36 +00009408 int len = ret;
9409 int reclen;
9410 de = dirp;
9411 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00009412 reclen = de->d_reclen;
bellard31e31b82003-02-18 22:55:36 +00009413 if (reclen > len)
9414 break;
bellard8083a3e2003-03-24 23:12:16 +00009415 de->d_reclen = tswap16(reclen);
bellard31e31b82003-02-18 22:55:36 +00009416 tswapls(&de->d_ino);
9417 tswapls(&de->d_off);
aurel326556a832008-10-13 21:08:17 +00009418 de = (struct linux_dirent *)((char *)de + reclen);
bellard31e31b82003-02-18 22:55:36 +00009419 len -= reclen;
9420 }
9421 }
pbrook53a59602006-03-25 19:31:22 +00009422 unlock_user(dirp, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00009423 }
bellard4add45b2003-06-05 01:52:59 +00009424#endif
Peter Maydell3307e232013-06-12 16:20:21 +01009425#else
9426 /* Implement getdents in terms of getdents64 */
9427 {
9428 struct linux_dirent64 *dirp;
9429 abi_long count = arg3;
9430
9431 dirp = lock_user(VERIFY_WRITE, arg2, count, 0);
9432 if (!dirp) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009433 return -TARGET_EFAULT;
Peter Maydell3307e232013-06-12 16:20:21 +01009434 }
9435 ret = get_errno(sys_getdents64(arg1, dirp, count));
9436 if (!is_error(ret)) {
9437 /* Convert the dirent64 structs to target dirent. We do this
9438 * in-place, since we can guarantee that a target_dirent is no
9439 * larger than a dirent64; however this means we have to be
9440 * careful to read everything before writing in the new format.
9441 */
9442 struct linux_dirent64 *de;
9443 struct target_dirent *tde;
9444 int len = ret;
9445 int tlen = 0;
9446
9447 de = dirp;
9448 tde = (struct target_dirent *)dirp;
9449 while (len > 0) {
9450 int namelen, treclen;
9451 int reclen = de->d_reclen;
9452 uint64_t ino = de->d_ino;
9453 int64_t off = de->d_off;
9454 uint8_t type = de->d_type;
9455
9456 namelen = strlen(de->d_name);
9457 treclen = offsetof(struct target_dirent, d_name)
9458 + namelen + 2;
9459 treclen = QEMU_ALIGN_UP(treclen, sizeof(abi_long));
9460
9461 memmove(tde->d_name, de->d_name, namelen + 1);
9462 tde->d_ino = tswapal(ino);
9463 tde->d_off = tswapal(off);
9464 tde->d_reclen = tswap16(treclen);
9465 /* The target_dirent type is in what was formerly a padding
9466 * byte at the end of the structure:
9467 */
9468 *(((char *)tde) + treclen - 1) = type;
9469
9470 de = (struct linux_dirent64 *)((char *)de + reclen);
9471 tde = (struct target_dirent *)((char *)tde + treclen);
9472 len -= reclen;
9473 tlen += treclen;
9474 }
9475 ret = tlen;
9476 }
9477 unlock_user(dirp, arg2, ret);
9478 }
9479#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009480 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009481#endif /* TARGET_NR_getdents */
ths3ae43202007-09-16 21:39:48 +00009482#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +00009483 case TARGET_NR_getdents64:
9484 {
aurel326556a832008-10-13 21:08:17 +00009485 struct linux_dirent64 *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00009486 abi_long count = arg3;
bellard579a97f2007-11-11 14:26:47 +00009487 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009488 return -TARGET_EFAULT;
bellarddab2ed92003-03-22 15:23:14 +00009489 ret = get_errno(sys_getdents64(arg1, dirp, count));
9490 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00009491 struct linux_dirent64 *de;
bellarddab2ed92003-03-22 15:23:14 +00009492 int len = ret;
9493 int reclen;
9494 de = dirp;
9495 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00009496 reclen = de->d_reclen;
bellarddab2ed92003-03-22 15:23:14 +00009497 if (reclen > len)
9498 break;
bellard8083a3e2003-03-24 23:12:16 +00009499 de->d_reclen = tswap16(reclen);
bellard8582a532007-11-11 23:11:36 +00009500 tswap64s((uint64_t *)&de->d_ino);
9501 tswap64s((uint64_t *)&de->d_off);
aurel326556a832008-10-13 21:08:17 +00009502 de = (struct linux_dirent64 *)((char *)de + reclen);
bellarddab2ed92003-03-22 15:23:14 +00009503 len -= reclen;
9504 }
9505 }
pbrook53a59602006-03-25 19:31:22 +00009506 unlock_user(dirp, arg2, ret);
bellarddab2ed92003-03-22 15:23:14 +00009507 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009508 return ret;
bellarda541f292004-04-12 20:39:29 +00009509#endif /* TARGET_NR_getdents64 */
Laurent Vivier9468a5d2013-01-10 22:30:50 +01009510#if defined(TARGET_NR__newselect)
bellard31e31b82003-02-18 22:55:36 +00009511 case TARGET_NR__newselect:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009512 return do_select(arg1, arg2, arg3, arg4, arg5);
thse5febef2007-04-01 18:31:35 +00009513#endif
Mike Frysingerd8035d42011-02-07 01:05:51 -05009514#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll)
9515# ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +00009516 case TARGET_NR_poll:
Mike Frysingerd8035d42011-02-07 01:05:51 -05009517# endif
9518# ifdef TARGET_NR_ppoll
9519 case TARGET_NR_ppoll:
9520# endif
bellard9de5e442003-03-23 16:49:39 +00009521 {
pbrook53a59602006-03-25 19:31:22 +00009522 struct target_pollfd *target_pfd;
bellard9de5e442003-03-23 16:49:39 +00009523 unsigned int nfds = arg2;
bellard9de5e442003-03-23 16:49:39 +00009524 struct pollfd *pfd;
bellard7854b052003-03-29 17:22:23 +00009525 unsigned int i;
bellard9de5e442003-03-23 16:49:39 +00009526
Laurent Vivier3e24bb32015-10-06 01:20:48 +02009527 pfd = NULL;
9528 target_pfd = NULL;
9529 if (nfds) {
Peter Maydellce9c1392016-07-18 16:30:36 +01009530 if (nfds > (INT_MAX / sizeof(struct target_pollfd))) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009531 return -TARGET_EINVAL;
Peter Maydellce9c1392016-07-18 16:30:36 +01009532 }
9533
Laurent Vivier3e24bb32015-10-06 01:20:48 +02009534 target_pfd = lock_user(VERIFY_WRITE, arg1,
9535 sizeof(struct target_pollfd) * nfds, 1);
9536 if (!target_pfd) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009537 return -TARGET_EFAULT;
Laurent Vivier3e24bb32015-10-06 01:20:48 +02009538 }
Mike Frysingerd8035d42011-02-07 01:05:51 -05009539
Laurent Vivier3e24bb32015-10-06 01:20:48 +02009540 pfd = alloca(sizeof(struct pollfd) * nfds);
9541 for (i = 0; i < nfds; i++) {
9542 pfd[i].fd = tswap32(target_pfd[i].fd);
9543 pfd[i].events = tswap16(target_pfd[i].events);
9544 }
bellard9de5e442003-03-23 16:49:39 +00009545 }
Mike Frysingerd8035d42011-02-07 01:05:51 -05009546
Peter Maydella6130232016-06-06 19:58:10 +01009547 switch (num) {
Mike Frysingerd8035d42011-02-07 01:05:51 -05009548# ifdef TARGET_NR_ppoll
Peter Maydella6130232016-06-06 19:58:10 +01009549 case TARGET_NR_ppoll:
9550 {
Mike Frysingerd8035d42011-02-07 01:05:51 -05009551 struct timespec _timeout_ts, *timeout_ts = &_timeout_ts;
9552 target_sigset_t *target_set;
9553 sigset_t _set, *set = &_set;
9554
9555 if (arg3) {
9556 if (target_to_host_timespec(timeout_ts, arg3)) {
9557 unlock_user(target_pfd, arg1, 0);
Richard Henderson2852aaf2018-08-18 12:01:06 -07009558 return -TARGET_EFAULT;
Mike Frysingerd8035d42011-02-07 01:05:51 -05009559 }
9560 } else {
9561 timeout_ts = NULL;
9562 }
9563
9564 if (arg4) {
Peter Maydellc8157012016-06-30 14:23:24 +01009565 if (arg5 != sizeof(target_sigset_t)) {
9566 unlock_user(target_pfd, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009567 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01009568 }
9569
Mike Frysingerd8035d42011-02-07 01:05:51 -05009570 target_set = lock_user(VERIFY_READ, arg4, sizeof(target_sigset_t), 1);
9571 if (!target_set) {
9572 unlock_user(target_pfd, arg1, 0);
Richard Henderson2852aaf2018-08-18 12:01:06 -07009573 return -TARGET_EFAULT;
Mike Frysingerd8035d42011-02-07 01:05:51 -05009574 }
9575 target_to_host_sigset(set, target_set);
9576 } else {
9577 set = NULL;
9578 }
9579
Peter Maydella6130232016-06-06 19:58:10 +01009580 ret = get_errno(safe_ppoll(pfd, nfds, timeout_ts,
9581 set, SIGSET_T_SIZE));
Mike Frysingerd8035d42011-02-07 01:05:51 -05009582
9583 if (!is_error(ret) && arg3) {
9584 host_to_target_timespec(arg3, timeout_ts);
9585 }
9586 if (arg4) {
9587 unlock_user(target_set, arg4, 0);
9588 }
Peter Maydella6130232016-06-06 19:58:10 +01009589 break;
9590 }
Mike Frysingerd8035d42011-02-07 01:05:51 -05009591# endif
Peter Maydella6130232016-06-06 19:58:10 +01009592# ifdef TARGET_NR_poll
9593 case TARGET_NR_poll:
9594 {
9595 struct timespec ts, *pts;
9596
9597 if (arg3 >= 0) {
9598 /* Convert ms to secs, ns */
9599 ts.tv_sec = arg3 / 1000;
9600 ts.tv_nsec = (arg3 % 1000) * 1000000LL;
9601 pts = &ts;
9602 } else {
9603 /* -ve poll() timeout means "infinite" */
9604 pts = NULL;
9605 }
9606 ret = get_errno(safe_ppoll(pfd, nfds, pts, NULL, 0));
9607 break;
9608 }
9609# endif
9610 default:
9611 g_assert_not_reached();
9612 }
Mike Frysingerd8035d42011-02-07 01:05:51 -05009613
bellard9de5e442003-03-23 16:49:39 +00009614 if (!is_error(ret)) {
9615 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00009616 target_pfd[i].revents = tswap16(pfd[i].revents);
bellard9de5e442003-03-23 16:49:39 +00009617 }
9618 }
Peter Maydell30cb4cd2011-02-25 10:27:40 +00009619 unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds);
bellard9de5e442003-03-23 16:49:39 +00009620 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009621 return ret;
thse5febef2007-04-01 18:31:35 +00009622#endif
bellard31e31b82003-02-18 22:55:36 +00009623 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +00009624 /* NOTE: the flock constant seems to be the same for every
9625 Linux platform */
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009626 return get_errno(safe_flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00009627 case TARGET_NR_readv:
9628 {
Richard Hendersonf287b2c2012-09-15 13:20:25 -07009629 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
9630 if (vec != NULL) {
Peter Maydell918c03e2016-06-06 19:58:02 +01009631 ret = get_errno(safe_readv(arg1, vec, arg3));
Richard Hendersonf287b2c2012-09-15 13:20:25 -07009632 unlock_iovec(vec, arg2, arg3, 1);
9633 } else {
9634 ret = -host_to_target_errno(errno);
9635 }
bellard31e31b82003-02-18 22:55:36 +00009636 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009637 return ret;
bellard31e31b82003-02-18 22:55:36 +00009638 case TARGET_NR_writev:
9639 {
Richard Hendersonf287b2c2012-09-15 13:20:25 -07009640 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
9641 if (vec != NULL) {
Peter Maydell918c03e2016-06-06 19:58:02 +01009642 ret = get_errno(safe_writev(arg1, vec, arg3));
Richard Hendersonf287b2c2012-09-15 13:20:25 -07009643 unlock_iovec(vec, arg2, arg3, 0);
9644 } else {
9645 ret = -host_to_target_errno(errno);
9646 }
bellard31e31b82003-02-18 22:55:36 +00009647 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009648 return ret;
Dejan Jovicevic0f263862016-10-11 11:52:46 +02009649#if defined(TARGET_NR_preadv)
9650 case TARGET_NR_preadv:
9651 {
9652 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
9653 if (vec != NULL) {
Max Filippov9ac22512018-04-04 17:30:41 -07009654 unsigned long low, high;
9655
9656 target_to_host_low_high(arg4, arg5, &low, &high);
9657 ret = get_errno(safe_preadv(arg1, vec, arg3, low, high));
Dejan Jovicevic0f263862016-10-11 11:52:46 +02009658 unlock_iovec(vec, arg2, arg3, 1);
9659 } else {
9660 ret = -host_to_target_errno(errno);
9661 }
9662 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009663 return ret;
Dejan Jovicevic0f263862016-10-11 11:52:46 +02009664#endif
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +02009665#if defined(TARGET_NR_pwritev)
9666 case TARGET_NR_pwritev:
9667 {
9668 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
9669 if (vec != NULL) {
Max Filippov9ac22512018-04-04 17:30:41 -07009670 unsigned long low, high;
9671
9672 target_to_host_low_high(arg4, arg5, &low, &high);
9673 ret = get_errno(safe_pwritev(arg1, vec, arg3, low, high));
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +02009674 unlock_iovec(vec, arg2, arg3, 0);
9675 } else {
9676 ret = -host_to_target_errno(errno);
9677 }
9678 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009679 return ret;
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +02009680#endif
bellard31e31b82003-02-18 22:55:36 +00009681 case TARGET_NR_getsid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009682 return get_errno(getsid(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +00009683#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +00009684 case TARGET_NR_fdatasync:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009685 return get_errno(fdatasync(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +00009686#endif
Chen Gang704eff62015-08-21 05:37:33 +08009687#ifdef TARGET_NR__sysctl
bellard31e31b82003-02-18 22:55:36 +00009688 case TARGET_NR__sysctl:
ths0da46a62007-10-20 20:23:07 +00009689 /* We don't implement this, but ENOTDIR is always a safe
bellard29e619b2004-09-13 21:41:04 +00009690 return value. */
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009691 return -TARGET_ENOTDIR;
Chen Gang704eff62015-08-21 05:37:33 +08009692#endif
Mike Frysinger737de1d2011-02-07 01:05:55 -05009693 case TARGET_NR_sched_getaffinity:
9694 {
9695 unsigned int mask_size;
9696 unsigned long *mask;
9697
9698 /*
9699 * sched_getaffinity needs multiples of ulong, so need to take
9700 * care of mismatches between target ulong and host ulong sizes.
9701 */
9702 if (arg2 & (sizeof(abi_ulong) - 1)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009703 return -TARGET_EINVAL;
Mike Frysinger737de1d2011-02-07 01:05:55 -05009704 }
9705 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
9706
9707 mask = alloca(mask_size);
Samuel Thibault2e0a8712018-01-09 21:16:43 +01009708 memset(mask, 0, mask_size);
Mike Frysinger737de1d2011-02-07 01:05:55 -05009709 ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
9710
9711 if (!is_error(ret)) {
Peter Maydellbe3bd282014-05-15 14:40:23 +01009712 if (ret > arg2) {
9713 /* More data returned than the caller's buffer will fit.
9714 * This only happens if sizeof(abi_long) < sizeof(long)
9715 * and the caller passed us a buffer holding an odd number
9716 * of abi_longs. If the host kernel is actually using the
9717 * extra 4 bytes then fail EINVAL; otherwise we can just
9718 * ignore them and only copy the interesting part.
9719 */
9720 int numcpus = sysconf(_SC_NPROCESSORS_CONF);
9721 if (numcpus > arg2 * 8) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009722 return -TARGET_EINVAL;
Peter Maydellbe3bd282014-05-15 14:40:23 +01009723 }
9724 ret = arg2;
9725 }
9726
Samuel Thibault5fdefcf2018-02-11 18:47:04 +01009727 if (host_to_target_cpu_mask(mask, mask_size, arg3, ret)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009728 return -TARGET_EFAULT;
Samuel Thibault5fdefcf2018-02-11 18:47:04 +01009729 }
Mike Frysinger737de1d2011-02-07 01:05:55 -05009730 }
9731 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009732 return ret;
Mike Frysinger737de1d2011-02-07 01:05:55 -05009733 case TARGET_NR_sched_setaffinity:
9734 {
9735 unsigned int mask_size;
9736 unsigned long *mask;
9737
9738 /*
9739 * sched_setaffinity needs multiples of ulong, so need to take
9740 * care of mismatches between target ulong and host ulong sizes.
9741 */
9742 if (arg2 & (sizeof(abi_ulong) - 1)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009743 return -TARGET_EINVAL;
Mike Frysinger737de1d2011-02-07 01:05:55 -05009744 }
9745 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
Mike Frysinger737de1d2011-02-07 01:05:55 -05009746 mask = alloca(mask_size);
Samuel Thibault2e0a8712018-01-09 21:16:43 +01009747
9748 ret = target_to_host_cpu_mask(mask, mask_size, arg3, arg2);
9749 if (ret) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009750 return ret;
Mike Frysinger737de1d2011-02-07 01:05:55 -05009751 }
Mike Frysinger737de1d2011-02-07 01:05:55 -05009752
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009753 return get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
Mike Frysinger737de1d2011-02-07 01:05:55 -05009754 }
Samuel Thibaultb827c3e2018-01-12 09:14:35 +01009755 case TARGET_NR_getcpu:
9756 {
9757 unsigned cpu, node;
9758 ret = get_errno(sys_getcpu(arg1 ? &cpu : NULL,
9759 arg2 ? &node : NULL,
9760 NULL));
9761 if (is_error(ret)) {
Richard Henderson259841c2018-08-18 12:01:09 -07009762 return ret;
Samuel Thibaultb827c3e2018-01-12 09:14:35 +01009763 }
9764 if (arg1 && put_user_u32(cpu, arg1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009765 return -TARGET_EFAULT;
Samuel Thibaultb827c3e2018-01-12 09:14:35 +01009766 }
9767 if (arg2 && put_user_u32(node, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009768 return -TARGET_EFAULT;
Samuel Thibaultb827c3e2018-01-12 09:14:35 +01009769 }
9770 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009771 return ret;
bellard31e31b82003-02-18 22:55:36 +00009772 case TARGET_NR_sched_setparam:
bellard5cd43932003-03-29 16:54:36 +00009773 {
pbrook53a59602006-03-25 19:31:22 +00009774 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00009775 struct sched_param schp;
pbrook53a59602006-03-25 19:31:22 +00009776
Tom Mustaa1d5c5b2014-08-12 13:53:38 -05009777 if (arg2 == 0) {
9778 return -TARGET_EINVAL;
9779 }
bellard579a97f2007-11-11 14:26:47 +00009780 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009781 return -TARGET_EFAULT;
bellard5cd43932003-03-29 16:54:36 +00009782 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00009783 unlock_user_struct(target_schp, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009784 return get_errno(sched_setparam(arg1, &schp));
bellard5cd43932003-03-29 16:54:36 +00009785 }
bellard31e31b82003-02-18 22:55:36 +00009786 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +00009787 {
pbrook53a59602006-03-25 19:31:22 +00009788 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00009789 struct sched_param schp;
Tom Mustaa1d5c5b2014-08-12 13:53:38 -05009790
9791 if (arg2 == 0) {
9792 return -TARGET_EINVAL;
9793 }
bellard5cd43932003-03-29 16:54:36 +00009794 ret = get_errno(sched_getparam(arg1, &schp));
9795 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00009796 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009797 return -TARGET_EFAULT;
bellard5cd43932003-03-29 16:54:36 +00009798 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +00009799 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +00009800 }
9801 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009802 return ret;
bellard31e31b82003-02-18 22:55:36 +00009803 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +00009804 {
pbrook53a59602006-03-25 19:31:22 +00009805 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00009806 struct sched_param schp;
Tom Mustaa1d5c5b2014-08-12 13:53:38 -05009807 if (arg3 == 0) {
9808 return -TARGET_EINVAL;
9809 }
bellard579a97f2007-11-11 14:26:47 +00009810 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009811 return -TARGET_EFAULT;
bellard5cd43932003-03-29 16:54:36 +00009812 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00009813 unlock_user_struct(target_schp, arg3, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009814 return get_errno(sched_setscheduler(arg1, arg2, &schp));
bellard5cd43932003-03-29 16:54:36 +00009815 }
bellard31e31b82003-02-18 22:55:36 +00009816 case TARGET_NR_sched_getscheduler:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009817 return get_errno(sched_getscheduler(arg1));
bellard31e31b82003-02-18 22:55:36 +00009818 case TARGET_NR_sched_yield:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009819 return get_errno(sched_yield());
bellard31e31b82003-02-18 22:55:36 +00009820 case TARGET_NR_sched_get_priority_max:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009821 return get_errno(sched_get_priority_max(arg1));
bellard31e31b82003-02-18 22:55:36 +00009822 case TARGET_NR_sched_get_priority_min:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009823 return get_errno(sched_get_priority_min(arg1));
bellard31e31b82003-02-18 22:55:36 +00009824 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +00009825 {
bellard5cd43932003-03-29 16:54:36 +00009826 struct timespec ts;
9827 ret = get_errno(sched_rr_get_interval(arg1, &ts));
9828 if (!is_error(ret)) {
Tom Mustad4290c42014-08-12 13:53:39 -05009829 ret = host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +00009830 }
9831 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009832 return ret;
bellard31e31b82003-02-18 22:55:36 +00009833 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +00009834 {
bellard1b6b0292003-03-22 17:31:38 +00009835 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +00009836 target_to_host_timespec(&req, arg1);
Peter Maydell9e518222016-06-06 19:58:09 +01009837 ret = get_errno(safe_nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +00009838 if (is_error(ret) && arg2) {
9839 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +00009840 }
9841 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009842 return ret;
bellard31e31b82003-02-18 22:55:36 +00009843 case TARGET_NR_prctl:
Peter Maydell1e6722f2012-02-03 14:48:03 +00009844 switch (arg1) {
9845 case PR_GET_PDEATHSIG:
9846 {
9847 int deathsig;
9848 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
9849 if (!is_error(ret) && arg2
9850 && put_user_ual(deathsig, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009851 return -TARGET_EFAULT;
thse5574482007-02-11 20:03:13 +00009852 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009853 return ret;
Peter Maydell1e6722f2012-02-03 14:48:03 +00009854 }
Peter Maydelldb9526b2012-02-03 14:48:03 +00009855#ifdef PR_GET_NAME
9856 case PR_GET_NAME:
9857 {
9858 void *name = lock_user(VERIFY_WRITE, arg2, 16, 1);
9859 if (!name) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009860 return -TARGET_EFAULT;
Peter Maydelldb9526b2012-02-03 14:48:03 +00009861 }
9862 ret = get_errno(prctl(arg1, (unsigned long)name,
9863 arg3, arg4, arg5));
9864 unlock_user(name, arg2, 16);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009865 return ret;
Peter Maydelldb9526b2012-02-03 14:48:03 +00009866 }
9867 case PR_SET_NAME:
9868 {
9869 void *name = lock_user(VERIFY_READ, arg2, 16, 1);
9870 if (!name) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009871 return -TARGET_EFAULT;
Peter Maydelldb9526b2012-02-03 14:48:03 +00009872 }
9873 ret = get_errno(prctl(arg1, (unsigned long)name,
9874 arg3, arg4, arg5));
9875 unlock_user(name, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009876 return ret;
Peter Maydelldb9526b2012-02-03 14:48:03 +00009877 }
9878#endif
Stefan Markovic5b702ff2018-10-12 12:57:35 +02009879#ifdef TARGET_MIPS
9880 case TARGET_PR_GET_FP_MODE:
Stefan Markovic64ea3d62018-10-26 13:17:43 +02009881 {
9882 CPUMIPSState *env = ((CPUMIPSState *)cpu_env);
9883 ret = 0;
9884 if (env->CP0_Status & (1 << CP0St_FR)) {
9885 ret |= TARGET_PR_FP_MODE_FR;
9886 }
9887 if (env->CP0_Config5 & (1 << CP0C5_FRE)) {
9888 ret |= TARGET_PR_FP_MODE_FRE;
9889 }
9890 return ret;
9891 }
Stefan Markovic5b702ff2018-10-12 12:57:35 +02009892 case TARGET_PR_SET_FP_MODE:
Stefan Markovic64ea3d62018-10-26 13:17:43 +02009893 {
9894 CPUMIPSState *env = ((CPUMIPSState *)cpu_env);
9895 bool old_fr = env->CP0_Status & (1 << CP0St_FR);
Stefan Markovic6456c512018-11-14 14:37:08 +01009896 bool old_fre = env->CP0_Config5 & (1 << CP0C5_FRE);
Stefan Markovic64ea3d62018-10-26 13:17:43 +02009897 bool new_fr = arg2 & TARGET_PR_FP_MODE_FR;
9898 bool new_fre = arg2 & TARGET_PR_FP_MODE_FRE;
9899
Stefan Markovic6456c512018-11-14 14:37:08 +01009900 const unsigned int known_bits = TARGET_PR_FP_MODE_FR |
9901 TARGET_PR_FP_MODE_FRE;
9902
9903 /* If nothing to change, return right away, successfully. */
9904 if (old_fr == new_fr && old_fre == new_fre) {
9905 return 0;
9906 }
9907 /* Check the value is valid */
9908 if (arg2 & ~known_bits) {
9909 return -TARGET_EOPNOTSUPP;
9910 }
9911 /* Setting FRE without FR is not supported. */
9912 if (new_fre && !new_fr) {
9913 return -TARGET_EOPNOTSUPP;
9914 }
Stefan Markovic64ea3d62018-10-26 13:17:43 +02009915 if (new_fr && !(env->active_fpu.fcr0 & (1 << FCR0_F64))) {
9916 /* FR1 is not supported */
9917 return -TARGET_EOPNOTSUPP;
9918 }
9919 if (!new_fr && (env->active_fpu.fcr0 & (1 << FCR0_F64))
9920 && !(env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
9921 /* cannot set FR=0 */
9922 return -TARGET_EOPNOTSUPP;
9923 }
9924 if (new_fre && !(env->active_fpu.fcr0 & (1 << FCR0_FREP))) {
9925 /* Cannot set FRE=1 */
9926 return -TARGET_EOPNOTSUPP;
9927 }
9928
9929 int i;
9930 fpr_t *fpr = env->active_fpu.fpr;
9931 for (i = 0; i < 32 ; i += 2) {
9932 if (!old_fr && new_fr) {
9933 fpr[i].w[!FP_ENDIAN_IDX] = fpr[i + 1].w[FP_ENDIAN_IDX];
9934 } else if (old_fr && !new_fr) {
9935 fpr[i + 1].w[FP_ENDIAN_IDX] = fpr[i].w[!FP_ENDIAN_IDX];
9936 }
9937 }
9938
9939 if (new_fr) {
9940 env->CP0_Status |= (1 << CP0St_FR);
9941 env->hflags |= MIPS_HFLAG_F64;
9942 } else {
9943 env->CP0_Status &= ~(1 << CP0St_FR);
Stefan Markovic6456c512018-11-14 14:37:08 +01009944 env->hflags &= ~MIPS_HFLAG_F64;
Stefan Markovic64ea3d62018-10-26 13:17:43 +02009945 }
9946 if (new_fre) {
9947 env->CP0_Config5 |= (1 << CP0C5_FRE);
9948 if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
9949 env->hflags |= MIPS_HFLAG_FRE;
9950 }
9951 } else {
9952 env->CP0_Config5 &= ~(1 << CP0C5_FRE);
Stefan Markovic6456c512018-11-14 14:37:08 +01009953 env->hflags &= ~MIPS_HFLAG_FRE;
Stefan Markovic64ea3d62018-10-26 13:17:43 +02009954 }
9955
9956 return 0;
9957 }
Stefan Markovic5b702ff2018-10-12 12:57:35 +02009958#endif /* MIPS */
Richard Henderson85fc7162018-03-09 17:09:43 +00009959#ifdef TARGET_AARCH64
9960 case TARGET_PR_SVE_SET_VL:
Richard Hendersonadf92ea2018-08-16 14:05:28 +01009961 /*
9962 * We cannot support either PR_SVE_SET_VL_ONEXEC or
9963 * PR_SVE_VL_INHERIT. Note the kernel definition
9964 * of sve_vl_valid allows for VQ=512, i.e. VL=8192,
9965 * even though the current architectural maximum is VQ=16.
9966 */
Richard Henderson85fc7162018-03-09 17:09:43 +00009967 ret = -TARGET_EINVAL;
Richard Henderson2fc0cc02019-03-22 17:41:14 -07009968 if (cpu_isar_feature(aa64_sve, env_archcpu(cpu_env))
Richard Hendersonadf92ea2018-08-16 14:05:28 +01009969 && arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
Richard Henderson85fc7162018-03-09 17:09:43 +00009970 CPUARMState *env = cpu_env;
Richard Henderson2fc0cc02019-03-22 17:41:14 -07009971 ARMCPU *cpu = env_archcpu(env);
Richard Hendersonadf92ea2018-08-16 14:05:28 +01009972 uint32_t vq, old_vq;
9973
9974 old_vq = (env->vfp.zcr_el[1] & 0xf) + 1;
9975 vq = MAX(arg2 / 16, 1);
9976 vq = MIN(vq, cpu->sve_max_vq);
Richard Henderson85fc7162018-03-09 17:09:43 +00009977
9978 if (vq < old_vq) {
9979 aarch64_sve_narrow_vq(env, vq);
9980 }
9981 env->vfp.zcr_el[1] = vq - 1;
9982 ret = vq * 16;
9983 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009984 return ret;
Richard Henderson85fc7162018-03-09 17:09:43 +00009985 case TARGET_PR_SVE_GET_VL:
9986 ret = -TARGET_EINVAL;
Richard Hendersoncd208a12018-10-24 07:50:17 +01009987 {
Richard Henderson2fc0cc02019-03-22 17:41:14 -07009988 ARMCPU *cpu = env_archcpu(cpu_env);
Richard Hendersoncd208a12018-10-24 07:50:17 +01009989 if (cpu_isar_feature(aa64_sve, cpu)) {
9990 ret = ((cpu->env.vfp.zcr_el[1] & 0xf) + 1) * 16;
9991 }
Richard Henderson85fc7162018-03-09 17:09:43 +00009992 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009993 return ret;
Richard Hendersonbff63fb2019-02-05 16:52:39 +00009994 case TARGET_PR_PAC_RESET_KEYS:
9995 {
9996 CPUARMState *env = cpu_env;
Richard Henderson2fc0cc02019-03-22 17:41:14 -07009997 ARMCPU *cpu = env_archcpu(env);
Richard Hendersonbff63fb2019-02-05 16:52:39 +00009998
9999 if (arg3 || arg4 || arg5) {
10000 return -TARGET_EINVAL;
10001 }
10002 if (cpu_isar_feature(aa64_pauth, cpu)) {
10003 int all = (TARGET_PR_PAC_APIAKEY | TARGET_PR_PAC_APIBKEY |
10004 TARGET_PR_PAC_APDAKEY | TARGET_PR_PAC_APDBKEY |
10005 TARGET_PR_PAC_APGAKEY);
Richard Henderson51977e22019-03-12 19:22:20 -070010006 int ret = 0;
10007 Error *err = NULL;
10008
Richard Hendersonbff63fb2019-02-05 16:52:39 +000010009 if (arg2 == 0) {
10010 arg2 = all;
10011 } else if (arg2 & ~all) {
10012 return -TARGET_EINVAL;
10013 }
10014 if (arg2 & TARGET_PR_PAC_APIAKEY) {
Richard Henderson108b3ba2019-03-14 17:28:32 -070010015 ret |= qemu_guest_getrandom(&env->keys.apia,
Richard Henderson51977e22019-03-12 19:22:20 -070010016 sizeof(ARMPACKey), &err);
Richard Hendersonbff63fb2019-02-05 16:52:39 +000010017 }
10018 if (arg2 & TARGET_PR_PAC_APIBKEY) {
Richard Henderson108b3ba2019-03-14 17:28:32 -070010019 ret |= qemu_guest_getrandom(&env->keys.apib,
Richard Henderson51977e22019-03-12 19:22:20 -070010020 sizeof(ARMPACKey), &err);
Richard Hendersonbff63fb2019-02-05 16:52:39 +000010021 }
10022 if (arg2 & TARGET_PR_PAC_APDAKEY) {
Richard Henderson108b3ba2019-03-14 17:28:32 -070010023 ret |= qemu_guest_getrandom(&env->keys.apda,
Richard Henderson51977e22019-03-12 19:22:20 -070010024 sizeof(ARMPACKey), &err);
Richard Hendersonbff63fb2019-02-05 16:52:39 +000010025 }
10026 if (arg2 & TARGET_PR_PAC_APDBKEY) {
Richard Henderson108b3ba2019-03-14 17:28:32 -070010027 ret |= qemu_guest_getrandom(&env->keys.apdb,
Richard Henderson51977e22019-03-12 19:22:20 -070010028 sizeof(ARMPACKey), &err);
Richard Hendersonbff63fb2019-02-05 16:52:39 +000010029 }
10030 if (arg2 & TARGET_PR_PAC_APGAKEY) {
Richard Henderson108b3ba2019-03-14 17:28:32 -070010031 ret |= qemu_guest_getrandom(&env->keys.apga,
Richard Henderson51977e22019-03-12 19:22:20 -070010032 sizeof(ARMPACKey), &err);
10033 }
10034 if (ret != 0) {
10035 /*
10036 * Some unknown failure in the crypto. The best
10037 * we can do is log it and fail the syscall.
10038 * The real syscall cannot fail this way.
10039 */
10040 qemu_log_mask(LOG_UNIMP,
10041 "PR_PAC_RESET_KEYS: Crypto failure: %s",
10042 error_get_pretty(err));
10043 error_free(err);
10044 return -TARGET_EIO;
Richard Hendersonbff63fb2019-02-05 16:52:39 +000010045 }
10046 return 0;
10047 }
10048 }
10049 return -TARGET_EINVAL;
Richard Henderson85fc7162018-03-09 17:09:43 +000010050#endif /* AARCH64 */
James Cowgilla8b154a2017-11-06 18:03:51 +000010051 case PR_GET_SECCOMP:
10052 case PR_SET_SECCOMP:
10053 /* Disable seccomp to prevent the target disabling syscalls we
10054 * need. */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010055 return -TARGET_EINVAL;
Peter Maydell1e6722f2012-02-03 14:48:03 +000010056 default:
10057 /* Most prctl options have no pointer arguments */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010058 return get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
Peter Maydell1e6722f2012-02-03 14:48:03 +000010059 }
ths39b9aae2007-02-11 18:36:44 +000010060 break;
bellardd2fd1af2007-11-14 18:08:56 +000010061#ifdef TARGET_NR_arch_prctl
10062 case TARGET_NR_arch_prctl:
10063#if defined(TARGET_I386) && !defined(TARGET_ABI32)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010064 return do_arch_prctl(cpu_env, arg1, arg2);
bellardd2fd1af2007-11-14 18:08:56 +000010065#else
Richard Henderson1a7b2b12018-08-18 12:01:08 -070010066#error unreachable
bellardd2fd1af2007-11-14 18:08:56 +000010067#endif
10068#endif
aurel32f2c7ba12008-03-28 22:32:06 +000010069#ifdef TARGET_NR_pread64
10070 case TARGET_NR_pread64:
James Clarke8bf8e9d2017-09-15 20:33:13 +010010071 if (regpairs_aligned(cpu_env, num)) {
Alexander Grafae017a52012-09-29 15:32:39 +000010072 arg4 = arg5;
10073 arg5 = arg6;
10074 }
Peter Maydell2bd3f892019-01-08 18:49:00 +000010075 if (arg2 == 0 && arg3 == 0) {
10076 /* Special-case NULL buffer and zero length, which should succeed */
10077 p = 0;
10078 } else {
10079 p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
10080 if (!p) {
10081 return -TARGET_EFAULT;
10082 }
10083 }
aurel32f2c7ba12008-03-28 22:32:06 +000010084 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
10085 unlock_user(p, arg2, ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010086 return ret;
aurel32f2c7ba12008-03-28 22:32:06 +000010087 case TARGET_NR_pwrite64:
James Clarke8bf8e9d2017-09-15 20:33:13 +010010088 if (regpairs_aligned(cpu_env, num)) {
Alexander Grafae017a52012-09-29 15:32:39 +000010089 arg4 = arg5;
10090 arg5 = arg6;
10091 }
Peter Maydell2bd3f892019-01-08 18:49:00 +000010092 if (arg2 == 0 && arg3 == 0) {
10093 /* Special-case NULL buffer and zero length, which should succeed */
10094 p = 0;
10095 } else {
10096 p = lock_user(VERIFY_READ, arg2, arg3, 1);
10097 if (!p) {
10098 return -TARGET_EFAULT;
10099 }
10100 }
aurel32f2c7ba12008-03-28 22:32:06 +000010101 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
10102 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010103 return ret;
aurel32f2c7ba12008-03-28 22:32:06 +000010104#endif
bellard31e31b82003-02-18 22:55:36 +000010105 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +000010106 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010107 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010108 ret = get_errno(sys_getcwd1(p, arg2));
10109 unlock_user(p, arg1, ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010110 return ret;
bellard31e31b82003-02-18 22:55:36 +000010111 case TARGET_NR_capget:
10112 case TARGET_NR_capset:
Peter Maydelle0eb2102014-03-17 12:15:35 +000010113 {
10114 struct target_user_cap_header *target_header;
10115 struct target_user_cap_data *target_data = NULL;
10116 struct __user_cap_header_struct header;
10117 struct __user_cap_data_struct data[2];
10118 struct __user_cap_data_struct *dataptr = NULL;
10119 int i, target_datalen;
10120 int data_items = 1;
10121
10122 if (!lock_user_struct(VERIFY_WRITE, target_header, arg1, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010123 return -TARGET_EFAULT;
Peter Maydelle0eb2102014-03-17 12:15:35 +000010124 }
10125 header.version = tswap32(target_header->version);
10126 header.pid = tswap32(target_header->pid);
10127
Peter Maydellec864872014-03-19 16:07:30 +000010128 if (header.version != _LINUX_CAPABILITY_VERSION) {
Peter Maydelle0eb2102014-03-17 12:15:35 +000010129 /* Version 2 and up takes pointer to two user_data structs */
10130 data_items = 2;
10131 }
10132
10133 target_datalen = sizeof(*target_data) * data_items;
10134
10135 if (arg2) {
10136 if (num == TARGET_NR_capget) {
10137 target_data = lock_user(VERIFY_WRITE, arg2, target_datalen, 0);
10138 } else {
10139 target_data = lock_user(VERIFY_READ, arg2, target_datalen, 1);
10140 }
10141 if (!target_data) {
10142 unlock_user_struct(target_header, arg1, 0);
Richard Henderson2852aaf2018-08-18 12:01:06 -070010143 return -TARGET_EFAULT;
Peter Maydelle0eb2102014-03-17 12:15:35 +000010144 }
10145
10146 if (num == TARGET_NR_capset) {
10147 for (i = 0; i < data_items; i++) {
10148 data[i].effective = tswap32(target_data[i].effective);
10149 data[i].permitted = tswap32(target_data[i].permitted);
10150 data[i].inheritable = tswap32(target_data[i].inheritable);
10151 }
10152 }
10153
10154 dataptr = data;
10155 }
10156
10157 if (num == TARGET_NR_capget) {
10158 ret = get_errno(capget(&header, dataptr));
10159 } else {
10160 ret = get_errno(capset(&header, dataptr));
10161 }
10162
10163 /* The kernel always updates version for both capget and capset */
10164 target_header->version = tswap32(header.version);
10165 unlock_user_struct(target_header, arg1, 1);
10166
10167 if (arg2) {
10168 if (num == TARGET_NR_capget) {
10169 for (i = 0; i < data_items; i++) {
10170 target_data[i].effective = tswap32(data[i].effective);
10171 target_data[i].permitted = tswap32(data[i].permitted);
10172 target_data[i].inheritable = tswap32(data[i].inheritable);
10173 }
10174 unlock_user(target_data, arg2, target_datalen);
10175 } else {
10176 unlock_user(target_data, arg2, 0);
10177 }
10178 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010179 return ret;
Peter Maydelle0eb2102014-03-17 12:15:35 +000010180 }
bellard31e31b82003-02-18 22:55:36 +000010181 case TARGET_NR_sigaltstack:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010182 return do_sigaltstack(arg1, arg2,
10183 get_sp_from_cpustate((CPUArchState *)cpu_env));
Peter Maydella8fd1ab2013-02-08 07:31:55 +000010184
10185#ifdef CONFIG_SENDFILE
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010186#ifdef TARGET_NR_sendfile
bellard31e31b82003-02-18 22:55:36 +000010187 case TARGET_NR_sendfile:
Peter Maydella8fd1ab2013-02-08 07:31:55 +000010188 {
10189 off_t *offp = NULL;
10190 off_t off;
10191 if (arg3) {
10192 ret = get_user_sal(off, arg3);
10193 if (is_error(ret)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010194 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000010195 }
10196 offp = &off;
10197 }
10198 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
10199 if (!is_error(ret) && arg3) {
10200 abi_long ret2 = put_user_sal(off, arg3);
10201 if (is_error(ret2)) {
10202 ret = ret2;
10203 }
10204 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010205 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000010206 }
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010207#endif
Peter Maydella8fd1ab2013-02-08 07:31:55 +000010208#ifdef TARGET_NR_sendfile64
10209 case TARGET_NR_sendfile64:
10210 {
10211 off_t *offp = NULL;
10212 off_t off;
10213 if (arg3) {
10214 ret = get_user_s64(off, arg3);
10215 if (is_error(ret)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010216 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000010217 }
10218 offp = &off;
10219 }
10220 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
10221 if (!is_error(ret) && arg3) {
10222 abi_long ret2 = put_user_s64(off, arg3);
10223 if (is_error(ret2)) {
10224 ret = ret2;
10225 }
10226 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010227 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000010228 }
10229#endif
bellardebc05482003-09-30 21:08:41 +000010230#endif
bellard048f6b42005-11-26 18:47:20 +000010231#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +000010232 case TARGET_NR_vfork:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010233 return get_errno(do_fork(cpu_env,
10234 CLONE_VFORK | CLONE_VM | TARGET_SIGCHLD,
10235 0, 0, 0, 0));
bellard048f6b42005-11-26 18:47:20 +000010236#endif
bellardebc05482003-09-30 21:08:41 +000010237#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +000010238 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +000010239 {
10240 struct rlimit rlim;
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +030010241 int resource = target_to_host_resource(arg1);
10242 ret = get_errno(getrlimit(resource, &rlim));
bellard728584b2003-04-29 20:43:36 +000010243 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +000010244 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +000010245 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010246 return -TARGET_EFAULT;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +090010247 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
10248 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +000010249 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +000010250 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010251 return ret;
bellard728584b2003-04-29 20:43:36 +000010252 }
bellardebc05482003-09-30 21:08:41 +000010253#endif
bellarda315a142005-01-30 22:59:18 +000010254#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +000010255 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +000010256 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010257 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010258 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
10259 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010260 return ret;
bellarda315a142005-01-30 22:59:18 +000010261#endif
10262#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +000010263 case TARGET_NR_ftruncate64:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010264 return target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellarda315a142005-01-30 22:59:18 +000010265#endif
10266#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +000010267 case TARGET_NR_stat64:
Richard Henderson2852aaf2018-08-18 12:01:06 -070010268 if (!(p = lock_user_string(arg1))) {
10269 return -TARGET_EFAULT;
10270 }
pbrook53a59602006-03-25 19:31:22 +000010271 ret = get_errno(stat(path(p), &st));
10272 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +000010273 if (!is_error(ret))
10274 ret = host_to_target_stat64(cpu_env, arg2, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010275 return ret;
bellarda315a142005-01-30 22:59:18 +000010276#endif
10277#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +000010278 case TARGET_NR_lstat64:
Richard Henderson2852aaf2018-08-18 12:01:06 -070010279 if (!(p = lock_user_string(arg1))) {
10280 return -TARGET_EFAULT;
10281 }
pbrook53a59602006-03-25 19:31:22 +000010282 ret = get_errno(lstat(path(p), &st));
10283 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +000010284 if (!is_error(ret))
10285 ret = host_to_target_stat64(cpu_env, arg2, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010286 return ret;
bellarda315a142005-01-30 22:59:18 +000010287#endif
10288#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +000010289 case TARGET_NR_fstat64:
balrog6a24a772008-09-20 02:23:36 +000010290 ret = get_errno(fstat(arg1, &st));
10291 if (!is_error(ret))
10292 ret = host_to_target_stat64(cpu_env, arg2, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010293 return ret;
bellardec86b0f2003-04-11 00:15:04 +000010294#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +010010295#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat))
aurel329d33b762009-04-08 23:07:05 +000010296#ifdef TARGET_NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +000010297 case TARGET_NR_fstatat64:
aurel329d33b762009-04-08 23:07:05 +000010298#endif
10299#ifdef TARGET_NR_newfstatat
10300 case TARGET_NR_newfstatat:
10301#endif
Richard Henderson2852aaf2018-08-18 12:01:06 -070010302 if (!(p = lock_user_string(arg2))) {
10303 return -TARGET_EFAULT;
10304 }
Peter Maydellc0d472b2013-06-12 16:20:21 +010010305 ret = get_errno(fstatat(arg1, path(p), &st, arg4));
Richard Henderson2852aaf2018-08-18 12:01:06 -070010306 unlock_user(p, arg2, 0);
balrog6a24a772008-09-20 02:23:36 +000010307 if (!is_error(ret))
10308 ret = host_to_target_stat64(cpu_env, arg3, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010309 return ret;
bellarda315a142005-01-30 22:59:18 +000010310#endif
Aleksandar Rikaloefa92182019-06-28 12:43:34 +020010311#if defined(TARGET_NR_statx)
10312 case TARGET_NR_statx:
10313 {
10314 struct target_statx *target_stx;
10315 int dirfd = arg1;
10316 int flags = arg3;
10317
10318 p = lock_user_string(arg2);
10319 if (p == NULL) {
10320 return -TARGET_EFAULT;
10321 }
10322#if defined(__NR_statx)
10323 {
10324 /*
10325 * It is assumed that struct statx is architecture independent.
10326 */
10327 struct target_statx host_stx;
10328 int mask = arg4;
10329
10330 ret = get_errno(sys_statx(dirfd, p, flags, mask, &host_stx));
10331 if (!is_error(ret)) {
10332 if (host_to_target_statx(&host_stx, arg5) != 0) {
10333 unlock_user(p, arg2, 0);
10334 return -TARGET_EFAULT;
10335 }
10336 }
10337
10338 if (ret != -TARGET_ENOSYS) {
10339 unlock_user(p, arg2, 0);
10340 return ret;
10341 }
10342 }
10343#endif
10344 ret = get_errno(fstatat(dirfd, path(p), &st, flags));
10345 unlock_user(p, arg2, 0);
10346
10347 if (!is_error(ret)) {
10348 if (!lock_user_struct(VERIFY_WRITE, target_stx, arg5, 0)) {
10349 return -TARGET_EFAULT;
10350 }
10351 memset(target_stx, 0, sizeof(*target_stx));
10352 __put_user(major(st.st_dev), &target_stx->stx_dev_major);
10353 __put_user(minor(st.st_dev), &target_stx->stx_dev_minor);
10354 __put_user(st.st_ino, &target_stx->stx_ino);
10355 __put_user(st.st_mode, &target_stx->stx_mode);
10356 __put_user(st.st_uid, &target_stx->stx_uid);
10357 __put_user(st.st_gid, &target_stx->stx_gid);
10358 __put_user(st.st_nlink, &target_stx->stx_nlink);
10359 __put_user(major(st.st_rdev), &target_stx->stx_rdev_major);
10360 __put_user(minor(st.st_rdev), &target_stx->stx_rdev_minor);
10361 __put_user(st.st_size, &target_stx->stx_size);
10362 __put_user(st.st_blksize, &target_stx->stx_blksize);
10363 __put_user(st.st_blocks, &target_stx->stx_blocks);
10364 __put_user(st.st_atime, &target_stx->stx_atime.tv_sec);
10365 __put_user(st.st_mtime, &target_stx->stx_mtime.tv_sec);
10366 __put_user(st.st_ctime, &target_stx->stx_ctime.tv_sec);
10367 unlock_user_struct(target_stx, arg5, 1);
10368 }
10369 }
10370 return ret;
10371#endif
Chen Gang704eff62015-08-21 05:37:33 +080010372#ifdef TARGET_NR_lchown
bellard67867302003-11-23 17:05:30 +000010373 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +000010374 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010375 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010376 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
10377 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010378 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080010379#endif
Riku Voipio0c866a72011-04-18 15:23:06 +030010380#ifdef TARGET_NR_getuid
bellard67867302003-11-23 17:05:30 +000010381 case TARGET_NR_getuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010382 return get_errno(high2lowuid(getuid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030010383#endif
10384#ifdef TARGET_NR_getgid
bellard67867302003-11-23 17:05:30 +000010385 case TARGET_NR_getgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010386 return get_errno(high2lowgid(getgid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030010387#endif
10388#ifdef TARGET_NR_geteuid
bellard67867302003-11-23 17:05:30 +000010389 case TARGET_NR_geteuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010390 return get_errno(high2lowuid(geteuid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030010391#endif
10392#ifdef TARGET_NR_getegid
bellard67867302003-11-23 17:05:30 +000010393 case TARGET_NR_getegid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010394 return get_errno(high2lowgid(getegid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030010395#endif
bellard67867302003-11-23 17:05:30 +000010396 case TARGET_NR_setreuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010397 return get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
bellard67867302003-11-23 17:05:30 +000010398 case TARGET_NR_setregid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010399 return get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
bellard67867302003-11-23 17:05:30 +000010400 case TARGET_NR_getgroups:
10401 {
10402 int gidsetsize = arg1;
Riku Voipio0c866a72011-04-18 15:23:06 +030010403 target_id *target_grouplist;
bellard67867302003-11-23 17:05:30 +000010404 gid_t *grouplist;
10405 int i;
10406
10407 grouplist = alloca(gidsetsize * sizeof(gid_t));
10408 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +000010409 if (gidsetsize == 0)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010410 return ret;
bellard67867302003-11-23 17:05:30 +000010411 if (!is_error(ret)) {
Andreas Schwab03903ff2013-04-09 05:41:33 +000010412 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * sizeof(target_id), 0);
bellard579a97f2007-11-11 14:26:47 +000010413 if (!target_grouplist)
Richard Henderson2852aaf2018-08-18 12:01:06 -070010414 return -TARGET_EFAULT;
balroga2155fc2008-09-20 02:12:08 +000010415 for(i = 0;i < ret; i++)
Riku Voipio0c866a72011-04-18 15:23:06 +030010416 target_grouplist[i] = tswapid(high2lowgid(grouplist[i]));
Andreas Schwab03903ff2013-04-09 05:41:33 +000010417 unlock_user(target_grouplist, arg2, gidsetsize * sizeof(target_id));
bellard67867302003-11-23 17:05:30 +000010418 }
10419 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010420 return ret;
bellard67867302003-11-23 17:05:30 +000010421 case TARGET_NR_setgroups:
10422 {
10423 int gidsetsize = arg1;
Riku Voipio0c866a72011-04-18 15:23:06 +030010424 target_id *target_grouplist;
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050010425 gid_t *grouplist = NULL;
bellard67867302003-11-23 17:05:30 +000010426 int i;
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050010427 if (gidsetsize) {
10428 grouplist = alloca(gidsetsize * sizeof(gid_t));
Andreas Schwab03903ff2013-04-09 05:41:33 +000010429 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * sizeof(target_id), 1);
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050010430 if (!target_grouplist) {
Richard Henderson259841c2018-08-18 12:01:09 -070010431 return -TARGET_EFAULT;
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050010432 }
10433 for (i = 0; i < gidsetsize; i++) {
10434 grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
10435 }
10436 unlock_user(target_grouplist, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +000010437 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010438 return get_errno(setgroups(gidsetsize, grouplist));
bellard67867302003-11-23 17:05:30 +000010439 }
bellard67867302003-11-23 17:05:30 +000010440 case TARGET_NR_fchown:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010441 return get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
Peter Maydellc0d472b2013-06-12 16:20:21 +010010442#if defined(TARGET_NR_fchownat)
thsccfa72b2007-09-24 09:23:34 +000010443 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +000010444 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010445 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +010010446 ret = get_errno(fchownat(arg1, p, low2highuid(arg3),
10447 low2highgid(arg4), arg5));
bellard579a97f2007-11-11 14:26:47 +000010448 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010449 return ret;
thsccfa72b2007-09-24 09:23:34 +000010450#endif
bellard67867302003-11-23 17:05:30 +000010451#ifdef TARGET_NR_setresuid
10452 case TARGET_NR_setresuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010453 return get_errno(sys_setresuid(low2highuid(arg1),
10454 low2highuid(arg2),
10455 low2highuid(arg3)));
bellard67867302003-11-23 17:05:30 +000010456#endif
10457#ifdef TARGET_NR_getresuid
10458 case TARGET_NR_getresuid:
10459 {
pbrook53a59602006-03-25 19:31:22 +000010460 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +000010461 ret = get_errno(getresuid(&ruid, &euid, &suid));
10462 if (!is_error(ret)) {
Peter Maydell76ca3102014-03-02 19:36:41 +000010463 if (put_user_id(high2lowuid(ruid), arg1)
10464 || put_user_id(high2lowuid(euid), arg2)
10465 || put_user_id(high2lowuid(suid), arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010466 return -TARGET_EFAULT;
bellard67867302003-11-23 17:05:30 +000010467 }
10468 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010469 return ret;
bellard67867302003-11-23 17:05:30 +000010470#endif
10471#ifdef TARGET_NR_getresgid
10472 case TARGET_NR_setresgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010473 return get_errno(sys_setresgid(low2highgid(arg1),
10474 low2highgid(arg2),
10475 low2highgid(arg3)));
bellard67867302003-11-23 17:05:30 +000010476#endif
10477#ifdef TARGET_NR_getresgid
10478 case TARGET_NR_getresgid:
10479 {
pbrook53a59602006-03-25 19:31:22 +000010480 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +000010481 ret = get_errno(getresgid(&rgid, &egid, &sgid));
10482 if (!is_error(ret)) {
Peter Maydell76ca3102014-03-02 19:36:41 +000010483 if (put_user_id(high2lowgid(rgid), arg1)
10484 || put_user_id(high2lowgid(egid), arg2)
10485 || put_user_id(high2lowgid(sgid), arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010486 return -TARGET_EFAULT;
bellard67867302003-11-23 17:05:30 +000010487 }
10488 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010489 return ret;
bellard67867302003-11-23 17:05:30 +000010490#endif
Chen Gang704eff62015-08-21 05:37:33 +080010491#ifdef TARGET_NR_chown
bellard67867302003-11-23 17:05:30 +000010492 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +000010493 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010494 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010495 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
10496 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010497 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080010498#endif
bellard67867302003-11-23 17:05:30 +000010499 case TARGET_NR_setuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010500 return get_errno(sys_setuid(low2highuid(arg1)));
bellard67867302003-11-23 17:05:30 +000010501 case TARGET_NR_setgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010502 return get_errno(sys_setgid(low2highgid(arg1)));
bellard67867302003-11-23 17:05:30 +000010503 case TARGET_NR_setfsuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010504 return get_errno(setfsuid(arg1));
bellard67867302003-11-23 17:05:30 +000010505 case TARGET_NR_setfsgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010506 return get_errno(setfsgid(arg1));
bellard67867302003-11-23 17:05:30 +000010507
bellarda315a142005-01-30 22:59:18 +000010508#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +000010509 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +000010510 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010511 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010512 ret = get_errno(lchown(p, arg2, arg3));
10513 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010514 return ret;
bellarda315a142005-01-30 22:59:18 +000010515#endif
10516#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +000010517 case TARGET_NR_getuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010518 return get_errno(getuid());
bellarda315a142005-01-30 22:59:18 +000010519#endif
aurel3264b4d282008-11-14 17:20:15 +000010520
10521#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
10522 /* Alpha specific */
10523 case TARGET_NR_getxuid:
Richard Hendersonba0e2762009-12-09 15:56:29 -080010524 {
10525 uid_t euid;
10526 euid=geteuid();
10527 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
10528 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010529 return get_errno(getuid());
aurel3264b4d282008-11-14 17:20:15 +000010530#endif
10531#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
10532 /* Alpha specific */
10533 case TARGET_NR_getxgid:
Richard Hendersonba0e2762009-12-09 15:56:29 -080010534 {
10535 uid_t egid;
10536 egid=getegid();
10537 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
10538 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010539 return get_errno(getgid());
aurel3264b4d282008-11-14 17:20:15 +000010540#endif
Richard Hendersonba0e2762009-12-09 15:56:29 -080010541#if defined(TARGET_NR_osf_getsysinfo) && defined(TARGET_ALPHA)
10542 /* Alpha specific */
10543 case TARGET_NR_osf_getsysinfo:
10544 ret = -TARGET_EOPNOTSUPP;
10545 switch (arg1) {
10546 case TARGET_GSI_IEEE_FP_CONTROL:
10547 {
Richard Henderson21ba8562019-04-26 15:20:51 -070010548 uint64_t fpcr = cpu_alpha_load_fpcr(cpu_env);
10549 uint64_t swcr = ((CPUAlphaState *)cpu_env)->swcr;
Richard Hendersonba0e2762009-12-09 15:56:29 -080010550
Richard Henderson21ba8562019-04-26 15:20:51 -070010551 swcr &= ~SWCR_STATUS_MASK;
10552 swcr |= (fpcr >> 35) & SWCR_STATUS_MASK;
Richard Hendersonba0e2762009-12-09 15:56:29 -080010553
10554 if (put_user_u64 (swcr, arg2))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010555 return -TARGET_EFAULT;
Richard Hendersonba0e2762009-12-09 15:56:29 -080010556 ret = 0;
10557 }
10558 break;
10559
10560 /* case GSI_IEEE_STATE_AT_SIGNAL:
10561 -- Not implemented in linux kernel.
10562 case GSI_UACPROC:
10563 -- Retrieves current unaligned access state; not much used.
10564 case GSI_PROC_TYPE:
10565 -- Retrieves implver information; surely not used.
10566 case GSI_GET_HWRPB:
10567 -- Grabs a copy of the HWRPB; surely not used.
10568 */
10569 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010570 return ret;
Richard Hendersonba0e2762009-12-09 15:56:29 -080010571#endif
10572#if defined(TARGET_NR_osf_setsysinfo) && defined(TARGET_ALPHA)
10573 /* Alpha specific */
10574 case TARGET_NR_osf_setsysinfo:
10575 ret = -TARGET_EOPNOTSUPP;
10576 switch (arg1) {
10577 case TARGET_SSI_IEEE_FP_CONTROL:
Richard Hendersonba0e2762009-12-09 15:56:29 -080010578 {
Richard Henderson21ba8562019-04-26 15:20:51 -070010579 uint64_t swcr, fpcr;
Richard Hendersonba0e2762009-12-09 15:56:29 -080010580
Richard Henderson6e06d512012-06-01 09:08:21 -070010581 if (get_user_u64 (swcr, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010582 return -TARGET_EFAULT;
Richard Henderson6e06d512012-06-01 09:08:21 -070010583 }
Richard Hendersonba0e2762009-12-09 15:56:29 -080010584
Richard Henderson21ba8562019-04-26 15:20:51 -070010585 /*
10586 * The kernel calls swcr_update_status to update the
10587 * status bits from the fpcr at every point that it
10588 * could be queried. Therefore, we store the status
10589 * bits only in FPCR.
10590 */
10591 ((CPUAlphaState *)cpu_env)->swcr
10592 = swcr & (SWCR_TRAP_ENABLE_MASK | SWCR_MAP_MASK);
Richard Hendersonba0e2762009-12-09 15:56:29 -080010593
Richard Henderson21ba8562019-04-26 15:20:51 -070010594 fpcr = cpu_alpha_load_fpcr(cpu_env);
10595 fpcr &= ((uint64_t)FPCR_DYN_MASK << 32);
10596 fpcr |= alpha_ieee_swcr_to_fpcr(swcr);
Richard Henderson6e06d512012-06-01 09:08:21 -070010597 cpu_alpha_store_fpcr(cpu_env, fpcr);
10598 ret = 0;
10599 }
10600 break;
10601
10602 case TARGET_SSI_IEEE_RAISE_EXCEPTION:
10603 {
Richard Henderson21ba8562019-04-26 15:20:51 -070010604 uint64_t exc, fpcr, fex;
Richard Henderson6e06d512012-06-01 09:08:21 -070010605
10606 if (get_user_u64(exc, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010607 return -TARGET_EFAULT;
Richard Henderson6e06d512012-06-01 09:08:21 -070010608 }
Richard Henderson21ba8562019-04-26 15:20:51 -070010609 exc &= SWCR_STATUS_MASK;
10610 fpcr = cpu_alpha_load_fpcr(cpu_env);
Richard Hendersonba0e2762009-12-09 15:56:29 -080010611
Richard Henderson6e06d512012-06-01 09:08:21 -070010612 /* Old exceptions are not signaled. */
Richard Henderson21ba8562019-04-26 15:20:51 -070010613 fex = alpha_ieee_fpcr_to_swcr(fpcr);
10614 fex = exc & ~fex;
10615 fex >>= SWCR_STATUS_TO_EXCSUM_SHIFT;
10616 fex &= ((CPUArchState *)cpu_env)->swcr;
Richard Hendersonba0e2762009-12-09 15:56:29 -080010617
Richard Henderson21ba8562019-04-26 15:20:51 -070010618 /* Update the hardware fpcr. */
10619 fpcr |= alpha_ieee_swcr_to_fpcr(exc);
10620 cpu_alpha_store_fpcr(cpu_env, fpcr);
10621
10622 if (fex) {
10623 int si_code = TARGET_FPE_FLTUNK;
Richard Henderson6e06d512012-06-01 09:08:21 -070010624 target_siginfo_t info;
Richard Henderson21ba8562019-04-26 15:20:51 -070010625
10626 if (fex & SWCR_TRAP_ENABLE_DNO) {
10627 si_code = TARGET_FPE_FLTUND;
10628 }
10629 if (fex & SWCR_TRAP_ENABLE_INE) {
10630 si_code = TARGET_FPE_FLTRES;
10631 }
10632 if (fex & SWCR_TRAP_ENABLE_UNF) {
10633 si_code = TARGET_FPE_FLTUND;
10634 }
10635 if (fex & SWCR_TRAP_ENABLE_OVF) {
10636 si_code = TARGET_FPE_FLTOVF;
10637 }
10638 if (fex & SWCR_TRAP_ENABLE_DZE) {
10639 si_code = TARGET_FPE_FLTDIV;
10640 }
10641 if (fex & SWCR_TRAP_ENABLE_INV) {
10642 si_code = TARGET_FPE_FLTINV;
10643 }
10644
Richard Henderson6e06d512012-06-01 09:08:21 -070010645 info.si_signo = SIGFPE;
10646 info.si_errno = 0;
10647 info.si_code = si_code;
10648 info._sifields._sigfault._addr
10649 = ((CPUArchState *)cpu_env)->pc;
Peter Maydell9d2803f2016-07-28 16:44:46 +010010650 queue_signal((CPUArchState *)cpu_env, info.si_signo,
10651 QEMU_SI_FAULT, &info);
Richard Hendersonba0e2762009-12-09 15:56:29 -080010652 }
Richard Henderson21ba8562019-04-26 15:20:51 -070010653 ret = 0;
Richard Hendersonba0e2762009-12-09 15:56:29 -080010654 }
10655 break;
10656
10657 /* case SSI_NVPAIRS:
10658 -- Used with SSIN_UACPROC to enable unaligned accesses.
10659 case SSI_IEEE_STATE_AT_SIGNAL:
10660 case SSI_IEEE_IGNORE_STATE_AT_SIGNAL:
10661 -- Not implemented in linux kernel
10662 */
10663 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010664 return ret;
Richard Hendersonba0e2762009-12-09 15:56:29 -080010665#endif
10666#ifdef TARGET_NR_osf_sigprocmask
10667 /* Alpha specific. */
10668 case TARGET_NR_osf_sigprocmask:
10669 {
10670 abi_ulong mask;
Juan Quintelabc088ba2011-06-16 17:37:10 +010010671 int how;
Richard Hendersonba0e2762009-12-09 15:56:29 -080010672 sigset_t set, oldset;
10673
10674 switch(arg1) {
10675 case TARGET_SIG_BLOCK:
10676 how = SIG_BLOCK;
10677 break;
10678 case TARGET_SIG_UNBLOCK:
10679 how = SIG_UNBLOCK;
10680 break;
10681 case TARGET_SIG_SETMASK:
10682 how = SIG_SETMASK;
10683 break;
10684 default:
Richard Henderson259841c2018-08-18 12:01:09 -070010685 return -TARGET_EINVAL;
Richard Hendersonba0e2762009-12-09 15:56:29 -080010686 }
10687 mask = arg2;
10688 target_to_host_old_sigset(&set, &mask);
Peter Maydell3d3efba2016-05-27 15:51:49 +010010689 ret = do_sigprocmask(how, &set, &oldset);
10690 if (!ret) {
10691 host_to_target_old_sigset(&mask, &oldset);
10692 ret = mask;
10693 }
Richard Hendersonba0e2762009-12-09 15:56:29 -080010694 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010695 return ret;
Richard Hendersonba0e2762009-12-09 15:56:29 -080010696#endif
aurel3264b4d282008-11-14 17:20:15 +000010697
bellarda315a142005-01-30 22:59:18 +000010698#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +000010699 case TARGET_NR_getgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010700 return get_errno(getgid());
bellarda315a142005-01-30 22:59:18 +000010701#endif
10702#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +000010703 case TARGET_NR_geteuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010704 return get_errno(geteuid());
bellarda315a142005-01-30 22:59:18 +000010705#endif
10706#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +000010707 case TARGET_NR_getegid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010708 return get_errno(getegid());
bellarda315a142005-01-30 22:59:18 +000010709#endif
10710#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +000010711 case TARGET_NR_setreuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010712 return get_errno(setreuid(arg1, arg2));
bellarda315a142005-01-30 22:59:18 +000010713#endif
10714#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +000010715 case TARGET_NR_setregid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010716 return get_errno(setregid(arg1, arg2));
bellarda315a142005-01-30 22:59:18 +000010717#endif
10718#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +000010719 case TARGET_NR_getgroups32:
bellard99c475a2005-01-31 20:45:13 +000010720 {
10721 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +000010722 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +000010723 gid_t *grouplist;
10724 int i;
10725
10726 grouplist = alloca(gidsetsize * sizeof(gid_t));
10727 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +000010728 if (gidsetsize == 0)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010729 return ret;
bellard99c475a2005-01-31 20:45:13 +000010730 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +000010731 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
10732 if (!target_grouplist) {
Richard Henderson259841c2018-08-18 12:01:09 -070010733 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000010734 }
balroga2155fc2008-09-20 02:12:08 +000010735 for(i = 0;i < ret; i++)
pbrook53a59602006-03-25 19:31:22 +000010736 target_grouplist[i] = tswap32(grouplist[i]);
10737 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +000010738 }
10739 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010740 return ret;
bellarda315a142005-01-30 22:59:18 +000010741#endif
10742#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +000010743 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +000010744 {
10745 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +000010746 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +000010747 gid_t *grouplist;
10748 int i;
ths3b46e622007-09-17 08:09:54 +000010749
bellard99c475a2005-01-31 20:45:13 +000010750 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +000010751 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
10752 if (!target_grouplist) {
Richard Henderson259841c2018-08-18 12:01:09 -070010753 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000010754 }
bellard99c475a2005-01-31 20:45:13 +000010755 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +000010756 grouplist[i] = tswap32(target_grouplist[i]);
10757 unlock_user(target_grouplist, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010758 return get_errno(setgroups(gidsetsize, grouplist));
bellard99c475a2005-01-31 20:45:13 +000010759 }
bellarda315a142005-01-30 22:59:18 +000010760#endif
10761#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +000010762 case TARGET_NR_fchown32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010763 return get_errno(fchown(arg1, arg2, arg3));
bellarda315a142005-01-30 22:59:18 +000010764#endif
10765#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +000010766 case TARGET_NR_setresuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010767 return get_errno(sys_setresuid(arg1, arg2, arg3));
bellarda315a142005-01-30 22:59:18 +000010768#endif
10769#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +000010770 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +000010771 {
pbrook53a59602006-03-25 19:31:22 +000010772 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +000010773 ret = get_errno(getresuid(&ruid, &euid, &suid));
10774 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +000010775 if (put_user_u32(ruid, arg1)
10776 || put_user_u32(euid, arg2)
10777 || put_user_u32(suid, arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010778 return -TARGET_EFAULT;
bellardb03c60f2003-03-23 17:19:56 +000010779 }
10780 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010781 return ret;
bellarda315a142005-01-30 22:59:18 +000010782#endif
10783#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +000010784 case TARGET_NR_setresgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010785 return get_errno(sys_setresgid(arg1, arg2, arg3));
bellarda315a142005-01-30 22:59:18 +000010786#endif
10787#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +000010788 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +000010789 {
pbrook53a59602006-03-25 19:31:22 +000010790 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +000010791 ret = get_errno(getresgid(&rgid, &egid, &sgid));
10792 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +000010793 if (put_user_u32(rgid, arg1)
10794 || put_user_u32(egid, arg2)
10795 || put_user_u32(sgid, arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010796 return -TARGET_EFAULT;
bellardb03c60f2003-03-23 17:19:56 +000010797 }
10798 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010799 return ret;
bellarda315a142005-01-30 22:59:18 +000010800#endif
10801#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +000010802 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +000010803 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010804 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010805 ret = get_errno(chown(p, arg2, arg3));
10806 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010807 return ret;
bellarda315a142005-01-30 22:59:18 +000010808#endif
10809#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +000010810 case TARGET_NR_setuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010811 return get_errno(sys_setuid(arg1));
bellarda315a142005-01-30 22:59:18 +000010812#endif
10813#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +000010814 case TARGET_NR_setgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010815 return get_errno(sys_setgid(arg1));
bellarda315a142005-01-30 22:59:18 +000010816#endif
10817#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +000010818 case TARGET_NR_setfsuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010819 return get_errno(setfsuid(arg1));
bellarda315a142005-01-30 22:59:18 +000010820#endif
10821#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +000010822 case TARGET_NR_setfsgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010823 return get_errno(setfsgid(arg1));
bellarda315a142005-01-30 22:59:18 +000010824#endif
bellardffa65c32004-01-04 23:57:22 +000010825#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +000010826 case TARGET_NR_mincore:
aurel3204bb9ac2008-10-01 21:46:41 +000010827 {
Richard Henderson259841c2018-08-18 12:01:09 -070010828 void *a = lock_user(VERIFY_READ, arg1, arg2, 0);
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000010829 if (!a) {
Richard Henderson259841c2018-08-18 12:01:09 -070010830 return -TARGET_ENOMEM;
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000010831 }
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000010832 p = lock_user_string(arg3);
10833 if (!p) {
Richard Henderson259841c2018-08-18 12:01:09 -070010834 ret = -TARGET_EFAULT;
10835 } else {
10836 ret = get_errno(mincore(a, arg2, p));
10837 unlock_user(p, arg3, ret);
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000010838 }
aurel3204bb9ac2008-10-01 21:46:41 +000010839 unlock_user(a, arg1, 0);
10840 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010841 return ret;
bellardffa65c32004-01-04 23:57:22 +000010842#endif
aurel32408321b2008-10-01 21:46:32 +000010843#ifdef TARGET_NR_arm_fadvise64_64
10844 case TARGET_NR_arm_fadvise64_64:
Peter Maydelle0156a92016-05-31 15:45:09 +010010845 /* arm_fadvise64_64 looks like fadvise64_64 but
10846 * with different argument order: fd, advice, offset, len
10847 * rather than the usual fd, offset, len, advice.
10848 * Note that offset and len are both 64-bit so appear as
10849 * pairs of 32-bit registers.
10850 */
10851 ret = posix_fadvise(arg1, target_offset64(arg3, arg4),
10852 target_offset64(arg5, arg6), arg2);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010853 return -host_to_target_errno(ret);
aurel32408321b2008-10-01 21:46:32 +000010854#endif
Peter Maydellbadd3cd2016-05-31 15:45:10 +010010855
10856#if TARGET_ABI_BITS == 32
10857
10858#ifdef TARGET_NR_fadvise64_64
10859 case TARGET_NR_fadvise64_64:
Max Filippov64a563d2018-04-01 15:02:34 -070010860#if defined(TARGET_PPC) || defined(TARGET_XTENSA)
Laurent Vivier43046b52017-03-02 01:11:45 +010010861 /* 6 args: fd, advice, offset (high, low), len (high, low) */
10862 ret = arg2;
10863 arg2 = arg3;
10864 arg3 = arg4;
10865 arg4 = arg5;
10866 arg5 = arg6;
10867 arg6 = ret;
10868#else
Peter Maydellbadd3cd2016-05-31 15:45:10 +010010869 /* 6 args: fd, offset (high, low), len (high, low), advice */
James Clarke8bf8e9d2017-09-15 20:33:13 +010010870 if (regpairs_aligned(cpu_env, num)) {
Peter Maydellbadd3cd2016-05-31 15:45:10 +010010871 /* offset is in (3,4), len in (5,6) and advice in 7 */
10872 arg2 = arg3;
10873 arg3 = arg4;
10874 arg4 = arg5;
10875 arg5 = arg6;
10876 arg6 = arg7;
10877 }
Laurent Vivier43046b52017-03-02 01:11:45 +010010878#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010879 ret = posix_fadvise(arg1, target_offset64(arg2, arg3),
10880 target_offset64(arg4, arg5), arg6);
10881 return -host_to_target_errno(ret);
Peter Maydellbadd3cd2016-05-31 15:45:10 +010010882#endif
10883
10884#ifdef TARGET_NR_fadvise64
10885 case TARGET_NR_fadvise64:
10886 /* 5 args: fd, offset (high, low), len, advice */
James Clarke8bf8e9d2017-09-15 20:33:13 +010010887 if (regpairs_aligned(cpu_env, num)) {
Peter Maydellbadd3cd2016-05-31 15:45:10 +010010888 /* offset is in (3,4), len in 5 and advice in 6 */
10889 arg2 = arg3;
10890 arg3 = arg4;
10891 arg4 = arg5;
10892 arg5 = arg6;
10893 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010894 ret = posix_fadvise(arg1, target_offset64(arg2, arg3), arg4, arg5);
10895 return -host_to_target_errno(ret);
Peter Maydellbadd3cd2016-05-31 15:45:10 +010010896#endif
10897
10898#else /* not a 32-bit ABI */
Peter Maydelle0156a92016-05-31 15:45:09 +010010899#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_fadvise64)
aurel32408321b2008-10-01 21:46:32 +000010900#ifdef TARGET_NR_fadvise64_64
10901 case TARGET_NR_fadvise64_64:
10902#endif
Ulrich Hechte72d2cc2009-07-24 19:10:31 +020010903#ifdef TARGET_NR_fadvise64
10904 case TARGET_NR_fadvise64:
10905#endif
10906#ifdef TARGET_S390X
10907 switch (arg4) {
10908 case 4: arg4 = POSIX_FADV_NOREUSE + 1; break; /* make sure it's an invalid value */
10909 case 5: arg4 = POSIX_FADV_NOREUSE + 2; break; /* ditto */
10910 case 6: arg4 = POSIX_FADV_DONTNEED; break;
10911 case 7: arg4 = POSIX_FADV_NOREUSE; break;
10912 default: break;
10913 }
10914#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010915 return -host_to_target_errno(posix_fadvise(arg1, arg2, arg3, arg4));
aurel32408321b2008-10-01 21:46:32 +000010916#endif
Peter Maydellbadd3cd2016-05-31 15:45:10 +010010917#endif /* end of 64-bit ABI fadvise handling */
10918
bellardffa65c32004-01-04 23:57:22 +000010919#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +000010920 case TARGET_NR_madvise:
pbrook24836682006-04-16 14:14:53 +000010921 /* A straight passthrough may not be safe because qemu sometimes
Lei Lid2d6b852013-05-20 17:20:50 +080010922 turns private file-backed mappings into anonymous mappings.
pbrook24836682006-04-16 14:14:53 +000010923 This will break MADV_DONTNEED.
10924 This is a hint, so ignoring and returning success is ok. */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010925 return 0;
bellardffa65c32004-01-04 23:57:22 +000010926#endif
blueswir1992f48a2007-10-14 16:27:31 +000010927#if TARGET_ABI_BITS == 32
bellard31e31b82003-02-18 22:55:36 +000010928 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +000010929 {
thsb1e341e2007-03-20 21:50:52 +000010930 int cmd;
bellard77e46722003-04-29 20:39:06 +000010931 struct flock64 fl;
Peter Maydell213d3e92016-06-13 11:22:05 +010010932 from_flock64_fn *copyfrom = copy_from_user_flock64;
10933 to_flock64_fn *copyto = copy_to_user_flock64;
10934
pbrookce4defa2006-02-09 16:49:55 +000010935#ifdef TARGET_ARM
Laurent Vivier7f254c52018-05-02 23:57:30 +020010936 if (!((CPUARMState *)cpu_env)->eabi) {
10937 copyfrom = copy_from_user_oabi_flock64;
10938 copyto = copy_to_user_oabi_flock64;
Peter Maydell213d3e92016-06-13 11:22:05 +010010939 }
pbrookce4defa2006-02-09 16:49:55 +000010940#endif
bellard77e46722003-04-29 20:39:06 +000010941
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +020010942 cmd = target_to_host_fcntl_cmd(arg2);
Peter Maydell31b63192011-12-05 23:11:50 +000010943 if (cmd == -TARGET_EINVAL) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010944 return cmd;
Peter Maydell31b63192011-12-05 23:11:50 +000010945 }
thsb1e341e2007-03-20 21:50:52 +000010946
bellard60cd49d2003-03-16 22:53:56 +000010947 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +000010948 case TARGET_F_GETLK64:
Peter Maydell213d3e92016-06-13 11:22:05 +010010949 ret = copyfrom(&fl, arg3);
10950 if (ret) {
10951 break;
ths58134272007-03-31 18:59:32 +000010952 }
Laurent Vivieraf8ab2b2018-07-13 14:58:05 +020010953 ret = get_errno(safe_fcntl(arg1, cmd, &fl));
Peter Maydell213d3e92016-06-13 11:22:05 +010010954 if (ret == 0) {
10955 ret = copyto(arg3, &fl);
10956 }
bellard77e46722003-04-29 20:39:06 +000010957 break;
10958
thsb1e341e2007-03-20 21:50:52 +000010959 case TARGET_F_SETLK64:
10960 case TARGET_F_SETLKW64:
Peter Maydell213d3e92016-06-13 11:22:05 +010010961 ret = copyfrom(&fl, arg3);
10962 if (ret) {
10963 break;
pbrookce4defa2006-02-09 16:49:55 +000010964 }
Peter Maydell435da5e2016-06-13 11:22:05 +010010965 ret = get_errno(safe_fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +000010966 break;
bellard60cd49d2003-03-16 22:53:56 +000010967 default:
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +020010968 ret = do_fcntl(arg1, arg2, arg3);
bellard60cd49d2003-03-16 22:53:56 +000010969 break;
10970 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010971 return ret;
bellard77e46722003-04-29 20:39:06 +000010972 }
bellard60cd49d2003-03-16 22:53:56 +000010973#endif
ths7d600c82006-12-08 01:32:58 +000010974#ifdef TARGET_NR_cacheflush
10975 case TARGET_NR_cacheflush:
10976 /* self-modifying code is handled automatically, so nothing needed */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010977 return 0;
ths7d600c82006-12-08 01:32:58 +000010978#endif
bellardc573ff62004-01-04 15:51:36 +000010979#ifdef TARGET_NR_getpagesize
10980 case TARGET_NR_getpagesize:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010981 return TARGET_PAGE_SIZE;
bellardc573ff62004-01-04 15:51:36 +000010982#endif
bellard31e31b82003-02-18 22:55:36 +000010983 case TARGET_NR_gettid:
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +000010984 return get_errno(sys_gettid());
thse5febef2007-04-01 18:31:35 +000010985#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +000010986 case TARGET_NR_readahead:
aurel322054ac92008-10-13 21:08:07 +000010987#if TARGET_ABI_BITS == 32
James Clarke8bf8e9d2017-09-15 20:33:13 +010010988 if (regpairs_aligned(cpu_env, num)) {
aurel322054ac92008-10-13 21:08:07 +000010989 arg2 = arg3;
10990 arg3 = arg4;
10991 arg4 = arg5;
10992 }
Lena Djokic77c68502016-11-24 17:08:56 +010010993 ret = get_errno(readahead(arg1, target_offset64(arg2, arg3) , arg4));
aurel322054ac92008-10-13 21:08:07 +000010994#else
10995 ret = get_errno(readahead(arg1, arg2, arg3));
10996#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010997 return ret;
thse5febef2007-04-01 18:31:35 +000010998#endif
An-Cheng Huanga790ae32011-08-09 12:34:06 -070010999#ifdef CONFIG_ATTR
bellardebc05482003-09-30 21:08:41 +000011000#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +000011001 case TARGET_NR_listxattr:
11002 case TARGET_NR_llistxattr:
Peter Maydellfb5590f2011-12-14 15:37:19 +000011003 {
11004 void *p, *b = 0;
11005 if (arg2) {
11006 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
11007 if (!b) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011008 return -TARGET_EFAULT;
Peter Maydellfb5590f2011-12-14 15:37:19 +000011009 }
11010 }
11011 p = lock_user_string(arg1);
11012 if (p) {
11013 if (num == TARGET_NR_listxattr) {
11014 ret = get_errno(listxattr(p, b, arg3));
11015 } else {
11016 ret = get_errno(llistxattr(p, b, arg3));
11017 }
11018 } else {
11019 ret = -TARGET_EFAULT;
11020 }
11021 unlock_user(p, arg1, 0);
11022 unlock_user(b, arg2, arg3);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011023 return ret;
Peter Maydellfb5590f2011-12-14 15:37:19 +000011024 }
11025 case TARGET_NR_flistxattr:
11026 {
11027 void *b = 0;
11028 if (arg2) {
11029 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
11030 if (!b) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011031 return -TARGET_EFAULT;
Peter Maydellfb5590f2011-12-14 15:37:19 +000011032 }
11033 }
11034 ret = get_errno(flistxattr(arg1, b, arg3));
11035 unlock_user(b, arg2, arg3);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011036 return ret;
Peter Maydellfb5590f2011-12-14 15:37:19 +000011037 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070011038 case TARGET_NR_setxattr:
Peter Maydell30297b52011-12-14 15:37:18 +000011039 case TARGET_NR_lsetxattr:
An-Cheng Huanga790ae32011-08-09 12:34:06 -070011040 {
Peter Maydelle3c33ec2011-12-14 15:37:17 +000011041 void *p, *n, *v = 0;
11042 if (arg3) {
11043 v = lock_user(VERIFY_READ, arg3, arg4, 1);
11044 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011045 return -TARGET_EFAULT;
Peter Maydelle3c33ec2011-12-14 15:37:17 +000011046 }
11047 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070011048 p = lock_user_string(arg1);
11049 n = lock_user_string(arg2);
Peter Maydelle3c33ec2011-12-14 15:37:17 +000011050 if (p && n) {
Peter Maydell30297b52011-12-14 15:37:18 +000011051 if (num == TARGET_NR_setxattr) {
11052 ret = get_errno(setxattr(p, n, v, arg4, arg5));
11053 } else {
11054 ret = get_errno(lsetxattr(p, n, v, arg4, arg5));
11055 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070011056 } else {
11057 ret = -TARGET_EFAULT;
11058 }
11059 unlock_user(p, arg1, 0);
11060 unlock_user(n, arg2, 0);
11061 unlock_user(v, arg3, 0);
11062 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011063 return ret;
Peter Maydell30297b52011-12-14 15:37:18 +000011064 case TARGET_NR_fsetxattr:
11065 {
11066 void *n, *v = 0;
11067 if (arg3) {
11068 v = lock_user(VERIFY_READ, arg3, arg4, 1);
11069 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011070 return -TARGET_EFAULT;
Peter Maydell30297b52011-12-14 15:37:18 +000011071 }
11072 }
11073 n = lock_user_string(arg2);
11074 if (n) {
11075 ret = get_errno(fsetxattr(arg1, n, v, arg4, arg5));
11076 } else {
11077 ret = -TARGET_EFAULT;
11078 }
11079 unlock_user(n, arg2, 0);
11080 unlock_user(v, arg3, 0);
11081 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011082 return ret;
An-Cheng Huanga790ae32011-08-09 12:34:06 -070011083 case TARGET_NR_getxattr:
Peter Maydell30297b52011-12-14 15:37:18 +000011084 case TARGET_NR_lgetxattr:
An-Cheng Huanga790ae32011-08-09 12:34:06 -070011085 {
Peter Maydelle3c33ec2011-12-14 15:37:17 +000011086 void *p, *n, *v = 0;
11087 if (arg3) {
11088 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
11089 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011090 return -TARGET_EFAULT;
Peter Maydelle3c33ec2011-12-14 15:37:17 +000011091 }
11092 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070011093 p = lock_user_string(arg1);
11094 n = lock_user_string(arg2);
Peter Maydelle3c33ec2011-12-14 15:37:17 +000011095 if (p && n) {
Peter Maydell30297b52011-12-14 15:37:18 +000011096 if (num == TARGET_NR_getxattr) {
11097 ret = get_errno(getxattr(p, n, v, arg4));
11098 } else {
11099 ret = get_errno(lgetxattr(p, n, v, arg4));
11100 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070011101 } else {
11102 ret = -TARGET_EFAULT;
11103 }
11104 unlock_user(p, arg1, 0);
11105 unlock_user(n, arg2, 0);
11106 unlock_user(v, arg3, arg4);
11107 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011108 return ret;
Peter Maydell30297b52011-12-14 15:37:18 +000011109 case TARGET_NR_fgetxattr:
11110 {
11111 void *n, *v = 0;
11112 if (arg3) {
11113 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
11114 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011115 return -TARGET_EFAULT;
Peter Maydell30297b52011-12-14 15:37:18 +000011116 }
11117 }
11118 n = lock_user_string(arg2);
11119 if (n) {
11120 ret = get_errno(fgetxattr(arg1, n, v, arg4));
11121 } else {
11122 ret = -TARGET_EFAULT;
11123 }
11124 unlock_user(n, arg2, 0);
11125 unlock_user(v, arg3, arg4);
11126 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011127 return ret;
An-Cheng Huanga790ae32011-08-09 12:34:06 -070011128 case TARGET_NR_removexattr:
Peter Maydell30297b52011-12-14 15:37:18 +000011129 case TARGET_NR_lremovexattr:
An-Cheng Huanga790ae32011-08-09 12:34:06 -070011130 {
11131 void *p, *n;
11132 p = lock_user_string(arg1);
11133 n = lock_user_string(arg2);
11134 if (p && n) {
Peter Maydell30297b52011-12-14 15:37:18 +000011135 if (num == TARGET_NR_removexattr) {
11136 ret = get_errno(removexattr(p, n));
11137 } else {
11138 ret = get_errno(lremovexattr(p, n));
11139 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070011140 } else {
11141 ret = -TARGET_EFAULT;
11142 }
11143 unlock_user(p, arg1, 0);
11144 unlock_user(n, arg2, 0);
11145 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011146 return ret;
Peter Maydell30297b52011-12-14 15:37:18 +000011147 case TARGET_NR_fremovexattr:
11148 {
11149 void *n;
11150 n = lock_user_string(arg2);
11151 if (n) {
11152 ret = get_errno(fremovexattr(arg1, n));
11153 } else {
11154 ret = -TARGET_EFAULT;
11155 }
11156 unlock_user(n, arg2, 0);
11157 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011158 return ret;
bellardebc05482003-09-30 21:08:41 +000011159#endif
An-Cheng Huanga790ae32011-08-09 12:34:06 -070011160#endif /* CONFIG_ATTR */
bellardebc05482003-09-30 21:08:41 +000011161#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +000011162 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +000011163#if defined(TARGET_MIPS)
Petar Jovanovicd2792792014-06-18 17:48:20 +020011164 ((CPUMIPSState *) cpu_env)->active_tc.CP0_UserLocal = arg1;
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011165 return 0;
edgar_iglef967792009-01-07 14:19:38 +000011166#elif defined(TARGET_CRIS)
11167 if (arg1 & 0xff)
11168 ret = -TARGET_EINVAL;
11169 else {
11170 ((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1;
11171 ret = 0;
11172 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011173 return ret;
bellard8d18e892007-11-14 15:18:40 +000011174#elif defined(TARGET_I386) && defined(TARGET_ABI32)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011175 return do_set_thread_area(cpu_env, arg1);
Peter Maydell1ccd9372013-07-16 18:44:55 +010011176#elif defined(TARGET_M68K)
11177 {
Andreas Färber0429a972013-08-26 18:14:44 +020011178 TaskState *ts = cpu->opaque;
Peter Maydell1ccd9372013-07-16 18:44:55 +010011179 ts->tp_value = arg1;
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011180 return 0;
Peter Maydell1ccd9372013-07-16 18:44:55 +010011181 }
ths6f5b89a2007-03-02 20:48:00 +000011182#else
Richard Henderson10f45d92018-08-18 12:01:07 -070011183 return -TARGET_ENOSYS;
ths6f5b89a2007-03-02 20:48:00 +000011184#endif
11185#endif
11186#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +000011187 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +000011188#if defined(TARGET_I386) && defined(TARGET_ABI32)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011189 return do_get_thread_area(cpu_env, arg1);
Peter Maydell1ccd9372013-07-16 18:44:55 +010011190#elif defined(TARGET_M68K)
11191 {
Andreas Färber0429a972013-08-26 18:14:44 +020011192 TaskState *ts = cpu->opaque;
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011193 return ts->tp_value;
Peter Maydell1ccd9372013-07-16 18:44:55 +010011194 }
bellard8d18e892007-11-14 15:18:40 +000011195#else
Richard Henderson10f45d92018-08-18 12:01:07 -070011196 return -TARGET_ENOSYS;
bellardebc05482003-09-30 21:08:41 +000011197#endif
bellard8d18e892007-11-14 15:18:40 +000011198#endif
bellard48dc41e2006-06-21 18:15:50 +000011199#ifdef TARGET_NR_getdomainname
11200 case TARGET_NR_getdomainname:
Richard Henderson10f45d92018-08-18 12:01:07 -070011201 return -TARGET_ENOSYS;
bellard48dc41e2006-06-21 18:15:50 +000011202#endif
ths6f5b89a2007-03-02 20:48:00 +000011203
Max Filippov12e33402018-04-01 13:13:49 -070011204#ifdef TARGET_NR_clock_settime
11205 case TARGET_NR_clock_settime:
11206 {
11207 struct timespec ts;
11208
11209 ret = target_to_host_timespec(&ts, arg2);
11210 if (!is_error(ret)) {
11211 ret = get_errno(clock_settime(arg1, &ts));
11212 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011213 return ret;
Max Filippov12e33402018-04-01 13:13:49 -070011214 }
11215#endif
thsb5906f92007-03-19 13:32:45 +000011216#ifdef TARGET_NR_clock_gettime
11217 case TARGET_NR_clock_gettime:
11218 {
11219 struct timespec ts;
11220 ret = get_errno(clock_gettime(arg1, &ts));
11221 if (!is_error(ret)) {
Max Filippovb9f99082018-04-01 13:14:04 -070011222 ret = host_to_target_timespec(arg2, &ts);
thsb5906f92007-03-19 13:32:45 +000011223 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011224 return ret;
thsb5906f92007-03-19 13:32:45 +000011225 }
11226#endif
11227#ifdef TARGET_NR_clock_getres
11228 case TARGET_NR_clock_getres:
11229 {
11230 struct timespec ts;
11231 ret = get_errno(clock_getres(arg1, &ts));
11232 if (!is_error(ret)) {
11233 host_to_target_timespec(arg2, &ts);
11234 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011235 return ret;
thsb5906f92007-03-19 13:32:45 +000011236 }
11237#endif
pbrook63d76512008-05-29 13:43:29 +000011238#ifdef TARGET_NR_clock_nanosleep
11239 case TARGET_NR_clock_nanosleep:
11240 {
11241 struct timespec ts;
11242 target_to_host_timespec(&ts, arg3);
Peter Maydell9e518222016-06-06 19:58:09 +010011243 ret = get_errno(safe_clock_nanosleep(arg1, arg2,
11244 &ts, arg4 ? &ts : NULL));
pbrook63d76512008-05-29 13:43:29 +000011245 if (arg4)
11246 host_to_target_timespec(arg4, &ts);
Tom Musta8fbe8fd2014-08-12 13:53:41 -050011247
11248#if defined(TARGET_PPC)
11249 /* clock_nanosleep is odd in that it returns positive errno values.
11250 * On PPC, CR0 bit 3 should be set in such a situation. */
Peter Maydell9e518222016-06-06 19:58:09 +010011251 if (ret && ret != -TARGET_ERESTARTSYS) {
Tom Musta8fbe8fd2014-08-12 13:53:41 -050011252 ((CPUPPCState *)cpu_env)->crf[0] |= 1;
11253 }
11254#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011255 return ret;
pbrook63d76512008-05-29 13:43:29 +000011256 }
11257#endif
thsb5906f92007-03-19 13:32:45 +000011258
ths6f5b89a2007-03-02 20:48:00 +000011259#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
11260 case TARGET_NR_set_tid_address:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011261 return get_errno(set_tid_address((int *)g2h(arg1)));
ths6f5b89a2007-03-02 20:48:00 +000011262#endif
11263
ths4cae1d12007-07-12 11:06:53 +000011264 case TARGET_NR_tkill:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011265 return get_errno(safe_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +000011266
ths71455572007-06-21 21:45:30 +000011267 case TARGET_NR_tgkill:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011268 return get_errno(safe_tgkill((int)arg1, (int)arg2,
11269 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +000011270
ths4f2b1fe2007-06-21 21:57:12 +000011271#ifdef TARGET_NR_set_robust_list
11272 case TARGET_NR_set_robust_list:
Peter Maydelle9a970a2013-02-08 04:34:54 +000011273 case TARGET_NR_get_robust_list:
11274 /* The ABI for supporting robust futexes has userspace pass
11275 * the kernel a pointer to a linked list which is updated by
11276 * userspace after the syscall; the list is walked by the kernel
11277 * when the thread exits. Since the linked list in QEMU guest
11278 * memory isn't a valid linked list for the host and we have
11279 * no way to reliably intercept the thread-death event, we can't
11280 * support these. Silently return ENOSYS so that guest userspace
11281 * falls back to a non-robust futex implementation (which should
11282 * be OK except in the corner case of the guest crashing while
11283 * holding a mutex that is shared with another process via
11284 * shared memory).
11285 */
Richard Henderson10f45d92018-08-18 12:01:07 -070011286 return -TARGET_ENOSYS;
ths4f2b1fe2007-06-21 21:57:12 +000011287#endif
11288
Peter Maydell1acae9f2013-07-02 14:04:12 +010011289#if defined(TARGET_NR_utimensat)
ths9007f0e2007-09-25 17:50:37 +000011290 case TARGET_NR_utimensat:
11291 {
Riku Voipioebc996f2009-04-21 15:01:51 +030011292 struct timespec *tsp, ts[2];
11293 if (!arg3) {
11294 tsp = NULL;
11295 } else {
11296 target_to_host_timespec(ts, arg3);
11297 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
11298 tsp = ts;
11299 }
ths9007f0e2007-09-25 17:50:37 +000011300 if (!arg2)
Riku Voipioebc996f2009-04-21 15:01:51 +030011301 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
ths9007f0e2007-09-25 17:50:37 +000011302 else {
bellard579a97f2007-11-11 14:26:47 +000011303 if (!(p = lock_user_string(arg2))) {
Richard Henderson259841c2018-08-18 12:01:09 -070011304 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000011305 }
Riku Voipioebc996f2009-04-21 15:01:51 +030011306 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
bellard579a97f2007-11-11 14:26:47 +000011307 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +000011308 }
11309 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011310 return ret;
ths9007f0e2007-09-25 17:50:37 +000011311#endif
pbrookbd0c5662008-05-29 14:34:11 +000011312 case TARGET_NR_futex:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011313 return do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
aurel32dbfe4c32009-04-08 21:29:30 +000011314#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
aurel3239b59762008-10-01 21:46:50 +000011315 case TARGET_NR_inotify_init:
11316 ret = get_errno(sys_inotify_init());
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030011317 if (ret >= 0) {
11318 fd_trans_register(ret, &target_inotify_trans);
11319 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011320 return ret;
aurel3239b59762008-10-01 21:46:50 +000011321#endif
Stefan Weila1606b02010-03-28 11:44:41 +020011322#ifdef CONFIG_INOTIFY1
Riku Voipioc05c7a72010-03-26 15:25:11 +000011323#if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1)
11324 case TARGET_NR_inotify_init1:
Lena Djokicfea243e2016-11-24 17:08:53 +010011325 ret = get_errno(sys_inotify_init1(target_to_host_bitmask(arg1,
11326 fcntl_flags_tbl)));
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030011327 if (ret >= 0) {
11328 fd_trans_register(ret, &target_inotify_trans);
11329 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011330 return ret;
Riku Voipioc05c7a72010-03-26 15:25:11 +000011331#endif
Stefan Weila1606b02010-03-28 11:44:41 +020011332#endif
aurel32dbfe4c32009-04-08 21:29:30 +000011333#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
aurel3239b59762008-10-01 21:46:50 +000011334 case TARGET_NR_inotify_add_watch:
11335 p = lock_user_string(arg2);
11336 ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3));
11337 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011338 return ret;
aurel3239b59762008-10-01 21:46:50 +000011339#endif
aurel32dbfe4c32009-04-08 21:29:30 +000011340#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
aurel3239b59762008-10-01 21:46:50 +000011341 case TARGET_NR_inotify_rm_watch:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011342 return get_errno(sys_inotify_rm_watch(arg1, arg2));
aurel3239b59762008-10-01 21:46:50 +000011343#endif
ths9007f0e2007-09-25 17:50:37 +000011344
Nathan Froyd8ec9cf82009-07-22 09:14:36 -070011345#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
aurel3224e10032009-04-15 16:11:43 +000011346 case TARGET_NR_mq_open:
11347 {
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020011348 struct mq_attr posix_mq_attr;
Lena Djokic26400772016-11-24 17:08:58 +010011349 struct mq_attr *pposix_mq_attr;
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020011350 int host_flags;
aurel3224e10032009-04-15 16:11:43 +000011351
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020011352 host_flags = target_to_host_bitmask(arg2, fcntl_flags_tbl);
Lena Djokic26400772016-11-24 17:08:58 +010011353 pposix_mq_attr = NULL;
11354 if (arg4) {
11355 if (copy_from_user_mq_attr(&posix_mq_attr, arg4) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011356 return -TARGET_EFAULT;
Lena Djokic26400772016-11-24 17:08:58 +010011357 }
11358 pposix_mq_attr = &posix_mq_attr;
Tom Mustab6ce1f62014-08-12 13:53:36 -050011359 }
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020011360 p = lock_user_string(arg1 - 1);
11361 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011362 return -TARGET_EFAULT;
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020011363 }
Lena Djokic26400772016-11-24 17:08:58 +010011364 ret = get_errno(mq_open(p, host_flags, arg3, pposix_mq_attr));
aurel3224e10032009-04-15 16:11:43 +000011365 unlock_user (p, arg1, 0);
11366 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011367 return ret;
aurel3224e10032009-04-15 16:11:43 +000011368
11369 case TARGET_NR_mq_unlink:
11370 p = lock_user_string(arg1 - 1);
Peter Maydell32112152016-07-12 13:02:13 +010011371 if (!p) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011372 return -TARGET_EFAULT;
Peter Maydell32112152016-07-12 13:02:13 +010011373 }
aurel3224e10032009-04-15 16:11:43 +000011374 ret = get_errno(mq_unlink(p));
11375 unlock_user (p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011376 return ret;
aurel3224e10032009-04-15 16:11:43 +000011377
11378 case TARGET_NR_mq_timedsend:
11379 {
11380 struct timespec ts;
11381
11382 p = lock_user (VERIFY_READ, arg2, arg3, 1);
11383 if (arg5 != 0) {
11384 target_to_host_timespec(&ts, arg5);
Peter Maydelld40ecd62016-06-06 19:58:06 +010011385 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts));
aurel3224e10032009-04-15 16:11:43 +000011386 host_to_target_timespec(arg5, &ts);
Peter Maydelld40ecd62016-06-06 19:58:06 +010011387 } else {
11388 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL));
aurel3224e10032009-04-15 16:11:43 +000011389 }
aurel3224e10032009-04-15 16:11:43 +000011390 unlock_user (p, arg2, arg3);
11391 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011392 return ret;
aurel3224e10032009-04-15 16:11:43 +000011393
11394 case TARGET_NR_mq_timedreceive:
11395 {
11396 struct timespec ts;
11397 unsigned int prio;
11398
11399 p = lock_user (VERIFY_READ, arg2, arg3, 1);
11400 if (arg5 != 0) {
11401 target_to_host_timespec(&ts, arg5);
Peter Maydelld40ecd62016-06-06 19:58:06 +010011402 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
11403 &prio, &ts));
aurel3224e10032009-04-15 16:11:43 +000011404 host_to_target_timespec(arg5, &ts);
Peter Maydelld40ecd62016-06-06 19:58:06 +010011405 } else {
11406 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
11407 &prio, NULL));
aurel3224e10032009-04-15 16:11:43 +000011408 }
aurel3224e10032009-04-15 16:11:43 +000011409 unlock_user (p, arg2, arg3);
11410 if (arg4 != 0)
11411 put_user_u32(prio, arg4);
11412 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011413 return ret;
aurel3224e10032009-04-15 16:11:43 +000011414
11415 /* Not implemented for now... */
11416/* case TARGET_NR_mq_notify: */
11417/* break; */
11418
11419 case TARGET_NR_mq_getsetattr:
11420 {
11421 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
11422 ret = 0;
aurel3224e10032009-04-15 16:11:43 +000011423 if (arg2 != 0) {
11424 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
Max Filippova23ea402018-03-31 08:20:15 -070011425 ret = get_errno(mq_setattr(arg1, &posix_mq_attr_in,
11426 &posix_mq_attr_out));
11427 } else if (arg3 != 0) {
11428 ret = get_errno(mq_getattr(arg1, &posix_mq_attr_out));
aurel3224e10032009-04-15 16:11:43 +000011429 }
Max Filippova23ea402018-03-31 08:20:15 -070011430 if (ret == 0 && arg3 != 0) {
11431 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
11432 }
aurel3224e10032009-04-15 16:11:43 +000011433 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011434 return ret;
aurel3224e10032009-04-15 16:11:43 +000011435#endif
11436
vibisreenivasan3ce34df2009-05-16 18:32:41 +053011437#ifdef CONFIG_SPLICE
11438#ifdef TARGET_NR_tee
11439 case TARGET_NR_tee:
11440 {
11441 ret = get_errno(tee(arg1,arg2,arg3,arg4));
11442 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011443 return ret;
vibisreenivasan3ce34df2009-05-16 18:32:41 +053011444#endif
11445#ifdef TARGET_NR_splice
11446 case TARGET_NR_splice:
11447 {
11448 loff_t loff_in, loff_out;
11449 loff_t *ploff_in = NULL, *ploff_out = NULL;
Andreas Schwab17644b32015-03-10 17:11:35 +010011450 if (arg2) {
11451 if (get_user_u64(loff_in, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011452 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010011453 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053011454 ploff_in = &loff_in;
11455 }
Andreas Schwab17644b32015-03-10 17:11:35 +010011456 if (arg4) {
11457 if (get_user_u64(loff_out, arg4)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011458 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010011459 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053011460 ploff_out = &loff_out;
11461 }
11462 ret = get_errno(splice(arg1, ploff_in, arg3, ploff_out, arg5, arg6));
Andreas Schwab17644b32015-03-10 17:11:35 +010011463 if (arg2) {
11464 if (put_user_u64(loff_in, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011465 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010011466 }
11467 }
11468 if (arg4) {
11469 if (put_user_u64(loff_out, arg4)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011470 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010011471 }
11472 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053011473 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011474 return ret;
vibisreenivasan3ce34df2009-05-16 18:32:41 +053011475#endif
11476#ifdef TARGET_NR_vmsplice
11477 case TARGET_NR_vmsplice:
11478 {
Richard Hendersonf287b2c2012-09-15 13:20:25 -070011479 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
11480 if (vec != NULL) {
11481 ret = get_errno(vmsplice(arg1, vec, arg3, arg4));
11482 unlock_iovec(vec, arg2, arg3, 0);
11483 } else {
11484 ret = -host_to_target_errno(errno);
11485 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053011486 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011487 return ret;
vibisreenivasan3ce34df2009-05-16 18:32:41 +053011488#endif
11489#endif /* CONFIG_SPLICE */
Riku Voipioc2882b92009-08-12 15:08:24 +030011490#ifdef CONFIG_EVENTFD
11491#if defined(TARGET_NR_eventfd)
11492 case TARGET_NR_eventfd:
11493 ret = get_errno(eventfd(arg1, 0));
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030011494 if (ret >= 0) {
11495 fd_trans_register(ret, &target_eventfd_trans);
11496 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011497 return ret;
Riku Voipioc2882b92009-08-12 15:08:24 +030011498#endif
11499#if defined(TARGET_NR_eventfd2)
11500 case TARGET_NR_eventfd2:
Petar Jovanovic5947c692013-04-08 20:26:10 +020011501 {
11502 int host_flags = arg2 & (~(TARGET_O_NONBLOCK | TARGET_O_CLOEXEC));
11503 if (arg2 & TARGET_O_NONBLOCK) {
11504 host_flags |= O_NONBLOCK;
11505 }
11506 if (arg2 & TARGET_O_CLOEXEC) {
11507 host_flags |= O_CLOEXEC;
11508 }
11509 ret = get_errno(eventfd(arg1, host_flags));
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030011510 if (ret >= 0) {
11511 fd_trans_register(ret, &target_eventfd_trans);
11512 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011513 return ret;
Petar Jovanovic5947c692013-04-08 20:26:10 +020011514 }
Riku Voipioc2882b92009-08-12 15:08:24 +030011515#endif
11516#endif /* CONFIG_EVENTFD */
Ulrich Hechtd0927932009-09-17 20:22:14 +030011517#if defined(CONFIG_FALLOCATE) && defined(TARGET_NR_fallocate)
11518 case TARGET_NR_fallocate:
Alexander Graf20249ae2012-02-06 21:37:07 +010011519#if TARGET_ABI_BITS == 32
11520 ret = get_errno(fallocate(arg1, arg2, target_offset64(arg3, arg4),
11521 target_offset64(arg5, arg6)));
11522#else
Ulrich Hechtd0927932009-09-17 20:22:14 +030011523 ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
Alexander Graf20249ae2012-02-06 21:37:07 +010011524#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011525 return ret;
Ulrich Hechtd0927932009-09-17 20:22:14 +030011526#endif
Peter Maydellc727f472011-01-06 11:05:10 +000011527#if defined(CONFIG_SYNC_FILE_RANGE)
11528#if defined(TARGET_NR_sync_file_range)
11529 case TARGET_NR_sync_file_range:
11530#if TARGET_ABI_BITS == 32
Riku Voipiobfcedc52011-06-20 16:24:39 +030011531#if defined(TARGET_MIPS)
11532 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
11533 target_offset64(arg5, arg6), arg7));
11534#else
Peter Maydellc727f472011-01-06 11:05:10 +000011535 ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3),
11536 target_offset64(arg4, arg5), arg6));
Riku Voipiobfcedc52011-06-20 16:24:39 +030011537#endif /* !TARGET_MIPS */
Peter Maydellc727f472011-01-06 11:05:10 +000011538#else
11539 ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4));
11540#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011541 return ret;
Peter Maydellc727f472011-01-06 11:05:10 +000011542#endif
11543#if defined(TARGET_NR_sync_file_range2)
11544 case TARGET_NR_sync_file_range2:
11545 /* This is like sync_file_range but the arguments are reordered */
11546#if TARGET_ABI_BITS == 32
11547 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
11548 target_offset64(arg5, arg6), arg2));
11549#else
11550 ret = get_errno(sync_file_range(arg1, arg3, arg4, arg2));
11551#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011552 return ret;
Peter Maydellc727f472011-01-06 11:05:10 +000011553#endif
11554#endif
Laurent Viviere36800c2015-10-02 14:48:09 +020011555#if defined(TARGET_NR_signalfd4)
11556 case TARGET_NR_signalfd4:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011557 return do_signalfd4(arg1, arg2, arg4);
Laurent Viviere36800c2015-10-02 14:48:09 +020011558#endif
11559#if defined(TARGET_NR_signalfd)
11560 case TARGET_NR_signalfd:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011561 return do_signalfd4(arg1, arg2, 0);
Laurent Viviere36800c2015-10-02 14:48:09 +020011562#endif
Peter Maydell3b6edd12011-02-15 18:35:05 +000011563#if defined(CONFIG_EPOLL)
11564#if defined(TARGET_NR_epoll_create)
11565 case TARGET_NR_epoll_create:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011566 return get_errno(epoll_create(arg1));
Peter Maydell3b6edd12011-02-15 18:35:05 +000011567#endif
11568#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1)
11569 case TARGET_NR_epoll_create1:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011570 return get_errno(epoll_create1(arg1));
Peter Maydell3b6edd12011-02-15 18:35:05 +000011571#endif
11572#if defined(TARGET_NR_epoll_ctl)
11573 case TARGET_NR_epoll_ctl:
11574 {
11575 struct epoll_event ep;
11576 struct epoll_event *epp = 0;
11577 if (arg4) {
11578 struct target_epoll_event *target_ep;
11579 if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011580 return -TARGET_EFAULT;
Peter Maydell3b6edd12011-02-15 18:35:05 +000011581 }
11582 ep.events = tswap32(target_ep->events);
11583 /* The epoll_data_t union is just opaque data to the kernel,
11584 * so we transfer all 64 bits across and need not worry what
11585 * actual data type it is.
11586 */
11587 ep.data.u64 = tswap64(target_ep->data.u64);
11588 unlock_user_struct(target_ep, arg4, 0);
11589 epp = &ep;
11590 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011591 return get_errno(epoll_ctl(arg1, arg2, arg3, epp));
Peter Maydell3b6edd12011-02-15 18:35:05 +000011592 }
11593#endif
11594
Peter Maydell227f0212016-06-06 19:58:11 +010011595#if defined(TARGET_NR_epoll_wait) || defined(TARGET_NR_epoll_pwait)
Peter Maydell3b6edd12011-02-15 18:35:05 +000011596#if defined(TARGET_NR_epoll_wait)
11597 case TARGET_NR_epoll_wait:
11598#endif
Peter Maydell227f0212016-06-06 19:58:11 +010011599#if defined(TARGET_NR_epoll_pwait)
Peter Maydell3b6edd12011-02-15 18:35:05 +000011600 case TARGET_NR_epoll_pwait:
11601#endif
11602 {
11603 struct target_epoll_event *target_ep;
11604 struct epoll_event *ep;
11605 int epfd = arg1;
11606 int maxevents = arg3;
11607 int timeout = arg4;
11608
Peter Maydell2ba7fae32016-07-18 15:35:59 +010011609 if (maxevents <= 0 || maxevents > TARGET_EP_MAX_EVENTS) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011610 return -TARGET_EINVAL;
Peter Maydell2ba7fae32016-07-18 15:35:59 +010011611 }
11612
Peter Maydell3b6edd12011-02-15 18:35:05 +000011613 target_ep = lock_user(VERIFY_WRITE, arg2,
11614 maxevents * sizeof(struct target_epoll_event), 1);
11615 if (!target_ep) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011616 return -TARGET_EFAULT;
Peter Maydell3b6edd12011-02-15 18:35:05 +000011617 }
11618
Peter Maydell04c95f42016-07-18 15:36:00 +010011619 ep = g_try_new(struct epoll_event, maxevents);
11620 if (!ep) {
11621 unlock_user(target_ep, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011622 return -TARGET_ENOMEM;
Peter Maydell04c95f42016-07-18 15:36:00 +010011623 }
Peter Maydell3b6edd12011-02-15 18:35:05 +000011624
11625 switch (num) {
Peter Maydell227f0212016-06-06 19:58:11 +010011626#if defined(TARGET_NR_epoll_pwait)
Peter Maydell3b6edd12011-02-15 18:35:05 +000011627 case TARGET_NR_epoll_pwait:
11628 {
11629 target_sigset_t *target_set;
11630 sigset_t _set, *set = &_set;
11631
11632 if (arg5) {
Peter Maydellc8157012016-06-30 14:23:24 +010011633 if (arg6 != sizeof(target_sigset_t)) {
11634 ret = -TARGET_EINVAL;
11635 break;
11636 }
11637
Peter Maydell3b6edd12011-02-15 18:35:05 +000011638 target_set = lock_user(VERIFY_READ, arg5,
11639 sizeof(target_sigset_t), 1);
11640 if (!target_set) {
Peter Maydell04c95f42016-07-18 15:36:00 +010011641 ret = -TARGET_EFAULT;
11642 break;
Peter Maydell3b6edd12011-02-15 18:35:05 +000011643 }
11644 target_to_host_sigset(set, target_set);
11645 unlock_user(target_set, arg5, 0);
11646 } else {
11647 set = NULL;
11648 }
11649
Peter Maydell227f0212016-06-06 19:58:11 +010011650 ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
11651 set, SIGSET_T_SIZE));
Peter Maydell3b6edd12011-02-15 18:35:05 +000011652 break;
11653 }
11654#endif
11655#if defined(TARGET_NR_epoll_wait)
11656 case TARGET_NR_epoll_wait:
Peter Maydell227f0212016-06-06 19:58:11 +010011657 ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
11658 NULL, 0));
Peter Maydell3b6edd12011-02-15 18:35:05 +000011659 break;
11660#endif
11661 default:
11662 ret = -TARGET_ENOSYS;
11663 }
11664 if (!is_error(ret)) {
11665 int i;
11666 for (i = 0; i < ret; i++) {
11667 target_ep[i].events = tswap32(ep[i].events);
11668 target_ep[i].data.u64 = tswap64(ep[i].data.u64);
11669 }
Peter Maydell04c95f42016-07-18 15:36:00 +010011670 unlock_user(target_ep, arg2,
11671 ret * sizeof(struct target_epoll_event));
11672 } else {
11673 unlock_user(target_ep, arg2, 0);
Peter Maydell3b6edd12011-02-15 18:35:05 +000011674 }
Peter Maydell04c95f42016-07-18 15:36:00 +010011675 g_free(ep);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011676 return ret;
Peter Maydell3b6edd12011-02-15 18:35:05 +000011677 }
11678#endif
11679#endif
Peter Maydell163a05a2011-06-27 17:44:52 +010011680#ifdef TARGET_NR_prlimit64
11681 case TARGET_NR_prlimit64:
11682 {
11683 /* args: pid, resource number, ptr to new rlimit, ptr to old rlimit */
11684 struct target_rlimit64 *target_rnew, *target_rold;
11685 struct host_rlimit64 rnew, rold, *rnewp = 0;
Felix Janda95018012014-12-02 22:11:17 +010011686 int resource = target_to_host_resource(arg2);
Peter Maydell163a05a2011-06-27 17:44:52 +010011687 if (arg3) {
11688 if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011689 return -TARGET_EFAULT;
Peter Maydell163a05a2011-06-27 17:44:52 +010011690 }
11691 rnew.rlim_cur = tswap64(target_rnew->rlim_cur);
11692 rnew.rlim_max = tswap64(target_rnew->rlim_max);
11693 unlock_user_struct(target_rnew, arg3, 0);
11694 rnewp = &rnew;
11695 }
11696
Felix Janda95018012014-12-02 22:11:17 +010011697 ret = get_errno(sys_prlimit64(arg1, resource, rnewp, arg4 ? &rold : 0));
Peter Maydell163a05a2011-06-27 17:44:52 +010011698 if (!is_error(ret) && arg4) {
11699 if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011700 return -TARGET_EFAULT;
Peter Maydell163a05a2011-06-27 17:44:52 +010011701 }
11702 target_rold->rlim_cur = tswap64(rold.rlim_cur);
11703 target_rold->rlim_max = tswap64(rold.rlim_max);
11704 unlock_user_struct(target_rold, arg4, 1);
11705 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011706 return ret;
Peter Maydell163a05a2011-06-27 17:44:52 +010011707 }
11708#endif
Richard Henderson3d21d292012-09-15 13:20:46 -070011709#ifdef TARGET_NR_gethostname
11710 case TARGET_NR_gethostname:
11711 {
11712 char *name = lock_user(VERIFY_WRITE, arg1, arg2, 0);
11713 if (name) {
11714 ret = get_errno(gethostname(name, arg2));
11715 unlock_user(name, arg1, arg2);
11716 } else {
11717 ret = -TARGET_EFAULT;
11718 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011719 return ret;
Richard Henderson3d21d292012-09-15 13:20:46 -070011720 }
11721#endif
Riku Voipio89aaf1a2013-07-24 09:44:26 +030011722#ifdef TARGET_NR_atomic_cmpxchg_32
11723 case TARGET_NR_atomic_cmpxchg_32:
11724 {
11725 /* should use start_exclusive from main.c */
11726 abi_ulong mem_value;
11727 if (get_user_u32(mem_value, arg6)) {
11728 target_siginfo_t info;
11729 info.si_signo = SIGSEGV;
11730 info.si_errno = 0;
11731 info.si_code = TARGET_SEGV_MAPERR;
11732 info._sifields._sigfault._addr = arg6;
Peter Maydell9d2803f2016-07-28 16:44:46 +010011733 queue_signal((CPUArchState *)cpu_env, info.si_signo,
11734 QEMU_SI_FAULT, &info);
Riku Voipio89aaf1a2013-07-24 09:44:26 +030011735 ret = 0xdeadbeef;
11736
11737 }
11738 if (mem_value == arg2)
11739 put_user_u32(arg1, arg6);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011740 return mem_value;
Riku Voipio89aaf1a2013-07-24 09:44:26 +030011741 }
11742#endif
11743#ifdef TARGET_NR_atomic_barrier
11744 case TARGET_NR_atomic_barrier:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011745 /* Like the kernel implementation and the
11746 qemu arm barrier, no-op this? */
11747 return 0;
Riku Voipio89aaf1a2013-07-24 09:44:26 +030011748#endif
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011749
11750#ifdef TARGET_NR_timer_create
11751 case TARGET_NR_timer_create:
11752 {
11753 /* args: clockid_t clockid, struct sigevent *sevp, timer_t *timerid */
11754
11755 struct sigevent host_sevp = { {0}, }, *phost_sevp = NULL;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011756
11757 int clkid = arg1;
11758 int timer_index = next_free_host_timer();
11759
11760 if (timer_index < 0) {
11761 ret = -TARGET_EAGAIN;
11762 } else {
11763 timer_t *phtimer = g_posix_timers + timer_index;
11764
11765 if (arg2) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011766 phost_sevp = &host_sevp;
Peter Maydellc0659762014-08-09 15:42:32 +010011767 ret = target_to_host_sigevent(phost_sevp, arg2);
11768 if (ret != 0) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011769 return ret;
Peter Maydellc0659762014-08-09 15:42:32 +010011770 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011771 }
11772
11773 ret = get_errno(timer_create(clkid, phost_sevp, phtimer));
11774 if (ret) {
11775 phtimer = NULL;
11776 } else {
Alexander Grafaecc8862014-11-10 21:33:03 +010011777 if (put_user(TIMER_MAGIC | timer_index, arg3, target_timer_t)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011778 return -TARGET_EFAULT;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011779 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011780 }
11781 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011782 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011783 }
11784#endif
11785
11786#ifdef TARGET_NR_timer_settime
11787 case TARGET_NR_timer_settime:
11788 {
11789 /* args: timer_t timerid, int flags, const struct itimerspec *new_value,
11790 * struct itimerspec * old_value */
Alexander Grafaecc8862014-11-10 21:33:03 +010011791 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020011792
Alexander Grafaecc8862014-11-10 21:33:03 +010011793 if (timerid < 0) {
11794 ret = timerid;
11795 } else if (arg3 == 0) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011796 ret = -TARGET_EINVAL;
11797 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020011798 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011799 struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
11800
Marc-André Lureau40c80b52017-01-19 10:15:32 -050011801 if (target_to_host_itimerspec(&hspec_new, arg3)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011802 return -TARGET_EFAULT;
Marc-André Lureau40c80b52017-01-19 10:15:32 -050011803 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011804 ret = get_errno(
11805 timer_settime(htimer, arg2, &hspec_new, &hspec_old));
Marc-André Lureau40c80b52017-01-19 10:15:32 -050011806 if (arg4 && host_to_target_itimerspec(arg4, &hspec_old)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011807 return -TARGET_EFAULT;
Marc-André Lureau40c80b52017-01-19 10:15:32 -050011808 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011809 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011810 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011811 }
11812#endif
11813
11814#ifdef TARGET_NR_timer_gettime
11815 case TARGET_NR_timer_gettime:
11816 {
11817 /* args: timer_t timerid, struct itimerspec *curr_value */
Alexander Grafaecc8862014-11-10 21:33:03 +010011818 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020011819
Alexander Grafaecc8862014-11-10 21:33:03 +010011820 if (timerid < 0) {
11821 ret = timerid;
11822 } else if (!arg2) {
11823 ret = -TARGET_EFAULT;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011824 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020011825 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011826 struct itimerspec hspec;
11827 ret = get_errno(timer_gettime(htimer, &hspec));
11828
11829 if (host_to_target_itimerspec(arg2, &hspec)) {
11830 ret = -TARGET_EFAULT;
11831 }
11832 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011833 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011834 }
11835#endif
11836
11837#ifdef TARGET_NR_timer_getoverrun
11838 case TARGET_NR_timer_getoverrun:
11839 {
11840 /* args: timer_t timerid */
Alexander Grafaecc8862014-11-10 21:33:03 +010011841 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020011842
Alexander Grafaecc8862014-11-10 21:33:03 +010011843 if (timerid < 0) {
11844 ret = timerid;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011845 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020011846 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011847 ret = get_errno(timer_getoverrun(htimer));
11848 }
Laurent Viviere36800c2015-10-02 14:48:09 +020011849 fd_trans_unregister(ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011850 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011851 }
11852#endif
11853
11854#ifdef TARGET_NR_timer_delete
11855 case TARGET_NR_timer_delete:
11856 {
11857 /* args: timer_t timerid */
Alexander Grafaecc8862014-11-10 21:33:03 +010011858 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020011859
Alexander Grafaecc8862014-11-10 21:33:03 +010011860 if (timerid < 0) {
11861 ret = timerid;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011862 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020011863 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011864 ret = get_errno(timer_delete(htimer));
Alexander Grafe52a99f2014-08-22 13:56:18 +020011865 g_posix_timers[timerid] = 0;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011866 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011867 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011868 }
11869#endif
11870
Riku Voipio51834342014-06-22 11:25:42 +010011871#if defined(TARGET_NR_timerfd_create) && defined(CONFIG_TIMERFD)
11872 case TARGET_NR_timerfd_create:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011873 return get_errno(timerfd_create(arg1,
11874 target_to_host_bitmask(arg2, fcntl_flags_tbl)));
Riku Voipio51834342014-06-22 11:25:42 +010011875#endif
11876
11877#if defined(TARGET_NR_timerfd_gettime) && defined(CONFIG_TIMERFD)
11878 case TARGET_NR_timerfd_gettime:
11879 {
11880 struct itimerspec its_curr;
11881
11882 ret = get_errno(timerfd_gettime(arg1, &its_curr));
11883
11884 if (arg2 && host_to_target_itimerspec(arg2, &its_curr)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011885 return -TARGET_EFAULT;
Riku Voipio51834342014-06-22 11:25:42 +010011886 }
11887 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011888 return ret;
Riku Voipio51834342014-06-22 11:25:42 +010011889#endif
11890
11891#if defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD)
11892 case TARGET_NR_timerfd_settime:
11893 {
11894 struct itimerspec its_new, its_old, *p_new;
11895
11896 if (arg3) {
11897 if (target_to_host_itimerspec(&its_new, arg3)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011898 return -TARGET_EFAULT;
Riku Voipio51834342014-06-22 11:25:42 +010011899 }
11900 p_new = &its_new;
11901 } else {
11902 p_new = NULL;
11903 }
11904
11905 ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
11906
11907 if (arg4 && host_to_target_itimerspec(arg4, &its_old)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011908 return -TARGET_EFAULT;
Riku Voipio51834342014-06-22 11:25:42 +010011909 }
11910 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011911 return ret;
Riku Voipio51834342014-06-22 11:25:42 +010011912#endif
11913
Paul Burtonab31cda2014-06-22 11:25:43 +010011914#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
11915 case TARGET_NR_ioprio_get:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011916 return get_errno(ioprio_get(arg1, arg2));
Paul Burtonab31cda2014-06-22 11:25:43 +010011917#endif
11918
11919#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
11920 case TARGET_NR_ioprio_set:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011921 return get_errno(ioprio_set(arg1, arg2, arg3));
Paul Burtonab31cda2014-06-22 11:25:43 +010011922#endif
11923
Riku Voipio9af5c902014-08-12 15:58:57 +030011924#if defined(TARGET_NR_setns) && defined(CONFIG_SETNS)
11925 case TARGET_NR_setns:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011926 return get_errno(setns(arg1, arg2));
Riku Voipio9af5c902014-08-12 15:58:57 +030011927#endif
11928#if defined(TARGET_NR_unshare) && defined(CONFIG_SETNS)
11929 case TARGET_NR_unshare:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011930 return get_errno(unshare(arg1));
Riku Voipio9af5c902014-08-12 15:58:57 +030011931#endif
Laurent Vivier2f147882016-09-25 22:20:20 +020011932#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
11933 case TARGET_NR_kcmp:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011934 return get_errno(kcmp(arg1, arg2, arg3, arg4, arg5));
Laurent Vivier2f147882016-09-25 22:20:20 +020011935#endif
Richard Hendersonfa97e382018-07-18 13:06:48 -070011936#ifdef TARGET_NR_swapcontext
11937 case TARGET_NR_swapcontext:
11938 /* PowerPC specific. */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011939 return do_swapcontext(cpu_env, arg1, arg2, arg3);
Richard Hendersonfa97e382018-07-18 13:06:48 -070011940#endif
Riku Voipio9af5c902014-08-12 15:58:57 +030011941
bellard31e31b82003-02-18 22:55:36 +000011942 default:
Philippe Mathieu-Daudé122f9c82018-07-06 12:51:25 -030011943 qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011944 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +000011945 }
bellard31e31b82003-02-18 22:55:36 +000011946 return ret;
11947}
Richard Hendersondc1ce182018-08-18 12:01:04 -070011948
11949abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
11950 abi_long arg2, abi_long arg3, abi_long arg4,
11951 abi_long arg5, abi_long arg6, abi_long arg7,
11952 abi_long arg8)
11953{
Richard Henderson29a0af62019-03-22 16:07:18 -070011954 CPUState *cpu = env_cpu(cpu_env);
Richard Hendersondc1ce182018-08-18 12:01:04 -070011955 abi_long ret;
11956
11957#ifdef DEBUG_ERESTARTSYS
11958 /* Debug-only code for exercising the syscall-restart code paths
11959 * in the per-architecture cpu main loops: restart every syscall
11960 * the guest makes once before letting it through.
11961 */
11962 {
11963 static bool flag;
11964 flag = !flag;
11965 if (flag) {
11966 return -TARGET_ERESTARTSYS;
11967 }
11968 }
11969#endif
11970
11971 trace_guest_user_syscall(cpu, num, arg1, arg2, arg3, arg4,
11972 arg5, arg6, arg7, arg8);
11973
11974 if (unlikely(do_strace)) {
11975 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
11976 ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4,
11977 arg5, arg6, arg7, arg8);
11978 print_syscall_ret(num, ret);
11979 } else {
11980 ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4,
11981 arg5, arg6, arg7, arg8);
11982 }
11983
11984 trace_guest_user_syscall_ret(cpu, num, ret);
11985 return ret;
11986}