blob: 208fd1813d6a932fe2c810c6b2713c42850bcaa6 [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>
aurel32607175e2009-04-15 16:11:59 +000040#include <sys/un.h>
bellard31e31b82003-02-18 22:55:36 +000041#include <sys/uio.h>
Felix Janda0839f112016-09-30 19:40:21 -040042#include <poll.h>
bellard32f36bc2003-03-30 21:29:48 +000043#include <sys/times.h>
bellard8853f862004-02-22 14:57:26 +000044#include <sys/shm.h>
thsfa294812007-02-02 22:05:00 +000045#include <sys/sem.h>
bellard56c8f682005-11-28 22:28:41 +000046#include <sys/statfs.h>
bellardebc05482003-09-30 21:08:41 +000047#include <utime.h>
bellarda5448a72004-06-19 16:59:03 +000048#include <sys/sysinfo.h>
Laurent Viviere36800c2015-10-02 14:48:09 +020049#include <sys/signalfd.h>
bellard72f03902003-02-18 23:33:18 +000050//#include <sys/user.h>
bellard8853f862004-02-22 14:57:26 +000051#include <netinet/ip.h>
bellard7854b052003-03-29 17:22:23 +000052#include <netinet/tcp.h>
Laurent Vivier86fcd942011-03-30 01:35:23 +020053#include <linux/wireless.h>
Jing Huang920394d2012-07-24 13:59:23 +000054#include <linux/icmp.h>
Helge Delleree1ac3a2017-02-18 23:31:30 +010055#include <linux/icmpv6.h>
56#include <linux/errqueue.h>
Marco A L Barbosad6d6d6f2017-10-05 10:55:30 -030057#include <linux/random.h>
Stefan Weil5a61cb62011-09-08 17:55:32 +020058#include "qemu-common.h"
Riku Voipiod80a1902014-10-01 16:05:46 +030059#ifdef CONFIG_TIMERFD
60#include <sys/timerfd.h>
61#endif
Juan Quintela9788c9c2009-07-27 16:13:02 +020062#ifdef TARGET_GPROF
aurel326d946cd2008-11-06 16:15:18 +000063#include <sys/gmon.h>
64#endif
Riku Voipioc2882b92009-08-12 15:08:24 +030065#ifdef CONFIG_EVENTFD
66#include <sys/eventfd.h>
67#endif
Peter Maydell3b6edd12011-02-15 18:35:05 +000068#ifdef CONFIG_EPOLL
69#include <sys/epoll.h>
70#endif
An-Cheng Huanga790ae32011-08-09 12:34:06 -070071#ifdef CONFIG_ATTR
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010072#include "qemu/xattr.h"
An-Cheng Huanga790ae32011-08-09 12:34:06 -070073#endif
Peter Maydella8fd1ab2013-02-08 07:31:55 +000074#ifdef CONFIG_SENDFILE
75#include <sys/sendfile.h>
76#endif
bellard31e31b82003-02-18 22:55:36 +000077
78#define termios host_termios
79#define winsize host_winsize
80#define termio host_termio
bellard04369ff2003-03-20 22:33:23 +000081#define sgttyb host_sgttyb /* same as target */
82#define tchars host_tchars /* same as target */
83#define ltchars host_ltchars /* same as target */
bellard31e31b82003-02-18 22:55:36 +000084
85#include <linux/termios.h>
86#include <linux/unistd.h>
bellard31e31b82003-02-18 22:55:36 +000087#include <linux/cdrom.h>
88#include <linux/hdreg.h>
89#include <linux/soundcard.h>
bellard19b84f32003-05-08 15:41:49 +000090#include <linux/kd.h>
balrog8fbd6b52008-09-20 03:03:09 +000091#include <linux/mtio.h>
Martin Mohring350d1772009-05-04 21:21:41 +030092#include <linux/fs.h>
Peter Maydelldace20d2011-01-10 13:11:24 +000093#if defined(CONFIG_FIEMAP)
Peter Maydell285da2b2011-01-06 15:04:18 +000094#include <linux/fiemap.h>
Peter Maydelldace20d2011-01-10 13:11:24 +000095#endif
Ulrich Hechtf7680a52009-10-16 17:00:44 +020096#include <linux/fb.h>
Cortland Tölva6c753a62018-10-08 09:35:20 -070097#if defined(CONFIG_USBFS)
98#include <linux/usbdevice_fs.h>
Cortland Tölvaa1333672018-10-08 09:35:21 -070099#include <linux/usb/ch9.h>
Cortland Tölva6c753a62018-10-08 09:35:20 -0700100#endif
Ulrich Hechtf7680a52009-10-16 17:00:44 +0200101#include <linux/vt.h>
Alexander Graf56e904e2012-01-31 18:42:06 +0100102#include <linux/dm-ioctl.h>
Laurent Vivierc07ecc62013-01-07 11:40:06 +0000103#include <linux/reboot.h>
Laurent Vivier7ff7b662013-07-02 14:04:12 +0100104#include <linux/route.h>
Laurent Vivierf57d4192013-08-30 01:46:41 +0200105#include <linux/filter.h>
Andreas Färberfff8c532014-01-18 07:38:30 +0100106#include <linux/blkpg.h>
Laurent Viviera82ea932016-06-27 00:18:22 +0200107#include <netpacket/packet.h>
Laurent Vivier6c5b5642016-05-22 18:56:19 +0200108#include <linux/netlink.h>
pbrookd7e40362008-05-23 16:06:43 +0000109#include "linux_loop.h"
Riku Voipio18cb0082014-02-19 12:59:58 +0200110#include "uname.h"
bellard31e31b82003-02-18 22:55:36 +0000111
bellard3ef693a2003-03-23 20:17:16 +0000112#include "qemu.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
bellard31e31b82003-02-18 22:55:36 +0000242
Peter Maydellb1cef6d2018-01-25 16:19:49 +0000243#if defined(__alpha__) || defined(__x86_64__) || defined(__s390x__)
bellard9af9eaa2003-04-07 21:34:41 +0000244#define __NR__llseek __NR_lseek
245#endif
246
James Hogana29e5ba2014-03-25 21:51:08 +0000247/* Newer kernel ports have llseek() instead of _llseek() */
248#if defined(TARGET_NR_llseek) && !defined(TARGET_NR__llseek)
249#define TARGET_NR__llseek TARGET_NR_llseek
250#endif
251
bellard72f03902003-02-18 23:33:18 +0000252#ifdef __NR_gettid
bellard31e31b82003-02-18 22:55:36 +0000253_syscall0(int, gettid)
bellard72f03902003-02-18 23:33:18 +0000254#else
ths0da46a62007-10-20 20:23:07 +0000255/* This is a replacement for the host gettid() and must return a host
256 errno. */
bellard72f03902003-02-18 23:33:18 +0000257static int gettid(void) {
258 return -ENOSYS;
259}
260#endif
Peter Maydell2b3f64c2018-04-19 13:57:40 +0100261
262/* For the 64-bit guest on 32-bit host case we must emulate
263 * getdents using getdents64, because otherwise the host
264 * might hand us back more dirent records than we can fit
265 * into the guest buffer after structure format conversion.
266 * Otherwise we emulate getdents with getdents if the host has it.
267 */
268#if defined(__NR_getdents) && HOST_LONG_BITS >= TARGET_ABI_BITS
269#define EMULATE_GETDENTS_WITH_GETDENTS
270#endif
271
272#if defined(TARGET_NR_getdents) && defined(EMULATE_GETDENTS_WITH_GETDENTS)
aurel323b3f24a2009-04-15 16:12:13 +0000273_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
Peter Maydell3307e232013-06-12 16:20:21 +0100274#endif
Peter Maydell2b3f64c2018-04-19 13:57:40 +0100275#if (defined(TARGET_NR_getdents) && \
276 !defined(EMULATE_GETDENTS_WITH_GETDENTS)) || \
Peter Maydell3307e232013-06-12 16:20:21 +0100277 (defined(TARGET_NR_getdents64) && defined(__NR_getdents64))
aurel323b3f24a2009-04-15 16:12:13 +0000278_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
279#endif
Richard Hendersond35b2612010-06-04 12:14:10 -0700280#if defined(TARGET_NR__llseek) && defined(__NR_llseek)
aurel323b3f24a2009-04-15 16:12:13 +0000281_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
282 loff_t *, res, uint, wh);
283#endif
Miloš Stojanovićc1a402a2017-05-15 16:59:45 +0200284_syscall3(int, sys_rt_sigqueueinfo, pid_t, pid, int, sig, siginfo_t *, uinfo)
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +0200285_syscall4(int, sys_rt_tgsigqueueinfo, pid_t, pid, pid_t, tid, int, sig,
286 siginfo_t *, uinfo)
aurel323b3f24a2009-04-15 16:12:13 +0000287_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
aurel323b3f24a2009-04-15 16:12:13 +0000288#ifdef __NR_exit_group
289_syscall1(int,exit_group,int,error_code)
290#endif
291#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
292_syscall1(int,set_tid_address,int *,tidptr)
293#endif
aurel323b3f24a2009-04-15 16:12:13 +0000294#if defined(TARGET_NR_futex) && defined(__NR_futex)
295_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
296 const struct timespec *,timeout,int *,uaddr2,int,val3)
297#endif
Mike Frysinger737de1d2011-02-07 01:05:55 -0500298#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
299_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
300 unsigned long *, user_mask_ptr);
301#define __NR_sys_sched_setaffinity __NR_sched_setaffinity
302_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
303 unsigned long *, user_mask_ptr);
Samuel Thibaultb827c3e2018-01-12 09:14:35 +0100304#define __NR_sys_getcpu __NR_getcpu
305_syscall3(int, sys_getcpu, unsigned *, cpu, unsigned *, node, void *, tcache);
Alexander Graf0f6b4d22011-09-27 14:39:42 +0200306_syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd,
307 void *, arg);
Peter Maydelle0eb2102014-03-17 12:15:35 +0000308_syscall2(int, capget, struct __user_cap_header_struct *, header,
309 struct __user_cap_data_struct *, data);
310_syscall2(int, capset, struct __user_cap_header_struct *, header,
311 struct __user_cap_data_struct *, data);
Paul Burtonab31cda2014-06-22 11:25:43 +0100312#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
313_syscall2(int, ioprio_get, int, which, int, who)
314#endif
315#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
316_syscall3(int, ioprio_set, int, which, int, who, int, ioprio)
317#endif
Laurent Vivierf894efd2016-02-21 10:56:23 +0100318#if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
319_syscall3(int, getrandom, void *, buf, size_t, buflen, unsigned int, flags)
320#endif
aurel323b3f24a2009-04-15 16:12:13 +0000321
Laurent Vivier2f147882016-09-25 22:20:20 +0200322#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
323_syscall5(int, kcmp, pid_t, pid1, pid_t, pid2, int, type,
324 unsigned long, idx1, unsigned long, idx2)
325#endif
326
aurel323b3f24a2009-04-15 16:12:13 +0000327static bitmask_transtbl fcntl_flags_tbl[] = {
328 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
329 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
330 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
331 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
332 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
333 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
334 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
335 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
Richard Hendersonafc87632012-07-25 14:30:34 -0700336 { TARGET_O_SYNC, TARGET_O_DSYNC, O_SYNC, O_DSYNC, },
aurel323b3f24a2009-04-15 16:12:13 +0000337 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
338 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
339 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
340 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
aurel323b3f24a2009-04-15 16:12:13 +0000341#if defined(O_DIRECT)
342 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
343#endif
Richard Hendersonafc87632012-07-25 14:30:34 -0700344#if defined(O_NOATIME)
345 { TARGET_O_NOATIME, TARGET_O_NOATIME, O_NOATIME, O_NOATIME },
346#endif
347#if defined(O_CLOEXEC)
348 { TARGET_O_CLOEXEC, TARGET_O_CLOEXEC, O_CLOEXEC, O_CLOEXEC },
349#endif
350#if defined(O_PATH)
351 { TARGET_O_PATH, TARGET_O_PATH, O_PATH, O_PATH },
352#endif
Riku Voipio5f9cee42017-08-08 16:01:19 +0300353#if defined(O_TMPFILE)
354 { TARGET_O_TMPFILE, TARGET_O_TMPFILE, O_TMPFILE, O_TMPFILE },
355#endif
Richard Hendersonafc87632012-07-25 14:30:34 -0700356 /* Don't terminate the list prematurely on 64-bit host+guest. */
357#if TARGET_O_LARGEFILE != 0 || O_LARGEFILE != 0
358 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
359#endif
aurel323b3f24a2009-04-15 16:12:13 +0000360 { 0, 0, 0, 0 }
361};
362
aurel323b3f24a2009-04-15 16:12:13 +0000363static int sys_getcwd1(char *buf, size_t size)
364{
365 if (getcwd(buf, size) == NULL) {
366 /* getcwd() sets errno */
367 return (-1);
368 }
aurel32aaf4ad32009-04-16 14:17:14 +0000369 return strlen(buf)+1;
aurel323b3f24a2009-04-15 16:12:13 +0000370}
371
Peter Maydell1acae9f2013-07-02 14:04:12 +0100372#ifdef TARGET_NR_utimensat
Peter Maydell700fa582016-07-18 11:47:55 +0100373#if defined(__NR_utimensat)
Peter Maydell1acae9f2013-07-02 14:04:12 +0100374#define __NR_sys_utimensat __NR_utimensat
ths9007f0e2007-09-25 17:50:37 +0000375_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
376 const struct timespec *,tsp,int,flags)
Peter Maydell1acae9f2013-07-02 14:04:12 +0100377#else
378static int sys_utimensat(int dirfd, const char *pathname,
379 const struct timespec times[2], int flags)
380{
381 errno = ENOSYS;
382 return -1;
383}
ths9007f0e2007-09-25 17:50:37 +0000384#endif
Peter Maydell1acae9f2013-07-02 14:04:12 +0100385#endif /* TARGET_NR_utimensat */
aurel323b3f24a2009-04-15 16:12:13 +0000386
Andreas Schwab95d03072018-01-23 11:53:31 +0100387#ifdef TARGET_NR_renameat2
388#if defined(__NR_renameat2)
389#define __NR_sys_renameat2 __NR_renameat2
390_syscall5(int, sys_renameat2, int, oldfd, const char *, old, int, newfd,
391 const char *, new, unsigned int, flags)
392#else
393static int sys_renameat2(int oldfd, const char *old,
394 int newfd, const char *new, int flags)
395{
396 if (flags == 0) {
397 return renameat(oldfd, old, newfd, new);
398 }
399 errno = ENOSYS;
400 return -1;
401}
402#endif
403#endif /* TARGET_NR_renameat2 */
404
aurel323b3f24a2009-04-15 16:12:13 +0000405#ifdef CONFIG_INOTIFY
aurel328690e422009-04-17 13:50:32 +0000406#include <sys/inotify.h>
aurel323b3f24a2009-04-15 16:12:13 +0000407
aurel3239b59762008-10-01 21:46:50 +0000408#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
aurel323b3f24a2009-04-15 16:12:13 +0000409static int sys_inotify_init(void)
410{
411 return (inotify_init());
412}
aurel3239b59762008-10-01 21:46:50 +0000413#endif
414#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
aurel323b3f24a2009-04-15 16:12:13 +0000415static int sys_inotify_add_watch(int fd,const char *pathname, int32_t mask)
416{
417 return (inotify_add_watch(fd, pathname, mask));
418}
aurel3239b59762008-10-01 21:46:50 +0000419#endif
420#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
aurel323b3f24a2009-04-15 16:12:13 +0000421static int sys_inotify_rm_watch(int fd, int32_t wd)
422{
aurel328690e422009-04-17 13:50:32 +0000423 return (inotify_rm_watch(fd, wd));
aurel323b3f24a2009-04-15 16:12:13 +0000424}
aurel3239b59762008-10-01 21:46:50 +0000425#endif
Riku Voipioc05c7a72010-03-26 15:25:11 +0000426#ifdef CONFIG_INOTIFY1
427#if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1)
428static int sys_inotify_init1(int flags)
429{
430 return (inotify_init1(flags));
431}
432#endif
433#endif
aurel323b3f24a2009-04-15 16:12:13 +0000434#else
435/* Userspace can usually survive runtime without inotify */
436#undef TARGET_NR_inotify_init
Riku Voipioc05c7a72010-03-26 15:25:11 +0000437#undef TARGET_NR_inotify_init1
aurel323b3f24a2009-04-15 16:12:13 +0000438#undef TARGET_NR_inotify_add_watch
439#undef TARGET_NR_inotify_rm_watch
440#endif /* CONFIG_INOTIFY */
441
Peter Maydell163a05a2011-06-27 17:44:52 +0100442#if defined(TARGET_NR_prlimit64)
443#ifndef __NR_prlimit64
444# define __NR_prlimit64 -1
445#endif
446#define __NR_sys_prlimit64 __NR_prlimit64
447/* The glibc rlimit structure may not be that used by the underlying syscall */
448struct host_rlimit64 {
449 uint64_t rlim_cur;
450 uint64_t rlim_max;
451};
452_syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
453 const struct host_rlimit64 *, new_limit,
454 struct host_rlimit64 *, old_limit)
455#endif
456
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +1100457
458#if defined(TARGET_NR_timer_create)
459/* Maxiumum of 32 active POSIX timers allowed at any one time. */
460static timer_t g_posix_timers[32] = { 0, } ;
461
462static inline int next_free_host_timer(void)
463{
464 int k ;
465 /* FIXME: Does finding the next free slot require a lock? */
466 for (k = 0; k < ARRAY_SIZE(g_posix_timers); k++) {
467 if (g_posix_timers[k] == 0) {
468 g_posix_timers[k] = (timer_t) 1;
469 return k;
470 }
471 }
472 return -1;
473}
474#endif
475
Riku Voipio48e515d2011-07-12 15:40:51 +0300476/* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
Alexander Graf4a1def42012-09-29 15:32:38 +0000477#ifdef TARGET_ARM
James Clarke8bf8e9d2017-09-15 20:33:13 +0100478static inline int regpairs_aligned(void *cpu_env, int num)
479{
Riku Voipio48e515d2011-07-12 15:40:51 +0300480 return ((((CPUARMState *)cpu_env)->eabi) == 1) ;
481}
Aleksandar Markovicd7779ac2016-09-19 13:44:42 +0200482#elif defined(TARGET_MIPS) && (TARGET_ABI_BITS == 32)
James Clarke8bf8e9d2017-09-15 20:33:13 +0100483static inline int regpairs_aligned(void *cpu_env, int num) { return 1; }
Alexander Graf4a1def42012-09-29 15:32:38 +0000484#elif defined(TARGET_PPC) && !defined(TARGET_PPC64)
485/* SysV AVI for PPC32 expects 64bit parameters to be passed on odd/even pairs
486 * of registers which translates to the same as ARM/MIPS, because we start with
487 * r3 as arg1 */
James Clarke8bf8e9d2017-09-15 20:33:13 +0100488static inline int regpairs_aligned(void *cpu_env, int num) { return 1; }
489#elif defined(TARGET_SH4)
490/* SH4 doesn't align register pairs, except for p{read,write}64 */
491static inline int regpairs_aligned(void *cpu_env, int num)
492{
493 switch (num) {
494 case TARGET_NR_pread64:
495 case TARGET_NR_pwrite64:
496 return 1;
497
498 default:
499 return 0;
500 }
501}
Max Filippovba7651f2017-01-25 10:54:11 -0800502#elif defined(TARGET_XTENSA)
503static inline int regpairs_aligned(void *cpu_env, int num) { return 1; }
Riku Voipio48e515d2011-07-12 15:40:51 +0300504#else
James Clarke8bf8e9d2017-09-15 20:33:13 +0100505static inline int regpairs_aligned(void *cpu_env, int num) { return 0; }
Riku Voipio48e515d2011-07-12 15:40:51 +0300506#endif
507
thsb92c47c2007-11-01 00:07:38 +0000508#define ERRNO_TABLE_SIZE 1200
509
510/* target_to_host_errno_table[] is initialized from
511 * host_to_target_errno_table[] in syscall_init(). */
512static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
513};
514
ths637947f2007-06-01 12:09:19 +0000515/*
thsfe8f0962007-07-12 10:59:21 +0000516 * This list is the union of errno values overridden in asm-<arch>/errno.h
ths637947f2007-06-01 12:09:19 +0000517 * minus the errnos that are not actually generic to all archs.
518 */
thsb92c47c2007-11-01 00:07:38 +0000519static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
Chen Gang08703b92015-09-07 10:35:06 +0800520 [EAGAIN] = TARGET_EAGAIN,
ths637947f2007-06-01 12:09:19 +0000521 [EIDRM] = TARGET_EIDRM,
522 [ECHRNG] = TARGET_ECHRNG,
523 [EL2NSYNC] = TARGET_EL2NSYNC,
524 [EL3HLT] = TARGET_EL3HLT,
525 [EL3RST] = TARGET_EL3RST,
526 [ELNRNG] = TARGET_ELNRNG,
527 [EUNATCH] = TARGET_EUNATCH,
528 [ENOCSI] = TARGET_ENOCSI,
529 [EL2HLT] = TARGET_EL2HLT,
530 [EDEADLK] = TARGET_EDEADLK,
531 [ENOLCK] = TARGET_ENOLCK,
532 [EBADE] = TARGET_EBADE,
533 [EBADR] = TARGET_EBADR,
534 [EXFULL] = TARGET_EXFULL,
535 [ENOANO] = TARGET_ENOANO,
536 [EBADRQC] = TARGET_EBADRQC,
537 [EBADSLT] = TARGET_EBADSLT,
538 [EBFONT] = TARGET_EBFONT,
539 [ENOSTR] = TARGET_ENOSTR,
540 [ENODATA] = TARGET_ENODATA,
541 [ETIME] = TARGET_ETIME,
542 [ENOSR] = TARGET_ENOSR,
543 [ENONET] = TARGET_ENONET,
544 [ENOPKG] = TARGET_ENOPKG,
545 [EREMOTE] = TARGET_EREMOTE,
546 [ENOLINK] = TARGET_ENOLINK,
547 [EADV] = TARGET_EADV,
548 [ESRMNT] = TARGET_ESRMNT,
549 [ECOMM] = TARGET_ECOMM,
550 [EPROTO] = TARGET_EPROTO,
551 [EDOTDOT] = TARGET_EDOTDOT,
552 [EMULTIHOP] = TARGET_EMULTIHOP,
553 [EBADMSG] = TARGET_EBADMSG,
554 [ENAMETOOLONG] = TARGET_ENAMETOOLONG,
555 [EOVERFLOW] = TARGET_EOVERFLOW,
556 [ENOTUNIQ] = TARGET_ENOTUNIQ,
557 [EBADFD] = TARGET_EBADFD,
558 [EREMCHG] = TARGET_EREMCHG,
559 [ELIBACC] = TARGET_ELIBACC,
560 [ELIBBAD] = TARGET_ELIBBAD,
561 [ELIBSCN] = TARGET_ELIBSCN,
562 [ELIBMAX] = TARGET_ELIBMAX,
563 [ELIBEXEC] = TARGET_ELIBEXEC,
564 [EILSEQ] = TARGET_EILSEQ,
565 [ENOSYS] = TARGET_ENOSYS,
566 [ELOOP] = TARGET_ELOOP,
567 [ERESTART] = TARGET_ERESTART,
568 [ESTRPIPE] = TARGET_ESTRPIPE,
569 [ENOTEMPTY] = TARGET_ENOTEMPTY,
570 [EUSERS] = TARGET_EUSERS,
571 [ENOTSOCK] = TARGET_ENOTSOCK,
572 [EDESTADDRREQ] = TARGET_EDESTADDRREQ,
573 [EMSGSIZE] = TARGET_EMSGSIZE,
574 [EPROTOTYPE] = TARGET_EPROTOTYPE,
575 [ENOPROTOOPT] = TARGET_ENOPROTOOPT,
576 [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT,
577 [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT,
578 [EOPNOTSUPP] = TARGET_EOPNOTSUPP,
579 [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT,
580 [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT,
581 [EADDRINUSE] = TARGET_EADDRINUSE,
582 [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL,
583 [ENETDOWN] = TARGET_ENETDOWN,
584 [ENETUNREACH] = TARGET_ENETUNREACH,
585 [ENETRESET] = TARGET_ENETRESET,
586 [ECONNABORTED] = TARGET_ECONNABORTED,
587 [ECONNRESET] = TARGET_ECONNRESET,
588 [ENOBUFS] = TARGET_ENOBUFS,
589 [EISCONN] = TARGET_EISCONN,
590 [ENOTCONN] = TARGET_ENOTCONN,
591 [EUCLEAN] = TARGET_EUCLEAN,
592 [ENOTNAM] = TARGET_ENOTNAM,
593 [ENAVAIL] = TARGET_ENAVAIL,
594 [EISNAM] = TARGET_EISNAM,
595 [EREMOTEIO] = TARGET_EREMOTEIO,
Aleksandar Markovic0444a3b2016-09-19 13:44:43 +0200596 [EDQUOT] = TARGET_EDQUOT,
ths637947f2007-06-01 12:09:19 +0000597 [ESHUTDOWN] = TARGET_ESHUTDOWN,
598 [ETOOMANYREFS] = TARGET_ETOOMANYREFS,
599 [ETIMEDOUT] = TARGET_ETIMEDOUT,
600 [ECONNREFUSED] = TARGET_ECONNREFUSED,
601 [EHOSTDOWN] = TARGET_EHOSTDOWN,
602 [EHOSTUNREACH] = TARGET_EHOSTUNREACH,
603 [EALREADY] = TARGET_EALREADY,
604 [EINPROGRESS] = TARGET_EINPROGRESS,
605 [ESTALE] = TARGET_ESTALE,
606 [ECANCELED] = TARGET_ECANCELED,
607 [ENOMEDIUM] = TARGET_ENOMEDIUM,
608 [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE,
thsb7fe5db2007-07-23 15:37:46 +0000609#ifdef ENOKEY
ths637947f2007-06-01 12:09:19 +0000610 [ENOKEY] = TARGET_ENOKEY,
thsb7fe5db2007-07-23 15:37:46 +0000611#endif
612#ifdef EKEYEXPIRED
ths637947f2007-06-01 12:09:19 +0000613 [EKEYEXPIRED] = TARGET_EKEYEXPIRED,
thsb7fe5db2007-07-23 15:37:46 +0000614#endif
615#ifdef EKEYREVOKED
ths637947f2007-06-01 12:09:19 +0000616 [EKEYREVOKED] = TARGET_EKEYREVOKED,
thsb7fe5db2007-07-23 15:37:46 +0000617#endif
618#ifdef EKEYREJECTED
ths637947f2007-06-01 12:09:19 +0000619 [EKEYREJECTED] = TARGET_EKEYREJECTED,
thsb7fe5db2007-07-23 15:37:46 +0000620#endif
621#ifdef EOWNERDEAD
ths637947f2007-06-01 12:09:19 +0000622 [EOWNERDEAD] = TARGET_EOWNERDEAD,
thsb7fe5db2007-07-23 15:37:46 +0000623#endif
624#ifdef ENOTRECOVERABLE
ths637947f2007-06-01 12:09:19 +0000625 [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
thsb7fe5db2007-07-23 15:37:46 +0000626#endif
Aleksandar Markovicda39db62016-09-22 18:56:56 +0200627#ifdef ENOMSG
628 [ENOMSG] = TARGET_ENOMSG,
629#endif
Richard Hendersonfe8ed7d2016-12-05 13:08:12 -0800630#ifdef ERKFILL
631 [ERFKILL] = TARGET_ERFKILL,
632#endif
633#ifdef EHWPOISON
634 [EHWPOISON] = TARGET_EHWPOISON,
635#endif
thsb92c47c2007-11-01 00:07:38 +0000636};
ths637947f2007-06-01 12:09:19 +0000637
638static inline int host_to_target_errno(int err)
639{
Timothy E Baldwin24661192016-05-12 18:47:25 +0100640 if (err >= 0 && err < ERRNO_TABLE_SIZE &&
641 host_to_target_errno_table[err]) {
ths637947f2007-06-01 12:09:19 +0000642 return host_to_target_errno_table[err];
Timothy E Baldwin24661192016-05-12 18:47:25 +0100643 }
ths637947f2007-06-01 12:09:19 +0000644 return err;
645}
646
thsb92c47c2007-11-01 00:07:38 +0000647static inline int target_to_host_errno(int err)
648{
Timothy E Baldwin24661192016-05-12 18:47:25 +0100649 if (err >= 0 && err < ERRNO_TABLE_SIZE &&
650 target_to_host_errno_table[err]) {
thsb92c47c2007-11-01 00:07:38 +0000651 return target_to_host_errno_table[err];
Timothy E Baldwin24661192016-05-12 18:47:25 +0100652 }
thsb92c47c2007-11-01 00:07:38 +0000653 return err;
654}
655
blueswir1992f48a2007-10-14 16:27:31 +0000656static inline abi_long get_errno(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000657{
658 if (ret == -1)
ths637947f2007-06-01 12:09:19 +0000659 return -host_to_target_errno(errno);
bellard31e31b82003-02-18 22:55:36 +0000660 else
661 return ret;
662}
663
Peter Maydell7dcdaea2016-06-06 19:58:18 +0100664const char *target_strerror(int err)
thsb92c47c2007-11-01 00:07:38 +0000665{
Peter Maydellda2a34f2016-06-06 19:58:19 +0100666 if (err == TARGET_ERESTARTSYS) {
667 return "To be restarted";
668 }
669 if (err == TARGET_QEMU_ESIGRETURN) {
670 return "Successful exit from sigreturn";
671 }
672
Alexander Graf962b2892011-11-21 12:04:07 +0100673 if ((err >= ERRNO_TABLE_SIZE) || (err < 0)) {
674 return NULL;
675 }
thsb92c47c2007-11-01 00:07:38 +0000676 return strerror(target_to_host_errno(err));
677}
678
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100679#define safe_syscall0(type, name) \
680static type safe_##name(void) \
681{ \
682 return safe_syscall(__NR_##name); \
683}
684
685#define safe_syscall1(type, name, type1, arg1) \
686static type safe_##name(type1 arg1) \
687{ \
688 return safe_syscall(__NR_##name, arg1); \
689}
690
691#define safe_syscall2(type, name, type1, arg1, type2, arg2) \
692static type safe_##name(type1 arg1, type2 arg2) \
693{ \
694 return safe_syscall(__NR_##name, arg1, arg2); \
695}
696
697#define safe_syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
698static type safe_##name(type1 arg1, type2 arg2, type3 arg3) \
699{ \
700 return safe_syscall(__NR_##name, arg1, arg2, arg3); \
701}
702
703#define safe_syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
704 type4, arg4) \
705static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
706{ \
707 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4); \
708}
709
710#define safe_syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \
711 type4, arg4, type5, arg5) \
712static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
713 type5 arg5) \
714{ \
715 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
716}
717
718#define safe_syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \
719 type4, arg4, type5, arg5, type6, arg6) \
720static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
721 type5 arg5, type6 arg6) \
722{ \
723 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
724}
725
Timothy E Baldwin50afd022016-05-12 18:47:47 +0100726safe_syscall3(ssize_t, read, int, fd, void *, buff, size_t, count)
727safe_syscall3(ssize_t, write, int, fd, const void *, buff, size_t, count)
Timothy E Baldwinc10a0732016-05-12 18:47:48 +0100728safe_syscall4(int, openat, int, dirfd, const char *, pathname, \
729 int, flags, mode_t, mode)
Timothy E Baldwin4af80a32016-05-12 18:47:49 +0100730safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \
731 struct rusage *, rusage)
732safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \
733 int, options, struct rusage *, rusage)
Timothy E Baldwinffdcbe22016-05-12 18:47:50 +0100734safe_syscall3(int, execve, const char *, filename, char **, argv, char **, envp)
Peter Maydell6df9d382016-05-12 18:47:51 +0100735safe_syscall6(int, pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, \
736 fd_set *, exceptfds, struct timespec *, timeout, void *, sig)
Peter Maydella6130232016-06-06 19:58:10 +0100737safe_syscall5(int, ppoll, struct pollfd *, ufds, unsigned int, nfds,
738 struct timespec *, tsp, const sigset_t *, sigmask,
739 size_t, sigsetsize)
Peter Maydell227f0212016-06-06 19:58:11 +0100740safe_syscall6(int, epoll_pwait, int, epfd, struct epoll_event *, events,
741 int, maxevents, int, timeout, const sigset_t *, sigmask,
742 size_t, sigsetsize)
Peter Maydelld509eeb2016-05-12 18:47:52 +0100743safe_syscall6(int,futex,int *,uaddr,int,op,int,val, \
744 const struct timespec *,timeout,int *,uaddr2,int,val3)
Peter Maydell2fe4fba2016-05-27 15:51:48 +0100745safe_syscall2(int, rt_sigsuspend, sigset_t *, newset, size_t, sigsetsize)
Peter Maydellbef653d2016-05-27 15:51:57 +0100746safe_syscall2(int, kill, pid_t, pid, int, sig)
747safe_syscall2(int, tkill, int, tid, int, sig)
748safe_syscall3(int, tgkill, int, tgid, int, pid, int, sig)
Peter Maydell918c03e2016-06-06 19:58:02 +0100749safe_syscall3(ssize_t, readv, int, fd, const struct iovec *, iov, int, iovcnt)
750safe_syscall3(ssize_t, writev, int, fd, const struct iovec *, iov, int, iovcnt)
Dejan Jovicevic0f263862016-10-11 11:52:46 +0200751safe_syscall5(ssize_t, preadv, int, fd, const struct iovec *, iov, int, iovcnt,
752 unsigned long, pos_l, unsigned long, pos_h)
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +0200753safe_syscall5(ssize_t, pwritev, int, fd, const struct iovec *, iov, int, iovcnt,
754 unsigned long, pos_l, unsigned long, pos_h)
Peter Maydell2a3c7612016-06-06 19:58:03 +0100755safe_syscall3(int, connect, int, fd, const struct sockaddr *, addr,
756 socklen_t, addrlen)
Peter Maydell66687532016-06-06 19:58:04 +0100757safe_syscall6(ssize_t, sendto, int, fd, const void *, buf, size_t, len,
758 int, flags, const struct sockaddr *, addr, socklen_t, addrlen)
759safe_syscall6(ssize_t, recvfrom, int, fd, void *, buf, size_t, len,
760 int, flags, struct sockaddr *, addr, socklen_t *, addrlen)
761safe_syscall3(ssize_t, sendmsg, int, fd, const struct msghdr *, msg, int, flags)
762safe_syscall3(ssize_t, recvmsg, int, fd, struct msghdr *, msg, int, flags)
Peter Maydell2a845982016-06-06 19:58:07 +0100763safe_syscall2(int, flock, int, fd, int, operation)
Peter Maydellb3f82332016-06-06 19:58:08 +0100764safe_syscall4(int, rt_sigtimedwait, const sigset_t *, these, siginfo_t *, uinfo,
765 const struct timespec *, uts, size_t, sigsetsize)
Peter Maydellff6dc132016-06-06 19:58:13 +0100766safe_syscall4(int, accept4, int, fd, struct sockaddr *, addr, socklen_t *, len,
767 int, flags)
Peter Maydell9e518222016-06-06 19:58:09 +0100768safe_syscall2(int, nanosleep, const struct timespec *, req,
769 struct timespec *, rem)
770#ifdef TARGET_NR_clock_nanosleep
771safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags,
772 const struct timespec *, req, struct timespec *, rem)
773#endif
Peter Maydell89f9fe42016-06-06 19:58:05 +0100774#ifdef __NR_msgsnd
775safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz,
776 int, flags)
777safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz,
778 long, msgtype, int, flags)
Peter Maydellffb7ee72016-06-06 19:58:12 +0100779safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops,
780 unsigned, nsops, const struct timespec *, timeout)
Peter Maydell89f9fe42016-06-06 19:58:05 +0100781#else
782/* This host kernel architecture uses a single ipc syscall; fake up
783 * wrappers for the sub-operations to hide this implementation detail.
784 * Annoyingly we can't include linux/ipc.h to get the constant definitions
785 * for the call parameter because some structs in there conflict with the
786 * sys/ipc.h ones. So we just define them here, and rely on them being
787 * the same for all host architectures.
788 */
Peter Maydellffb7ee72016-06-06 19:58:12 +0100789#define Q_SEMTIMEDOP 4
Peter Maydell89f9fe42016-06-06 19:58:05 +0100790#define Q_MSGSND 11
791#define Q_MSGRCV 12
792#define Q_IPCCALL(VERSION, OP) ((VERSION) << 16 | (OP))
793
794safe_syscall6(int, ipc, int, call, long, first, long, second, long, third,
795 void *, ptr, long, fifth)
796static int safe_msgsnd(int msgid, const void *msgp, size_t sz, int flags)
797{
798 return safe_ipc(Q_IPCCALL(0, Q_MSGSND), msgid, sz, flags, (void *)msgp, 0);
799}
800static int safe_msgrcv(int msgid, void *msgp, size_t sz, long type, int flags)
801{
802 return safe_ipc(Q_IPCCALL(1, Q_MSGRCV), msgid, sz, flags, msgp, type);
803}
Peter Maydellffb7ee72016-06-06 19:58:12 +0100804static int safe_semtimedop(int semid, struct sembuf *tsops, unsigned nsops,
805 const struct timespec *timeout)
806{
807 return safe_ipc(Q_IPCCALL(0, Q_SEMTIMEDOP), semid, nsops, 0, tsops,
808 (long)timeout);
809}
Peter Maydell89f9fe42016-06-06 19:58:05 +0100810#endif
Peter Maydelld40ecd62016-06-06 19:58:06 +0100811#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
812safe_syscall5(int, mq_timedsend, int, mqdes, const char *, msg_ptr,
813 size_t, len, unsigned, prio, const struct timespec *, timeout)
814safe_syscall5(int, mq_timedreceive, int, mqdes, char *, msg_ptr,
815 size_t, len, unsigned *, prio, const struct timespec *, timeout)
816#endif
Peter Maydell49ca6f32016-06-06 19:58:14 +0100817/* We do ioctl like this rather than via safe_syscall3 to preserve the
818 * "third argument might be integer or pointer or not present" behaviour of
819 * the libc function.
820 */
821#define safe_ioctl(...) safe_syscall(__NR_ioctl, __VA_ARGS__)
Peter Maydell435da5e2016-06-13 11:22:05 +0100822/* Similarly for fcntl. Note that callers must always:
823 * pass the F_GETLK64 etc constants rather than the unsuffixed F_GETLK
824 * use the flock64 struct rather than unsuffixed flock
825 * This will then work and use a 64-bit offset for both 32-bit and 64-bit hosts.
826 */
827#ifdef __NR_fcntl64
828#define safe_fcntl(...) safe_syscall(__NR_fcntl64, __VA_ARGS__)
829#else
830#define safe_fcntl(...) safe_syscall(__NR_fcntl, __VA_ARGS__)
831#endif
Timothy E Baldwin50afd022016-05-12 18:47:47 +0100832
Paul Burton8289d112014-06-22 11:25:33 +0100833static inline int host_to_target_sock_type(int host_type)
834{
835 int target_type;
836
837 switch (host_type & 0xf /* SOCK_TYPE_MASK */) {
838 case SOCK_DGRAM:
839 target_type = TARGET_SOCK_DGRAM;
840 break;
841 case SOCK_STREAM:
842 target_type = TARGET_SOCK_STREAM;
843 break;
844 default:
845 target_type = host_type & 0xf /* SOCK_TYPE_MASK */;
846 break;
847 }
848
849#if defined(SOCK_CLOEXEC)
850 if (host_type & SOCK_CLOEXEC) {
851 target_type |= TARGET_SOCK_CLOEXEC;
852 }
853#endif
854
855#if defined(SOCK_NONBLOCK)
856 if (host_type & SOCK_NONBLOCK) {
857 target_type |= TARGET_SOCK_NONBLOCK;
858 }
859#endif
860
861 return target_type;
862}
863
blueswir1992f48a2007-10-14 16:27:31 +0000864static abi_ulong target_brk;
865static abi_ulong target_original_brk;
vincent4d1de872011-06-14 21:56:33 +0000866static abi_ulong brk_page;
bellard31e31b82003-02-18 22:55:36 +0000867
blueswir1992f48a2007-10-14 16:27:31 +0000868void target_set_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000869{
blueswir14c1de732007-07-07 20:45:44 +0000870 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
vincent4d1de872011-06-14 21:56:33 +0000871 brk_page = HOST_PAGE_ALIGN(target_brk);
bellard31e31b82003-02-18 22:55:36 +0000872}
873
vincent4d1de872011-06-14 21:56:33 +0000874//#define DEBUGF_BRK(message, args...) do { fprintf(stderr, (message), ## args); } while (0)
875#define DEBUGF_BRK(message, args...)
876
ths0da46a62007-10-20 20:23:07 +0000877/* do_brk() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000878abi_long do_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000879{
blueswir1992f48a2007-10-14 16:27:31 +0000880 abi_long mapped_addr;
Peter Maydellef4330c2016-07-22 13:41:52 +0100881 abi_ulong new_alloc_size;
bellard31e31b82003-02-18 22:55:36 +0000882
Paul Brook3a0c6c42012-02-09 19:04:27 +0000883 DEBUGF_BRK("do_brk(" TARGET_ABI_FMT_lx ") -> ", new_brk);
ths3b46e622007-09-17 08:09:54 +0000884
vincent4d1de872011-06-14 21:56:33 +0000885 if (!new_brk) {
Paul Brook3a0c6c42012-02-09 19:04:27 +0000886 DEBUGF_BRK(TARGET_ABI_FMT_lx " (!new_brk)\n", target_brk);
vincent4d1de872011-06-14 21:56:33 +0000887 return target_brk;
888 }
889 if (new_brk < target_original_brk) {
Paul Brook3a0c6c42012-02-09 19:04:27 +0000890 DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk < target_original_brk)\n",
891 target_brk);
vincent4d1de872011-06-14 21:56:33 +0000892 return target_brk;
893 }
bellard31e31b82003-02-18 22:55:36 +0000894
vincent4d1de872011-06-14 21:56:33 +0000895 /* If the new brk is less than the highest page reserved to the
896 * target heap allocation, set it and we're almost done... */
897 if (new_brk <= brk_page) {
898 /* Heap contents are initialized to zero, as for anonymous
899 * mapped pages. */
900 if (new_brk > target_brk) {
901 memset(g2h(target_brk), 0, new_brk - target_brk);
902 }
bellard31e31b82003-02-18 22:55:36 +0000903 target_brk = new_brk;
Paul Brook3a0c6c42012-02-09 19:04:27 +0000904 DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk <= brk_page)\n", target_brk);
Paolo Bonzini72e21db2018-12-13 23:37:36 +0100905 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000906 }
907
Peter Maydell00faf082011-04-18 16:34:24 +0100908 /* We need to allocate more memory after the brk... Note that
909 * we don't use MAP_FIXED because that will map over the top of
910 * any existing mapping (like the one with the host libc or qemu
911 * itself); instead we treat "mapped but at wrong address" as
912 * a failure and unmap again.
913 */
vincent4d1de872011-06-14 21:56:33 +0000914 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page);
ths5fafdf22007-09-16 21:08:06 +0000915 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
bellard54936002003-05-13 00:25:15 +0000916 PROT_READ|PROT_WRITE,
Peter Maydell00faf082011-04-18 16:34:24 +0100917 MAP_ANON|MAP_PRIVATE, 0, 0));
918
919 if (mapped_addr == brk_page) {
Cédric VINCENT70afc342011-08-26 10:56:50 +0200920 /* Heap contents are initialized to zero, as for anonymous
921 * mapped pages. Technically the new pages are already
922 * initialized to zero since they *are* anonymous mapped
923 * pages, however we have to take care with the contents that
924 * come from the remaining part of the previous page: it may
925 * contains garbage data due to a previous heap usage (grown
926 * then shrunken). */
927 memset(g2h(target_brk), 0, brk_page - target_brk);
928
Peter Maydell00faf082011-04-18 16:34:24 +0100929 target_brk = new_brk;
vincent4d1de872011-06-14 21:56:33 +0000930 brk_page = HOST_PAGE_ALIGN(target_brk);
Paul Brook3a0c6c42012-02-09 19:04:27 +0000931 DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr == brk_page)\n",
932 target_brk);
Peter Maydell00faf082011-04-18 16:34:24 +0100933 return target_brk;
934 } else if (mapped_addr != -1) {
935 /* Mapped but at wrong address, meaning there wasn't actually
936 * enough space for this brk.
937 */
938 target_munmap(mapped_addr, new_alloc_size);
939 mapped_addr = -1;
Paul Brook3a0c6c42012-02-09 19:04:27 +0000940 DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr != -1)\n", target_brk);
vincent4d1de872011-06-14 21:56:33 +0000941 }
942 else {
Paul Brook3a0c6c42012-02-09 19:04:27 +0000943 DEBUGF_BRK(TARGET_ABI_FMT_lx " (otherwise)\n", target_brk);
Peter Maydell00faf082011-04-18 16:34:24 +0100944 }
balrog7ab240a2008-04-26 12:17:34 +0000945
Richard Henderson7dd46c02010-05-03 10:07:49 -0700946#if defined(TARGET_ALPHA)
947 /* We (partially) emulate OSF/1 on Alpha, which requires we
948 return a proper errno, not an unchanged brk value. */
Peter Maydell00faf082011-04-18 16:34:24 +0100949 return -TARGET_ENOMEM;
Richard Henderson7dd46c02010-05-03 10:07:49 -0700950#endif
Peter Maydell00faf082011-04-18 16:34:24 +0100951 /* For everything else, return the previous break. */
balrog7ab240a2008-04-26 12:17:34 +0000952 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000953}
954
ths26edcf42007-12-09 02:25:24 +0000955static inline abi_long copy_from_user_fdset(fd_set *fds,
956 abi_ulong target_fds_addr,
957 int n)
bellard31e31b82003-02-18 22:55:36 +0000958{
ths26edcf42007-12-09 02:25:24 +0000959 int i, nw, j, k;
960 abi_ulong b, *target_fds;
961
Laurent Vivierb1b2db22016-05-31 18:36:02 +0200962 nw = DIV_ROUND_UP(n, TARGET_ABI_BITS);
ths26edcf42007-12-09 02:25:24 +0000963 if (!(target_fds = lock_user(VERIFY_READ,
964 target_fds_addr,
965 sizeof(abi_ulong) * nw,
966 1)))
967 return -TARGET_EFAULT;
968
969 FD_ZERO(fds);
970 k = 0;
971 for (i = 0; i < nw; i++) {
972 /* grab the abi_ulong */
973 __get_user(b, &target_fds[i]);
974 for (j = 0; j < TARGET_ABI_BITS; j++) {
975 /* check the bit inside the abi_ulong */
976 if ((b >> j) & 1)
977 FD_SET(k, fds);
978 k++;
bellard31e31b82003-02-18 22:55:36 +0000979 }
bellard31e31b82003-02-18 22:55:36 +0000980 }
ths26edcf42007-12-09 02:25:24 +0000981
982 unlock_user(target_fds, target_fds_addr, 0);
983
984 return 0;
bellard31e31b82003-02-18 22:55:36 +0000985}
986
Mike Frysinger055e0902011-06-03 17:01:49 -0400987static inline abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr,
988 abi_ulong target_fds_addr,
989 int n)
990{
991 if (target_fds_addr) {
992 if (copy_from_user_fdset(fds, target_fds_addr, n))
993 return -TARGET_EFAULT;
994 *fds_ptr = fds;
995 } else {
996 *fds_ptr = NULL;
997 }
998 return 0;
999}
1000
ths26edcf42007-12-09 02:25:24 +00001001static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
1002 const fd_set *fds,
1003 int n)
bellard31e31b82003-02-18 22:55:36 +00001004{
bellard31e31b82003-02-18 22:55:36 +00001005 int i, nw, j, k;
blueswir1992f48a2007-10-14 16:27:31 +00001006 abi_long v;
ths26edcf42007-12-09 02:25:24 +00001007 abi_ulong *target_fds;
bellard31e31b82003-02-18 22:55:36 +00001008
Laurent Vivierb1b2db22016-05-31 18:36:02 +02001009 nw = DIV_ROUND_UP(n, TARGET_ABI_BITS);
ths26edcf42007-12-09 02:25:24 +00001010 if (!(target_fds = lock_user(VERIFY_WRITE,
1011 target_fds_addr,
1012 sizeof(abi_ulong) * nw,
1013 0)))
1014 return -TARGET_EFAULT;
1015
1016 k = 0;
1017 for (i = 0; i < nw; i++) {
1018 v = 0;
1019 for (j = 0; j < TARGET_ABI_BITS; j++) {
Andreas Schwab9ab709b2013-04-09 01:02:34 +00001020 v |= ((abi_ulong)(FD_ISSET(k, fds) != 0) << j);
ths26edcf42007-12-09 02:25:24 +00001021 k++;
bellard31e31b82003-02-18 22:55:36 +00001022 }
ths26edcf42007-12-09 02:25:24 +00001023 __put_user(v, &target_fds[i]);
bellard31e31b82003-02-18 22:55:36 +00001024 }
ths26edcf42007-12-09 02:25:24 +00001025
1026 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
1027
1028 return 0;
bellard31e31b82003-02-18 22:55:36 +00001029}
1030
bellardc596ed12003-07-13 17:32:31 +00001031#if defined(__alpha__)
1032#define HOST_HZ 1024
1033#else
1034#define HOST_HZ 100
1035#endif
1036
blueswir1992f48a2007-10-14 16:27:31 +00001037static inline abi_long host_to_target_clock_t(long ticks)
bellardc596ed12003-07-13 17:32:31 +00001038{
1039#if HOST_HZ == TARGET_HZ
1040 return ticks;
1041#else
1042 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
1043#endif
1044}
1045
bellard579a97f2007-11-11 14:26:47 +00001046static inline abi_long host_to_target_rusage(abi_ulong target_addr,
1047 const struct rusage *rusage)
bellardb4091862003-05-16 15:39:34 +00001048{
pbrook53a59602006-03-25 19:31:22 +00001049 struct target_rusage *target_rusage;
1050
bellard579a97f2007-11-11 14:26:47 +00001051 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
1052 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001053 target_rusage->ru_utime.tv_sec = tswapal(rusage->ru_utime.tv_sec);
1054 target_rusage->ru_utime.tv_usec = tswapal(rusage->ru_utime.tv_usec);
1055 target_rusage->ru_stime.tv_sec = tswapal(rusage->ru_stime.tv_sec);
1056 target_rusage->ru_stime.tv_usec = tswapal(rusage->ru_stime.tv_usec);
1057 target_rusage->ru_maxrss = tswapal(rusage->ru_maxrss);
1058 target_rusage->ru_ixrss = tswapal(rusage->ru_ixrss);
1059 target_rusage->ru_idrss = tswapal(rusage->ru_idrss);
1060 target_rusage->ru_isrss = tswapal(rusage->ru_isrss);
1061 target_rusage->ru_minflt = tswapal(rusage->ru_minflt);
1062 target_rusage->ru_majflt = tswapal(rusage->ru_majflt);
1063 target_rusage->ru_nswap = tswapal(rusage->ru_nswap);
1064 target_rusage->ru_inblock = tswapal(rusage->ru_inblock);
1065 target_rusage->ru_oublock = tswapal(rusage->ru_oublock);
1066 target_rusage->ru_msgsnd = tswapal(rusage->ru_msgsnd);
1067 target_rusage->ru_msgrcv = tswapal(rusage->ru_msgrcv);
1068 target_rusage->ru_nsignals = tswapal(rusage->ru_nsignals);
1069 target_rusage->ru_nvcsw = tswapal(rusage->ru_nvcsw);
1070 target_rusage->ru_nivcsw = tswapal(rusage->ru_nivcsw);
pbrook53a59602006-03-25 19:31:22 +00001071 unlock_user_struct(target_rusage, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001072
1073 return 0;
bellardb4091862003-05-16 15:39:34 +00001074}
1075
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001076static inline rlim_t target_to_host_rlim(abi_ulong target_rlim)
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001077{
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001078 abi_ulong target_rlim_swap;
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001079 rlim_t result;
1080
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001081 target_rlim_swap = tswapal(target_rlim);
1082 if (target_rlim_swap == TARGET_RLIM_INFINITY)
1083 return RLIM_INFINITY;
1084
1085 result = target_rlim_swap;
1086 if (target_rlim_swap != (rlim_t)result)
1087 return RLIM_INFINITY;
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001088
1089 return result;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001090}
1091
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001092static inline abi_ulong host_to_target_rlim(rlim_t rlim)
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001093{
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001094 abi_ulong target_rlim_swap;
1095 abi_ulong result;
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001096
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001097 if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim)
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001098 target_rlim_swap = TARGET_RLIM_INFINITY;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001099 else
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001100 target_rlim_swap = rlim;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001101 result = tswapal(target_rlim_swap);
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001102
1103 return result;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001104}
1105
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03001106static inline int target_to_host_resource(int code)
1107{
1108 switch (code) {
1109 case TARGET_RLIMIT_AS:
1110 return RLIMIT_AS;
1111 case TARGET_RLIMIT_CORE:
1112 return RLIMIT_CORE;
1113 case TARGET_RLIMIT_CPU:
1114 return RLIMIT_CPU;
1115 case TARGET_RLIMIT_DATA:
1116 return RLIMIT_DATA;
1117 case TARGET_RLIMIT_FSIZE:
1118 return RLIMIT_FSIZE;
1119 case TARGET_RLIMIT_LOCKS:
1120 return RLIMIT_LOCKS;
1121 case TARGET_RLIMIT_MEMLOCK:
1122 return RLIMIT_MEMLOCK;
1123 case TARGET_RLIMIT_MSGQUEUE:
1124 return RLIMIT_MSGQUEUE;
1125 case TARGET_RLIMIT_NICE:
1126 return RLIMIT_NICE;
1127 case TARGET_RLIMIT_NOFILE:
1128 return RLIMIT_NOFILE;
1129 case TARGET_RLIMIT_NPROC:
1130 return RLIMIT_NPROC;
1131 case TARGET_RLIMIT_RSS:
1132 return RLIMIT_RSS;
1133 case TARGET_RLIMIT_RTPRIO:
1134 return RLIMIT_RTPRIO;
1135 case TARGET_RLIMIT_SIGPENDING:
1136 return RLIMIT_SIGPENDING;
1137 case TARGET_RLIMIT_STACK:
1138 return RLIMIT_STACK;
1139 default:
1140 return code;
1141 }
1142}
1143
ths788f5ec2007-12-09 02:37:05 +00001144static inline abi_long copy_from_user_timeval(struct timeval *tv,
1145 abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +00001146{
pbrook53a59602006-03-25 19:31:22 +00001147 struct target_timeval *target_tv;
1148
ths788f5ec2007-12-09 02:37:05 +00001149 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
bellard579a97f2007-11-11 14:26:47 +00001150 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +00001151
1152 __get_user(tv->tv_sec, &target_tv->tv_sec);
1153 __get_user(tv->tv_usec, &target_tv->tv_usec);
1154
1155 unlock_user_struct(target_tv, target_tv_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001156
1157 return 0;
bellard31e31b82003-02-18 22:55:36 +00001158}
1159
ths788f5ec2007-12-09 02:37:05 +00001160static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
1161 const struct timeval *tv)
bellard31e31b82003-02-18 22:55:36 +00001162{
pbrook53a59602006-03-25 19:31:22 +00001163 struct target_timeval *target_tv;
1164
ths788f5ec2007-12-09 02:37:05 +00001165 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
bellard579a97f2007-11-11 14:26:47 +00001166 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +00001167
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);
bellard579a97f2007-11-11 14:26:47 +00001172
1173 return 0;
bellard31e31b82003-02-18 22:55:36 +00001174}
1175
Paul Burtonef4467e2014-06-22 11:25:40 +01001176static inline abi_long copy_from_user_timezone(struct timezone *tz,
1177 abi_ulong target_tz_addr)
1178{
1179 struct target_timezone *target_tz;
1180
1181 if (!lock_user_struct(VERIFY_READ, target_tz, target_tz_addr, 1)) {
1182 return -TARGET_EFAULT;
1183 }
1184
1185 __get_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
1186 __get_user(tz->tz_dsttime, &target_tz->tz_dsttime);
1187
1188 unlock_user_struct(target_tz, target_tz_addr, 0);
1189
1190 return 0;
1191}
1192
Nathan Froyd8ec9cf82009-07-22 09:14:36 -07001193#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
1194#include <mqueue.h>
1195
aurel3224e10032009-04-15 16:11:43 +00001196static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr,
1197 abi_ulong target_mq_attr_addr)
1198{
1199 struct target_mq_attr *target_mq_attr;
1200
1201 if (!lock_user_struct(VERIFY_READ, target_mq_attr,
1202 target_mq_attr_addr, 1))
1203 return -TARGET_EFAULT;
1204
1205 __get_user(attr->mq_flags, &target_mq_attr->mq_flags);
1206 __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
1207 __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
1208 __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
1209
1210 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0);
1211
1212 return 0;
1213}
1214
1215static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
1216 const struct mq_attr *attr)
1217{
1218 struct target_mq_attr *target_mq_attr;
1219
1220 if (!lock_user_struct(VERIFY_WRITE, target_mq_attr,
1221 target_mq_attr_addr, 0))
1222 return -TARGET_EFAULT;
1223
1224 __put_user(attr->mq_flags, &target_mq_attr->mq_flags);
1225 __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
1226 __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
1227 __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
1228
1229 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1);
1230
1231 return 0;
1232}
Nathan Froyd8ec9cf82009-07-22 09:14:36 -07001233#endif
bellard31e31b82003-02-18 22:55:36 +00001234
Mike Frysinger055e0902011-06-03 17:01:49 -04001235#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect)
ths0da46a62007-10-20 20:23:07 +00001236/* do_select() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001237static abi_long do_select(int n,
ths26edcf42007-12-09 02:25:24 +00001238 abi_ulong rfd_addr, abi_ulong wfd_addr,
1239 abi_ulong efd_addr, abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +00001240{
1241 fd_set rfds, wfds, efds;
1242 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
Peter Maydell6df9d382016-05-12 18:47:51 +01001243 struct timeval tv;
1244 struct timespec ts, *ts_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00001245 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00001246
Mike Frysinger055e0902011-06-03 17:01:49 -04001247 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
1248 if (ret) {
1249 return ret;
pbrook53a59602006-03-25 19:31:22 +00001250 }
Mike Frysinger055e0902011-06-03 17:01:49 -04001251 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
1252 if (ret) {
1253 return ret;
pbrook53a59602006-03-25 19:31:22 +00001254 }
Mike Frysinger055e0902011-06-03 17:01:49 -04001255 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
1256 if (ret) {
1257 return ret;
pbrook53a59602006-03-25 19:31:22 +00001258 }
ths3b46e622007-09-17 08:09:54 +00001259
ths26edcf42007-12-09 02:25:24 +00001260 if (target_tv_addr) {
ths788f5ec2007-12-09 02:37:05 +00001261 if (copy_from_user_timeval(&tv, target_tv_addr))
1262 return -TARGET_EFAULT;
Peter Maydell6df9d382016-05-12 18:47:51 +01001263 ts.tv_sec = tv.tv_sec;
1264 ts.tv_nsec = tv.tv_usec * 1000;
1265 ts_ptr = &ts;
bellard31e31b82003-02-18 22:55:36 +00001266 } else {
Peter Maydell6df9d382016-05-12 18:47:51 +01001267 ts_ptr = NULL;
bellard31e31b82003-02-18 22:55:36 +00001268 }
ths26edcf42007-12-09 02:25:24 +00001269
Peter Maydell6df9d382016-05-12 18:47:51 +01001270 ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
1271 ts_ptr, NULL));
pbrook53a59602006-03-25 19:31:22 +00001272
ths26edcf42007-12-09 02:25:24 +00001273 if (!is_error(ret)) {
1274 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
1275 return -TARGET_EFAULT;
1276 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
1277 return -TARGET_EFAULT;
1278 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
1279 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00001280
Peter Maydell6df9d382016-05-12 18:47:51 +01001281 if (target_tv_addr) {
1282 tv.tv_sec = ts.tv_sec;
1283 tv.tv_usec = ts.tv_nsec / 1000;
1284 if (copy_to_user_timeval(target_tv_addr, &tv)) {
1285 return -TARGET_EFAULT;
1286 }
1287 }
bellard31e31b82003-02-18 22:55:36 +00001288 }
bellard579a97f2007-11-11 14:26:47 +00001289
bellard31e31b82003-02-18 22:55:36 +00001290 return ret;
1291}
Laurent Vivier5457dc92016-07-08 01:17:27 +02001292
1293#if defined(TARGET_WANT_OLD_SYS_SELECT)
1294static abi_long do_old_select(abi_ulong arg1)
1295{
1296 struct target_sel_arg_struct *sel;
1297 abi_ulong inp, outp, exp, tvp;
1298 long nsel;
1299
1300 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1)) {
1301 return -TARGET_EFAULT;
1302 }
1303
1304 nsel = tswapal(sel->n);
1305 inp = tswapal(sel->inp);
1306 outp = tswapal(sel->outp);
1307 exp = tswapal(sel->exp);
1308 tvp = tswapal(sel->tvp);
1309
1310 unlock_user_struct(sel, arg1, 0);
1311
1312 return do_select(nsel, inp, outp, exp, tvp);
1313}
1314#endif
Mike Frysinger055e0902011-06-03 17:01:49 -04001315#endif
bellard31e31b82003-02-18 22:55:36 +00001316
Riku Voipio099d6b02009-05-05 12:10:04 +03001317static abi_long do_pipe2(int host_pipe[], int flags)
1318{
1319#ifdef CONFIG_PIPE2
1320 return pipe2(host_pipe, flags);
1321#else
1322 return -ENOSYS;
1323#endif
1324}
1325
Richard Hendersonfb41a662010-05-03 10:07:52 -07001326static abi_long do_pipe(void *cpu_env, abi_ulong pipedes,
1327 int flags, int is_pipe2)
Riku Voipio099d6b02009-05-05 12:10:04 +03001328{
1329 int host_pipe[2];
1330 abi_long ret;
1331 ret = flags ? do_pipe2(host_pipe, flags) : pipe(host_pipe);
1332
1333 if (is_error(ret))
1334 return get_errno(ret);
Richard Hendersonfb41a662010-05-03 10:07:52 -07001335
1336 /* Several targets have special calling conventions for the original
1337 pipe syscall, but didn't replicate this into the pipe2 syscall. */
1338 if (!is_pipe2) {
1339#if defined(TARGET_ALPHA)
1340 ((CPUAlphaState *)cpu_env)->ir[IR_A4] = host_pipe[1];
1341 return host_pipe[0];
1342#elif defined(TARGET_MIPS)
1343 ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1];
1344 return host_pipe[0];
1345#elif defined(TARGET_SH4)
takasi-y@ops.dti.ne.jp597c0212010-02-18 00:35:03 +09001346 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
Richard Hendersonfb41a662010-05-03 10:07:52 -07001347 return host_pipe[0];
Peter Maydell82f05b62013-07-06 17:39:48 +01001348#elif defined(TARGET_SPARC)
1349 ((CPUSPARCState*)cpu_env)->regwptr[1] = host_pipe[1];
1350 return host_pipe[0];
takasi-y@ops.dti.ne.jp597c0212010-02-18 00:35:03 +09001351#endif
Richard Hendersonfb41a662010-05-03 10:07:52 -07001352 }
1353
Riku Voipio099d6b02009-05-05 12:10:04 +03001354 if (put_user_s32(host_pipe[0], pipedes)
1355 || put_user_s32(host_pipe[1], pipedes + sizeof(host_pipe[0])))
1356 return -TARGET_EFAULT;
Riku Voipio099d6b02009-05-05 12:10:04 +03001357 return get_errno(ret);
1358}
1359
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001360static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
1361 abi_ulong target_addr,
1362 socklen_t len)
1363{
1364 struct target_ip_mreqn *target_smreqn;
1365
1366 target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
1367 if (!target_smreqn)
1368 return -TARGET_EFAULT;
1369 mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
1370 mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
1371 if (len == sizeof(struct target_ip_mreqn))
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001372 mreqn->imr_ifindex = tswapal(target_smreqn->imr_ifindex);
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001373 unlock_user(target_smreqn, target_addr, 0);
1374
1375 return 0;
1376}
1377
Laurent Vivier7b36f782015-10-28 21:40:44 +01001378static inline abi_long target_to_host_sockaddr(int fd, struct sockaddr *addr,
bellard579a97f2007-11-11 14:26:47 +00001379 abi_ulong target_addr,
1380 socklen_t len)
bellard7854b052003-03-29 17:22:23 +00001381{
aurel32607175e2009-04-15 16:11:59 +00001382 const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
1383 sa_family_t sa_family;
pbrook53a59602006-03-25 19:31:22 +00001384 struct target_sockaddr *target_saddr;
1385
Laurent Vivier7b36f782015-10-28 21:40:44 +01001386 if (fd_trans_target_to_host_addr(fd)) {
1387 return fd_trans_target_to_host_addr(fd)(addr, target_addr, len);
1388 }
1389
bellard579a97f2007-11-11 14:26:47 +00001390 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
1391 if (!target_saddr)
1392 return -TARGET_EFAULT;
aurel32607175e2009-04-15 16:11:59 +00001393
1394 sa_family = tswap16(target_saddr->sa_family);
1395
1396 /* Oops. The caller might send a incomplete sun_path; sun_path
1397 * must be terminated by \0 (see the manual page), but
1398 * unfortunately it is quite common to specify sockaddr_un
1399 * length as "strlen(x->sun_path)" while it should be
1400 * "strlen(...) + 1". We'll fix that here if needed.
1401 * Linux kernel has a similar feature.
1402 */
1403
1404 if (sa_family == AF_UNIX) {
1405 if (len < unix_maxlen && len > 0) {
1406 char *cp = (char*)target_saddr;
1407
1408 if ( cp[len-1] && !cp[len] )
1409 len++;
1410 }
1411 if (len > unix_maxlen)
1412 len = unix_maxlen;
1413 }
1414
pbrook53a59602006-03-25 19:31:22 +00001415 memcpy(addr, target_saddr, len);
aurel32607175e2009-04-15 16:11:59 +00001416 addr->sa_family = sa_family;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02001417 if (sa_family == AF_NETLINK) {
1418 struct sockaddr_nl *nladdr;
1419
1420 nladdr = (struct sockaddr_nl *)addr;
1421 nladdr->nl_pid = tswap32(nladdr->nl_pid);
1422 nladdr->nl_groups = tswap32(nladdr->nl_groups);
1423 } else if (sa_family == AF_PACKET) {
Joakim Tjernlund33a29b52014-07-12 15:47:07 +02001424 struct target_sockaddr_ll *lladdr;
1425
1426 lladdr = (struct target_sockaddr_ll *)addr;
1427 lladdr->sll_ifindex = tswap32(lladdr->sll_ifindex);
1428 lladdr->sll_hatype = tswap16(lladdr->sll_hatype);
1429 }
pbrook53a59602006-03-25 19:31:22 +00001430 unlock_user(target_saddr, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001431
1432 return 0;
bellard7854b052003-03-29 17:22:23 +00001433}
1434
bellard579a97f2007-11-11 14:26:47 +00001435static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
1436 struct sockaddr *addr,
1437 socklen_t len)
bellard7854b052003-03-29 17:22:23 +00001438{
pbrook53a59602006-03-25 19:31:22 +00001439 struct target_sockaddr *target_saddr;
1440
Peter Maydella1e22192016-07-07 15:44:43 +01001441 if (len == 0) {
1442 return 0;
1443 }
Philippe Mathieu-Daudé68607102017-07-26 23:42:18 -03001444 assert(addr);
Peter Maydella1e22192016-07-07 15:44:43 +01001445
bellard579a97f2007-11-11 14:26:47 +00001446 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
1447 if (!target_saddr)
1448 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001449 memcpy(target_saddr, addr, len);
Peter Maydella1e22192016-07-07 15:44:43 +01001450 if (len >= offsetof(struct target_sockaddr, sa_family) +
1451 sizeof(target_saddr->sa_family)) {
1452 target_saddr->sa_family = tswap16(addr->sa_family);
1453 }
1454 if (addr->sa_family == AF_NETLINK && len >= sizeof(struct sockaddr_nl)) {
Laurent Vivier6c5b5642016-05-22 18:56:19 +02001455 struct sockaddr_nl *target_nl = (struct sockaddr_nl *)target_saddr;
1456 target_nl->nl_pid = tswap32(target_nl->nl_pid);
1457 target_nl->nl_groups = tswap32(target_nl->nl_groups);
Laurent Viviera82ea932016-06-27 00:18:22 +02001458 } else if (addr->sa_family == AF_PACKET) {
1459 struct sockaddr_ll *target_ll = (struct sockaddr_ll *)target_saddr;
1460 target_ll->sll_ifindex = tswap32(target_ll->sll_ifindex);
1461 target_ll->sll_hatype = tswap16(target_ll->sll_hatype);
Helge Delleree1ac3a2017-02-18 23:31:30 +01001462 } else if (addr->sa_family == AF_INET6 &&
1463 len >= sizeof(struct target_sockaddr_in6)) {
1464 struct target_sockaddr_in6 *target_in6 =
1465 (struct target_sockaddr_in6 *)target_saddr;
1466 target_in6->sin6_scope_id = tswap16(target_in6->sin6_scope_id);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02001467 }
pbrook53a59602006-03-25 19:31:22 +00001468 unlock_user(target_saddr, target_addr, len);
bellard579a97f2007-11-11 14:26:47 +00001469
1470 return 0;
bellard7854b052003-03-29 17:22:23 +00001471}
1472
bellard5a4a8982007-11-11 17:39:18 +00001473static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
1474 struct target_msghdr *target_msgh)
bellard7854b052003-03-29 17:22:23 +00001475{
1476 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001477 abi_long msg_controllen;
1478 abi_ulong target_cmsg_addr;
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001479 struct target_cmsghdr *target_cmsg, *target_cmsg_start;
bellard7854b052003-03-29 17:22:23 +00001480 socklen_t space = 0;
bellard5a4a8982007-11-11 17:39:18 +00001481
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001482 msg_controllen = tswapal(target_msgh->msg_controllen);
bellard5a4a8982007-11-11 17:39:18 +00001483 if (msg_controllen < sizeof (struct target_cmsghdr))
1484 goto the_end;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001485 target_cmsg_addr = tswapal(target_msgh->msg_control);
bellard5a4a8982007-11-11 17:39:18 +00001486 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001487 target_cmsg_start = target_cmsg;
bellard5a4a8982007-11-11 17:39:18 +00001488 if (!target_cmsg)
1489 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001490
1491 while (cmsg && target_cmsg) {
1492 void *data = CMSG_DATA(cmsg);
1493 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1494
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001495 int len = tswapal(target_cmsg->cmsg_len)
Peter Maydellad762b92017-12-15 13:52:56 +00001496 - sizeof(struct target_cmsghdr);
bellard7854b052003-03-29 17:22:23 +00001497
1498 space += CMSG_SPACE(len);
1499 if (space > msgh->msg_controllen) {
1500 space -= CMSG_SPACE(len);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001501 /* This is a QEMU bug, since we allocated the payload
1502 * area ourselves (unlike overflow in host-to-target
1503 * conversion, which is just the guest giving us a buffer
1504 * that's too small). It can't happen for the payload types
1505 * we currently support; if it becomes an issue in future
1506 * we would need to improve our allocation strategy to
1507 * something more intelligent than "twice the size of the
1508 * target buffer we're reading from".
1509 */
bellard31febb72005-12-18 20:03:27 +00001510 gemu_log("Host cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +00001511 break;
1512 }
1513
Petar Jovanovicdbf4f792013-09-13 19:27:29 +02001514 if (tswap32(target_cmsg->cmsg_level) == TARGET_SOL_SOCKET) {
1515 cmsg->cmsg_level = SOL_SOCKET;
1516 } else {
1517 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
1518 }
bellard7854b052003-03-29 17:22:23 +00001519 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
1520 cmsg->cmsg_len = CMSG_LEN(len);
1521
Alex Suykov30b8b682014-12-23 07:52:58 +02001522 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +00001523 int *fd = (int *)data;
1524 int *target_fd = (int *)target_data;
1525 int i, numfds = len / sizeof(int);
1526
Peter Maydell876e23c2015-05-26 19:46:32 +01001527 for (i = 0; i < numfds; i++) {
1528 __get_user(fd[i], target_fd + i);
1529 }
Alex Suykov30b8b682014-12-23 07:52:58 +02001530 } else if (cmsg->cmsg_level == SOL_SOCKET
1531 && cmsg->cmsg_type == SCM_CREDENTIALS) {
1532 struct ucred *cred = (struct ucred *)data;
1533 struct target_ucred *target_cred =
1534 (struct target_ucred *)target_data;
1535
Peter Maydell876e23c2015-05-26 19:46:32 +01001536 __get_user(cred->pid, &target_cred->pid);
1537 __get_user(cred->uid, &target_cred->uid);
1538 __get_user(cred->gid, &target_cred->gid);
Alex Suykov30b8b682014-12-23 07:52:58 +02001539 } else {
1540 gemu_log("Unsupported ancillary data: %d/%d\n",
1541 cmsg->cmsg_level, cmsg->cmsg_type);
1542 memcpy(data, target_data, len);
bellard7854b052003-03-29 17:22:23 +00001543 }
1544
1545 cmsg = CMSG_NXTHDR(msgh, cmsg);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001546 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg,
1547 target_cmsg_start);
bellard7854b052003-03-29 17:22:23 +00001548 }
bellard5a4a8982007-11-11 17:39:18 +00001549 unlock_user(target_cmsg, target_cmsg_addr, 0);
1550 the_end:
bellard7854b052003-03-29 17:22:23 +00001551 msgh->msg_controllen = space;
bellard5a4a8982007-11-11 17:39:18 +00001552 return 0;
bellard7854b052003-03-29 17:22:23 +00001553}
1554
bellard5a4a8982007-11-11 17:39:18 +00001555static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
1556 struct msghdr *msgh)
bellard7854b052003-03-29 17:22:23 +00001557{
1558 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001559 abi_long msg_controllen;
1560 abi_ulong target_cmsg_addr;
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001561 struct target_cmsghdr *target_cmsg, *target_cmsg_start;
bellard7854b052003-03-29 17:22:23 +00001562 socklen_t space = 0;
1563
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001564 msg_controllen = tswapal(target_msgh->msg_controllen);
bellard5a4a8982007-11-11 17:39:18 +00001565 if (msg_controllen < sizeof (struct target_cmsghdr))
1566 goto the_end;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001567 target_cmsg_addr = tswapal(target_msgh->msg_control);
bellard5a4a8982007-11-11 17:39:18 +00001568 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001569 target_cmsg_start = target_cmsg;
bellard5a4a8982007-11-11 17:39:18 +00001570 if (!target_cmsg)
1571 return -TARGET_EFAULT;
1572
bellard7854b052003-03-29 17:22:23 +00001573 while (cmsg && target_cmsg) {
1574 void *data = CMSG_DATA(cmsg);
1575 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1576
Peter Maydellad762b92017-12-15 13:52:56 +00001577 int len = cmsg->cmsg_len - sizeof(struct cmsghdr);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001578 int tgt_len, tgt_space;
bellard7854b052003-03-29 17:22:23 +00001579
Peter Maydellc2aeb252015-05-26 19:46:31 +01001580 /* We never copy a half-header but may copy half-data;
1581 * this is Linux's behaviour in put_cmsg(). Note that
1582 * truncation here is a guest problem (which we report
1583 * to the guest via the CTRUNC bit), unlike truncation
1584 * in target_to_host_cmsg, which is a QEMU bug.
1585 */
Peter Maydell71749702017-12-15 13:52:55 +00001586 if (msg_controllen < sizeof(struct target_cmsghdr)) {
Peter Maydellc2aeb252015-05-26 19:46:31 +01001587 target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
bellard7854b052003-03-29 17:22:23 +00001588 break;
1589 }
1590
Petar Jovanovicdbf4f792013-09-13 19:27:29 +02001591 if (cmsg->cmsg_level == SOL_SOCKET) {
1592 target_cmsg->cmsg_level = tswap32(TARGET_SOL_SOCKET);
1593 } else {
1594 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
1595 }
bellard7854b052003-03-29 17:22:23 +00001596 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
bellard7854b052003-03-29 17:22:23 +00001597
Peter Maydellc2aeb252015-05-26 19:46:31 +01001598 /* Payload types which need a different size of payload on
1599 * the target must adjust tgt_len here.
1600 */
Peter Maydell309786c2018-05-18 19:47:15 +01001601 tgt_len = len;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001602 switch (cmsg->cmsg_level) {
1603 case SOL_SOCKET:
1604 switch (cmsg->cmsg_type) {
1605 case SO_TIMESTAMP:
1606 tgt_len = sizeof(struct target_timeval);
1607 break;
1608 default:
1609 break;
1610 }
Peter Maydell309786c2018-05-18 19:47:15 +01001611 break;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001612 default:
1613 break;
1614 }
1615
Peter Maydell71749702017-12-15 13:52:55 +00001616 if (msg_controllen < TARGET_CMSG_LEN(tgt_len)) {
Peter Maydellc2aeb252015-05-26 19:46:31 +01001617 target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
Peter Maydell71749702017-12-15 13:52:55 +00001618 tgt_len = msg_controllen - sizeof(struct target_cmsghdr);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001619 }
1620
1621 /* We must now copy-and-convert len bytes of payload
1622 * into tgt_len bytes of destination space. Bear in mind
1623 * that in both source and destination we may be dealing
1624 * with a truncated value!
1625 */
Huw Davies52b65492014-04-17 14:02:47 +01001626 switch (cmsg->cmsg_level) {
1627 case SOL_SOCKET:
1628 switch (cmsg->cmsg_type) {
1629 case SCM_RIGHTS:
1630 {
1631 int *fd = (int *)data;
1632 int *target_fd = (int *)target_data;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001633 int i, numfds = tgt_len / sizeof(int);
bellard7854b052003-03-29 17:22:23 +00001634
Peter Maydell876e23c2015-05-26 19:46:32 +01001635 for (i = 0; i < numfds; i++) {
1636 __put_user(fd[i], target_fd + i);
1637 }
Huw Davies52b65492014-04-17 14:02:47 +01001638 break;
1639 }
1640 case SO_TIMESTAMP:
1641 {
1642 struct timeval *tv = (struct timeval *)data;
1643 struct target_timeval *target_tv =
1644 (struct target_timeval *)target_data;
Jing Huangaebf5bc2012-07-24 14:01:42 +00001645
Peter Maydellc2aeb252015-05-26 19:46:31 +01001646 if (len != sizeof(struct timeval) ||
1647 tgt_len != sizeof(struct target_timeval)) {
Huw Davies52b65492014-04-17 14:02:47 +01001648 goto unimplemented;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001649 }
Huw Davies52b65492014-04-17 14:02:47 +01001650
1651 /* copy struct timeval to target */
Peter Maydell876e23c2015-05-26 19:46:32 +01001652 __put_user(tv->tv_sec, &target_tv->tv_sec);
1653 __put_user(tv->tv_usec, &target_tv->tv_usec);
Huw Davies52b65492014-04-17 14:02:47 +01001654 break;
1655 }
Huw Davies4bc29752014-04-17 14:02:48 +01001656 case SCM_CREDENTIALS:
1657 {
1658 struct ucred *cred = (struct ucred *)data;
1659 struct target_ucred *target_cred =
1660 (struct target_ucred *)target_data;
1661
1662 __put_user(cred->pid, &target_cred->pid);
1663 __put_user(cred->uid, &target_cred->uid);
1664 __put_user(cred->gid, &target_cred->gid);
1665 break;
1666 }
Huw Davies52b65492014-04-17 14:02:47 +01001667 default:
1668 goto unimplemented;
1669 }
1670 break;
1671
Helge Delleree1ac3a2017-02-18 23:31:30 +01001672 case SOL_IP:
1673 switch (cmsg->cmsg_type) {
1674 case IP_TTL:
1675 {
1676 uint32_t *v = (uint32_t *)data;
1677 uint32_t *t_int = (uint32_t *)target_data;
1678
Peter Maydell71749702017-12-15 13:52:55 +00001679 if (len != sizeof(uint32_t) ||
1680 tgt_len != sizeof(uint32_t)) {
1681 goto unimplemented;
1682 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01001683 __put_user(*v, t_int);
1684 break;
1685 }
1686 case IP_RECVERR:
1687 {
1688 struct errhdr_t {
1689 struct sock_extended_err ee;
1690 struct sockaddr_in offender;
1691 };
1692 struct errhdr_t *errh = (struct errhdr_t *)data;
1693 struct errhdr_t *target_errh =
1694 (struct errhdr_t *)target_data;
1695
Peter Maydell71749702017-12-15 13:52:55 +00001696 if (len != sizeof(struct errhdr_t) ||
1697 tgt_len != sizeof(struct errhdr_t)) {
1698 goto unimplemented;
1699 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01001700 __put_user(errh->ee.ee_errno, &target_errh->ee.ee_errno);
1701 __put_user(errh->ee.ee_origin, &target_errh->ee.ee_origin);
1702 __put_user(errh->ee.ee_type, &target_errh->ee.ee_type);
1703 __put_user(errh->ee.ee_code, &target_errh->ee.ee_code);
1704 __put_user(errh->ee.ee_pad, &target_errh->ee.ee_pad);
1705 __put_user(errh->ee.ee_info, &target_errh->ee.ee_info);
1706 __put_user(errh->ee.ee_data, &target_errh->ee.ee_data);
1707 host_to_target_sockaddr((unsigned long) &target_errh->offender,
1708 (void *) &errh->offender, sizeof(errh->offender));
1709 break;
1710 }
1711 default:
1712 goto unimplemented;
1713 }
1714 break;
1715
1716 case SOL_IPV6:
1717 switch (cmsg->cmsg_type) {
1718 case IPV6_HOPLIMIT:
1719 {
1720 uint32_t *v = (uint32_t *)data;
1721 uint32_t *t_int = (uint32_t *)target_data;
1722
Peter Maydell71749702017-12-15 13:52:55 +00001723 if (len != sizeof(uint32_t) ||
1724 tgt_len != sizeof(uint32_t)) {
1725 goto unimplemented;
1726 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01001727 __put_user(*v, t_int);
1728 break;
1729 }
1730 case IPV6_RECVERR:
1731 {
1732 struct errhdr6_t {
1733 struct sock_extended_err ee;
1734 struct sockaddr_in6 offender;
1735 };
1736 struct errhdr6_t *errh = (struct errhdr6_t *)data;
1737 struct errhdr6_t *target_errh =
1738 (struct errhdr6_t *)target_data;
1739
Peter Maydell71749702017-12-15 13:52:55 +00001740 if (len != sizeof(struct errhdr6_t) ||
1741 tgt_len != sizeof(struct errhdr6_t)) {
1742 goto unimplemented;
1743 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01001744 __put_user(errh->ee.ee_errno, &target_errh->ee.ee_errno);
1745 __put_user(errh->ee.ee_origin, &target_errh->ee.ee_origin);
1746 __put_user(errh->ee.ee_type, &target_errh->ee.ee_type);
1747 __put_user(errh->ee.ee_code, &target_errh->ee.ee_code);
1748 __put_user(errh->ee.ee_pad, &target_errh->ee.ee_pad);
1749 __put_user(errh->ee.ee_info, &target_errh->ee.ee_info);
1750 __put_user(errh->ee.ee_data, &target_errh->ee.ee_data);
1751 host_to_target_sockaddr((unsigned long) &target_errh->offender,
1752 (void *) &errh->offender, sizeof(errh->offender));
1753 break;
1754 }
1755 default:
1756 goto unimplemented;
1757 }
1758 break;
1759
Huw Davies52b65492014-04-17 14:02:47 +01001760 default:
1761 unimplemented:
Jing Huangaebf5bc2012-07-24 14:01:42 +00001762 gemu_log("Unsupported ancillary data: %d/%d\n",
1763 cmsg->cmsg_level, cmsg->cmsg_type);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001764 memcpy(target_data, data, MIN(len, tgt_len));
1765 if (tgt_len > len) {
1766 memset(target_data + len, 0, tgt_len - len);
1767 }
bellard7854b052003-03-29 17:22:23 +00001768 }
1769
Peter Maydell71749702017-12-15 13:52:55 +00001770 target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(tgt_len));
1771 tgt_space = TARGET_CMSG_SPACE(tgt_len);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001772 if (msg_controllen < tgt_space) {
1773 tgt_space = msg_controllen;
1774 }
1775 msg_controllen -= tgt_space;
1776 space += tgt_space;
bellard7854b052003-03-29 17:22:23 +00001777 cmsg = CMSG_NXTHDR(msgh, cmsg);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001778 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg,
1779 target_cmsg_start);
bellard7854b052003-03-29 17:22:23 +00001780 }
bellard5a4a8982007-11-11 17:39:18 +00001781 unlock_user(target_cmsg, target_cmsg_addr, space);
1782 the_end:
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001783 target_msgh->msg_controllen = tswapal(space);
bellard5a4a8982007-11-11 17:39:18 +00001784 return 0;
bellard7854b052003-03-29 17:22:23 +00001785}
1786
ths0da46a62007-10-20 20:23:07 +00001787/* do_setsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001788static abi_long do_setsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00001789 abi_ulong optval_addr, socklen_t optlen)
bellard7854b052003-03-29 17:22:23 +00001790{
blueswir1992f48a2007-10-14 16:27:31 +00001791 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +00001792 int val;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001793 struct ip_mreqn *ip_mreq;
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02001794 struct ip_mreq_source *ip_mreq_source;
ths3b46e622007-09-17 08:09:54 +00001795
bellard8853f862004-02-22 14:57:26 +00001796 switch(level) {
1797 case SOL_TCP:
bellard7854b052003-03-29 17:22:23 +00001798 /* TCP options all take an 'int' value. */
bellard7854b052003-03-29 17:22:23 +00001799 if (optlen < sizeof(uint32_t))
ths0da46a62007-10-20 20:23:07 +00001800 return -TARGET_EINVAL;
ths3b46e622007-09-17 08:09:54 +00001801
bellard2f619692007-11-16 10:46:05 +00001802 if (get_user_u32(val, optval_addr))
1803 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001804 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1805 break;
1806 case SOL_IP:
1807 switch(optname) {
bellard2efbe912005-07-23 15:10:20 +00001808 case IP_TOS:
1809 case IP_TTL:
bellard8853f862004-02-22 14:57:26 +00001810 case IP_HDRINCL:
bellard2efbe912005-07-23 15:10:20 +00001811 case IP_ROUTER_ALERT:
1812 case IP_RECVOPTS:
1813 case IP_RETOPTS:
1814 case IP_PKTINFO:
1815 case IP_MTU_DISCOVER:
1816 case IP_RECVERR:
Helge Delleree1ac3a2017-02-18 23:31:30 +01001817 case IP_RECVTTL:
bellard2efbe912005-07-23 15:10:20 +00001818 case IP_RECVTOS:
1819#ifdef IP_FREEBIND
1820 case IP_FREEBIND:
1821#endif
1822 case IP_MULTICAST_TTL:
1823 case IP_MULTICAST_LOOP:
bellard8853f862004-02-22 14:57:26 +00001824 val = 0;
1825 if (optlen >= sizeof(uint32_t)) {
bellard2f619692007-11-16 10:46:05 +00001826 if (get_user_u32(val, optval_addr))
1827 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001828 } else if (optlen >= 1) {
bellard2f619692007-11-16 10:46:05 +00001829 if (get_user_u8(val, optval_addr))
1830 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001831 }
1832 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1833 break;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001834 case IP_ADD_MEMBERSHIP:
1835 case IP_DROP_MEMBERSHIP:
1836 if (optlen < sizeof (struct target_ip_mreq) ||
1837 optlen > sizeof (struct target_ip_mreqn))
1838 return -TARGET_EINVAL;
1839
1840 ip_mreq = (struct ip_mreqn *) alloca(optlen);
1841 target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
1842 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen));
1843 break;
1844
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02001845 case IP_BLOCK_SOURCE:
1846 case IP_UNBLOCK_SOURCE:
1847 case IP_ADD_SOURCE_MEMBERSHIP:
1848 case IP_DROP_SOURCE_MEMBERSHIP:
1849 if (optlen != sizeof (struct target_ip_mreq_source))
1850 return -TARGET_EINVAL;
1851
1852 ip_mreq_source = lock_user(VERIFY_READ, optval_addr, optlen, 1);
1853 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen));
1854 unlock_user (ip_mreq_source, optval_addr, 0);
1855 break;
1856
bellard8853f862004-02-22 14:57:26 +00001857 default:
1858 goto unimplemented;
1859 }
1860 break;
Laurent Vivier0d78b3b2013-08-30 01:46:43 +02001861 case SOL_IPV6:
1862 switch (optname) {
1863 case IPV6_MTU_DISCOVER:
1864 case IPV6_MTU:
1865 case IPV6_V6ONLY:
1866 case IPV6_RECVPKTINFO:
Helge Delleree1ac3a2017-02-18 23:31:30 +01001867 case IPV6_UNICAST_HOPS:
Laurent Vivier21749c42018-06-27 23:21:52 +02001868 case IPV6_MULTICAST_HOPS:
1869 case IPV6_MULTICAST_LOOP:
Helge Delleree1ac3a2017-02-18 23:31:30 +01001870 case IPV6_RECVERR:
1871 case IPV6_RECVHOPLIMIT:
1872 case IPV6_2292HOPLIMIT:
1873 case IPV6_CHECKSUM:
Laurent Vivier0d78b3b2013-08-30 01:46:43 +02001874 val = 0;
1875 if (optlen < sizeof(uint32_t)) {
1876 return -TARGET_EINVAL;
1877 }
1878 if (get_user_u32(val, optval_addr)) {
1879 return -TARGET_EFAULT;
1880 }
1881 ret = get_errno(setsockopt(sockfd, level, optname,
1882 &val, sizeof(val)));
1883 break;
Helge Delleree1ac3a2017-02-18 23:31:30 +01001884 case IPV6_PKTINFO:
1885 {
1886 struct in6_pktinfo pki;
1887
1888 if (optlen < sizeof(pki)) {
1889 return -TARGET_EINVAL;
1890 }
1891
1892 if (copy_from_user(&pki, optval_addr, sizeof(pki))) {
1893 return -TARGET_EFAULT;
1894 }
1895
1896 pki.ipi6_ifindex = tswap32(pki.ipi6_ifindex);
1897
1898 ret = get_errno(setsockopt(sockfd, level, optname,
1899 &pki, sizeof(pki)));
1900 break;
1901 }
1902 default:
1903 goto unimplemented;
1904 }
1905 break;
1906 case SOL_ICMPV6:
1907 switch (optname) {
1908 case ICMPV6_FILTER:
1909 {
1910 struct icmp6_filter icmp6f;
1911
1912 if (optlen > sizeof(icmp6f)) {
1913 optlen = sizeof(icmp6f);
1914 }
1915
1916 if (copy_from_user(&icmp6f, optval_addr, optlen)) {
1917 return -TARGET_EFAULT;
1918 }
1919
1920 for (val = 0; val < 8; val++) {
1921 icmp6f.data[val] = tswap32(icmp6f.data[val]);
1922 }
1923
1924 ret = get_errno(setsockopt(sockfd, level, optname,
1925 &icmp6f, optlen));
1926 break;
1927 }
Laurent Vivier0d78b3b2013-08-30 01:46:43 +02001928 default:
1929 goto unimplemented;
1930 }
1931 break;
Jing Huang920394d2012-07-24 13:59:23 +00001932 case SOL_RAW:
1933 switch (optname) {
1934 case ICMP_FILTER:
Helge Delleree1ac3a2017-02-18 23:31:30 +01001935 case IPV6_CHECKSUM:
1936 /* those take an u32 value */
Jing Huang920394d2012-07-24 13:59:23 +00001937 if (optlen < sizeof(uint32_t)) {
1938 return -TARGET_EINVAL;
1939 }
1940
1941 if (get_user_u32(val, optval_addr)) {
1942 return -TARGET_EFAULT;
1943 }
1944 ret = get_errno(setsockopt(sockfd, level, optname,
1945 &val, sizeof(val)));
1946 break;
1947
1948 default:
1949 goto unimplemented;
1950 }
1951 break;
bellard3532fa72006-06-24 15:06:03 +00001952 case TARGET_SOL_SOCKET:
bellard8853f862004-02-22 14:57:26 +00001953 switch (optname) {
Laurent Vivier1b09aeb2013-01-01 08:24:11 +00001954 case TARGET_SO_RCVTIMEO:
1955 {
1956 struct timeval tv;
1957
1958 optname = SO_RCVTIMEO;
1959
1960set_timeout:
1961 if (optlen != sizeof(struct target_timeval)) {
1962 return -TARGET_EINVAL;
1963 }
1964
1965 if (copy_from_user_timeval(&tv, optval_addr)) {
1966 return -TARGET_EFAULT;
1967 }
1968
1969 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
1970 &tv, sizeof(tv)));
1971 return ret;
1972 }
1973 case TARGET_SO_SNDTIMEO:
1974 optname = SO_SNDTIMEO;
1975 goto set_timeout;
Laurent Vivierf57d4192013-08-30 01:46:41 +02001976 case TARGET_SO_ATTACH_FILTER:
1977 {
1978 struct target_sock_fprog *tfprog;
1979 struct target_sock_filter *tfilter;
1980 struct sock_fprog fprog;
1981 struct sock_filter *filter;
1982 int i;
1983
1984 if (optlen != sizeof(*tfprog)) {
1985 return -TARGET_EINVAL;
1986 }
1987 if (!lock_user_struct(VERIFY_READ, tfprog, optval_addr, 0)) {
1988 return -TARGET_EFAULT;
1989 }
1990 if (!lock_user_struct(VERIFY_READ, tfilter,
1991 tswapal(tfprog->filter), 0)) {
1992 unlock_user_struct(tfprog, optval_addr, 1);
1993 return -TARGET_EFAULT;
1994 }
1995
1996 fprog.len = tswap16(tfprog->len);
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05301997 filter = g_try_new(struct sock_filter, fprog.len);
Laurent Vivierf57d4192013-08-30 01:46:41 +02001998 if (filter == NULL) {
1999 unlock_user_struct(tfilter, tfprog->filter, 1);
2000 unlock_user_struct(tfprog, optval_addr, 1);
2001 return -TARGET_ENOMEM;
2002 }
2003 for (i = 0; i < fprog.len; i++) {
2004 filter[i].code = tswap16(tfilter[i].code);
2005 filter[i].jt = tfilter[i].jt;
2006 filter[i].jf = tfilter[i].jf;
2007 filter[i].k = tswap32(tfilter[i].k);
2008 }
2009 fprog.filter = filter;
2010
2011 ret = get_errno(setsockopt(sockfd, SOL_SOCKET,
2012 SO_ATTACH_FILTER, &fprog, sizeof(fprog)));
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05302013 g_free(filter);
Laurent Vivierf57d4192013-08-30 01:46:41 +02002014
2015 unlock_user_struct(tfilter, tfprog->filter, 1);
2016 unlock_user_struct(tfprog, optval_addr, 1);
2017 return ret;
2018 }
Joakim Tjernlund451aaf62014-07-12 15:47:06 +02002019 case TARGET_SO_BINDTODEVICE:
2020 {
2021 char *dev_ifname, *addr_ifname;
2022
2023 if (optlen > IFNAMSIZ - 1) {
2024 optlen = IFNAMSIZ - 1;
2025 }
2026 dev_ifname = lock_user(VERIFY_READ, optval_addr, optlen, 1);
2027 if (!dev_ifname) {
2028 return -TARGET_EFAULT;
2029 }
2030 optname = SO_BINDTODEVICE;
2031 addr_ifname = alloca(IFNAMSIZ);
2032 memcpy(addr_ifname, dev_ifname, optlen);
2033 addr_ifname[optlen] = 0;
Chen Gangfad6c582016-01-11 13:58:50 +08002034 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
2035 addr_ifname, optlen));
Joakim Tjernlund451aaf62014-07-12 15:47:06 +02002036 unlock_user (dev_ifname, optval_addr, 0);
2037 return ret;
2038 }
Carlo Marcelo Arenas Belón83eb6e52018-08-24 01:56:01 -07002039 case TARGET_SO_LINGER:
2040 {
2041 struct linger lg;
2042 struct target_linger *tlg;
2043
2044 if (optlen != sizeof(struct target_linger)) {
2045 return -TARGET_EINVAL;
2046 }
2047 if (!lock_user_struct(VERIFY_READ, tlg, optval_addr, 1)) {
2048 return -TARGET_EFAULT;
2049 }
2050 __get_user(lg.l_onoff, &tlg->l_onoff);
2051 __get_user(lg.l_linger, &tlg->l_linger);
2052 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, SO_LINGER,
2053 &lg, sizeof(lg)));
2054 unlock_user_struct(tlg, optval_addr, 0);
2055 return ret;
2056 }
bellard8853f862004-02-22 14:57:26 +00002057 /* Options with 'int' argument. */
bellard3532fa72006-06-24 15:06:03 +00002058 case TARGET_SO_DEBUG:
2059 optname = SO_DEBUG;
2060 break;
2061 case TARGET_SO_REUSEADDR:
2062 optname = SO_REUSEADDR;
2063 break;
Yunqiang Su113a9dd2018-10-30 13:55:08 +01002064#ifdef SO_REUSEPORT
2065 case TARGET_SO_REUSEPORT:
2066 optname = SO_REUSEPORT;
2067 break;
2068#endif
bellard3532fa72006-06-24 15:06:03 +00002069 case TARGET_SO_TYPE:
2070 optname = SO_TYPE;
2071 break;
2072 case TARGET_SO_ERROR:
2073 optname = SO_ERROR;
2074 break;
2075 case TARGET_SO_DONTROUTE:
2076 optname = SO_DONTROUTE;
2077 break;
2078 case TARGET_SO_BROADCAST:
2079 optname = SO_BROADCAST;
2080 break;
2081 case TARGET_SO_SNDBUF:
2082 optname = SO_SNDBUF;
2083 break;
Paul Burtond79b6cc2014-06-22 11:25:35 +01002084 case TARGET_SO_SNDBUFFORCE:
2085 optname = SO_SNDBUFFORCE;
2086 break;
bellard3532fa72006-06-24 15:06:03 +00002087 case TARGET_SO_RCVBUF:
2088 optname = SO_RCVBUF;
2089 break;
Paul Burtond79b6cc2014-06-22 11:25:35 +01002090 case TARGET_SO_RCVBUFFORCE:
2091 optname = SO_RCVBUFFORCE;
2092 break;
bellard3532fa72006-06-24 15:06:03 +00002093 case TARGET_SO_KEEPALIVE:
2094 optname = SO_KEEPALIVE;
2095 break;
2096 case TARGET_SO_OOBINLINE:
2097 optname = SO_OOBINLINE;
2098 break;
2099 case TARGET_SO_NO_CHECK:
2100 optname = SO_NO_CHECK;
2101 break;
2102 case TARGET_SO_PRIORITY:
2103 optname = SO_PRIORITY;
2104 break;
bellard5e83e8e2005-03-01 22:32:06 +00002105#ifdef SO_BSDCOMPAT
bellard3532fa72006-06-24 15:06:03 +00002106 case TARGET_SO_BSDCOMPAT:
2107 optname = SO_BSDCOMPAT;
2108 break;
bellard5e83e8e2005-03-01 22:32:06 +00002109#endif
bellard3532fa72006-06-24 15:06:03 +00002110 case TARGET_SO_PASSCRED:
2111 optname = SO_PASSCRED;
2112 break;
Paul Burton82d0fe62014-06-22 11:25:36 +01002113 case TARGET_SO_PASSSEC:
2114 optname = SO_PASSSEC;
2115 break;
bellard3532fa72006-06-24 15:06:03 +00002116 case TARGET_SO_TIMESTAMP:
2117 optname = SO_TIMESTAMP;
2118 break;
2119 case TARGET_SO_RCVLOWAT:
2120 optname = SO_RCVLOWAT;
2121 break;
bellard8853f862004-02-22 14:57:26 +00002122 default:
2123 goto unimplemented;
2124 }
bellard3532fa72006-06-24 15:06:03 +00002125 if (optlen < sizeof(uint32_t))
bellard2f619692007-11-16 10:46:05 +00002126 return -TARGET_EINVAL;
bellard3532fa72006-06-24 15:06:03 +00002127
bellard2f619692007-11-16 10:46:05 +00002128 if (get_user_u32(val, optval_addr))
2129 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00002130 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
bellard8853f862004-02-22 14:57:26 +00002131 break;
bellard7854b052003-03-29 17:22:23 +00002132 default:
bellard8853f862004-02-22 14:57:26 +00002133 unimplemented:
Stefan Weilb2bedb22011-09-12 22:33:01 +02002134 gemu_log("Unsupported setsockopt level=%d optname=%d\n", level, optname);
ths6fa13c12007-12-18 02:41:04 +00002135 ret = -TARGET_ENOPROTOOPT;
bellard7854b052003-03-29 17:22:23 +00002136 }
bellard8853f862004-02-22 14:57:26 +00002137 return ret;
bellard7854b052003-03-29 17:22:23 +00002138}
2139
ths0da46a62007-10-20 20:23:07 +00002140/* do_getsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002141static abi_long do_getsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00002142 abi_ulong optval_addr, abi_ulong optlen)
bellard7854b052003-03-29 17:22:23 +00002143{
blueswir1992f48a2007-10-14 16:27:31 +00002144 abi_long ret;
blueswir1b55266b2008-09-20 08:07:15 +00002145 int len, val;
2146 socklen_t lv;
bellard8853f862004-02-22 14:57:26 +00002147
2148 switch(level) {
bellard3532fa72006-06-24 15:06:03 +00002149 case TARGET_SOL_SOCKET:
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002150 level = SOL_SOCKET;
2151 switch (optname) {
2152 /* These don't just return a single integer */
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002153 case TARGET_SO_RCVTIMEO:
2154 case TARGET_SO_SNDTIMEO:
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002155 case TARGET_SO_PEERNAME:
2156 goto unimplemented;
Akos PASZTORY583359a2011-11-14 15:09:49 +02002157 case TARGET_SO_PEERCRED: {
2158 struct ucred cr;
2159 socklen_t crlen;
2160 struct target_ucred *tcr;
2161
2162 if (get_user_u32(len, optlen)) {
2163 return -TARGET_EFAULT;
2164 }
2165 if (len < 0) {
2166 return -TARGET_EINVAL;
2167 }
2168
2169 crlen = sizeof(cr);
2170 ret = get_errno(getsockopt(sockfd, level, SO_PEERCRED,
2171 &cr, &crlen));
2172 if (ret < 0) {
2173 return ret;
2174 }
2175 if (len > crlen) {
2176 len = crlen;
2177 }
2178 if (!lock_user_struct(VERIFY_WRITE, tcr, optval_addr, 0)) {
2179 return -TARGET_EFAULT;
2180 }
2181 __put_user(cr.pid, &tcr->pid);
2182 __put_user(cr.uid, &tcr->uid);
2183 __put_user(cr.gid, &tcr->gid);
2184 unlock_user_struct(tcr, optval_addr, 1);
2185 if (put_user_u32(len, optlen)) {
2186 return -TARGET_EFAULT;
2187 }
2188 break;
2189 }
Carlo Marcelo Arenas Belón83eb6e52018-08-24 01:56:01 -07002190 case TARGET_SO_LINGER:
2191 {
2192 struct linger lg;
2193 socklen_t lglen;
2194 struct target_linger *tlg;
2195
2196 if (get_user_u32(len, optlen)) {
2197 return -TARGET_EFAULT;
2198 }
2199 if (len < 0) {
2200 return -TARGET_EINVAL;
2201 }
2202
2203 lglen = sizeof(lg);
2204 ret = get_errno(getsockopt(sockfd, level, SO_LINGER,
2205 &lg, &lglen));
2206 if (ret < 0) {
2207 return ret;
2208 }
2209 if (len > lglen) {
2210 len = lglen;
2211 }
2212 if (!lock_user_struct(VERIFY_WRITE, tlg, optval_addr, 0)) {
2213 return -TARGET_EFAULT;
2214 }
2215 __put_user(lg.l_onoff, &tlg->l_onoff);
2216 __put_user(lg.l_linger, &tlg->l_linger);
2217 unlock_user_struct(tlg, optval_addr, 1);
2218 if (put_user_u32(len, optlen)) {
2219 return -TARGET_EFAULT;
2220 }
2221 break;
2222 }
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002223 /* Options with 'int' argument. */
2224 case TARGET_SO_DEBUG:
2225 optname = SO_DEBUG;
2226 goto int_case;
2227 case TARGET_SO_REUSEADDR:
2228 optname = SO_REUSEADDR;
2229 goto int_case;
Yunqiang Su113a9dd2018-10-30 13:55:08 +01002230#ifdef SO_REUSEPORT
2231 case TARGET_SO_REUSEPORT:
2232 optname = SO_REUSEPORT;
2233 goto int_case;
2234#endif
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002235 case TARGET_SO_TYPE:
2236 optname = SO_TYPE;
2237 goto int_case;
2238 case TARGET_SO_ERROR:
2239 optname = SO_ERROR;
2240 goto int_case;
2241 case TARGET_SO_DONTROUTE:
2242 optname = SO_DONTROUTE;
2243 goto int_case;
2244 case TARGET_SO_BROADCAST:
2245 optname = SO_BROADCAST;
2246 goto int_case;
2247 case TARGET_SO_SNDBUF:
2248 optname = SO_SNDBUF;
2249 goto int_case;
2250 case TARGET_SO_RCVBUF:
2251 optname = SO_RCVBUF;
2252 goto int_case;
2253 case TARGET_SO_KEEPALIVE:
2254 optname = SO_KEEPALIVE;
2255 goto int_case;
2256 case TARGET_SO_OOBINLINE:
2257 optname = SO_OOBINLINE;
2258 goto int_case;
2259 case TARGET_SO_NO_CHECK:
2260 optname = SO_NO_CHECK;
2261 goto int_case;
2262 case TARGET_SO_PRIORITY:
2263 optname = SO_PRIORITY;
2264 goto int_case;
2265#ifdef SO_BSDCOMPAT
2266 case TARGET_SO_BSDCOMPAT:
2267 optname = SO_BSDCOMPAT;
2268 goto int_case;
2269#endif
2270 case TARGET_SO_PASSCRED:
2271 optname = SO_PASSCRED;
2272 goto int_case;
2273 case TARGET_SO_TIMESTAMP:
2274 optname = SO_TIMESTAMP;
2275 goto int_case;
2276 case TARGET_SO_RCVLOWAT:
2277 optname = SO_RCVLOWAT;
2278 goto int_case;
Paul Burtonaec1ca42014-06-22 11:25:34 +01002279 case TARGET_SO_ACCEPTCONN:
2280 optname = SO_ACCEPTCONN;
2281 goto int_case;
bellard8853f862004-02-22 14:57:26 +00002282 default:
bellard2efbe912005-07-23 15:10:20 +00002283 goto int_case;
2284 }
2285 break;
2286 case SOL_TCP:
2287 /* TCP options all take an 'int' value. */
2288 int_case:
bellard2f619692007-11-16 10:46:05 +00002289 if (get_user_u32(len, optlen))
2290 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002291 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00002292 return -TARGET_EINVAL;
Mike Frysinger73160d92011-02-07 01:05:49 -05002293 lv = sizeof(lv);
bellard2efbe912005-07-23 15:10:20 +00002294 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2295 if (ret < 0)
2296 return ret;
Paul Burton8289d112014-06-22 11:25:33 +01002297 if (optname == SO_TYPE) {
2298 val = host_to_target_sock_type(val);
2299 }
bellard2efbe912005-07-23 15:10:20 +00002300 if (len > lv)
2301 len = lv;
bellard2f619692007-11-16 10:46:05 +00002302 if (len == 4) {
2303 if (put_user_u32(val, optval_addr))
2304 return -TARGET_EFAULT;
2305 } else {
2306 if (put_user_u8(val, optval_addr))
2307 return -TARGET_EFAULT;
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002308 }
bellard2f619692007-11-16 10:46:05 +00002309 if (put_user_u32(len, optlen))
2310 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002311 break;
2312 case SOL_IP:
2313 switch(optname) {
2314 case IP_TOS:
2315 case IP_TTL:
2316 case IP_HDRINCL:
2317 case IP_ROUTER_ALERT:
2318 case IP_RECVOPTS:
2319 case IP_RETOPTS:
2320 case IP_PKTINFO:
2321 case IP_MTU_DISCOVER:
2322 case IP_RECVERR:
2323 case IP_RECVTOS:
2324#ifdef IP_FREEBIND
2325 case IP_FREEBIND:
2326#endif
2327 case IP_MULTICAST_TTL:
2328 case IP_MULTICAST_LOOP:
bellard2f619692007-11-16 10:46:05 +00002329 if (get_user_u32(len, optlen))
2330 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00002331 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00002332 return -TARGET_EINVAL;
Mike Frysinger73160d92011-02-07 01:05:49 -05002333 lv = sizeof(lv);
bellard8853f862004-02-22 14:57:26 +00002334 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2335 if (ret < 0)
2336 return ret;
bellard2efbe912005-07-23 15:10:20 +00002337 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
bellard2efbe912005-07-23 15:10:20 +00002338 len = 1;
bellard2f619692007-11-16 10:46:05 +00002339 if (put_user_u32(len, optlen)
2340 || put_user_u8(val, optval_addr))
2341 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002342 } else {
bellard2efbe912005-07-23 15:10:20 +00002343 if (len > sizeof(int))
2344 len = sizeof(int);
bellard2f619692007-11-16 10:46:05 +00002345 if (put_user_u32(len, optlen)
2346 || put_user_u32(val, optval_addr))
2347 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002348 }
bellard8853f862004-02-22 14:57:26 +00002349 break;
bellard2efbe912005-07-23 15:10:20 +00002350 default:
thsc02f4992007-12-18 02:39:59 +00002351 ret = -TARGET_ENOPROTOOPT;
2352 break;
bellard8853f862004-02-22 14:57:26 +00002353 }
2354 break;
Tom Deseynbd8ed482018-12-13 14:06:11 +01002355 case SOL_IPV6:
2356 switch (optname) {
2357 case IPV6_MTU_DISCOVER:
2358 case IPV6_MTU:
2359 case IPV6_V6ONLY:
2360 case IPV6_RECVPKTINFO:
2361 case IPV6_UNICAST_HOPS:
2362 case IPV6_MULTICAST_HOPS:
2363 case IPV6_MULTICAST_LOOP:
2364 case IPV6_RECVERR:
2365 case IPV6_RECVHOPLIMIT:
2366 case IPV6_2292HOPLIMIT:
2367 case IPV6_CHECKSUM:
2368 if (get_user_u32(len, optlen))
2369 return -TARGET_EFAULT;
2370 if (len < 0)
2371 return -TARGET_EINVAL;
2372 lv = sizeof(lv);
2373 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2374 if (ret < 0)
2375 return ret;
2376 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
2377 len = 1;
2378 if (put_user_u32(len, optlen)
2379 || put_user_u8(val, optval_addr))
2380 return -TARGET_EFAULT;
2381 } else {
2382 if (len > sizeof(int))
2383 len = sizeof(int);
2384 if (put_user_u32(len, optlen)
2385 || put_user_u32(val, optval_addr))
2386 return -TARGET_EFAULT;
2387 }
2388 break;
2389 default:
2390 ret = -TARGET_ENOPROTOOPT;
2391 break;
2392 }
2393 break;
bellard8853f862004-02-22 14:57:26 +00002394 default:
2395 unimplemented:
2396 gemu_log("getsockopt level=%d optname=%d not yet supported\n",
2397 level, optname);
thsc02f4992007-12-18 02:39:59 +00002398 ret = -TARGET_EOPNOTSUPP;
bellard8853f862004-02-22 14:57:26 +00002399 break;
2400 }
2401 return ret;
bellard7854b052003-03-29 17:22:23 +00002402}
2403
Max Filippov9ac22512018-04-04 17:30:41 -07002404/* Convert target low/high pair representing file offset into the host
2405 * low/high pair. This function doesn't handle offsets bigger than 64 bits
2406 * as the kernel doesn't handle them either.
2407 */
2408static void target_to_host_low_high(abi_ulong tlow,
2409 abi_ulong thigh,
2410 unsigned long *hlow,
2411 unsigned long *hhigh)
2412{
2413 uint64_t off = tlow |
2414 ((unsigned long long)thigh << TARGET_LONG_BITS / 2) <<
2415 TARGET_LONG_BITS / 2;
2416
2417 *hlow = off;
2418 *hhigh = (off >> HOST_LONG_BITS / 2) >> HOST_LONG_BITS / 2;
2419}
2420
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002421static struct iovec *lock_iovec(int type, abi_ulong target_addr,
Peter Maydelldab32b32016-07-15 14:57:26 +01002422 abi_ulong count, int copy)
pbrook53a59602006-03-25 19:31:22 +00002423{
2424 struct target_iovec *target_vec;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002425 struct iovec *vec;
2426 abi_ulong total_len, max_len;
balrogd732dcb2008-10-28 10:21:03 +00002427 int i;
Peter Maydell501bb4b2014-02-17 18:55:33 +00002428 int err = 0;
Tom Musta29560a62014-08-12 13:53:43 -05002429 bool bad_address = false;
pbrook53a59602006-03-25 19:31:22 +00002430
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002431 if (count == 0) {
2432 errno = 0;
2433 return NULL;
pbrook53a59602006-03-25 19:31:22 +00002434 }
Peter Maydelldab32b32016-07-15 14:57:26 +01002435 if (count > IOV_MAX) {
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002436 errno = EINVAL;
2437 return NULL;
2438 }
2439
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05302440 vec = g_try_new0(struct iovec, count);
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002441 if (vec == NULL) {
2442 errno = ENOMEM;
2443 return NULL;
2444 }
2445
2446 target_vec = lock_user(VERIFY_READ, target_addr,
2447 count * sizeof(struct target_iovec), 1);
2448 if (target_vec == NULL) {
Peter Maydell501bb4b2014-02-17 18:55:33 +00002449 err = EFAULT;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002450 goto fail2;
2451 }
2452
2453 /* ??? If host page size > target page size, this will result in a
2454 value larger than what we can actually support. */
2455 max_len = 0x7fffffff & TARGET_PAGE_MASK;
2456 total_len = 0;
2457
2458 for (i = 0; i < count; i++) {
2459 abi_ulong base = tswapal(target_vec[i].iov_base);
2460 abi_long len = tswapal(target_vec[i].iov_len);
2461
2462 if (len < 0) {
Peter Maydell501bb4b2014-02-17 18:55:33 +00002463 err = EINVAL;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002464 goto fail;
2465 } else if (len == 0) {
2466 /* Zero length pointer is ignored. */
2467 vec[i].iov_base = 0;
2468 } else {
2469 vec[i].iov_base = lock_user(type, base, len, copy);
Tom Musta29560a62014-08-12 13:53:43 -05002470 /* If the first buffer pointer is bad, this is a fault. But
2471 * subsequent bad buffers will result in a partial write; this
2472 * is realized by filling the vector with null pointers and
2473 * zero lengths. */
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002474 if (!vec[i].iov_base) {
Tom Musta29560a62014-08-12 13:53:43 -05002475 if (i == 0) {
2476 err = EFAULT;
2477 goto fail;
2478 } else {
2479 bad_address = true;
2480 }
2481 }
2482 if (bad_address) {
2483 len = 0;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002484 }
2485 if (len > max_len - total_len) {
2486 len = max_len - total_len;
2487 }
2488 }
2489 vec[i].iov_len = len;
2490 total_len += len;
2491 }
2492
2493 unlock_user(target_vec, target_addr, 0);
2494 return vec;
2495
2496 fail:
Chen Gang S7eff5182015-01-23 18:01:09 +08002497 while (--i >= 0) {
2498 if (tswapal(target_vec[i].iov_len) > 0) {
2499 unlock_user(vec[i].iov_base, tswapal(target_vec[i].iov_base), 0);
2500 }
2501 }
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002502 unlock_user(target_vec, target_addr, 0);
Peter Maydell501bb4b2014-02-17 18:55:33 +00002503 fail2:
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05302504 g_free(vec);
Peter Maydell501bb4b2014-02-17 18:55:33 +00002505 errno = err;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002506 return NULL;
pbrook53a59602006-03-25 19:31:22 +00002507}
2508
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002509static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
Peter Maydelldab32b32016-07-15 14:57:26 +01002510 abi_ulong count, int copy)
pbrook53a59602006-03-25 19:31:22 +00002511{
2512 struct target_iovec *target_vec;
pbrook53a59602006-03-25 19:31:22 +00002513 int i;
2514
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002515 target_vec = lock_user(VERIFY_READ, target_addr,
2516 count * sizeof(struct target_iovec), 1);
2517 if (target_vec) {
2518 for (i = 0; i < count; i++) {
2519 abi_ulong base = tswapal(target_vec[i].iov_base);
Chen Gang S71ec7ce2015-01-23 18:07:50 +08002520 abi_long len = tswapal(target_vec[i].iov_len);
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002521 if (len < 0) {
2522 break;
2523 }
balrogd732dcb2008-10-28 10:21:03 +00002524 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
2525 }
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002526 unlock_user(target_vec, target_addr, 0);
pbrook53a59602006-03-25 19:31:22 +00002527 }
bellard579a97f2007-11-11 14:26:47 +00002528
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05302529 g_free(vec);
pbrook53a59602006-03-25 19:31:22 +00002530}
2531
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02002532static inline int target_to_host_sock_type(int *type)
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02002533{
2534 int host_type = 0;
2535 int target_type = *type;
2536
2537 switch (target_type & TARGET_SOCK_TYPE_MASK) {
2538 case TARGET_SOCK_DGRAM:
2539 host_type = SOCK_DGRAM;
2540 break;
2541 case TARGET_SOCK_STREAM:
2542 host_type = SOCK_STREAM;
2543 break;
2544 default:
2545 host_type = target_type & TARGET_SOCK_TYPE_MASK;
2546 break;
2547 }
2548 if (target_type & TARGET_SOCK_CLOEXEC) {
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02002549#if defined(SOCK_CLOEXEC)
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02002550 host_type |= SOCK_CLOEXEC;
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02002551#else
2552 return -TARGET_EINVAL;
2553#endif
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02002554 }
2555 if (target_type & TARGET_SOCK_NONBLOCK) {
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02002556#if defined(SOCK_NONBLOCK)
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02002557 host_type |= SOCK_NONBLOCK;
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02002558#elif !defined(O_NONBLOCK)
2559 return -TARGET_EINVAL;
2560#endif
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02002561 }
2562 *type = host_type;
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02002563 return 0;
2564}
2565
2566/* Try to emulate socket type flags after socket creation. */
2567static int sock_flags_fixup(int fd, int target_type)
2568{
2569#if !defined(SOCK_NONBLOCK) && defined(O_NONBLOCK)
2570 if (target_type & TARGET_SOCK_NONBLOCK) {
2571 int flags = fcntl(fd, F_GETFL);
2572 if (fcntl(fd, F_SETFL, O_NONBLOCK | flags) == -1) {
2573 close(fd);
2574 return -TARGET_EINVAL;
2575 }
2576 }
2577#endif
2578 return fd;
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02002579}
2580
ths0da46a62007-10-20 20:23:07 +00002581/* do_socket() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002582static abi_long do_socket(int domain, int type, int protocol)
bellard3532fa72006-06-24 15:06:03 +00002583{
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02002584 int target_type = type;
2585 int ret;
2586
2587 ret = target_to_host_sock_type(&type);
2588 if (ret) {
2589 return ret;
2590 }
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02002591
Laurent Vivier575b22b2016-06-02 22:14:15 +02002592 if (domain == PF_NETLINK && !(
2593#ifdef CONFIG_RTNETLINK
2594 protocol == NETLINK_ROUTE ||
2595#endif
2596 protocol == NETLINK_KOBJECT_UEVENT ||
2597 protocol == NETLINK_AUDIT)) {
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002598 return -EPFNOSUPPORT;
2599 }
Laurent Vivierff626f22015-10-28 21:40:42 +01002600
2601 if (domain == AF_PACKET ||
2602 (domain == AF_INET && type == SOCK_PACKET)) {
2603 protocol = tswap16(protocol);
2604 }
2605
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02002606 ret = get_errno(socket(domain, type, protocol));
2607 if (ret >= 0) {
2608 ret = sock_flags_fixup(ret, target_type);
Laurent Vivier0cf22722015-10-28 21:40:45 +01002609 if (type == SOCK_PACKET) {
2610 /* Manage an obsolete case :
2611 * if socket type is SOCK_PACKET, bind by name
2612 */
2613 fd_trans_register(ret, &target_packet_trans);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002614 } else if (domain == PF_NETLINK) {
2615 switch (protocol) {
Laurent Vivier575b22b2016-06-02 22:14:15 +02002616#ifdef CONFIG_RTNETLINK
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002617 case NETLINK_ROUTE:
2618 fd_trans_register(ret, &target_netlink_route_trans);
2619 break;
Laurent Vivier575b22b2016-06-02 22:14:15 +02002620#endif
Laurent Vivierb2656202016-05-22 18:56:20 +02002621 case NETLINK_KOBJECT_UEVENT:
2622 /* nothing to do: messages are strings */
2623 break;
Laurent Vivier5ce9bb52016-05-22 18:56:21 +02002624 case NETLINK_AUDIT:
2625 fd_trans_register(ret, &target_netlink_audit_trans);
2626 break;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002627 default:
2628 g_assert_not_reached();
2629 }
Laurent Vivier0cf22722015-10-28 21:40:45 +01002630 }
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02002631 }
2632 return ret;
bellard3532fa72006-06-24 15:06:03 +00002633}
2634
ths0da46a62007-10-20 20:23:07 +00002635/* do_bind() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002636static abi_long do_bind(int sockfd, abi_ulong target_addr,
2637 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00002638{
aurel328f7aeaf2009-01-30 19:47:57 +00002639 void *addr;
Arnaud Patard917507b2009-06-19 10:44:45 +03002640 abi_long ret;
aurel328f7aeaf2009-01-30 19:47:57 +00002641
Blue Swirl38724252010-09-18 05:53:14 +00002642 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00002643 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00002644 }
aurel328f7aeaf2009-01-30 19:47:57 +00002645
aurel32607175e2009-04-15 16:11:59 +00002646 addr = alloca(addrlen+1);
ths3b46e622007-09-17 08:09:54 +00002647
Laurent Vivier7b36f782015-10-28 21:40:44 +01002648 ret = target_to_host_sockaddr(sockfd, addr, target_addr, addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03002649 if (ret)
2650 return ret;
2651
bellard3532fa72006-06-24 15:06:03 +00002652 return get_errno(bind(sockfd, addr, addrlen));
2653}
2654
ths0da46a62007-10-20 20:23:07 +00002655/* do_connect() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002656static abi_long do_connect(int sockfd, abi_ulong target_addr,
2657 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00002658{
aurel328f7aeaf2009-01-30 19:47:57 +00002659 void *addr;
Arnaud Patard917507b2009-06-19 10:44:45 +03002660 abi_long ret;
aurel328f7aeaf2009-01-30 19:47:57 +00002661
Blue Swirl38724252010-09-18 05:53:14 +00002662 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00002663 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00002664 }
aurel328f7aeaf2009-01-30 19:47:57 +00002665
Joakim Tjernlund2dd08df2014-07-11 17:18:03 +02002666 addr = alloca(addrlen+1);
ths3b46e622007-09-17 08:09:54 +00002667
Laurent Vivier7b36f782015-10-28 21:40:44 +01002668 ret = target_to_host_sockaddr(sockfd, addr, target_addr, addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03002669 if (ret)
2670 return ret;
2671
Peter Maydell2a3c7612016-06-06 19:58:03 +01002672 return get_errno(safe_connect(sockfd, addr, addrlen));
bellard3532fa72006-06-24 15:06:03 +00002673}
2674
Alexander Graff19e00d2014-03-02 19:36:42 +00002675/* do_sendrecvmsg_locked() Must return target values and target errnos. */
2676static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
2677 int flags, int send)
bellard3532fa72006-06-24 15:06:03 +00002678{
balrog6de645c2008-10-28 10:26:29 +00002679 abi_long ret, len;
bellard3532fa72006-06-24 15:06:03 +00002680 struct msghdr msg;
Peter Maydelldab32b32016-07-15 14:57:26 +01002681 abi_ulong count;
bellard3532fa72006-06-24 15:06:03 +00002682 struct iovec *vec;
blueswir1992f48a2007-10-14 16:27:31 +00002683 abi_ulong target_vec;
bellard3532fa72006-06-24 15:06:03 +00002684
bellard3532fa72006-06-24 15:06:03 +00002685 if (msgp->msg_name) {
2686 msg.msg_namelen = tswap32(msgp->msg_namelen);
Joakim Tjernlund2dd08df2014-07-11 17:18:03 +02002687 msg.msg_name = alloca(msg.msg_namelen+1);
Laurent Vivier7b36f782015-10-28 21:40:44 +01002688 ret = target_to_host_sockaddr(fd, msg.msg_name,
2689 tswapal(msgp->msg_name),
2690 msg.msg_namelen);
Peter Maydell26a6fc92016-07-15 14:57:28 +01002691 if (ret == -TARGET_EFAULT) {
2692 /* For connected sockets msg_name and msg_namelen must
2693 * be ignored, so returning EFAULT immediately is wrong.
2694 * Instead, pass a bad msg_name to the host kernel, and
2695 * let it decide whether to return EFAULT or not.
2696 */
2697 msg.msg_name = (void *)-1;
2698 } else if (ret) {
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002699 goto out2;
Arnaud Patard917507b2009-06-19 10:44:45 +03002700 }
bellard3532fa72006-06-24 15:06:03 +00002701 } else {
2702 msg.msg_name = NULL;
2703 msg.msg_namelen = 0;
2704 }
Matthias Brauncbb21ee2011-08-12 19:57:41 +02002705 msg.msg_controllen = 2 * tswapal(msgp->msg_controllen);
bellard3532fa72006-06-24 15:06:03 +00002706 msg.msg_control = alloca(msg.msg_controllen);
Jonas Schievink1d3d1b22018-07-12 00:12:44 +02002707 memset(msg.msg_control, 0, msg.msg_controllen);
2708
bellard3532fa72006-06-24 15:06:03 +00002709 msg.msg_flags = tswap32(msgp->msg_flags);
ths3b46e622007-09-17 08:09:54 +00002710
Matthias Brauncbb21ee2011-08-12 19:57:41 +02002711 count = tswapal(msgp->msg_iovlen);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02002712 target_vec = tswapal(msgp->msg_iov);
Peter Maydell97b07972016-07-15 14:57:27 +01002713
2714 if (count > IOV_MAX) {
2715 /* sendrcvmsg returns a different errno for this condition than
2716 * readv/writev, so we must catch it here before lock_iovec() does.
2717 */
2718 ret = -TARGET_EMSGSIZE;
2719 goto out2;
2720 }
2721
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002722 vec = lock_iovec(send ? VERIFY_READ : VERIFY_WRITE,
2723 target_vec, count, send);
2724 if (vec == NULL) {
2725 ret = -host_to_target_errno(errno);
2726 goto out2;
2727 }
bellard3532fa72006-06-24 15:06:03 +00002728 msg.msg_iovlen = count;
2729 msg.msg_iov = vec;
ths3b46e622007-09-17 08:09:54 +00002730
bellard3532fa72006-06-24 15:06:03 +00002731 if (send) {
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002732 if (fd_trans_target_to_host_data(fd)) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02002733 void *host_msg;
2734
2735 host_msg = g_malloc(msg.msg_iov->iov_len);
2736 memcpy(host_msg, msg.msg_iov->iov_base, msg.msg_iov->iov_len);
2737 ret = fd_trans_target_to_host_data(fd)(host_msg,
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002738 msg.msg_iov->iov_len);
Laurent Vivier7d61d892016-06-21 19:51:14 +02002739 if (ret >= 0) {
2740 msg.msg_iov->iov_base = host_msg;
2741 ret = get_errno(safe_sendmsg(fd, &msg, flags));
2742 }
2743 g_free(host_msg);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002744 } else {
2745 ret = target_to_host_cmsg(&msg, msgp);
Laurent Vivier7d61d892016-06-21 19:51:14 +02002746 if (ret == 0) {
2747 ret = get_errno(safe_sendmsg(fd, &msg, flags));
2748 }
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002749 }
bellard3532fa72006-06-24 15:06:03 +00002750 } else {
Peter Maydell66687532016-06-06 19:58:04 +01002751 ret = get_errno(safe_recvmsg(fd, &msg, flags));
balrog6de645c2008-10-28 10:26:29 +00002752 if (!is_error(ret)) {
2753 len = ret;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002754 if (fd_trans_host_to_target_data(fd)) {
2755 ret = fd_trans_host_to_target_data(fd)(msg.msg_iov->iov_base,
Laurent Vivier2a03d3e2018-08-20 19:15:54 +02002756 MIN(msg.msg_iov->iov_len, len));
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002757 } else {
2758 ret = host_to_target_cmsg(msgp, &msg);
2759 }
Jing Huangca619062012-07-24 13:58:02 +00002760 if (!is_error(ret)) {
2761 msgp->msg_namelen = tswap32(msg.msg_namelen);
Andreas Schwab24894f32019-02-12 17:34:35 +01002762 msgp->msg_flags = tswap32(msg.msg_flags);
Peter Maydell26a6fc92016-07-15 14:57:28 +01002763 if (msg.msg_name != NULL && msg.msg_name != (void *)-1) {
Jing Huangca619062012-07-24 13:58:02 +00002764 ret = host_to_target_sockaddr(tswapal(msgp->msg_name),
2765 msg.msg_name, msg.msg_namelen);
2766 if (ret) {
2767 goto out;
2768 }
2769 }
2770
balrog6de645c2008-10-28 10:26:29 +00002771 ret = len;
Jing Huangca619062012-07-24 13:58:02 +00002772 }
balrog6de645c2008-10-28 10:26:29 +00002773 }
bellard3532fa72006-06-24 15:06:03 +00002774 }
Jing Huangca619062012-07-24 13:58:02 +00002775
2776out:
bellard3532fa72006-06-24 15:06:03 +00002777 unlock_iovec(vec, target_vec, count, !send);
Richard Hendersonf287b2c2012-09-15 13:20:25 -07002778out2:
Alexander Graff19e00d2014-03-02 19:36:42 +00002779 return ret;
2780}
2781
2782static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
2783 int flags, int send)
2784{
2785 abi_long ret;
2786 struct target_msghdr *msgp;
2787
2788 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
2789 msgp,
2790 target_msg,
2791 send ? 1 : 0)) {
2792 return -TARGET_EFAULT;
2793 }
2794 ret = do_sendrecvmsg_locked(fd, msgp, flags, send);
bellard579a97f2007-11-11 14:26:47 +00002795 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
bellard3532fa72006-06-24 15:06:03 +00002796 return ret;
2797}
2798
Alexander Graff19e00d2014-03-02 19:36:42 +00002799/* We don't rely on the C library to have sendmmsg/recvmmsg support,
2800 * so it might not have this *mmsg-specific flag either.
2801 */
2802#ifndef MSG_WAITFORONE
2803#define MSG_WAITFORONE 0x10000
2804#endif
2805
2806static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec,
2807 unsigned int vlen, unsigned int flags,
2808 int send)
2809{
2810 struct target_mmsghdr *mmsgp;
2811 abi_long ret = 0;
2812 int i;
2813
2814 if (vlen > UIO_MAXIOV) {
2815 vlen = UIO_MAXIOV;
2816 }
2817
2818 mmsgp = lock_user(VERIFY_WRITE, target_msgvec, sizeof(*mmsgp) * vlen, 1);
2819 if (!mmsgp) {
2820 return -TARGET_EFAULT;
2821 }
2822
2823 for (i = 0; i < vlen; i++) {
2824 ret = do_sendrecvmsg_locked(fd, &mmsgp[i].msg_hdr, flags, send);
2825 if (is_error(ret)) {
2826 break;
2827 }
2828 mmsgp[i].msg_len = tswap32(ret);
2829 /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
2830 if (flags & MSG_WAITFORONE) {
2831 flags |= MSG_DONTWAIT;
2832 }
2833 }
2834
2835 unlock_user(mmsgp, target_msgvec, sizeof(*mmsgp) * i);
2836
2837 /* Return number of datagrams sent if we sent any at all;
2838 * otherwise return the error.
2839 */
2840 if (i) {
2841 return i;
2842 }
2843 return ret;
2844}
Alexander Graff19e00d2014-03-02 19:36:42 +00002845
Peter Maydella94b4982013-02-08 04:35:04 +00002846/* do_accept4() Must return target values and target errnos. */
2847static abi_long do_accept4(int fd, abi_ulong target_addr,
2848 abi_ulong target_addrlen_addr, int flags)
pbrook1be9e1d2006-11-19 15:26:04 +00002849{
Andreas Schwabcd813362019-02-14 12:43:40 +01002850 socklen_t addrlen, ret_addrlen;
bellard2f619692007-11-16 10:46:05 +00002851 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00002852 abi_long ret;
Petar Jovanovicd25295d2014-03-31 17:41:23 +02002853 int host_flags;
2854
2855 host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
pbrook1be9e1d2006-11-19 15:26:04 +00002856
Peter Maydella94b4982013-02-08 04:35:04 +00002857 if (target_addr == 0) {
Peter Maydellff6dc132016-06-06 19:58:13 +01002858 return get_errno(safe_accept4(fd, NULL, NULL, host_flags));
Peter Maydella94b4982013-02-08 04:35:04 +00002859 }
Arnaud Patard917507b2009-06-19 10:44:45 +03002860
2861 /* linux returns EINVAL if addrlen pointer is invalid */
bellard2f619692007-11-16 10:46:05 +00002862 if (get_user_u32(addrlen, target_addrlen_addr))
Arnaud Patard917507b2009-06-19 10:44:45 +03002863 return -TARGET_EINVAL;
bellard2f619692007-11-16 10:46:05 +00002864
Blue Swirl38724252010-09-18 05:53:14 +00002865 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00002866 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00002867 }
aurel328f7aeaf2009-01-30 19:47:57 +00002868
Arnaud Patard917507b2009-06-19 10:44:45 +03002869 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
2870 return -TARGET_EINVAL;
2871
bellard2f619692007-11-16 10:46:05 +00002872 addr = alloca(addrlen);
2873
Andreas Schwabcd813362019-02-14 12:43:40 +01002874 ret_addrlen = addrlen;
2875 ret = get_errno(safe_accept4(fd, addr, &ret_addrlen, host_flags));
pbrook1be9e1d2006-11-19 15:26:04 +00002876 if (!is_error(ret)) {
Andreas Schwabcd813362019-02-14 12:43:40 +01002877 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
2878 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
bellard2f619692007-11-16 10:46:05 +00002879 ret = -TARGET_EFAULT;
Andreas Schwabcd813362019-02-14 12:43:40 +01002880 }
pbrook1be9e1d2006-11-19 15:26:04 +00002881 }
2882 return ret;
2883}
2884
ths0da46a62007-10-20 20:23:07 +00002885/* do_getpeername() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002886static abi_long do_getpeername(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00002887 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00002888{
Andreas Schwabcd813362019-02-14 12:43:40 +01002889 socklen_t addrlen, ret_addrlen;
bellard2f619692007-11-16 10:46:05 +00002890 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00002891 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00002892
bellard2f619692007-11-16 10:46:05 +00002893 if (get_user_u32(addrlen, target_addrlen_addr))
2894 return -TARGET_EFAULT;
2895
Blue Swirl38724252010-09-18 05:53:14 +00002896 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00002897 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00002898 }
aurel328f7aeaf2009-01-30 19:47:57 +00002899
Arnaud Patard917507b2009-06-19 10:44:45 +03002900 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
2901 return -TARGET_EFAULT;
2902
bellard2f619692007-11-16 10:46:05 +00002903 addr = alloca(addrlen);
2904
Andreas Schwabcd813362019-02-14 12:43:40 +01002905 ret_addrlen = addrlen;
2906 ret = get_errno(getpeername(fd, addr, &ret_addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00002907 if (!is_error(ret)) {
Andreas Schwabcd813362019-02-14 12:43:40 +01002908 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
2909 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
bellard2f619692007-11-16 10:46:05 +00002910 ret = -TARGET_EFAULT;
Andreas Schwabcd813362019-02-14 12:43:40 +01002911 }
pbrook1be9e1d2006-11-19 15:26:04 +00002912 }
2913 return ret;
2914}
2915
ths0da46a62007-10-20 20:23:07 +00002916/* do_getsockname() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002917static abi_long do_getsockname(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00002918 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00002919{
Andreas Schwabcd813362019-02-14 12:43:40 +01002920 socklen_t addrlen, ret_addrlen;
bellard2f619692007-11-16 10:46:05 +00002921 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00002922 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00002923
bellard2f619692007-11-16 10:46:05 +00002924 if (get_user_u32(addrlen, target_addrlen_addr))
2925 return -TARGET_EFAULT;
2926
Blue Swirl38724252010-09-18 05:53:14 +00002927 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00002928 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00002929 }
aurel328f7aeaf2009-01-30 19:47:57 +00002930
Arnaud Patard917507b2009-06-19 10:44:45 +03002931 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
2932 return -TARGET_EFAULT;
2933
bellard2f619692007-11-16 10:46:05 +00002934 addr = alloca(addrlen);
2935
Andreas Schwabcd813362019-02-14 12:43:40 +01002936 ret_addrlen = addrlen;
2937 ret = get_errno(getsockname(fd, addr, &ret_addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00002938 if (!is_error(ret)) {
Andreas Schwabcd813362019-02-14 12:43:40 +01002939 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
2940 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
bellard2f619692007-11-16 10:46:05 +00002941 ret = -TARGET_EFAULT;
Andreas Schwabcd813362019-02-14 12:43:40 +01002942 }
pbrook1be9e1d2006-11-19 15:26:04 +00002943 }
2944 return ret;
2945}
2946
ths0da46a62007-10-20 20:23:07 +00002947/* do_socketpair() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002948static abi_long do_socketpair(int domain, int type, int protocol,
bellard2f619692007-11-16 10:46:05 +00002949 abi_ulong target_tab_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00002950{
2951 int tab[2];
blueswir1992f48a2007-10-14 16:27:31 +00002952 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00002953
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02002954 target_to_host_sock_type(&type);
2955
pbrook1be9e1d2006-11-19 15:26:04 +00002956 ret = get_errno(socketpair(domain, type, protocol, tab));
2957 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00002958 if (put_user_s32(tab[0], target_tab_addr)
2959 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
2960 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00002961 }
2962 return ret;
2963}
2964
ths0da46a62007-10-20 20:23:07 +00002965/* do_sendto() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002966static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
2967 abi_ulong target_addr, socklen_t addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00002968{
2969 void *addr;
2970 void *host_msg;
Laurent Vivier7d61d892016-06-21 19:51:14 +02002971 void *copy_msg = NULL;
blueswir1992f48a2007-10-14 16:27:31 +00002972 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00002973
Blue Swirl38724252010-09-18 05:53:14 +00002974 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00002975 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00002976 }
aurel328f7aeaf2009-01-30 19:47:57 +00002977
bellard579a97f2007-11-11 14:26:47 +00002978 host_msg = lock_user(VERIFY_READ, msg, len, 1);
2979 if (!host_msg)
2980 return -TARGET_EFAULT;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002981 if (fd_trans_target_to_host_data(fd)) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02002982 copy_msg = host_msg;
2983 host_msg = g_malloc(len);
2984 memcpy(host_msg, copy_msg, len);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002985 ret = fd_trans_target_to_host_data(fd)(host_msg, len);
2986 if (ret < 0) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02002987 goto fail;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02002988 }
2989 }
pbrook1be9e1d2006-11-19 15:26:04 +00002990 if (target_addr) {
Joakim Tjernlund2dd08df2014-07-11 17:18:03 +02002991 addr = alloca(addrlen+1);
Laurent Vivier7b36f782015-10-28 21:40:44 +01002992 ret = target_to_host_sockaddr(fd, addr, target_addr, addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03002993 if (ret) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02002994 goto fail;
Arnaud Patard917507b2009-06-19 10:44:45 +03002995 }
Peter Maydell66687532016-06-06 19:58:04 +01002996 ret = get_errno(safe_sendto(fd, host_msg, len, flags, addr, addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00002997 } else {
Peter Maydell66687532016-06-06 19:58:04 +01002998 ret = get_errno(safe_sendto(fd, host_msg, len, flags, NULL, 0));
pbrook1be9e1d2006-11-19 15:26:04 +00002999 }
Laurent Vivier7d61d892016-06-21 19:51:14 +02003000fail:
3001 if (copy_msg) {
3002 g_free(host_msg);
3003 host_msg = copy_msg;
3004 }
pbrook1be9e1d2006-11-19 15:26:04 +00003005 unlock_user(host_msg, msg, 0);
3006 return ret;
3007}
3008
ths0da46a62007-10-20 20:23:07 +00003009/* do_recvfrom() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003010static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
3011 abi_ulong target_addr,
3012 abi_ulong target_addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00003013{
Andreas Schwabcd813362019-02-14 12:43:40 +01003014 socklen_t addrlen, ret_addrlen;
pbrook1be9e1d2006-11-19 15:26:04 +00003015 void *addr;
3016 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00003017 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003018
bellard579a97f2007-11-11 14:26:47 +00003019 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
3020 if (!host_msg)
3021 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00003022 if (target_addr) {
bellard2f619692007-11-16 10:46:05 +00003023 if (get_user_u32(addrlen, target_addrlen)) {
3024 ret = -TARGET_EFAULT;
3025 goto fail;
3026 }
Blue Swirl38724252010-09-18 05:53:14 +00003027 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003028 ret = -TARGET_EINVAL;
3029 goto fail;
3030 }
pbrook1be9e1d2006-11-19 15:26:04 +00003031 addr = alloca(addrlen);
Andreas Schwabcd813362019-02-14 12:43:40 +01003032 ret_addrlen = addrlen;
Peter Maydell66687532016-06-06 19:58:04 +01003033 ret = get_errno(safe_recvfrom(fd, host_msg, len, flags,
Andreas Schwabcd813362019-02-14 12:43:40 +01003034 addr, &ret_addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003035 } else {
3036 addr = NULL; /* To keep compiler quiet. */
Andreas Schwabcd813362019-02-14 12:43:40 +01003037 addrlen = 0; /* To keep compiler quiet. */
Peter Maydell66687532016-06-06 19:58:04 +01003038 ret = get_errno(safe_recvfrom(fd, host_msg, len, flags, NULL, 0));
pbrook1be9e1d2006-11-19 15:26:04 +00003039 }
3040 if (!is_error(ret)) {
Laurent Vivierc35e1f92016-06-21 19:51:15 +02003041 if (fd_trans_host_to_target_data(fd)) {
Laurent Vivier2a03d3e2018-08-20 19:15:54 +02003042 abi_long trans;
3043 trans = fd_trans_host_to_target_data(fd)(host_msg, MIN(ret, len));
3044 if (is_error(trans)) {
3045 ret = trans;
3046 goto fail;
3047 }
Laurent Vivierc35e1f92016-06-21 19:51:15 +02003048 }
pbrook1be9e1d2006-11-19 15:26:04 +00003049 if (target_addr) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003050 host_to_target_sockaddr(target_addr, addr,
3051 MIN(addrlen, ret_addrlen));
3052 if (put_user_u32(ret_addrlen, target_addrlen)) {
bellard2f619692007-11-16 10:46:05 +00003053 ret = -TARGET_EFAULT;
3054 goto fail;
3055 }
pbrook1be9e1d2006-11-19 15:26:04 +00003056 }
3057 unlock_user(host_msg, msg, len);
3058 } else {
bellard2f619692007-11-16 10:46:05 +00003059fail:
pbrook1be9e1d2006-11-19 15:26:04 +00003060 unlock_user(host_msg, msg, 0);
3061 }
3062 return ret;
3063}
3064
j_mayer32407102007-09-26 23:01:49 +00003065#ifdef TARGET_NR_socketcall
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003066/* do_socketcall() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003067static abi_long do_socketcall(int num, abi_ulong vptr)
bellard31e31b82003-02-18 22:55:36 +00003068{
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003069 static const unsigned nargs[] = { /* number of arguments per operation */
3070 [TARGET_SYS_SOCKET] = 3, /* domain, type, protocol */
3071 [TARGET_SYS_BIND] = 3, /* fd, addr, addrlen */
3072 [TARGET_SYS_CONNECT] = 3, /* fd, addr, addrlen */
3073 [TARGET_SYS_LISTEN] = 2, /* fd, backlog */
3074 [TARGET_SYS_ACCEPT] = 3, /* fd, addr, addrlen */
3075 [TARGET_SYS_GETSOCKNAME] = 3, /* fd, addr, addrlen */
3076 [TARGET_SYS_GETPEERNAME] = 3, /* fd, addr, addrlen */
3077 [TARGET_SYS_SOCKETPAIR] = 4, /* domain, type, protocol, tab */
3078 [TARGET_SYS_SEND] = 4, /* fd, msg, len, flags */
3079 [TARGET_SYS_RECV] = 4, /* fd, msg, len, flags */
3080 [TARGET_SYS_SENDTO] = 6, /* fd, msg, len, flags, addr, addrlen */
3081 [TARGET_SYS_RECVFROM] = 6, /* fd, msg, len, flags, addr, addrlen */
3082 [TARGET_SYS_SHUTDOWN] = 2, /* fd, how */
3083 [TARGET_SYS_SETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
3084 [TARGET_SYS_GETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
3085 [TARGET_SYS_SENDMSG] = 3, /* fd, msg, flags */
3086 [TARGET_SYS_RECVMSG] = 3, /* fd, msg, flags */
3087 [TARGET_SYS_ACCEPT4] = 4, /* fd, addr, addrlen, flags */
3088 [TARGET_SYS_RECVMMSG] = 4, /* fd, msgvec, vlen, flags */
3089 [TARGET_SYS_SENDMMSG] = 4, /* fd, msgvec, vlen, flags */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003090 };
3091 abi_long a[6]; /* max 6 args */
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003092 unsigned i;
bellard31e31b82003-02-18 22:55:36 +00003093
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003094 /* check the range of the first argument num */
3095 /* (TARGET_SYS_SENDMMSG is the highest among TARGET_SYS_xxx) */
3096 if (num < 1 || num > TARGET_SYS_SENDMMSG) {
3097 return -TARGET_EINVAL;
3098 }
3099 /* ensure we have space for args */
3100 if (nargs[num] > ARRAY_SIZE(a)) {
3101 return -TARGET_EINVAL;
3102 }
3103 /* collect the arguments in a[] according to nargs[] */
3104 for (i = 0; i < nargs[num]; ++i) {
3105 if (get_user_ual(a[i], vptr + i * sizeof(abi_long)) != 0) {
3106 return -TARGET_EFAULT;
André Hentschelb9d36eb2014-01-06 20:18:52 +01003107 }
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003108 }
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003109 /* now when we have the args, invoke the appropriate underlying function */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003110 switch (num) {
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003111 case TARGET_SYS_SOCKET: /* domain, type, protocol */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003112 return do_socket(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003113 case TARGET_SYS_BIND: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003114 return do_bind(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003115 case TARGET_SYS_CONNECT: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003116 return do_connect(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003117 case TARGET_SYS_LISTEN: /* sockfd, backlog */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003118 return get_errno(listen(a[0], a[1]));
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003119 case TARGET_SYS_ACCEPT: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003120 return do_accept4(a[0], a[1], a[2], 0);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003121 case TARGET_SYS_GETSOCKNAME: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003122 return do_getsockname(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003123 case TARGET_SYS_GETPEERNAME: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003124 return do_getpeername(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003125 case TARGET_SYS_SOCKETPAIR: /* domain, type, protocol, tab */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003126 return do_socketpair(a[0], a[1], a[2], a[3]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003127 case TARGET_SYS_SEND: /* sockfd, msg, len, flags */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003128 return do_sendto(a[0], a[1], a[2], a[3], 0, 0);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003129 case TARGET_SYS_RECV: /* sockfd, msg, len, flags */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003130 return do_recvfrom(a[0], a[1], a[2], a[3], 0, 0);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003131 case TARGET_SYS_SENDTO: /* sockfd, msg, len, flags, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003132 return do_sendto(a[0], a[1], a[2], a[3], a[4], a[5]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003133 case TARGET_SYS_RECVFROM: /* sockfd, msg, len, flags, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003134 return do_recvfrom(a[0], a[1], a[2], a[3], a[4], a[5]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003135 case TARGET_SYS_SHUTDOWN: /* sockfd, how */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003136 return get_errno(shutdown(a[0], a[1]));
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003137 case TARGET_SYS_SETSOCKOPT: /* sockfd, level, optname, optval, optlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003138 return do_setsockopt(a[0], a[1], a[2], a[3], a[4]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003139 case TARGET_SYS_GETSOCKOPT: /* sockfd, level, optname, optval, optlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003140 return do_getsockopt(a[0], a[1], a[2], a[3], a[4]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003141 case TARGET_SYS_SENDMSG: /* sockfd, msg, flags */
3142 return do_sendrecvmsg(a[0], a[1], a[2], 1);
3143 case TARGET_SYS_RECVMSG: /* sockfd, msg, flags */
3144 return do_sendrecvmsg(a[0], a[1], a[2], 0);
3145 case TARGET_SYS_ACCEPT4: /* sockfd, addr, addrlen, flags */
3146 return do_accept4(a[0], a[1], a[2], a[3]);
3147 case TARGET_SYS_RECVMMSG: /* sockfd, msgvec, vlen, flags */
3148 return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0);
3149 case TARGET_SYS_SENDMMSG: /* sockfd, msgvec, vlen, flags */
3150 return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 1);
bellard31e31b82003-02-18 22:55:36 +00003151 default:
3152 gemu_log("Unsupported socketcall: %d\n", num);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003153 return -TARGET_EINVAL;
bellard31e31b82003-02-18 22:55:36 +00003154 }
bellard31e31b82003-02-18 22:55:36 +00003155}
j_mayer32407102007-09-26 23:01:49 +00003156#endif
bellard31e31b82003-02-18 22:55:36 +00003157
bellard8853f862004-02-22 14:57:26 +00003158#define N_SHM_REGIONS 32
3159
3160static struct shm_region {
Peter Maydellb6e17872016-02-09 15:57:11 +00003161 abi_ulong start;
3162 abi_ulong size;
3163 bool in_use;
bellard8853f862004-02-22 14:57:26 +00003164} shm_regions[N_SHM_REGIONS];
3165
Peter Maydell005eb2a2016-07-15 16:50:47 +01003166#ifndef TARGET_SEMID64_DS
3167/* asm-generic version of this struct */
3168struct target_semid64_ds
ths3eb6b042007-06-03 14:26:27 +00003169{
3170 struct target_ipc_perm sem_perm;
blueswir1992f48a2007-10-14 16:27:31 +00003171 abi_ulong sem_otime;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003172#if TARGET_ABI_BITS == 32
blueswir1992f48a2007-10-14 16:27:31 +00003173 abi_ulong __unused1;
Tom Musta03527342014-08-12 13:53:32 -05003174#endif
blueswir1992f48a2007-10-14 16:27:31 +00003175 abi_ulong sem_ctime;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003176#if TARGET_ABI_BITS == 32
blueswir1992f48a2007-10-14 16:27:31 +00003177 abi_ulong __unused2;
Tom Musta03527342014-08-12 13:53:32 -05003178#endif
blueswir1992f48a2007-10-14 16:27:31 +00003179 abi_ulong sem_nsems;
3180 abi_ulong __unused3;
3181 abi_ulong __unused4;
ths3eb6b042007-06-03 14:26:27 +00003182};
Peter Maydell005eb2a2016-07-15 16:50:47 +01003183#endif
ths3eb6b042007-06-03 14:26:27 +00003184
bellard579a97f2007-11-11 14:26:47 +00003185static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
3186 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00003187{
3188 struct target_ipc_perm *target_ip;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003189 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003190
bellard579a97f2007-11-11 14:26:47 +00003191 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
3192 return -TARGET_EFAULT;
Michael S. Tsirkine8bbe362009-09-30 18:56:44 +00003193 target_ip = &(target_sd->sem_perm);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003194 host_ip->__key = tswap32(target_ip->__key);
3195 host_ip->uid = tswap32(target_ip->uid);
3196 host_ip->gid = tswap32(target_ip->gid);
3197 host_ip->cuid = tswap32(target_ip->cuid);
3198 host_ip->cgid = tswap32(target_ip->cgid);
3199#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
3200 host_ip->mode = tswap32(target_ip->mode);
3201#else
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003202 host_ip->mode = tswap16(target_ip->mode);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003203#endif
3204#if defined(TARGET_PPC)
3205 host_ip->__seq = tswap32(target_ip->__seq);
3206#else
3207 host_ip->__seq = tswap16(target_ip->__seq);
3208#endif
ths3eb6b042007-06-03 14:26:27 +00003209 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00003210 return 0;
ths3eb6b042007-06-03 14:26:27 +00003211}
3212
bellard579a97f2007-11-11 14:26:47 +00003213static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
3214 struct ipc_perm *host_ip)
ths3eb6b042007-06-03 14:26:27 +00003215{
3216 struct target_ipc_perm *target_ip;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003217 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003218
bellard579a97f2007-11-11 14:26:47 +00003219 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3220 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00003221 target_ip = &(target_sd->sem_perm);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003222 target_ip->__key = tswap32(host_ip->__key);
3223 target_ip->uid = tswap32(host_ip->uid);
3224 target_ip->gid = tswap32(host_ip->gid);
3225 target_ip->cuid = tswap32(host_ip->cuid);
3226 target_ip->cgid = tswap32(host_ip->cgid);
3227#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
3228 target_ip->mode = tswap32(host_ip->mode);
3229#else
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003230 target_ip->mode = tswap16(host_ip->mode);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003231#endif
3232#if defined(TARGET_PPC)
3233 target_ip->__seq = tswap32(host_ip->__seq);
3234#else
3235 target_ip->__seq = tswap16(host_ip->__seq);
3236#endif
ths3eb6b042007-06-03 14:26:27 +00003237 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00003238 return 0;
ths3eb6b042007-06-03 14:26:27 +00003239}
3240
bellard579a97f2007-11-11 14:26:47 +00003241static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
3242 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00003243{
Peter Maydell005eb2a2016-07-15 16:50:47 +01003244 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003245
bellard579a97f2007-11-11 14:26:47 +00003246 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
3247 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00003248 if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
3249 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003250 host_sd->sem_nsems = tswapal(target_sd->sem_nsems);
3251 host_sd->sem_otime = tswapal(target_sd->sem_otime);
3252 host_sd->sem_ctime = tswapal(target_sd->sem_ctime);
ths3eb6b042007-06-03 14:26:27 +00003253 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00003254 return 0;
ths3eb6b042007-06-03 14:26:27 +00003255}
3256
bellard579a97f2007-11-11 14:26:47 +00003257static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
3258 struct semid_ds *host_sd)
ths3eb6b042007-06-03 14:26:27 +00003259{
Peter Maydell005eb2a2016-07-15 16:50:47 +01003260 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003261
bellard579a97f2007-11-11 14:26:47 +00003262 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3263 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00003264 if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
Dong Xu Wang3a931132011-11-29 16:52:38 +08003265 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003266 target_sd->sem_nsems = tswapal(host_sd->sem_nsems);
3267 target_sd->sem_otime = tswapal(host_sd->sem_otime);
3268 target_sd->sem_ctime = tswapal(host_sd->sem_ctime);
ths3eb6b042007-06-03 14:26:27 +00003269 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00003270 return 0;
ths3eb6b042007-06-03 14:26:27 +00003271}
3272
aurel32e5289082009-04-18 16:16:12 +00003273struct target_seminfo {
3274 int semmap;
3275 int semmni;
3276 int semmns;
3277 int semmnu;
3278 int semmsl;
3279 int semopm;
3280 int semume;
3281 int semusz;
3282 int semvmx;
3283 int semaem;
3284};
3285
3286static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
3287 struct seminfo *host_seminfo)
3288{
3289 struct target_seminfo *target_seminfo;
3290 if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
3291 return -TARGET_EFAULT;
3292 __put_user(host_seminfo->semmap, &target_seminfo->semmap);
3293 __put_user(host_seminfo->semmni, &target_seminfo->semmni);
3294 __put_user(host_seminfo->semmns, &target_seminfo->semmns);
3295 __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
3296 __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
3297 __put_user(host_seminfo->semopm, &target_seminfo->semopm);
3298 __put_user(host_seminfo->semume, &target_seminfo->semume);
3299 __put_user(host_seminfo->semusz, &target_seminfo->semusz);
3300 __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
3301 __put_user(host_seminfo->semaem, &target_seminfo->semaem);
3302 unlock_user_struct(target_seminfo, target_addr, 1);
3303 return 0;
3304}
3305
thsfa294812007-02-02 22:05:00 +00003306union semun {
3307 int val;
ths3eb6b042007-06-03 14:26:27 +00003308 struct semid_ds *buf;
thsfa294812007-02-02 22:05:00 +00003309 unsigned short *array;
aurel32e5289082009-04-18 16:16:12 +00003310 struct seminfo *__buf;
thsfa294812007-02-02 22:05:00 +00003311};
3312
ths3eb6b042007-06-03 14:26:27 +00003313union target_semun {
3314 int val;
aurel32e5289082009-04-18 16:16:12 +00003315 abi_ulong buf;
3316 abi_ulong array;
3317 abi_ulong __buf;
ths3eb6b042007-06-03 14:26:27 +00003318};
3319
aurel32e5289082009-04-18 16:16:12 +00003320static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
3321 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00003322{
aurel32e5289082009-04-18 16:16:12 +00003323 int nsems;
3324 unsigned short *array;
3325 union semun semun;
3326 struct semid_ds semid_ds;
3327 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00003328
aurel32e5289082009-04-18 16:16:12 +00003329 semun.buf = &semid_ds;
3330
3331 ret = semctl(semid, 0, IPC_STAT, semun);
3332 if (ret == -1)
3333 return get_errno(ret);
3334
3335 nsems = semid_ds.sem_nsems;
3336
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303337 *host_array = g_try_new(unsigned short, nsems);
Peter Maydell69d4c702014-02-17 18:55:34 +00003338 if (!*host_array) {
3339 return -TARGET_ENOMEM;
3340 }
aurel32e5289082009-04-18 16:16:12 +00003341 array = lock_user(VERIFY_READ, target_addr,
3342 nsems*sizeof(unsigned short), 1);
Peter Maydell69d4c702014-02-17 18:55:34 +00003343 if (!array) {
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303344 g_free(*host_array);
aurel32e5289082009-04-18 16:16:12 +00003345 return -TARGET_EFAULT;
Peter Maydell69d4c702014-02-17 18:55:34 +00003346 }
aurel32e5289082009-04-18 16:16:12 +00003347
3348 for(i=0; i<nsems; i++) {
3349 __get_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00003350 }
aurel32e5289082009-04-18 16:16:12 +00003351 unlock_user(array, target_addr, 0);
3352
bellard579a97f2007-11-11 14:26:47 +00003353 return 0;
ths3eb6b042007-06-03 14:26:27 +00003354}
3355
aurel32e5289082009-04-18 16:16:12 +00003356static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
3357 unsigned short **host_array)
ths3eb6b042007-06-03 14:26:27 +00003358{
aurel32e5289082009-04-18 16:16:12 +00003359 int nsems;
3360 unsigned short *array;
3361 union semun semun;
3362 struct semid_ds semid_ds;
3363 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00003364
aurel32e5289082009-04-18 16:16:12 +00003365 semun.buf = &semid_ds;
3366
3367 ret = semctl(semid, 0, IPC_STAT, semun);
3368 if (ret == -1)
3369 return get_errno(ret);
3370
3371 nsems = semid_ds.sem_nsems;
3372
3373 array = lock_user(VERIFY_WRITE, target_addr,
3374 nsems*sizeof(unsigned short), 0);
3375 if (!array)
3376 return -TARGET_EFAULT;
3377
3378 for(i=0; i<nsems; i++) {
3379 __put_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00003380 }
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303381 g_free(*host_array);
aurel32e5289082009-04-18 16:16:12 +00003382 unlock_user(array, target_addr, 1);
3383
bellard579a97f2007-11-11 14:26:47 +00003384 return 0;
ths3eb6b042007-06-03 14:26:27 +00003385}
3386
aurel32e5289082009-04-18 16:16:12 +00003387static inline abi_long do_semctl(int semid, int semnum, int cmd,
Stefan Weild1c002b2015-02-08 15:40:58 +01003388 abi_ulong target_arg)
ths3eb6b042007-06-03 14:26:27 +00003389{
Stefan Weild1c002b2015-02-08 15:40:58 +01003390 union target_semun target_su = { .buf = target_arg };
ths3eb6b042007-06-03 14:26:27 +00003391 union semun arg;
3392 struct semid_ds dsarg;
vibi sreenivasan7b8118e2009-06-19 13:34:39 +05303393 unsigned short *array = NULL;
aurel32e5289082009-04-18 16:16:12 +00003394 struct seminfo seminfo;
3395 abi_long ret = -TARGET_EINVAL;
3396 abi_long err;
3397 cmd &= 0xff;
ths3eb6b042007-06-03 14:26:27 +00003398
3399 switch( cmd ) {
3400 case GETVAL:
ths3eb6b042007-06-03 14:26:27 +00003401 case SETVAL:
Tom Musta5464bae2014-08-12 13:53:34 -05003402 /* In 64 bit cross-endian situations, we will erroneously pick up
3403 * the wrong half of the union for the "val" element. To rectify
3404 * this, the entire 8-byte structure is byteswapped, followed by
3405 * a swap of the 4 byte val field. In other cases, the data is
3406 * already in proper host byte order. */
3407 if (sizeof(target_su.val) != (sizeof(target_su.buf))) {
3408 target_su.buf = tswapal(target_su.buf);
3409 arg.val = tswap32(target_su.val);
3410 } else {
3411 arg.val = target_su.val;
3412 }
aurel32e5289082009-04-18 16:16:12 +00003413 ret = get_errno(semctl(semid, semnum, cmd, arg));
ths3eb6b042007-06-03 14:26:27 +00003414 break;
3415 case GETALL:
ths3eb6b042007-06-03 14:26:27 +00003416 case SETALL:
aurel32e5289082009-04-18 16:16:12 +00003417 err = target_to_host_semarray(semid, &array, target_su.array);
3418 if (err)
3419 return err;
3420 arg.array = array;
3421 ret = get_errno(semctl(semid, semnum, cmd, arg));
3422 err = host_to_target_semarray(semid, target_su.array, &array);
3423 if (err)
3424 return err;
ths3eb6b042007-06-03 14:26:27 +00003425 break;
3426 case IPC_STAT:
ths3eb6b042007-06-03 14:26:27 +00003427 case IPC_SET:
aurel32e5289082009-04-18 16:16:12 +00003428 case SEM_STAT:
3429 err = target_to_host_semid_ds(&dsarg, target_su.buf);
3430 if (err)
3431 return err;
3432 arg.buf = &dsarg;
3433 ret = get_errno(semctl(semid, semnum, cmd, arg));
3434 err = host_to_target_semid_ds(target_su.buf, &dsarg);
3435 if (err)
3436 return err;
ths3eb6b042007-06-03 14:26:27 +00003437 break;
aurel32e5289082009-04-18 16:16:12 +00003438 case IPC_INFO:
3439 case SEM_INFO:
3440 arg.__buf = &seminfo;
3441 ret = get_errno(semctl(semid, semnum, cmd, arg));
3442 err = host_to_target_seminfo(target_su.__buf, &seminfo);
3443 if (err)
3444 return err;
3445 break;
3446 case IPC_RMID:
3447 case GETPID:
3448 case GETNCNT:
3449 case GETZCNT:
3450 ret = get_errno(semctl(semid, semnum, cmd, NULL));
3451 break;
ths3eb6b042007-06-03 14:26:27 +00003452 }
3453
3454 return ret;
3455}
3456
aurel32e5289082009-04-18 16:16:12 +00003457struct target_sembuf {
3458 unsigned short sem_num;
3459 short sem_op;
3460 short sem_flg;
3461};
3462
3463static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
3464 abi_ulong target_addr,
3465 unsigned nsops)
3466{
3467 struct target_sembuf *target_sembuf;
3468 int i;
3469
3470 target_sembuf = lock_user(VERIFY_READ, target_addr,
3471 nsops*sizeof(struct target_sembuf), 1);
3472 if (!target_sembuf)
3473 return -TARGET_EFAULT;
3474
3475 for(i=0; i<nsops; i++) {
3476 __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
3477 __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
3478 __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
3479 }
3480
3481 unlock_user(target_sembuf, target_addr, 0);
3482
3483 return 0;
3484}
3485
3486static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops)
3487{
3488 struct sembuf sops[nsops];
3489
3490 if (target_to_host_sembuf(sops, ptr, nsops))
3491 return -TARGET_EFAULT;
3492
Peter Maydellffb7ee72016-06-06 19:58:12 +01003493 return get_errno(safe_semtimedop(semid, sops, nsops, NULL));
aurel32e5289082009-04-18 16:16:12 +00003494}
3495
ths1bc012f2007-06-03 14:27:49 +00003496struct target_msqid_ds
3497{
aurel321c54ff92008-10-13 21:08:44 +00003498 struct target_ipc_perm msg_perm;
3499 abi_ulong msg_stime;
3500#if TARGET_ABI_BITS == 32
3501 abi_ulong __unused1;
3502#endif
3503 abi_ulong msg_rtime;
3504#if TARGET_ABI_BITS == 32
3505 abi_ulong __unused2;
3506#endif
3507 abi_ulong msg_ctime;
3508#if TARGET_ABI_BITS == 32
3509 abi_ulong __unused3;
3510#endif
3511 abi_ulong __msg_cbytes;
3512 abi_ulong msg_qnum;
3513 abi_ulong msg_qbytes;
3514 abi_ulong msg_lspid;
3515 abi_ulong msg_lrpid;
3516 abi_ulong __unused4;
3517 abi_ulong __unused5;
ths1bc012f2007-06-03 14:27:49 +00003518};
3519
bellard579a97f2007-11-11 14:26:47 +00003520static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
3521 abi_ulong target_addr)
ths1bc012f2007-06-03 14:27:49 +00003522{
3523 struct target_msqid_ds *target_md;
3524
bellard579a97f2007-11-11 14:26:47 +00003525 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
3526 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00003527 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
3528 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003529 host_md->msg_stime = tswapal(target_md->msg_stime);
3530 host_md->msg_rtime = tswapal(target_md->msg_rtime);
3531 host_md->msg_ctime = tswapal(target_md->msg_ctime);
3532 host_md->__msg_cbytes = tswapal(target_md->__msg_cbytes);
3533 host_md->msg_qnum = tswapal(target_md->msg_qnum);
3534 host_md->msg_qbytes = tswapal(target_md->msg_qbytes);
3535 host_md->msg_lspid = tswapal(target_md->msg_lspid);
3536 host_md->msg_lrpid = tswapal(target_md->msg_lrpid);
ths1bc012f2007-06-03 14:27:49 +00003537 unlock_user_struct(target_md, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00003538 return 0;
ths1bc012f2007-06-03 14:27:49 +00003539}
3540
bellard579a97f2007-11-11 14:26:47 +00003541static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
3542 struct msqid_ds *host_md)
ths1bc012f2007-06-03 14:27:49 +00003543{
3544 struct target_msqid_ds *target_md;
3545
bellard579a97f2007-11-11 14:26:47 +00003546 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
3547 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00003548 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
3549 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003550 target_md->msg_stime = tswapal(host_md->msg_stime);
3551 target_md->msg_rtime = tswapal(host_md->msg_rtime);
3552 target_md->msg_ctime = tswapal(host_md->msg_ctime);
3553 target_md->__msg_cbytes = tswapal(host_md->__msg_cbytes);
3554 target_md->msg_qnum = tswapal(host_md->msg_qnum);
3555 target_md->msg_qbytes = tswapal(host_md->msg_qbytes);
3556 target_md->msg_lspid = tswapal(host_md->msg_lspid);
3557 target_md->msg_lrpid = tswapal(host_md->msg_lrpid);
ths1bc012f2007-06-03 14:27:49 +00003558 unlock_user_struct(target_md, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00003559 return 0;
ths1bc012f2007-06-03 14:27:49 +00003560}
3561
aurel321c54ff92008-10-13 21:08:44 +00003562struct target_msginfo {
3563 int msgpool;
3564 int msgmap;
3565 int msgmax;
3566 int msgmnb;
3567 int msgmni;
3568 int msgssz;
3569 int msgtql;
3570 unsigned short int msgseg;
3571};
3572
3573static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
3574 struct msginfo *host_msginfo)
3575{
3576 struct target_msginfo *target_msginfo;
3577 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
3578 return -TARGET_EFAULT;
3579 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
3580 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
3581 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
3582 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
3583 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
3584 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
3585 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
3586 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
3587 unlock_user_struct(target_msginfo, target_addr, 1);
aurel3200b229a2008-10-24 13:12:52 +00003588 return 0;
aurel321c54ff92008-10-13 21:08:44 +00003589}
3590
3591static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
ths1bc012f2007-06-03 14:27:49 +00003592{
3593 struct msqid_ds dsarg;
aurel321c54ff92008-10-13 21:08:44 +00003594 struct msginfo msginfo;
3595 abi_long ret = -TARGET_EINVAL;
3596
3597 cmd &= 0xff;
3598
3599 switch (cmd) {
ths1bc012f2007-06-03 14:27:49 +00003600 case IPC_STAT:
3601 case IPC_SET:
aurel321c54ff92008-10-13 21:08:44 +00003602 case MSG_STAT:
3603 if (target_to_host_msqid_ds(&dsarg,ptr))
3604 return -TARGET_EFAULT;
3605 ret = get_errno(msgctl(msgid, cmd, &dsarg));
3606 if (host_to_target_msqid_ds(ptr,&dsarg))
3607 return -TARGET_EFAULT;
3608 break;
3609 case IPC_RMID:
3610 ret = get_errno(msgctl(msgid, cmd, NULL));
3611 break;
3612 case IPC_INFO:
3613 case MSG_INFO:
3614 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
3615 if (host_to_target_msginfo(ptr, &msginfo))
3616 return -TARGET_EFAULT;
3617 break;
ths1bc012f2007-06-03 14:27:49 +00003618 }
aurel321c54ff92008-10-13 21:08:44 +00003619
ths1bc012f2007-06-03 14:27:49 +00003620 return ret;
3621}
3622
3623struct target_msgbuf {
aurel321c54ff92008-10-13 21:08:44 +00003624 abi_long mtype;
3625 char mtext[1];
ths1bc012f2007-06-03 14:27:49 +00003626};
3627
blueswir1992f48a2007-10-14 16:27:31 +00003628static inline abi_long do_msgsnd(int msqid, abi_long msgp,
Tom Mustaedcc5f92014-08-12 13:53:37 -05003629 ssize_t msgsz, int msgflg)
ths1bc012f2007-06-03 14:27:49 +00003630{
3631 struct target_msgbuf *target_mb;
3632 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00003633 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00003634
Tom Mustaedcc5f92014-08-12 13:53:37 -05003635 if (msgsz < 0) {
3636 return -TARGET_EINVAL;
3637 }
3638
bellard579a97f2007-11-11 14:26:47 +00003639 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
3640 return -TARGET_EFAULT;
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303641 host_mb = g_try_malloc(msgsz + sizeof(long));
zhanghailiang29e03fc2014-08-14 15:29:18 +08003642 if (!host_mb) {
3643 unlock_user_struct(target_mb, msgp, 0);
3644 return -TARGET_ENOMEM;
3645 }
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003646 host_mb->mtype = (abi_long) tswapal(target_mb->mtype);
aurel321c54ff92008-10-13 21:08:44 +00003647 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
Peter Maydell89f9fe42016-06-06 19:58:05 +01003648 ret = get_errno(safe_msgsnd(msqid, host_mb, msgsz, msgflg));
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303649 g_free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00003650 unlock_user_struct(target_mb, msgp, 0);
3651
3652 return ret;
3653}
3654
blueswir1992f48a2007-10-14 16:27:31 +00003655static inline abi_long do_msgrcv(int msqid, abi_long msgp,
Peter Maydell99874f62016-05-20 19:00:56 +01003656 ssize_t msgsz, abi_long msgtyp,
blueswir1992f48a2007-10-14 16:27:31 +00003657 int msgflg)
ths1bc012f2007-06-03 14:27:49 +00003658{
3659 struct target_msgbuf *target_mb;
bellard579a97f2007-11-11 14:26:47 +00003660 char *target_mtext;
ths1bc012f2007-06-03 14:27:49 +00003661 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00003662 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00003663
Peter Maydell99874f62016-05-20 19:00:56 +01003664 if (msgsz < 0) {
3665 return -TARGET_EINVAL;
3666 }
3667
bellard579a97f2007-11-11 14:26:47 +00003668 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
3669 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00003670
Peter Maydell415d8472016-05-20 19:00:57 +01003671 host_mb = g_try_malloc(msgsz + sizeof(long));
3672 if (!host_mb) {
3673 ret = -TARGET_ENOMEM;
3674 goto end;
3675 }
Peter Maydell89f9fe42016-06-06 19:58:05 +01003676 ret = get_errno(safe_msgrcv(msqid, host_mb, msgsz, msgtyp, msgflg));
aurel321c54ff92008-10-13 21:08:44 +00003677
bellard579a97f2007-11-11 14:26:47 +00003678 if (ret > 0) {
3679 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
3680 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
3681 if (!target_mtext) {
3682 ret = -TARGET_EFAULT;
3683 goto end;
3684 }
aurel321c54ff92008-10-13 21:08:44 +00003685 memcpy(target_mb->mtext, host_mb->mtext, ret);
bellard579a97f2007-11-11 14:26:47 +00003686 unlock_user(target_mtext, target_mtext_addr, ret);
3687 }
aurel321c54ff92008-10-13 21:08:44 +00003688
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003689 target_mb->mtype = tswapal(host_mb->mtype);
ths1bc012f2007-06-03 14:27:49 +00003690
bellard579a97f2007-11-11 14:26:47 +00003691end:
3692 if (target_mb)
3693 unlock_user_struct(target_mb, msgp, 1);
Jim Meyering0d07fe42012-08-22 13:55:53 +02003694 g_free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00003695 return ret;
3696}
3697
Riku Voipio88a8c982009-04-03 10:42:00 +03003698static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
3699 abi_ulong target_addr)
3700{
3701 struct target_shmid_ds *target_sd;
3702
3703 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
3704 return -TARGET_EFAULT;
3705 if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
3706 return -TARGET_EFAULT;
3707 __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
3708 __get_user(host_sd->shm_atime, &target_sd->shm_atime);
3709 __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
3710 __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
3711 __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
3712 __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
3713 __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
3714 unlock_user_struct(target_sd, target_addr, 0);
3715 return 0;
3716}
3717
3718static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
3719 struct shmid_ds *host_sd)
3720{
3721 struct target_shmid_ds *target_sd;
3722
3723 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3724 return -TARGET_EFAULT;
3725 if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
3726 return -TARGET_EFAULT;
3727 __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
3728 __put_user(host_sd->shm_atime, &target_sd->shm_atime);
3729 __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
3730 __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
3731 __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
3732 __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
3733 __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
3734 unlock_user_struct(target_sd, target_addr, 1);
3735 return 0;
3736}
3737
3738struct target_shminfo {
3739 abi_ulong shmmax;
3740 abi_ulong shmmin;
3741 abi_ulong shmmni;
3742 abi_ulong shmseg;
3743 abi_ulong shmall;
3744};
3745
3746static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
3747 struct shminfo *host_shminfo)
3748{
3749 struct target_shminfo *target_shminfo;
3750 if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
3751 return -TARGET_EFAULT;
3752 __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
3753 __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
3754 __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
3755 __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
3756 __put_user(host_shminfo->shmall, &target_shminfo->shmall);
3757 unlock_user_struct(target_shminfo, target_addr, 1);
3758 return 0;
3759}
3760
3761struct target_shm_info {
3762 int used_ids;
3763 abi_ulong shm_tot;
3764 abi_ulong shm_rss;
3765 abi_ulong shm_swp;
3766 abi_ulong swap_attempts;
3767 abi_ulong swap_successes;
3768};
3769
3770static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
3771 struct shm_info *host_shm_info)
3772{
3773 struct target_shm_info *target_shm_info;
3774 if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
3775 return -TARGET_EFAULT;
3776 __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
3777 __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
3778 __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
3779 __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
3780 __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
3781 __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
3782 unlock_user_struct(target_shm_info, target_addr, 1);
3783 return 0;
3784}
3785
3786static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
3787{
3788 struct shmid_ds dsarg;
3789 struct shminfo shminfo;
3790 struct shm_info shm_info;
3791 abi_long ret = -TARGET_EINVAL;
3792
3793 cmd &= 0xff;
3794
3795 switch(cmd) {
3796 case IPC_STAT:
3797 case IPC_SET:
3798 case SHM_STAT:
3799 if (target_to_host_shmid_ds(&dsarg, buf))
3800 return -TARGET_EFAULT;
3801 ret = get_errno(shmctl(shmid, cmd, &dsarg));
3802 if (host_to_target_shmid_ds(buf, &dsarg))
3803 return -TARGET_EFAULT;
3804 break;
3805 case IPC_INFO:
3806 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
3807 if (host_to_target_shminfo(buf, &shminfo))
3808 return -TARGET_EFAULT;
3809 break;
3810 case SHM_INFO:
3811 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
3812 if (host_to_target_shm_info(buf, &shm_info))
3813 return -TARGET_EFAULT;
3814 break;
3815 case IPC_RMID:
3816 case SHM_LOCK:
3817 case SHM_UNLOCK:
3818 ret = get_errno(shmctl(shmid, cmd, NULL));
3819 break;
3820 }
3821
3822 return ret;
3823}
3824
Peter Maydellee8e7612016-07-11 16:48:11 +01003825#ifndef TARGET_FORCE_SHMLBA
3826/* For most architectures, SHMLBA is the same as the page size;
3827 * some architectures have larger values, in which case they should
3828 * define TARGET_FORCE_SHMLBA and provide a target_shmlba() function.
3829 * This corresponds to the kernel arch code defining __ARCH_FORCE_SHMLBA
3830 * and defining its own value for SHMLBA.
3831 *
3832 * The kernel also permits SHMLBA to be set by the architecture to a
3833 * value larger than the page size without setting __ARCH_FORCE_SHMLBA;
3834 * this means that addresses are rounded to the large size if
3835 * SHM_RND is set but addresses not aligned to that size are not rejected
3836 * as long as they are at least page-aligned. Since the only architecture
3837 * which uses this is ia64 this code doesn't provide for that oddity.
3838 */
3839static inline abi_ulong target_shmlba(CPUArchState *cpu_env)
3840{
3841 return TARGET_PAGE_SIZE;
3842}
3843#endif
3844
3845static inline abi_ulong do_shmat(CPUArchState *cpu_env,
3846 int shmid, abi_ulong shmaddr, int shmflg)
Riku Voipio88a8c982009-04-03 10:42:00 +03003847{
3848 abi_long raddr;
3849 void *host_raddr;
3850 struct shmid_ds shm_info;
3851 int i,ret;
Peter Maydellee8e7612016-07-11 16:48:11 +01003852 abi_ulong shmlba;
Riku Voipio88a8c982009-04-03 10:42:00 +03003853
3854 /* find out the length of the shared memory segment */
3855 ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
3856 if (is_error(ret)) {
3857 /* can't get length, bail out */
3858 return ret;
3859 }
3860
Peter Maydellee8e7612016-07-11 16:48:11 +01003861 shmlba = target_shmlba(cpu_env);
3862
3863 if (shmaddr & (shmlba - 1)) {
3864 if (shmflg & SHM_RND) {
3865 shmaddr &= ~(shmlba - 1);
3866 } else {
3867 return -TARGET_EINVAL;
3868 }
3869 }
Max Filippovebf9a362018-03-07 13:50:10 -08003870 if (!guest_range_valid(shmaddr, shm_info.shm_segsz)) {
3871 return -TARGET_EINVAL;
3872 }
Peter Maydellee8e7612016-07-11 16:48:11 +01003873
Riku Voipio88a8c982009-04-03 10:42:00 +03003874 mmap_lock();
3875
3876 if (shmaddr)
3877 host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg);
3878 else {
3879 abi_ulong mmap_start;
3880
3881 mmap_start = mmap_find_vma(0, shm_info.shm_segsz);
3882
3883 if (mmap_start == -1) {
3884 errno = ENOMEM;
3885 host_raddr = (void *)-1;
3886 } else
3887 host_raddr = shmat(shmid, g2h(mmap_start), shmflg | SHM_REMAP);
3888 }
3889
3890 if (host_raddr == (void *)-1) {
3891 mmap_unlock();
3892 return get_errno((long)host_raddr);
3893 }
3894 raddr=h2g((unsigned long)host_raddr);
3895
3896 page_set_flags(raddr, raddr + shm_info.shm_segsz,
3897 PAGE_VALID | PAGE_READ |
3898 ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE));
3899
3900 for (i = 0; i < N_SHM_REGIONS; i++) {
Peter Maydellb6e17872016-02-09 15:57:11 +00003901 if (!shm_regions[i].in_use) {
3902 shm_regions[i].in_use = true;
Riku Voipio88a8c982009-04-03 10:42:00 +03003903 shm_regions[i].start = raddr;
3904 shm_regions[i].size = shm_info.shm_segsz;
3905 break;
3906 }
3907 }
3908
3909 mmap_unlock();
3910 return raddr;
3911
3912}
3913
3914static inline abi_long do_shmdt(abi_ulong shmaddr)
3915{
3916 int i;
Max Filippov3c5f6a52018-02-28 14:16:04 -08003917 abi_long rv;
3918
3919 mmap_lock();
Riku Voipio88a8c982009-04-03 10:42:00 +03003920
3921 for (i = 0; i < N_SHM_REGIONS; ++i) {
Peter Maydellb6e17872016-02-09 15:57:11 +00003922 if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
3923 shm_regions[i].in_use = false;
takasi-y@ops.dti.ne.jpe00ac242010-04-11 02:09:57 +09003924 page_set_flags(shmaddr, shmaddr + shm_regions[i].size, 0);
Riku Voipio88a8c982009-04-03 10:42:00 +03003925 break;
3926 }
3927 }
Max Filippov3c5f6a52018-02-28 14:16:04 -08003928 rv = get_errno(shmdt(g2h(shmaddr)));
Riku Voipio88a8c982009-04-03 10:42:00 +03003929
Max Filippov3c5f6a52018-02-28 14:16:04 -08003930 mmap_unlock();
3931
3932 return rv;
Riku Voipio88a8c982009-04-03 10:42:00 +03003933}
3934
aurel321c54ff92008-10-13 21:08:44 +00003935#ifdef TARGET_NR_ipc
pbrook53a59602006-03-25 19:31:22 +00003936/* ??? This only works with linear mappings. */
ths0da46a62007-10-20 20:23:07 +00003937/* do_ipc() must return target values and target errnos. */
Peter Maydellee8e7612016-07-11 16:48:11 +01003938static abi_long do_ipc(CPUArchState *cpu_env,
3939 unsigned int call, abi_long first,
Tom Musta37ed0952014-08-12 13:53:35 -05003940 abi_long second, abi_long third,
blueswir1992f48a2007-10-14 16:27:31 +00003941 abi_long ptr, abi_long fifth)
bellard8853f862004-02-22 14:57:26 +00003942{
3943 int version;
blueswir1992f48a2007-10-14 16:27:31 +00003944 abi_long ret = 0;
bellard8853f862004-02-22 14:57:26 +00003945
3946 version = call >> 16;
3947 call &= 0xffff;
3948
3949 switch (call) {
thsfa294812007-02-02 22:05:00 +00003950 case IPCOP_semop:
aurel32e5289082009-04-18 16:16:12 +00003951 ret = do_semop(first, ptr, second);
thsfa294812007-02-02 22:05:00 +00003952 break;
3953
3954 case IPCOP_semget:
3955 ret = get_errno(semget(first, second, third));
3956 break;
3957
Tom Musta5d2fa8e2014-08-12 13:53:33 -05003958 case IPCOP_semctl: {
3959 /* The semun argument to semctl is passed by value, so dereference the
3960 * ptr argument. */
3961 abi_ulong atptr;
Tom Musta37ed0952014-08-12 13:53:35 -05003962 get_user_ual(atptr, ptr);
Stefan Weild1c002b2015-02-08 15:40:58 +01003963 ret = do_semctl(first, second, third, atptr);
thsfa294812007-02-02 22:05:00 +00003964 break;
Tom Musta5d2fa8e2014-08-12 13:53:33 -05003965 }
thsd96372e2007-02-02 22:05:44 +00003966
aurel321c54ff92008-10-13 21:08:44 +00003967 case IPCOP_msgget:
3968 ret = get_errno(msgget(first, second));
3969 break;
thsd96372e2007-02-02 22:05:44 +00003970
aurel321c54ff92008-10-13 21:08:44 +00003971 case IPCOP_msgsnd:
3972 ret = do_msgsnd(first, ptr, second, third);
3973 break;
thsd96372e2007-02-02 22:05:44 +00003974
aurel321c54ff92008-10-13 21:08:44 +00003975 case IPCOP_msgctl:
3976 ret = do_msgctl(first, second, ptr);
3977 break;
thsd96372e2007-02-02 22:05:44 +00003978
aurel321c54ff92008-10-13 21:08:44 +00003979 case IPCOP_msgrcv:
3980 switch (version) {
3981 case 0:
3982 {
3983 struct target_ipc_kludge {
3984 abi_long msgp;
3985 abi_long msgtyp;
3986 } *tmp;
thsd96372e2007-02-02 22:05:44 +00003987
aurel321c54ff92008-10-13 21:08:44 +00003988 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
3989 ret = -TARGET_EFAULT;
3990 break;
ths1bc012f2007-06-03 14:27:49 +00003991 }
aurel321c54ff92008-10-13 21:08:44 +00003992
Laurent Vivier79dd77d2012-12-20 11:00:11 +00003993 ret = do_msgrcv(first, tswapal(tmp->msgp), second, tswapal(tmp->msgtyp), third);
aurel321c54ff92008-10-13 21:08:44 +00003994
3995 unlock_user_struct(tmp, ptr, 0);
3996 break;
3997 }
3998 default:
3999 ret = do_msgrcv(first, ptr, second, fifth, third);
4000 }
4001 break;
thsd96372e2007-02-02 22:05:44 +00004002
bellard8853f862004-02-22 14:57:26 +00004003 case IPCOP_shmat:
Riku Voipio88a8c982009-04-03 10:42:00 +03004004 switch (version) {
4005 default:
bellard5a4a8982007-11-11 17:39:18 +00004006 {
4007 abi_ulong raddr;
Peter Maydellee8e7612016-07-11 16:48:11 +01004008 raddr = do_shmat(cpu_env, first, ptr, second);
Riku Voipio88a8c982009-04-03 10:42:00 +03004009 if (is_error(raddr))
4010 return get_errno(raddr);
bellard2f619692007-11-16 10:46:05 +00004011 if (put_user_ual(raddr, third))
bellard5a4a8982007-11-11 17:39:18 +00004012 return -TARGET_EFAULT;
Riku Voipio88a8c982009-04-03 10:42:00 +03004013 break;
4014 }
4015 case 1:
4016 ret = -TARGET_EINVAL;
4017 break;
bellard5a4a8982007-11-11 17:39:18 +00004018 }
bellard8853f862004-02-22 14:57:26 +00004019 break;
4020 case IPCOP_shmdt:
Riku Voipio88a8c982009-04-03 10:42:00 +03004021 ret = do_shmdt(ptr);
bellard8853f862004-02-22 14:57:26 +00004022 break;
4023
4024 case IPCOP_shmget:
4025 /* IPC_* flag values are the same on all linux platforms */
4026 ret = get_errno(shmget(first, second, third));
4027 break;
4028
4029 /* IPC_* and SHM_* command values are the same on all linux platforms */
4030 case IPCOP_shmctl:
Petar Jovanovica2926782013-10-30 14:46:32 +01004031 ret = do_shmctl(first, second, ptr);
bellard8853f862004-02-22 14:57:26 +00004032 break;
4033 default:
j_mayer32407102007-09-26 23:01:49 +00004034 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00004035 ret = -TARGET_ENOSYS;
bellard8853f862004-02-22 14:57:26 +00004036 break;
4037 }
4038 return ret;
4039}
j_mayer32407102007-09-26 23:01:49 +00004040#endif
bellard8853f862004-02-22 14:57:26 +00004041
bellard31e31b82003-02-18 22:55:36 +00004042/* kernel structure types definitions */
bellard31e31b82003-02-18 22:55:36 +00004043
Blue Swirl001faf32009-05-13 17:53:17 +00004044#define STRUCT(name, ...) STRUCT_ ## name,
bellard31e31b82003-02-18 22:55:36 +00004045#define STRUCT_SPECIAL(name) STRUCT_ ## name,
4046enum {
4047#include "syscall_types.h"
Alexander Graf8be656b2015-05-06 23:47:32 +02004048STRUCT_MAX
bellard31e31b82003-02-18 22:55:36 +00004049};
4050#undef STRUCT
4051#undef STRUCT_SPECIAL
4052
Blue Swirl001faf32009-05-13 17:53:17 +00004053#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
bellard31e31b82003-02-18 22:55:36 +00004054#define STRUCT_SPECIAL(name)
4055#include "syscall_types.h"
4056#undef STRUCT
4057#undef STRUCT_SPECIAL
4058
Peter Maydelld2ef05b2011-01-06 15:04:17 +00004059typedef struct IOCTLEntry IOCTLEntry;
4060
4061typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004062 int fd, int cmd, abi_long arg);
Peter Maydelld2ef05b2011-01-06 15:04:17 +00004063
4064struct IOCTLEntry {
Ed Swierk9c6bf9c2014-12-16 12:55:31 -08004065 int target_cmd;
bellard2ab83ea2003-06-15 19:56:46 +00004066 unsigned int host_cmd;
bellard31e31b82003-02-18 22:55:36 +00004067 const char *name;
4068 int access;
Peter Maydelld2ef05b2011-01-06 15:04:17 +00004069 do_ioctl_fn *do_ioctl;
bellard1a9353d2003-03-16 20:28:50 +00004070 const argtype arg_type[5];
Peter Maydelld2ef05b2011-01-06 15:04:17 +00004071};
bellard31e31b82003-02-18 22:55:36 +00004072
4073#define IOC_R 0x0001
4074#define IOC_W 0x0002
4075#define IOC_RW (IOC_R | IOC_W)
4076
4077#define MAX_STRUCT_SIZE 4096
4078
Peter Maydelldace20d2011-01-10 13:11:24 +00004079#ifdef CONFIG_FIEMAP
Peter Maydell285da2b2011-01-06 15:04:18 +00004080/* So fiemap access checks don't overflow on 32 bit systems.
4081 * This is very slightly smaller than the limit imposed by
4082 * the underlying kernel.
4083 */
4084#define FIEMAP_MAX_EXTENTS ((UINT_MAX - sizeof(struct fiemap)) \
4085 / sizeof(struct fiemap_extent))
4086
4087static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004088 int fd, int cmd, abi_long arg)
Peter Maydell285da2b2011-01-06 15:04:18 +00004089{
4090 /* The parameter for this ioctl is a struct fiemap followed
4091 * by an array of struct fiemap_extent whose size is set
4092 * in fiemap->fm_extent_count. The array is filled in by the
4093 * ioctl.
4094 */
4095 int target_size_in, target_size_out;
4096 struct fiemap *fm;
4097 const argtype *arg_type = ie->arg_type;
4098 const argtype extent_arg_type[] = { MK_STRUCT(STRUCT_fiemap_extent) };
4099 void *argptr, *p;
4100 abi_long ret;
4101 int i, extent_size = thunk_type_size(extent_arg_type, 0);
4102 uint32_t outbufsz;
4103 int free_fm = 0;
4104
4105 assert(arg_type[0] == TYPE_PTR);
4106 assert(ie->access == IOC_RW);
4107 arg_type++;
4108 target_size_in = thunk_type_size(arg_type, 0);
4109 argptr = lock_user(VERIFY_READ, arg, target_size_in, 1);
4110 if (!argptr) {
4111 return -TARGET_EFAULT;
4112 }
4113 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4114 unlock_user(argptr, arg, 0);
4115 fm = (struct fiemap *)buf_temp;
4116 if (fm->fm_extent_count > FIEMAP_MAX_EXTENTS) {
4117 return -TARGET_EINVAL;
4118 }
4119
4120 outbufsz = sizeof (*fm) +
4121 (sizeof(struct fiemap_extent) * fm->fm_extent_count);
4122
4123 if (outbufsz > MAX_STRUCT_SIZE) {
4124 /* We can't fit all the extents into the fixed size buffer.
4125 * Allocate one that is large enough and use it instead.
4126 */
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304127 fm = g_try_malloc(outbufsz);
Peter Maydell285da2b2011-01-06 15:04:18 +00004128 if (!fm) {
4129 return -TARGET_ENOMEM;
4130 }
4131 memcpy(fm, buf_temp, sizeof(struct fiemap));
4132 free_fm = 1;
4133 }
Peter Maydell49ca6f32016-06-06 19:58:14 +01004134 ret = get_errno(safe_ioctl(fd, ie->host_cmd, fm));
Peter Maydell285da2b2011-01-06 15:04:18 +00004135 if (!is_error(ret)) {
4136 target_size_out = target_size_in;
4137 /* An extent_count of 0 means we were only counting the extents
4138 * so there are no structs to copy
4139 */
4140 if (fm->fm_extent_count != 0) {
4141 target_size_out += fm->fm_mapped_extents * extent_size;
4142 }
4143 argptr = lock_user(VERIFY_WRITE, arg, target_size_out, 0);
4144 if (!argptr) {
4145 ret = -TARGET_EFAULT;
4146 } else {
4147 /* Convert the struct fiemap */
4148 thunk_convert(argptr, fm, arg_type, THUNK_TARGET);
4149 if (fm->fm_extent_count != 0) {
4150 p = argptr + target_size_in;
4151 /* ...and then all the struct fiemap_extents */
4152 for (i = 0; i < fm->fm_mapped_extents; i++) {
4153 thunk_convert(p, &fm->fm_extents[i], extent_arg_type,
4154 THUNK_TARGET);
4155 p += extent_size;
4156 }
4157 }
4158 unlock_user(argptr, arg, target_size_out);
4159 }
4160 }
4161 if (free_fm) {
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304162 g_free(fm);
Peter Maydell285da2b2011-01-06 15:04:18 +00004163 }
4164 return ret;
4165}
Peter Maydelldace20d2011-01-10 13:11:24 +00004166#endif
Peter Maydell285da2b2011-01-06 15:04:18 +00004167
Laurent Vivier059c2f22011-03-30 00:12:12 +02004168static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004169 int fd, int cmd, abi_long arg)
Laurent Vivier059c2f22011-03-30 00:12:12 +02004170{
4171 const argtype *arg_type = ie->arg_type;
4172 int target_size;
4173 void *argptr;
4174 int ret;
4175 struct ifconf *host_ifconf;
4176 uint32_t outbufsz;
4177 const argtype ifreq_arg_type[] = { MK_STRUCT(STRUCT_sockaddr_ifreq) };
4178 int target_ifreq_size;
4179 int nb_ifreq;
4180 int free_buf = 0;
4181 int i;
4182 int target_ifc_len;
4183 abi_long target_ifc_buf;
4184 int host_ifc_len;
4185 char *host_ifc_buf;
4186
4187 assert(arg_type[0] == TYPE_PTR);
4188 assert(ie->access == IOC_RW);
4189
4190 arg_type++;
4191 target_size = thunk_type_size(arg_type, 0);
4192
4193 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4194 if (!argptr)
4195 return -TARGET_EFAULT;
4196 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4197 unlock_user(argptr, arg, 0);
4198
4199 host_ifconf = (struct ifconf *)(unsigned long)buf_temp;
Laurent Vivier059c2f22011-03-30 00:12:12 +02004200 target_ifc_buf = (abi_long)(unsigned long)host_ifconf->ifc_buf;
Laurent Vivier059c2f22011-03-30 00:12:12 +02004201 target_ifreq_size = thunk_type_size(ifreq_arg_type, 0);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004202
Kan Li22e4a2672018-10-24 20:13:03 +00004203 if (target_ifc_buf != 0) {
4204 target_ifc_len = host_ifconf->ifc_len;
4205 nb_ifreq = target_ifc_len / target_ifreq_size;
4206 host_ifc_len = nb_ifreq * sizeof(struct ifreq);
4207
4208 outbufsz = sizeof(*host_ifconf) + host_ifc_len;
4209 if (outbufsz > MAX_STRUCT_SIZE) {
4210 /*
4211 * We can't fit all the extents into the fixed size buffer.
4212 * Allocate one that is large enough and use it instead.
4213 */
4214 host_ifconf = malloc(outbufsz);
4215 if (!host_ifconf) {
4216 return -TARGET_ENOMEM;
4217 }
4218 memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf));
4219 free_buf = 1;
Laurent Vivier059c2f22011-03-30 00:12:12 +02004220 }
Kan Li22e4a2672018-10-24 20:13:03 +00004221 host_ifc_buf = (char *)host_ifconf + sizeof(*host_ifconf);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004222
Kan Li22e4a2672018-10-24 20:13:03 +00004223 host_ifconf->ifc_len = host_ifc_len;
4224 } else {
4225 host_ifc_buf = NULL;
4226 }
Laurent Vivier059c2f22011-03-30 00:12:12 +02004227 host_ifconf->ifc_buf = host_ifc_buf;
4228
Peter Maydell49ca6f32016-06-06 19:58:14 +01004229 ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_ifconf));
Laurent Vivier059c2f22011-03-30 00:12:12 +02004230 if (!is_error(ret)) {
4231 /* convert host ifc_len to target ifc_len */
4232
4233 nb_ifreq = host_ifconf->ifc_len / sizeof(struct ifreq);
4234 target_ifc_len = nb_ifreq * target_ifreq_size;
4235 host_ifconf->ifc_len = target_ifc_len;
4236
4237 /* restore target ifc_buf */
4238
4239 host_ifconf->ifc_buf = (char *)(unsigned long)target_ifc_buf;
4240
4241 /* copy struct ifconf to target user */
4242
4243 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
4244 if (!argptr)
4245 return -TARGET_EFAULT;
4246 thunk_convert(argptr, host_ifconf, arg_type, THUNK_TARGET);
4247 unlock_user(argptr, arg, target_size);
4248
Kan Li22e4a2672018-10-24 20:13:03 +00004249 if (target_ifc_buf != 0) {
4250 /* copy ifreq[] to target user */
4251 argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0);
4252 for (i = 0; i < nb_ifreq ; i++) {
4253 thunk_convert(argptr + i * target_ifreq_size,
4254 host_ifc_buf + i * sizeof(struct ifreq),
4255 ifreq_arg_type, THUNK_TARGET);
4256 }
4257 unlock_user(argptr, target_ifc_buf, target_ifc_len);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004258 }
Laurent Vivier059c2f22011-03-30 00:12:12 +02004259 }
4260
4261 if (free_buf) {
4262 free(host_ifconf);
4263 }
4264
4265 return ret;
4266}
4267
Cortland Tölvaa1333672018-10-08 09:35:21 -07004268#if defined(CONFIG_USBFS)
4269#if HOST_LONG_BITS > 64
4270#error USBDEVFS thunks do not support >64 bit hosts yet.
4271#endif
4272struct live_urb {
4273 uint64_t target_urb_adr;
4274 uint64_t target_buf_adr;
4275 char *target_buf_ptr;
4276 struct usbdevfs_urb host_urb;
4277};
4278
4279static GHashTable *usbdevfs_urb_hashtable(void)
4280{
4281 static GHashTable *urb_hashtable;
4282
4283 if (!urb_hashtable) {
4284 urb_hashtable = g_hash_table_new(g_int64_hash, g_int64_equal);
4285 }
4286 return urb_hashtable;
4287}
4288
4289static void urb_hashtable_insert(struct live_urb *urb)
4290{
4291 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
4292 g_hash_table_insert(urb_hashtable, urb, urb);
4293}
4294
4295static struct live_urb *urb_hashtable_lookup(uint64_t target_urb_adr)
4296{
4297 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
4298 return g_hash_table_lookup(urb_hashtable, &target_urb_adr);
4299}
4300
4301static void urb_hashtable_remove(struct live_urb *urb)
4302{
4303 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
4304 g_hash_table_remove(urb_hashtable, urb);
4305}
4306
4307static abi_long
4308do_ioctl_usbdevfs_reapurb(const IOCTLEntry *ie, uint8_t *buf_temp,
4309 int fd, int cmd, abi_long arg)
4310{
4311 const argtype usbfsurb_arg_type[] = { MK_STRUCT(STRUCT_usbdevfs_urb) };
4312 const argtype ptrvoid_arg_type[] = { TYPE_PTRVOID, 0, 0 };
4313 struct live_urb *lurb;
4314 void *argptr;
4315 uint64_t hurb;
4316 int target_size;
4317 uintptr_t target_urb_adr;
4318 abi_long ret;
4319
4320 target_size = thunk_type_size(usbfsurb_arg_type, THUNK_TARGET);
4321
4322 memset(buf_temp, 0, sizeof(uint64_t));
4323 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
4324 if (is_error(ret)) {
4325 return ret;
4326 }
4327
4328 memcpy(&hurb, buf_temp, sizeof(uint64_t));
4329 lurb = (void *)((uintptr_t)hurb - offsetof(struct live_urb, host_urb));
4330 if (!lurb->target_urb_adr) {
4331 return -TARGET_EFAULT;
4332 }
4333 urb_hashtable_remove(lurb);
4334 unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr,
4335 lurb->host_urb.buffer_length);
4336 lurb->target_buf_ptr = NULL;
4337
4338 /* restore the guest buffer pointer */
4339 lurb->host_urb.buffer = (void *)(uintptr_t)lurb->target_buf_adr;
4340
4341 /* update the guest urb struct */
4342 argptr = lock_user(VERIFY_WRITE, lurb->target_urb_adr, target_size, 0);
4343 if (!argptr) {
4344 g_free(lurb);
4345 return -TARGET_EFAULT;
4346 }
4347 thunk_convert(argptr, &lurb->host_urb, usbfsurb_arg_type, THUNK_TARGET);
4348 unlock_user(argptr, lurb->target_urb_adr, target_size);
4349
4350 target_size = thunk_type_size(ptrvoid_arg_type, THUNK_TARGET);
4351 /* write back the urb handle */
4352 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
4353 if (!argptr) {
4354 g_free(lurb);
4355 return -TARGET_EFAULT;
4356 }
4357
4358 /* GHashTable uses 64-bit keys but thunk_convert expects uintptr_t */
4359 target_urb_adr = lurb->target_urb_adr;
4360 thunk_convert(argptr, &target_urb_adr, ptrvoid_arg_type, THUNK_TARGET);
4361 unlock_user(argptr, arg, target_size);
4362
4363 g_free(lurb);
4364 return ret;
4365}
4366
4367static abi_long
4368do_ioctl_usbdevfs_discardurb(const IOCTLEntry *ie,
4369 uint8_t *buf_temp __attribute__((unused)),
4370 int fd, int cmd, abi_long arg)
4371{
4372 struct live_urb *lurb;
4373
4374 /* map target address back to host URB with metadata. */
4375 lurb = urb_hashtable_lookup(arg);
4376 if (!lurb) {
4377 return -TARGET_EFAULT;
4378 }
4379 return get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
4380}
4381
4382static abi_long
4383do_ioctl_usbdevfs_submiturb(const IOCTLEntry *ie, uint8_t *buf_temp,
4384 int fd, int cmd, abi_long arg)
4385{
4386 const argtype *arg_type = ie->arg_type;
4387 int target_size;
4388 abi_long ret;
4389 void *argptr;
4390 int rw_dir;
4391 struct live_urb *lurb;
4392
4393 /*
4394 * each submitted URB needs to map to a unique ID for the
4395 * kernel, and that unique ID needs to be a pointer to
4396 * host memory. hence, we need to malloc for each URB.
4397 * isochronous transfers have a variable length struct.
4398 */
4399 arg_type++;
4400 target_size = thunk_type_size(arg_type, THUNK_TARGET);
4401
4402 /* construct host copy of urb and metadata */
4403 lurb = g_try_malloc0(sizeof(struct live_urb));
4404 if (!lurb) {
4405 return -TARGET_ENOMEM;
4406 }
4407
4408 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4409 if (!argptr) {
4410 g_free(lurb);
4411 return -TARGET_EFAULT;
4412 }
4413 thunk_convert(&lurb->host_urb, argptr, arg_type, THUNK_HOST);
4414 unlock_user(argptr, arg, 0);
4415
4416 lurb->target_urb_adr = arg;
4417 lurb->target_buf_adr = (uintptr_t)lurb->host_urb.buffer;
4418
4419 /* buffer space used depends on endpoint type so lock the entire buffer */
4420 /* control type urbs should check the buffer contents for true direction */
4421 rw_dir = lurb->host_urb.endpoint & USB_DIR_IN ? VERIFY_WRITE : VERIFY_READ;
4422 lurb->target_buf_ptr = lock_user(rw_dir, lurb->target_buf_adr,
4423 lurb->host_urb.buffer_length, 1);
4424 if (lurb->target_buf_ptr == NULL) {
4425 g_free(lurb);
4426 return -TARGET_EFAULT;
4427 }
4428
4429 /* update buffer pointer in host copy */
4430 lurb->host_urb.buffer = lurb->target_buf_ptr;
4431
4432 ret = get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
4433 if (is_error(ret)) {
4434 unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr, 0);
4435 g_free(lurb);
4436 } else {
4437 urb_hashtable_insert(lurb);
4438 }
4439
4440 return ret;
4441}
4442#endif /* CONFIG_USBFS */
4443
Alexander Graf56e904e2012-01-31 18:42:06 +01004444static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004445 int cmd, abi_long arg)
Alexander Graf56e904e2012-01-31 18:42:06 +01004446{
4447 void *argptr;
4448 struct dm_ioctl *host_dm;
4449 abi_long guest_data;
4450 uint32_t guest_data_size;
4451 int target_size;
4452 const argtype *arg_type = ie->arg_type;
4453 abi_long ret;
4454 void *big_buf = NULL;
4455 char *host_data;
4456
4457 arg_type++;
4458 target_size = thunk_type_size(arg_type, 0);
4459 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4460 if (!argptr) {
4461 ret = -TARGET_EFAULT;
4462 goto out;
4463 }
4464 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4465 unlock_user(argptr, arg, 0);
4466
4467 /* buf_temp is too small, so fetch things into a bigger buffer */
4468 big_buf = g_malloc0(((struct dm_ioctl*)buf_temp)->data_size * 2);
4469 memcpy(big_buf, buf_temp, target_size);
4470 buf_temp = big_buf;
4471 host_dm = big_buf;
4472
4473 guest_data = arg + host_dm->data_start;
4474 if ((guest_data - arg) < 0) {
Peter Maydellf9757b12016-07-12 13:02:14 +01004475 ret = -TARGET_EINVAL;
Alexander Graf56e904e2012-01-31 18:42:06 +01004476 goto out;
4477 }
4478 guest_data_size = host_dm->data_size - host_dm->data_start;
4479 host_data = (char*)host_dm + host_dm->data_start;
4480
4481 argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1);
Peter Maydell32112152016-07-12 13:02:13 +01004482 if (!argptr) {
4483 ret = -TARGET_EFAULT;
4484 goto out;
4485 }
4486
Alexander Graf56e904e2012-01-31 18:42:06 +01004487 switch (ie->host_cmd) {
4488 case DM_REMOVE_ALL:
4489 case DM_LIST_DEVICES:
4490 case DM_DEV_CREATE:
4491 case DM_DEV_REMOVE:
4492 case DM_DEV_SUSPEND:
4493 case DM_DEV_STATUS:
4494 case DM_DEV_WAIT:
4495 case DM_TABLE_STATUS:
4496 case DM_TABLE_CLEAR:
4497 case DM_TABLE_DEPS:
4498 case DM_LIST_VERSIONS:
4499 /* no input data */
4500 break;
4501 case DM_DEV_RENAME:
4502 case DM_DEV_SET_GEOMETRY:
4503 /* data contains only strings */
4504 memcpy(host_data, argptr, guest_data_size);
4505 break;
4506 case DM_TARGET_MSG:
4507 memcpy(host_data, argptr, guest_data_size);
4508 *(uint64_t*)host_data = tswap64(*(uint64_t*)argptr);
4509 break;
4510 case DM_TABLE_LOAD:
4511 {
4512 void *gspec = argptr;
4513 void *cur_data = host_data;
4514 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
4515 int spec_size = thunk_type_size(arg_type, 0);
4516 int i;
4517
4518 for (i = 0; i < host_dm->target_count; i++) {
4519 struct dm_target_spec *spec = cur_data;
4520 uint32_t next;
4521 int slen;
4522
4523 thunk_convert(spec, gspec, arg_type, THUNK_HOST);
4524 slen = strlen((char*)gspec + spec_size) + 1;
4525 next = spec->next;
4526 spec->next = sizeof(*spec) + slen;
4527 strcpy((char*)&spec[1], gspec + spec_size);
4528 gspec += next;
4529 cur_data += spec->next;
4530 }
4531 break;
4532 }
4533 default:
4534 ret = -TARGET_EINVAL;
Chen Gang Sdec04732015-01-25 08:00:42 +08004535 unlock_user(argptr, guest_data, 0);
Alexander Graf56e904e2012-01-31 18:42:06 +01004536 goto out;
4537 }
4538 unlock_user(argptr, guest_data, 0);
4539
Peter Maydell49ca6f32016-06-06 19:58:14 +01004540 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
Alexander Graf56e904e2012-01-31 18:42:06 +01004541 if (!is_error(ret)) {
4542 guest_data = arg + host_dm->data_start;
4543 guest_data_size = host_dm->data_size - host_dm->data_start;
4544 argptr = lock_user(VERIFY_WRITE, guest_data, guest_data_size, 0);
4545 switch (ie->host_cmd) {
4546 case DM_REMOVE_ALL:
4547 case DM_DEV_CREATE:
4548 case DM_DEV_REMOVE:
4549 case DM_DEV_RENAME:
4550 case DM_DEV_SUSPEND:
4551 case DM_DEV_STATUS:
4552 case DM_TABLE_LOAD:
4553 case DM_TABLE_CLEAR:
4554 case DM_TARGET_MSG:
4555 case DM_DEV_SET_GEOMETRY:
4556 /* no return data */
4557 break;
4558 case DM_LIST_DEVICES:
4559 {
4560 struct dm_name_list *nl = (void*)host_dm + host_dm->data_start;
4561 uint32_t remaining_data = guest_data_size;
4562 void *cur_data = argptr;
4563 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
4564 int nl_size = 12; /* can't use thunk_size due to alignment */
4565
4566 while (1) {
4567 uint32_t next = nl->next;
4568 if (next) {
4569 nl->next = nl_size + (strlen(nl->name) + 1);
4570 }
4571 if (remaining_data < nl->next) {
4572 host_dm->flags |= DM_BUFFER_FULL_FLAG;
4573 break;
4574 }
4575 thunk_convert(cur_data, nl, arg_type, THUNK_TARGET);
4576 strcpy(cur_data + nl_size, nl->name);
4577 cur_data += nl->next;
4578 remaining_data -= nl->next;
4579 if (!next) {
4580 break;
4581 }
4582 nl = (void*)nl + next;
4583 }
4584 break;
4585 }
4586 case DM_DEV_WAIT:
4587 case DM_TABLE_STATUS:
4588 {
4589 struct dm_target_spec *spec = (void*)host_dm + host_dm->data_start;
4590 void *cur_data = argptr;
4591 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
4592 int spec_size = thunk_type_size(arg_type, 0);
4593 int i;
4594
4595 for (i = 0; i < host_dm->target_count; i++) {
4596 uint32_t next = spec->next;
4597 int slen = strlen((char*)&spec[1]) + 1;
4598 spec->next = (cur_data - argptr) + spec_size + slen;
4599 if (guest_data_size < spec->next) {
4600 host_dm->flags |= DM_BUFFER_FULL_FLAG;
4601 break;
4602 }
4603 thunk_convert(cur_data, spec, arg_type, THUNK_TARGET);
4604 strcpy(cur_data + spec_size, (char*)&spec[1]);
4605 cur_data = argptr + spec->next;
4606 spec = (void*)host_dm + host_dm->data_start + next;
4607 }
4608 break;
4609 }
4610 case DM_TABLE_DEPS:
4611 {
4612 void *hdata = (void*)host_dm + host_dm->data_start;
4613 int count = *(uint32_t*)hdata;
4614 uint64_t *hdev = hdata + 8;
4615 uint64_t *gdev = argptr + 8;
4616 int i;
4617
4618 *(uint32_t*)argptr = tswap32(count);
4619 for (i = 0; i < count; i++) {
4620 *gdev = tswap64(*hdev);
4621 gdev++;
4622 hdev++;
4623 }
4624 break;
4625 }
4626 case DM_LIST_VERSIONS:
4627 {
4628 struct dm_target_versions *vers = (void*)host_dm + host_dm->data_start;
4629 uint32_t remaining_data = guest_data_size;
4630 void *cur_data = argptr;
4631 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_versions) };
4632 int vers_size = thunk_type_size(arg_type, 0);
4633
4634 while (1) {
4635 uint32_t next = vers->next;
4636 if (next) {
4637 vers->next = vers_size + (strlen(vers->name) + 1);
4638 }
4639 if (remaining_data < vers->next) {
4640 host_dm->flags |= DM_BUFFER_FULL_FLAG;
4641 break;
4642 }
4643 thunk_convert(cur_data, vers, arg_type, THUNK_TARGET);
4644 strcpy(cur_data + vers_size, vers->name);
4645 cur_data += vers->next;
4646 remaining_data -= vers->next;
4647 if (!next) {
4648 break;
4649 }
4650 vers = (void*)vers + next;
4651 }
4652 break;
4653 }
4654 default:
Chen Gang Sdec04732015-01-25 08:00:42 +08004655 unlock_user(argptr, guest_data, 0);
Alexander Graf56e904e2012-01-31 18:42:06 +01004656 ret = -TARGET_EINVAL;
4657 goto out;
4658 }
4659 unlock_user(argptr, guest_data, guest_data_size);
4660
4661 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
4662 if (!argptr) {
4663 ret = -TARGET_EFAULT;
4664 goto out;
4665 }
4666 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
4667 unlock_user(argptr, arg, target_size);
4668 }
4669out:
Stefan Weilad11ad72012-09-04 22:14:19 +02004670 g_free(big_buf);
Alexander Graf56e904e2012-01-31 18:42:06 +01004671 return ret;
4672}
4673
Alexander Grafa59b5e32014-08-22 13:15:50 +02004674static abi_long do_ioctl_blkpg(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004675 int cmd, abi_long arg)
Alexander Grafa59b5e32014-08-22 13:15:50 +02004676{
4677 void *argptr;
4678 int target_size;
4679 const argtype *arg_type = ie->arg_type;
4680 const argtype part_arg_type[] = { MK_STRUCT(STRUCT_blkpg_partition) };
4681 abi_long ret;
4682
4683 struct blkpg_ioctl_arg *host_blkpg = (void*)buf_temp;
4684 struct blkpg_partition host_part;
4685
4686 /* Read and convert blkpg */
4687 arg_type++;
4688 target_size = thunk_type_size(arg_type, 0);
4689 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4690 if (!argptr) {
4691 ret = -TARGET_EFAULT;
4692 goto out;
4693 }
4694 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4695 unlock_user(argptr, arg, 0);
4696
4697 switch (host_blkpg->op) {
4698 case BLKPG_ADD_PARTITION:
4699 case BLKPG_DEL_PARTITION:
4700 /* payload is struct blkpg_partition */
4701 break;
4702 default:
4703 /* Unknown opcode */
4704 ret = -TARGET_EINVAL;
4705 goto out;
4706 }
4707
4708 /* Read and convert blkpg->data */
4709 arg = (abi_long)(uintptr_t)host_blkpg->data;
4710 target_size = thunk_type_size(part_arg_type, 0);
4711 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4712 if (!argptr) {
4713 ret = -TARGET_EFAULT;
4714 goto out;
4715 }
4716 thunk_convert(&host_part, argptr, part_arg_type, THUNK_HOST);
4717 unlock_user(argptr, arg, 0);
4718
4719 /* Swizzle the data pointer to our local copy and call! */
4720 host_blkpg->data = &host_part;
Peter Maydell49ca6f32016-06-06 19:58:14 +01004721 ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_blkpg));
Alexander Grafa59b5e32014-08-22 13:15:50 +02004722
4723out:
4724 return ret;
4725}
4726
Laurent Vivier7ff7b662013-07-02 14:04:12 +01004727static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004728 int fd, int cmd, abi_long arg)
Laurent Vivier7ff7b662013-07-02 14:04:12 +01004729{
4730 const argtype *arg_type = ie->arg_type;
4731 const StructEntry *se;
4732 const argtype *field_types;
4733 const int *dst_offsets, *src_offsets;
4734 int target_size;
4735 void *argptr;
Marc-André Lureaub78c5222019-03-05 16:15:00 +01004736 abi_ulong *target_rt_dev_ptr = NULL;
4737 unsigned long *host_rt_dev_ptr = NULL;
Laurent Vivier7ff7b662013-07-02 14:04:12 +01004738 abi_long ret;
4739 int i;
4740
4741 assert(ie->access == IOC_W);
4742 assert(*arg_type == TYPE_PTR);
4743 arg_type++;
4744 assert(*arg_type == TYPE_STRUCT);
4745 target_size = thunk_type_size(arg_type, 0);
4746 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4747 if (!argptr) {
4748 return -TARGET_EFAULT;
4749 }
4750 arg_type++;
4751 assert(*arg_type == (int)STRUCT_rtentry);
4752 se = struct_entries + *arg_type++;
4753 assert(se->convert[0] == NULL);
4754 /* convert struct here to be able to catch rt_dev string */
4755 field_types = se->field_types;
4756 dst_offsets = se->field_offsets[THUNK_HOST];
4757 src_offsets = se->field_offsets[THUNK_TARGET];
4758 for (i = 0; i < se->nb_fields; i++) {
4759 if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) {
4760 assert(*field_types == TYPE_PTRVOID);
4761 target_rt_dev_ptr = (abi_ulong *)(argptr + src_offsets[i]);
4762 host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]);
4763 if (*target_rt_dev_ptr != 0) {
4764 *host_rt_dev_ptr = (unsigned long)lock_user_string(
4765 tswapal(*target_rt_dev_ptr));
4766 if (!*host_rt_dev_ptr) {
4767 unlock_user(argptr, arg, 0);
4768 return -TARGET_EFAULT;
4769 }
4770 } else {
4771 *host_rt_dev_ptr = 0;
4772 }
4773 field_types++;
4774 continue;
4775 }
4776 field_types = thunk_convert(buf_temp + dst_offsets[i],
4777 argptr + src_offsets[i],
4778 field_types, THUNK_HOST);
4779 }
4780 unlock_user(argptr, arg, 0);
4781
Peter Maydell49ca6f32016-06-06 19:58:14 +01004782 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
Marc-André Lureaub78c5222019-03-05 16:15:00 +01004783
4784 assert(host_rt_dev_ptr != NULL);
4785 assert(target_rt_dev_ptr != NULL);
Laurent Vivier7ff7b662013-07-02 14:04:12 +01004786 if (*host_rt_dev_ptr != 0) {
4787 unlock_user((void *)*host_rt_dev_ptr,
4788 *target_rt_dev_ptr, 0);
4789 }
4790 return ret;
4791}
4792
Paul Burtonca56f5b2014-06-22 11:25:47 +01004793static abi_long do_ioctl_kdsigaccept(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004794 int fd, int cmd, abi_long arg)
Paul Burtonca56f5b2014-06-22 11:25:47 +01004795{
4796 int sig = target_to_host_signal(arg);
Peter Maydell49ca6f32016-06-06 19:58:14 +01004797 return get_errno(safe_ioctl(fd, ie->host_cmd, sig));
Paul Burtonca56f5b2014-06-22 11:25:47 +01004798}
4799
Andreas Schwab2b74f622018-01-29 11:47:06 +01004800#ifdef TIOCGPTPEER
4801static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry *ie, uint8_t *buf_temp,
4802 int fd, int cmd, abi_long arg)
4803{
4804 int flags = target_to_host_bitmask(arg, fcntl_flags_tbl);
4805 return get_errno(safe_ioctl(fd, ie->host_cmd, flags));
4806}
4807#endif
4808
blueswir19f106a72008-10-05 10:52:52 +00004809static IOCTLEntry ioctl_entries[] = {
Blue Swirl001faf32009-05-13 17:53:17 +00004810#define IOCTL(cmd, access, ...) \
Peter Maydelld2ef05b2011-01-06 15:04:17 +00004811 { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
4812#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
4813 { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
Helge Deller8cb762f2016-12-06 16:24:03 +01004814#define IOCTL_IGNORE(cmd) \
4815 { TARGET_ ## cmd, 0, #cmd },
bellard31e31b82003-02-18 22:55:36 +00004816#include "ioctls.h"
4817 { 0, 0, },
4818};
4819
pbrook53a59602006-03-25 19:31:22 +00004820/* ??? Implement proper locking for ioctls. */
ths0da46a62007-10-20 20:23:07 +00004821/* do_ioctl() Must return target values and target errnos. */
Laurent Vivier45c874e2015-06-16 00:35:28 +02004822static abi_long do_ioctl(int fd, int cmd, abi_long arg)
bellard31e31b82003-02-18 22:55:36 +00004823{
4824 const IOCTLEntry *ie;
4825 const argtype *arg_type;
blueswir1992f48a2007-10-14 16:27:31 +00004826 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00004827 uint8_t buf_temp[MAX_STRUCT_SIZE];
pbrook53a59602006-03-25 19:31:22 +00004828 int target_size;
4829 void *argptr;
bellard31e31b82003-02-18 22:55:36 +00004830
4831 ie = ioctl_entries;
4832 for(;;) {
4833 if (ie->target_cmd == 0) {
j_mayer32407102007-09-26 23:01:49 +00004834 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
ths0da46a62007-10-20 20:23:07 +00004835 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00004836 }
4837 if (ie->target_cmd == cmd)
4838 break;
4839 ie++;
4840 }
4841 arg_type = ie->arg_type;
Peter Maydelld2ef05b2011-01-06 15:04:17 +00004842 if (ie->do_ioctl) {
4843 return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
Helge Deller8cb762f2016-12-06 16:24:03 +01004844 } else if (!ie->host_cmd) {
4845 /* Some architectures define BSD ioctls in their headers
4846 that are not implemented in Linux. */
4847 return -TARGET_ENOSYS;
Peter Maydelld2ef05b2011-01-06 15:04:17 +00004848 }
4849
bellard31e31b82003-02-18 22:55:36 +00004850 switch(arg_type[0]) {
4851 case TYPE_NULL:
4852 /* no argument */
Peter Maydell49ca6f32016-06-06 19:58:14 +01004853 ret = get_errno(safe_ioctl(fd, ie->host_cmd));
bellard31e31b82003-02-18 22:55:36 +00004854 break;
4855 case TYPE_PTRVOID:
4856 case TYPE_INT:
Peter Maydell49ca6f32016-06-06 19:58:14 +01004857 ret = get_errno(safe_ioctl(fd, ie->host_cmd, arg));
bellard31e31b82003-02-18 22:55:36 +00004858 break;
4859 case TYPE_PTR:
4860 arg_type++;
pbrook53a59602006-03-25 19:31:22 +00004861 target_size = thunk_type_size(arg_type, 0);
bellard31e31b82003-02-18 22:55:36 +00004862 switch(ie->access) {
4863 case IOC_R:
Peter Maydell49ca6f32016-06-06 19:58:14 +01004864 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
bellard31e31b82003-02-18 22:55:36 +00004865 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004866 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
4867 if (!argptr)
4868 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00004869 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
4870 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00004871 }
4872 break;
4873 case IOC_W:
bellard579a97f2007-11-11 14:26:47 +00004874 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4875 if (!argptr)
4876 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00004877 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4878 unlock_user(argptr, arg, 0);
Peter Maydell49ca6f32016-06-06 19:58:14 +01004879 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
bellard31e31b82003-02-18 22:55:36 +00004880 break;
4881 default:
4882 case IOC_RW:
bellard579a97f2007-11-11 14:26:47 +00004883 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4884 if (!argptr)
4885 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00004886 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4887 unlock_user(argptr, arg, 0);
Peter Maydell49ca6f32016-06-06 19:58:14 +01004888 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
bellard31e31b82003-02-18 22:55:36 +00004889 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004890 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
4891 if (!argptr)
4892 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00004893 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
4894 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00004895 }
4896 break;
4897 }
4898 break;
4899 default:
j_mayer32407102007-09-26 23:01:49 +00004900 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
4901 (long)cmd, arg_type[0]);
ths0da46a62007-10-20 20:23:07 +00004902 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00004903 break;
4904 }
4905 return ret;
4906}
4907
blueswir1b39bc502008-10-05 10:51:10 +00004908static const bitmask_transtbl iflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00004909 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
4910 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
4911 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
4912 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
4913 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
4914 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
4915 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
4916 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
4917 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
4918 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
4919 { TARGET_IXON, TARGET_IXON, IXON, IXON },
4920 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
4921 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
4922 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
4923 { 0, 0, 0, 0 }
4924};
4925
blueswir1b39bc502008-10-05 10:51:10 +00004926static const bitmask_transtbl oflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00004927 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
4928 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
4929 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
4930 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
4931 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
4932 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
4933 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
4934 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
4935 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
4936 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
4937 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
4938 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
4939 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
4940 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
4941 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
4942 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
4943 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
4944 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
4945 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
4946 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
4947 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
4948 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
4949 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
4950 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
4951 { 0, 0, 0, 0 }
4952};
4953
blueswir1b39bc502008-10-05 10:51:10 +00004954static const bitmask_transtbl cflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00004955 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
4956 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
4957 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
4958 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
4959 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
4960 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
4961 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
4962 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
4963 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
4964 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
4965 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
4966 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
4967 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
4968 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
4969 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
4970 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
4971 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
4972 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
4973 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
4974 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
4975 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
4976 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
4977 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
4978 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
4979 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
4980 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
4981 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
4982 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
4983 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
4984 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
4985 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
4986 { 0, 0, 0, 0 }
4987};
4988
blueswir1b39bc502008-10-05 10:51:10 +00004989static const bitmask_transtbl lflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00004990 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
4991 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
4992 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
4993 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
4994 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
4995 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
4996 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
4997 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
4998 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
4999 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
5000 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
5001 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
5002 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
5003 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
5004 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
5005 { 0, 0, 0, 0 }
5006};
5007
5008static void target_to_host_termios (void *dst, const void *src)
5009{
5010 struct host_termios *host = dst;
5011 const struct target_termios *target = src;
ths3b46e622007-09-17 08:09:54 +00005012
ths5fafdf22007-09-16 21:08:06 +00005013 host->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00005014 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00005015 host->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00005016 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00005017 host->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00005018 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00005019 host->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00005020 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
5021 host->c_line = target->c_line;
ths3b46e622007-09-17 08:09:54 +00005022
Arnaud Patard44607122009-04-21 17:39:08 +03005023 memset(host->c_cc, 0, sizeof(host->c_cc));
ths5fafdf22007-09-16 21:08:06 +00005024 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
5025 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
ths3b46e622007-09-17 08:09:54 +00005026 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
ths5fafdf22007-09-16 21:08:06 +00005027 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
ths3b46e622007-09-17 08:09:54 +00005028 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
ths5fafdf22007-09-16 21:08:06 +00005029 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
ths3b46e622007-09-17 08:09:54 +00005030 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
ths5fafdf22007-09-16 21:08:06 +00005031 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
ths3b46e622007-09-17 08:09:54 +00005032 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
ths5fafdf22007-09-16 21:08:06 +00005033 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
5034 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
ths3b46e622007-09-17 08:09:54 +00005035 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
5036 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
5037 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
5038 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
5039 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
ths5fafdf22007-09-16 21:08:06 +00005040 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
bellard31e31b82003-02-18 22:55:36 +00005041}
ths3b46e622007-09-17 08:09:54 +00005042
bellard31e31b82003-02-18 22:55:36 +00005043static void host_to_target_termios (void *dst, const void *src)
5044{
5045 struct target_termios *target = dst;
5046 const struct host_termios *host = src;
5047
ths5fafdf22007-09-16 21:08:06 +00005048 target->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00005049 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00005050 target->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00005051 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00005052 target->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00005053 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00005054 target->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00005055 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
5056 target->c_line = host->c_line;
ths3b46e622007-09-17 08:09:54 +00005057
Arnaud Patard44607122009-04-21 17:39:08 +03005058 memset(target->c_cc, 0, sizeof(target->c_cc));
bellard31e31b82003-02-18 22:55:36 +00005059 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
5060 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
5061 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
5062 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
5063 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
5064 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
5065 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
5066 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
5067 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
5068 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
5069 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
5070 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
5071 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
5072 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
5073 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
5074 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
5075 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
5076}
5077
blueswir18e853dc2008-10-05 10:49:32 +00005078static const StructEntry struct_termios_def = {
bellard31e31b82003-02-18 22:55:36 +00005079 .convert = { host_to_target_termios, target_to_host_termios },
5080 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
5081 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
5082};
5083
bellard5286db72003-06-05 00:57:30 +00005084static bitmask_transtbl mmap_flags_tbl[] = {
Helge Deller541e1692017-10-31 13:53:58 +01005085 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
5086 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
5087 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
5088 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS,
5089 MAP_ANONYMOUS, MAP_ANONYMOUS },
5090 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN,
5091 MAP_GROWSDOWN, MAP_GROWSDOWN },
5092 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE,
5093 MAP_DENYWRITE, MAP_DENYWRITE },
5094 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE,
5095 MAP_EXECUTABLE, MAP_EXECUTABLE },
5096 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
5097 { TARGET_MAP_NORESERVE, TARGET_MAP_NORESERVE,
5098 MAP_NORESERVE, MAP_NORESERVE },
5099 { TARGET_MAP_HUGETLB, TARGET_MAP_HUGETLB, MAP_HUGETLB, MAP_HUGETLB },
5100 /* MAP_STACK had been ignored by the kernel for quite some time.
5101 Recognize it for the target insofar as we do not want to pass
5102 it through to the host. */
5103 { TARGET_MAP_STACK, TARGET_MAP_STACK, 0, 0 },
5104 { 0, 0, 0, 0 }
bellard5286db72003-06-05 00:57:30 +00005105};
5106
bellard2ab83ea2003-06-15 19:56:46 +00005107#if defined(TARGET_I386)
bellard6dbad632003-03-16 18:05:05 +00005108
5109/* NOTE: there is really one LDT for all the threads */
blueswir1b1d8e522008-10-26 13:43:07 +00005110static uint8_t *ldt_table;
bellard6dbad632003-03-16 18:05:05 +00005111
bellard03acab62007-11-11 14:57:14 +00005112static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00005113{
5114 int size;
pbrook53a59602006-03-25 19:31:22 +00005115 void *p;
bellard6dbad632003-03-16 18:05:05 +00005116
5117 if (!ldt_table)
5118 return 0;
5119 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
5120 if (size > bytecount)
5121 size = bytecount;
bellard579a97f2007-11-11 14:26:47 +00005122 p = lock_user(VERIFY_WRITE, ptr, size, 0);
5123 if (!p)
bellard03acab62007-11-11 14:57:14 +00005124 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00005125 /* ??? Should this by byteswapped? */
pbrook53a59602006-03-25 19:31:22 +00005126 memcpy(p, ldt_table, size);
5127 unlock_user(p, ptr, size);
bellard6dbad632003-03-16 18:05:05 +00005128 return size;
5129}
5130
5131/* XXX: add locking support */
bellard03acab62007-11-11 14:57:14 +00005132static abi_long write_ldt(CPUX86State *env,
5133 abi_ulong ptr, unsigned long bytecount, int oldmode)
bellard6dbad632003-03-16 18:05:05 +00005134{
5135 struct target_modify_ldt_ldt_s ldt_info;
pbrook53a59602006-03-25 19:31:22 +00005136 struct target_modify_ldt_ldt_s *target_ldt_info;
bellard6dbad632003-03-16 18:05:05 +00005137 int seg_32bit, contents, read_exec_only, limit_in_pages;
bellard8d18e892007-11-14 15:18:40 +00005138 int seg_not_present, useable, lm;
bellard6dbad632003-03-16 18:05:05 +00005139 uint32_t *lp, entry_1, entry_2;
5140
5141 if (bytecount != sizeof(ldt_info))
bellard03acab62007-11-11 14:57:14 +00005142 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +00005143 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
bellard03acab62007-11-11 14:57:14 +00005144 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005145 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02005146 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
pbrook53a59602006-03-25 19:31:22 +00005147 ldt_info.limit = tswap32(target_ldt_info->limit);
5148 ldt_info.flags = tswap32(target_ldt_info->flags);
5149 unlock_user_struct(target_ldt_info, ptr, 0);
ths3b46e622007-09-17 08:09:54 +00005150
bellard6dbad632003-03-16 18:05:05 +00005151 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
bellard03acab62007-11-11 14:57:14 +00005152 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00005153 seg_32bit = ldt_info.flags & 1;
5154 contents = (ldt_info.flags >> 1) & 3;
5155 read_exec_only = (ldt_info.flags >> 3) & 1;
5156 limit_in_pages = (ldt_info.flags >> 4) & 1;
5157 seg_not_present = (ldt_info.flags >> 5) & 1;
5158 useable = (ldt_info.flags >> 6) & 1;
bellard8d18e892007-11-14 15:18:40 +00005159#ifdef TARGET_ABI32
5160 lm = 0;
5161#else
5162 lm = (ldt_info.flags >> 7) & 1;
5163#endif
bellard6dbad632003-03-16 18:05:05 +00005164 if (contents == 3) {
5165 if (oldmode)
bellard03acab62007-11-11 14:57:14 +00005166 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00005167 if (seg_not_present == 0)
bellard03acab62007-11-11 14:57:14 +00005168 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00005169 }
5170 /* allocate the LDT */
5171 if (!ldt_table) {
balroge4415702008-11-10 02:55:33 +00005172 env->ldt.base = target_mmap(0,
5173 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
5174 PROT_READ|PROT_WRITE,
5175 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
5176 if (env->ldt.base == -1)
bellard03acab62007-11-11 14:57:14 +00005177 return -TARGET_ENOMEM;
balroge4415702008-11-10 02:55:33 +00005178 memset(g2h(env->ldt.base), 0,
5179 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
bellard6dbad632003-03-16 18:05:05 +00005180 env->ldt.limit = 0xffff;
balroge4415702008-11-10 02:55:33 +00005181 ldt_table = g2h(env->ldt.base);
bellard6dbad632003-03-16 18:05:05 +00005182 }
5183
5184 /* NOTE: same code as Linux kernel */
5185 /* Allow LDTs to be cleared by the user. */
5186 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
5187 if (oldmode ||
5188 (contents == 0 &&
5189 read_exec_only == 1 &&
5190 seg_32bit == 0 &&
5191 limit_in_pages == 0 &&
5192 seg_not_present == 1 &&
5193 useable == 0 )) {
5194 entry_1 = 0;
5195 entry_2 = 0;
5196 goto install;
5197 }
5198 }
ths3b46e622007-09-17 08:09:54 +00005199
bellard6dbad632003-03-16 18:05:05 +00005200 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
5201 (ldt_info.limit & 0x0ffff);
5202 entry_2 = (ldt_info.base_addr & 0xff000000) |
5203 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
5204 (ldt_info.limit & 0xf0000) |
5205 ((read_exec_only ^ 1) << 9) |
5206 (contents << 10) |
5207 ((seg_not_present ^ 1) << 15) |
5208 (seg_32bit << 22) |
5209 (limit_in_pages << 23) |
bellard8d18e892007-11-14 15:18:40 +00005210 (lm << 21) |
bellard6dbad632003-03-16 18:05:05 +00005211 0x7000;
5212 if (!oldmode)
5213 entry_2 |= (useable << 20);
bellard14ae3ba2003-05-27 23:25:06 +00005214
bellard6dbad632003-03-16 18:05:05 +00005215 /* Install the new entry ... */
5216install:
5217 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
5218 lp[0] = tswap32(entry_1);
5219 lp[1] = tswap32(entry_2);
5220 return 0;
5221}
5222
5223/* specific and weird i386 syscalls */
blueswir18fcd3692008-08-17 20:26:25 +00005224static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
5225 unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00005226{
bellard03acab62007-11-11 14:57:14 +00005227 abi_long ret;
ths3b46e622007-09-17 08:09:54 +00005228
bellard6dbad632003-03-16 18:05:05 +00005229 switch (func) {
5230 case 0:
5231 ret = read_ldt(ptr, bytecount);
5232 break;
5233 case 1:
5234 ret = write_ldt(env, ptr, bytecount, 1);
5235 break;
5236 case 0x11:
5237 ret = write_ldt(env, ptr, bytecount, 0);
5238 break;
bellard03acab62007-11-11 14:57:14 +00005239 default:
5240 ret = -TARGET_ENOSYS;
5241 break;
bellard6dbad632003-03-16 18:05:05 +00005242 }
5243 return ret;
5244}
bellard1b6b0292003-03-22 17:31:38 +00005245
blueswir14583f582008-08-24 10:35:55 +00005246#if defined(TARGET_I386) && defined(TARGET_ABI32)
Alexander Grafbc22eb42013-07-16 18:44:58 +01005247abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00005248{
5249 uint64_t *gdt_table = g2h(env->gdt.base);
5250 struct target_modify_ldt_ldt_s ldt_info;
5251 struct target_modify_ldt_ldt_s *target_ldt_info;
5252 int seg_32bit, contents, read_exec_only, limit_in_pages;
5253 int seg_not_present, useable, lm;
5254 uint32_t *lp, entry_1, entry_2;
5255 int i;
5256
5257 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
5258 if (!target_ldt_info)
5259 return -TARGET_EFAULT;
5260 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02005261 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
bellard8d18e892007-11-14 15:18:40 +00005262 ldt_info.limit = tswap32(target_ldt_info->limit);
5263 ldt_info.flags = tswap32(target_ldt_info->flags);
5264 if (ldt_info.entry_number == -1) {
5265 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
5266 if (gdt_table[i] == 0) {
5267 ldt_info.entry_number = i;
5268 target_ldt_info->entry_number = tswap32(i);
5269 break;
5270 }
5271 }
5272 }
5273 unlock_user_struct(target_ldt_info, ptr, 1);
5274
5275 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
5276 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
5277 return -TARGET_EINVAL;
5278 seg_32bit = ldt_info.flags & 1;
5279 contents = (ldt_info.flags >> 1) & 3;
5280 read_exec_only = (ldt_info.flags >> 3) & 1;
5281 limit_in_pages = (ldt_info.flags >> 4) & 1;
5282 seg_not_present = (ldt_info.flags >> 5) & 1;
5283 useable = (ldt_info.flags >> 6) & 1;
5284#ifdef TARGET_ABI32
5285 lm = 0;
5286#else
5287 lm = (ldt_info.flags >> 7) & 1;
5288#endif
5289
5290 if (contents == 3) {
5291 if (seg_not_present == 0)
5292 return -TARGET_EINVAL;
5293 }
5294
5295 /* NOTE: same code as Linux kernel */
5296 /* Allow LDTs to be cleared by the user. */
5297 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
5298 if ((contents == 0 &&
5299 read_exec_only == 1 &&
5300 seg_32bit == 0 &&
5301 limit_in_pages == 0 &&
5302 seg_not_present == 1 &&
5303 useable == 0 )) {
5304 entry_1 = 0;
5305 entry_2 = 0;
5306 goto install;
5307 }
5308 }
5309
5310 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
5311 (ldt_info.limit & 0x0ffff);
5312 entry_2 = (ldt_info.base_addr & 0xff000000) |
5313 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
5314 (ldt_info.limit & 0xf0000) |
5315 ((read_exec_only ^ 1) << 9) |
5316 (contents << 10) |
5317 ((seg_not_present ^ 1) << 15) |
5318 (seg_32bit << 22) |
5319 (limit_in_pages << 23) |
5320 (useable << 20) |
5321 (lm << 21) |
5322 0x7000;
5323
5324 /* Install the new entry ... */
5325install:
5326 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
5327 lp[0] = tswap32(entry_1);
5328 lp[1] = tswap32(entry_2);
5329 return 0;
5330}
5331
blueswir18fcd3692008-08-17 20:26:25 +00005332static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00005333{
5334 struct target_modify_ldt_ldt_s *target_ldt_info;
5335 uint64_t *gdt_table = g2h(env->gdt.base);
5336 uint32_t base_addr, limit, flags;
5337 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
5338 int seg_not_present, useable, lm;
5339 uint32_t *lp, entry_1, entry_2;
5340
5341 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
5342 if (!target_ldt_info)
5343 return -TARGET_EFAULT;
5344 idx = tswap32(target_ldt_info->entry_number);
5345 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
5346 idx > TARGET_GDT_ENTRY_TLS_MAX) {
5347 unlock_user_struct(target_ldt_info, ptr, 1);
5348 return -TARGET_EINVAL;
5349 }
5350 lp = (uint32_t *)(gdt_table + idx);
5351 entry_1 = tswap32(lp[0]);
5352 entry_2 = tswap32(lp[1]);
5353
5354 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
5355 contents = (entry_2 >> 10) & 3;
5356 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
5357 seg_32bit = (entry_2 >> 22) & 1;
5358 limit_in_pages = (entry_2 >> 23) & 1;
5359 useable = (entry_2 >> 20) & 1;
5360#ifdef TARGET_ABI32
5361 lm = 0;
5362#else
5363 lm = (entry_2 >> 21) & 1;
5364#endif
5365 flags = (seg_32bit << 0) | (contents << 1) |
5366 (read_exec_only << 3) | (limit_in_pages << 4) |
5367 (seg_not_present << 5) | (useable << 6) | (lm << 7);
5368 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
5369 base_addr = (entry_1 >> 16) |
5370 (entry_2 & 0xff000000) |
5371 ((entry_2 & 0xff) << 16);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02005372 target_ldt_info->base_addr = tswapal(base_addr);
bellard8d18e892007-11-14 15:18:40 +00005373 target_ldt_info->limit = tswap32(limit);
5374 target_ldt_info->flags = tswap32(flags);
5375 unlock_user_struct(target_ldt_info, ptr, 1);
5376 return 0;
5377}
blueswir14583f582008-08-24 10:35:55 +00005378#endif /* TARGET_I386 && TARGET_ABI32 */
bellard8d18e892007-11-14 15:18:40 +00005379
bellardd2fd1af2007-11-14 18:08:56 +00005380#ifndef TARGET_ABI32
Peter Maydell2667e712013-07-16 18:44:59 +01005381abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
bellardd2fd1af2007-11-14 18:08:56 +00005382{
Juan Quintela1add8692011-06-16 17:37:09 +01005383 abi_long ret = 0;
bellardd2fd1af2007-11-14 18:08:56 +00005384 abi_ulong val;
5385 int idx;
Juan Quintela1add8692011-06-16 17:37:09 +01005386
bellardd2fd1af2007-11-14 18:08:56 +00005387 switch(code) {
5388 case TARGET_ARCH_SET_GS:
5389 case TARGET_ARCH_SET_FS:
5390 if (code == TARGET_ARCH_SET_GS)
5391 idx = R_GS;
5392 else
5393 idx = R_FS;
5394 cpu_x86_load_seg(env, idx, 0);
5395 env->segs[idx].base = addr;
5396 break;
5397 case TARGET_ARCH_GET_GS:
5398 case TARGET_ARCH_GET_FS:
5399 if (code == TARGET_ARCH_GET_GS)
5400 idx = R_GS;
5401 else
5402 idx = R_FS;
5403 val = env->segs[idx].base;
5404 if (put_user(val, addr, abi_ulong))
Juan Quintela1add8692011-06-16 17:37:09 +01005405 ret = -TARGET_EFAULT;
bellardd2fd1af2007-11-14 18:08:56 +00005406 break;
5407 default:
5408 ret = -TARGET_EINVAL;
5409 break;
5410 }
Juan Quintela1add8692011-06-16 17:37:09 +01005411 return ret;
bellardd2fd1af2007-11-14 18:08:56 +00005412}
5413#endif
5414
bellard2ab83ea2003-06-15 19:56:46 +00005415#endif /* defined(TARGET_I386) */
5416
Riku Voipio05098a92011-03-04 15:27:29 +02005417#define NEW_STACK_SIZE 0x40000
pbrookd865bab2008-06-07 22:12:17 +00005418
pbrookd865bab2008-06-07 22:12:17 +00005419
5420static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
5421typedef struct {
Andreas Färber9349b4f2012-03-14 01:38:32 +01005422 CPUArchState *env;
pbrookd865bab2008-06-07 22:12:17 +00005423 pthread_mutex_t mutex;
5424 pthread_cond_t cond;
5425 pthread_t thread;
5426 uint32_t tid;
5427 abi_ulong child_tidptr;
5428 abi_ulong parent_tidptr;
5429 sigset_t sigmask;
5430} new_thread_info;
5431
5432static void *clone_func(void *arg)
5433{
5434 new_thread_info *info = arg;
Andreas Färber9349b4f2012-03-14 01:38:32 +01005435 CPUArchState *env;
Andreas Färber0d342822012-12-17 07:12:13 +01005436 CPUState *cpu;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03005437 TaskState *ts;
pbrookd865bab2008-06-07 22:12:17 +00005438
Emilio G. Cota70903762015-08-23 20:23:41 -04005439 rcu_register_thread();
Emilio G. Cota3468b592017-07-19 18:57:58 -04005440 tcg_register_thread();
pbrookd865bab2008-06-07 22:12:17 +00005441 env = info->env;
Andreas Färber0d342822012-12-17 07:12:13 +01005442 cpu = ENV_GET_CPU(env);
Andreas Färbera2247f82013-06-09 19:47:04 +02005443 thread_cpu = cpu;
Andreas Färber0429a972013-08-26 18:14:44 +02005444 ts = (TaskState *)cpu->opaque;
pbrookd865bab2008-06-07 22:12:17 +00005445 info->tid = gettid();
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03005446 task_settid(ts);
pbrookd865bab2008-06-07 22:12:17 +00005447 if (info->child_tidptr)
5448 put_user_u32(info->tid, info->child_tidptr);
5449 if (info->parent_tidptr)
5450 put_user_u32(info->tid, info->parent_tidptr);
5451 /* Enable signals. */
5452 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
5453 /* Signal to the parent that we're ready. */
5454 pthread_mutex_lock(&info->mutex);
5455 pthread_cond_broadcast(&info->cond);
5456 pthread_mutex_unlock(&info->mutex);
Emilio G. Cotaa4dd3d52017-10-18 18:01:41 -04005457 /* Wait until the parent has finished initializing the tls state. */
pbrookd865bab2008-06-07 22:12:17 +00005458 pthread_mutex_lock(&clone_lock);
5459 pthread_mutex_unlock(&clone_lock);
5460 cpu_loop(env);
5461 /* never exits */
5462 return NULL;
5463}
bellard1b6b0292003-03-22 17:31:38 +00005464
ths0da46a62007-10-20 20:23:07 +00005465/* do_fork() Must return host values and target errnos (unlike most
5466 do_*() functions). */
Andreas Färber9349b4f2012-03-14 01:38:32 +01005467static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
pbrookd865bab2008-06-07 22:12:17 +00005468 abi_ulong parent_tidptr, target_ulong newtls,
5469 abi_ulong child_tidptr)
bellard1b6b0292003-03-22 17:31:38 +00005470{
Andreas Färber0429a972013-08-26 18:14:44 +02005471 CPUState *cpu = ENV_GET_CPU(env);
bellard1b6b0292003-03-22 17:31:38 +00005472 int ret;
bellard5cd43932003-03-29 16:54:36 +00005473 TaskState *ts;
Andreas Färber0429a972013-08-26 18:14:44 +02005474 CPUState *new_cpu;
Andreas Färber9349b4f2012-03-14 01:38:32 +01005475 CPUArchState *new_env;
pbrookd865bab2008-06-07 22:12:17 +00005476 sigset_t sigmask;
ths3b46e622007-09-17 08:09:54 +00005477
Peter Maydell5ea2fc82016-08-02 18:41:27 +01005478 flags &= ~CLONE_IGNORED_FLAGS;
5479
balrog436d1242008-09-21 02:39:45 +00005480 /* Emulate vfork() with fork() */
5481 if (flags & CLONE_VFORK)
5482 flags &= ~(CLONE_VFORK | CLONE_VM);
5483
bellard1b6b0292003-03-22 17:31:38 +00005484 if (flags & CLONE_VM) {
Andreas Färber0429a972013-08-26 18:14:44 +02005485 TaskState *parent_ts = (TaskState *)cpu->opaque;
pbrookd865bab2008-06-07 22:12:17 +00005486 new_thread_info info;
5487 pthread_attr_t attr;
Peter Maydell24cb36a2013-07-16 18:45:00 +01005488
Peter Maydell5ea2fc82016-08-02 18:41:27 +01005489 if (((flags & CLONE_THREAD_FLAGS) != CLONE_THREAD_FLAGS) ||
5490 (flags & CLONE_INVALID_THREAD_FLAGS)) {
5491 return -TARGET_EINVAL;
5492 }
5493
Markus Armbrusterc78d65e2015-09-14 13:53:03 +02005494 ts = g_new0(TaskState, 1);
pbrook624f7972008-05-31 16:11:38 +00005495 init_task_state(ts);
Max Filippov73a988d2018-03-30 06:19:58 -07005496
5497 /* Grab a mutex so that thread setup appears atomic. */
5498 pthread_mutex_lock(&clone_lock);
5499
bellard1b6b0292003-03-22 17:31:38 +00005500 /* we create a new CPU instance. */
thsc5be9f02007-02-28 20:20:53 +00005501 new_env = cpu_copy(env);
pbrook6e68e072008-05-30 17:22:15 +00005502 /* Init regs that differ from the parent. */
5503 cpu_clone_regs(new_env, newsp);
Andreas Färber0429a972013-08-26 18:14:44 +02005504 new_cpu = ENV_GET_CPU(new_env);
5505 new_cpu->opaque = ts;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03005506 ts->bprm = parent_ts->bprm;
5507 ts->info = parent_ts->info;
Peter Maydell3d3efba2016-05-27 15:51:49 +01005508 ts->signal_mask = parent_ts->signal_mask;
pbrookd865bab2008-06-07 22:12:17 +00005509
Peter Maydell7cfbd382016-08-02 18:41:26 +01005510 if (flags & CLONE_CHILD_CLEARTID) {
pbrookc2764712009-03-07 15:24:59 +00005511 ts->child_tidptr = child_tidptr;
5512 }
5513
Peter Maydell7cfbd382016-08-02 18:41:26 +01005514 if (flags & CLONE_SETTLS) {
pbrookd865bab2008-06-07 22:12:17 +00005515 cpu_set_tls (new_env, newtls);
Peter Maydell7cfbd382016-08-02 18:41:26 +01005516 }
pbrookd865bab2008-06-07 22:12:17 +00005517
pbrookd865bab2008-06-07 22:12:17 +00005518 memset(&info, 0, sizeof(info));
5519 pthread_mutex_init(&info.mutex, NULL);
5520 pthread_mutex_lock(&info.mutex);
5521 pthread_cond_init(&info.cond, NULL);
5522 info.env = new_env;
Peter Maydell7cfbd382016-08-02 18:41:26 +01005523 if (flags & CLONE_CHILD_SETTID) {
pbrookd865bab2008-06-07 22:12:17 +00005524 info.child_tidptr = child_tidptr;
Peter Maydell7cfbd382016-08-02 18:41:26 +01005525 }
5526 if (flags & CLONE_PARENT_SETTID) {
pbrookd865bab2008-06-07 22:12:17 +00005527 info.parent_tidptr = parent_tidptr;
Peter Maydell7cfbd382016-08-02 18:41:26 +01005528 }
pbrookd865bab2008-06-07 22:12:17 +00005529
5530 ret = pthread_attr_init(&attr);
Nathan Froyd48e15fc2010-10-29 07:48:57 -07005531 ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE);
5532 ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pbrookd865bab2008-06-07 22:12:17 +00005533 /* It is not safe to deliver signals until the child has finished
5534 initializing, so temporarily block all signals. */
5535 sigfillset(&sigmask);
5536 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
5537
Alex Bennéeb67cb682016-10-05 11:13:04 -07005538 /* If this is our first additional thread, we need to ensure we
5539 * generate code for parallel execution and flush old translations.
5540 */
5541 if (!parallel_cpus) {
5542 parallel_cpus = true;
5543 tb_flush(cpu);
5544 }
5545
pbrookd865bab2008-06-07 22:12:17 +00005546 ret = pthread_create(&info.thread, &attr, clone_func, &info);
pbrookc2764712009-03-07 15:24:59 +00005547 /* TODO: Free new CPU state if thread creation failed. */
pbrookd865bab2008-06-07 22:12:17 +00005548
5549 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
5550 pthread_attr_destroy(&attr);
5551 if (ret == 0) {
5552 /* Wait for the child to initialize. */
5553 pthread_cond_wait(&info.cond, &info.mutex);
5554 ret = info.tid;
pbrookd865bab2008-06-07 22:12:17 +00005555 } else {
5556 ret = -1;
5557 }
5558 pthread_mutex_unlock(&info.mutex);
5559 pthread_cond_destroy(&info.cond);
5560 pthread_mutex_destroy(&info.mutex);
5561 pthread_mutex_unlock(&clone_lock);
bellard1b6b0292003-03-22 17:31:38 +00005562 } else {
5563 /* if no CLONE_VM, we consider it is a fork */
Peter Maydell5ea2fc82016-08-02 18:41:27 +01005564 if (flags & CLONE_INVALID_FORK_FLAGS) {
5565 return -TARGET_EINVAL;
5566 }
5567
5568 /* We can't support custom termination signals */
5569 if ((flags & CSIGNAL) != TARGET_SIGCHLD) {
Timothy E Baldwin93b4eff2015-08-31 00:26:21 +01005570 return -TARGET_EINVAL;
5571 }
Timothy E Baldwin7d92d342016-05-27 15:51:58 +01005572
5573 if (block_signals()) {
5574 return -TARGET_ERESTARTSYS;
5575 }
5576
pbrookd865bab2008-06-07 22:12:17 +00005577 fork_start();
bellard1b6b0292003-03-22 17:31:38 +00005578 ret = fork();
pbrookd865bab2008-06-07 22:12:17 +00005579 if (ret == 0) {
aurel322b1319c2008-12-18 22:44:04 +00005580 /* Child Process. */
pbrookd865bab2008-06-07 22:12:17 +00005581 cpu_clone_regs(env, newsp);
5582 fork_end(1);
aurel322b1319c2008-12-18 22:44:04 +00005583 /* There is a race condition here. The parent process could
5584 theoretically read the TID in the child process before the child
5585 tid is set. This would require using either ptrace
5586 (not implemented) or having *_tidptr to point at a shared memory
5587 mapping. We can't repeat the spinlock hack used above because
5588 the child process gets its own copy of the lock. */
pbrookd865bab2008-06-07 22:12:17 +00005589 if (flags & CLONE_CHILD_SETTID)
5590 put_user_u32(gettid(), child_tidptr);
5591 if (flags & CLONE_PARENT_SETTID)
5592 put_user_u32(gettid(), parent_tidptr);
Andreas Färber0429a972013-08-26 18:14:44 +02005593 ts = (TaskState *)cpu->opaque;
pbrookd865bab2008-06-07 22:12:17 +00005594 if (flags & CLONE_SETTLS)
5595 cpu_set_tls (env, newtls);
pbrookc2764712009-03-07 15:24:59 +00005596 if (flags & CLONE_CHILD_CLEARTID)
5597 ts->child_tidptr = child_tidptr;
pbrookd865bab2008-06-07 22:12:17 +00005598 } else {
5599 fork_end(0);
5600 }
bellard1b6b0292003-03-22 17:31:38 +00005601 }
5602 return ret;
5603}
5604
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02005605/* warning : doesn't handle linux specific flags... */
5606static int target_to_host_fcntl_cmd(int cmd)
5607{
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05005608 int ret;
5609
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02005610 switch(cmd) {
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05005611 case TARGET_F_DUPFD:
5612 case TARGET_F_GETFD:
5613 case TARGET_F_SETFD:
5614 case TARGET_F_GETFL:
5615 case TARGET_F_SETFL:
5616 ret = cmd;
5617 break;
5618 case TARGET_F_GETLK:
5619 ret = F_GETLK64;
5620 break;
5621 case TARGET_F_SETLK:
5622 ret = F_SETLK64;
5623 break;
5624 case TARGET_F_SETLKW:
5625 ret = F_SETLKW64;
5626 break;
5627 case TARGET_F_GETOWN:
5628 ret = F_GETOWN;
5629 break;
5630 case TARGET_F_SETOWN:
5631 ret = F_SETOWN;
5632 break;
5633 case TARGET_F_GETSIG:
5634 ret = F_GETSIG;
5635 break;
5636 case TARGET_F_SETSIG:
5637 ret = F_SETSIG;
5638 break;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02005639#if TARGET_ABI_BITS == 32
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05005640 case TARGET_F_GETLK64:
5641 ret = F_GETLK64;
5642 break;
5643 case TARGET_F_SETLK64:
5644 ret = F_SETLK64;
5645 break;
5646 case TARGET_F_SETLKW64:
5647 ret = F_SETLKW64;
5648 break;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02005649#endif
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05005650 case TARGET_F_SETLEASE:
5651 ret = F_SETLEASE;
5652 break;
5653 case TARGET_F_GETLEASE:
5654 ret = F_GETLEASE;
5655 break;
malcfbd5de92009-09-06 06:31:59 +04005656#ifdef F_DUPFD_CLOEXEC
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05005657 case TARGET_F_DUPFD_CLOEXEC:
5658 ret = F_DUPFD_CLOEXEC;
5659 break;
malcfbd5de92009-09-06 06:31:59 +04005660#endif
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05005661 case TARGET_F_NOTIFY:
5662 ret = F_NOTIFY;
5663 break;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01005664#ifdef F_GETOWN_EX
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05005665 case TARGET_F_GETOWN_EX:
5666 ret = F_GETOWN_EX;
5667 break;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01005668#endif
5669#ifdef F_SETOWN_EX
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05005670 case TARGET_F_SETOWN_EX:
5671 ret = F_SETOWN_EX;
5672 break;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01005673#endif
Peter Maydellddf31aa2016-06-30 17:33:49 +01005674#ifdef F_SETPIPE_SZ
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05005675 case TARGET_F_SETPIPE_SZ:
5676 ret = F_SETPIPE_SZ;
5677 break;
5678 case TARGET_F_GETPIPE_SZ:
5679 ret = F_GETPIPE_SZ;
5680 break;
Peter Maydellddf31aa2016-06-30 17:33:49 +01005681#endif
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05005682 default:
5683 ret = -TARGET_EINVAL;
5684 break;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02005685 }
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05005686
5687#if defined(__powerpc64__)
5688 /* On PPC64, glibc headers has the F_*LK* defined to 12, 13 and 14 and
5689 * is not supported by kernel. The glibc fcntl call actually adjusts
5690 * them to 5, 6 and 7 before making the syscall(). Since we make the
5691 * syscall directly, adjust to what is supported by the kernel.
5692 */
5693 if (ret >= F_GETLK64 && ret <= F_SETLKW64) {
5694 ret -= F_GETLK64 - 5;
5695 }
5696#endif
5697
5698 return ret;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02005699}
5700
Laurent Vivierae68ad92018-05-10 01:11:21 +02005701#define FLOCK_TRANSTBL \
5702 switch (type) { \
5703 TRANSTBL_CONVERT(F_RDLCK); \
5704 TRANSTBL_CONVERT(F_WRLCK); \
5705 TRANSTBL_CONVERT(F_UNLCK); \
5706 TRANSTBL_CONVERT(F_EXLCK); \
5707 TRANSTBL_CONVERT(F_SHLCK); \
5708 }
5709
5710static int target_to_host_flock(int type)
5711{
5712#define TRANSTBL_CONVERT(a) case TARGET_##a: return a
5713 FLOCK_TRANSTBL
5714#undef TRANSTBL_CONVERT
5715 return -TARGET_EINVAL;
5716}
5717
5718static int host_to_target_flock(int type)
5719{
5720#define TRANSTBL_CONVERT(a) case a: return TARGET_##a
5721 FLOCK_TRANSTBL
5722#undef TRANSTBL_CONVERT
5723 /* if we don't know how to convert the value coming
5724 * from the host we copy to the target field as-is
5725 */
5726 return type;
5727}
Laurent Vivier2ba7f732013-01-10 21:42:48 +01005728
Peter Maydell213d3e92016-06-13 11:22:05 +01005729static inline abi_long copy_from_user_flock(struct flock64 *fl,
5730 abi_ulong target_flock_addr)
5731{
5732 struct target_flock *target_fl;
Laurent Vivierae68ad92018-05-10 01:11:21 +02005733 int l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01005734
5735 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
5736 return -TARGET_EFAULT;
5737 }
5738
5739 __get_user(l_type, &target_fl->l_type);
Laurent Vivierae68ad92018-05-10 01:11:21 +02005740 l_type = target_to_host_flock(l_type);
5741 if (l_type < 0) {
5742 return l_type;
5743 }
5744 fl->l_type = l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01005745 __get_user(fl->l_whence, &target_fl->l_whence);
5746 __get_user(fl->l_start, &target_fl->l_start);
5747 __get_user(fl->l_len, &target_fl->l_len);
5748 __get_user(fl->l_pid, &target_fl->l_pid);
5749 unlock_user_struct(target_fl, target_flock_addr, 0);
5750 return 0;
5751}
5752
5753static inline abi_long copy_to_user_flock(abi_ulong target_flock_addr,
5754 const struct flock64 *fl)
5755{
5756 struct target_flock *target_fl;
5757 short l_type;
5758
5759 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
5760 return -TARGET_EFAULT;
5761 }
5762
Laurent Vivierae68ad92018-05-10 01:11:21 +02005763 l_type = host_to_target_flock(fl->l_type);
Peter Maydell213d3e92016-06-13 11:22:05 +01005764 __put_user(l_type, &target_fl->l_type);
5765 __put_user(fl->l_whence, &target_fl->l_whence);
5766 __put_user(fl->l_start, &target_fl->l_start);
5767 __put_user(fl->l_len, &target_fl->l_len);
5768 __put_user(fl->l_pid, &target_fl->l_pid);
5769 unlock_user_struct(target_fl, target_flock_addr, 1);
5770 return 0;
5771}
5772
5773typedef abi_long from_flock64_fn(struct flock64 *fl, abi_ulong target_addr);
5774typedef abi_long to_flock64_fn(abi_ulong target_addr, const struct flock64 *fl);
5775
5776#if defined(TARGET_ARM) && TARGET_ABI_BITS == 32
Laurent Vivier7f254c52018-05-02 23:57:30 +02005777static inline abi_long copy_from_user_oabi_flock64(struct flock64 *fl,
Peter Maydell213d3e92016-06-13 11:22:05 +01005778 abi_ulong target_flock_addr)
5779{
Laurent Vivier7f254c52018-05-02 23:57:30 +02005780 struct target_oabi_flock64 *target_fl;
Laurent Vivierae68ad92018-05-10 01:11:21 +02005781 int l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01005782
5783 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
5784 return -TARGET_EFAULT;
5785 }
5786
5787 __get_user(l_type, &target_fl->l_type);
Laurent Vivierae68ad92018-05-10 01:11:21 +02005788 l_type = target_to_host_flock(l_type);
5789 if (l_type < 0) {
5790 return l_type;
5791 }
5792 fl->l_type = l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01005793 __get_user(fl->l_whence, &target_fl->l_whence);
5794 __get_user(fl->l_start, &target_fl->l_start);
5795 __get_user(fl->l_len, &target_fl->l_len);
5796 __get_user(fl->l_pid, &target_fl->l_pid);
5797 unlock_user_struct(target_fl, target_flock_addr, 0);
5798 return 0;
5799}
5800
Laurent Vivier7f254c52018-05-02 23:57:30 +02005801static inline abi_long copy_to_user_oabi_flock64(abi_ulong target_flock_addr,
Peter Maydell213d3e92016-06-13 11:22:05 +01005802 const struct flock64 *fl)
5803{
Laurent Vivier7f254c52018-05-02 23:57:30 +02005804 struct target_oabi_flock64 *target_fl;
Peter Maydell213d3e92016-06-13 11:22:05 +01005805 short l_type;
5806
5807 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
5808 return -TARGET_EFAULT;
5809 }
5810
Laurent Vivierae68ad92018-05-10 01:11:21 +02005811 l_type = host_to_target_flock(fl->l_type);
Peter Maydell213d3e92016-06-13 11:22:05 +01005812 __put_user(l_type, &target_fl->l_type);
5813 __put_user(fl->l_whence, &target_fl->l_whence);
5814 __put_user(fl->l_start, &target_fl->l_start);
5815 __put_user(fl->l_len, &target_fl->l_len);
5816 __put_user(fl->l_pid, &target_fl->l_pid);
5817 unlock_user_struct(target_fl, target_flock_addr, 1);
5818 return 0;
5819}
5820#endif
5821
5822static inline abi_long copy_from_user_flock64(struct flock64 *fl,
5823 abi_ulong target_flock_addr)
5824{
5825 struct target_flock64 *target_fl;
Laurent Vivierae68ad92018-05-10 01:11:21 +02005826 int l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01005827
5828 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
5829 return -TARGET_EFAULT;
5830 }
5831
5832 __get_user(l_type, &target_fl->l_type);
Laurent Vivierae68ad92018-05-10 01:11:21 +02005833 l_type = target_to_host_flock(l_type);
5834 if (l_type < 0) {
5835 return l_type;
5836 }
5837 fl->l_type = l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01005838 __get_user(fl->l_whence, &target_fl->l_whence);
5839 __get_user(fl->l_start, &target_fl->l_start);
5840 __get_user(fl->l_len, &target_fl->l_len);
5841 __get_user(fl->l_pid, &target_fl->l_pid);
5842 unlock_user_struct(target_fl, target_flock_addr, 0);
5843 return 0;
5844}
5845
5846static inline abi_long copy_to_user_flock64(abi_ulong target_flock_addr,
5847 const struct flock64 *fl)
5848{
5849 struct target_flock64 *target_fl;
5850 short l_type;
5851
5852 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
5853 return -TARGET_EFAULT;
5854 }
5855
Laurent Vivierae68ad92018-05-10 01:11:21 +02005856 l_type = host_to_target_flock(fl->l_type);
Peter Maydell213d3e92016-06-13 11:22:05 +01005857 __put_user(l_type, &target_fl->l_type);
5858 __put_user(fl->l_whence, &target_fl->l_whence);
5859 __put_user(fl->l_start, &target_fl->l_start);
5860 __put_user(fl->l_len, &target_fl->l_len);
5861 __put_user(fl->l_pid, &target_fl->l_pid);
5862 unlock_user_struct(target_fl, target_flock_addr, 1);
5863 return 0;
5864}
5865
blueswir1992f48a2007-10-14 16:27:31 +00005866static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
bellard7775e9e2003-05-14 22:46:48 +00005867{
ths43f238d2007-01-05 20:55:49 +00005868 struct flock64 fl64;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01005869#ifdef F_GETOWN_EX
5870 struct f_owner_ex fox;
5871 struct target_f_owner_ex *target_fox;
5872#endif
blueswir1992f48a2007-10-14 16:27:31 +00005873 abi_long ret;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02005874 int host_cmd = target_to_host_fcntl_cmd(cmd);
5875
5876 if (host_cmd == -TARGET_EINVAL)
5877 return host_cmd;
pbrook53a59602006-03-25 19:31:22 +00005878
bellard7775e9e2003-05-14 22:46:48 +00005879 switch(cmd) {
5880 case TARGET_F_GETLK:
Peter Maydell213d3e92016-06-13 11:22:05 +01005881 ret = copy_from_user_flock(&fl64, arg);
5882 if (ret) {
5883 return ret;
5884 }
Peter Maydell435da5e2016-06-13 11:22:05 +01005885 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00005886 if (ret == 0) {
Peter Maydell213d3e92016-06-13 11:22:05 +01005887 ret = copy_to_user_flock(arg, &fl64);
bellard7775e9e2003-05-14 22:46:48 +00005888 }
5889 break;
ths3b46e622007-09-17 08:09:54 +00005890
bellard7775e9e2003-05-14 22:46:48 +00005891 case TARGET_F_SETLK:
5892 case TARGET_F_SETLKW:
Peter Maydell213d3e92016-06-13 11:22:05 +01005893 ret = copy_from_user_flock(&fl64, arg);
5894 if (ret) {
5895 return ret;
5896 }
Peter Maydell435da5e2016-06-13 11:22:05 +01005897 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00005898 break;
ths3b46e622007-09-17 08:09:54 +00005899
bellard7775e9e2003-05-14 22:46:48 +00005900 case TARGET_F_GETLK64:
Peter Maydell213d3e92016-06-13 11:22:05 +01005901 ret = copy_from_user_flock64(&fl64, arg);
5902 if (ret) {
5903 return ret;
5904 }
Peter Maydell435da5e2016-06-13 11:22:05 +01005905 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
ths43f238d2007-01-05 20:55:49 +00005906 if (ret == 0) {
Peter Maydell213d3e92016-06-13 11:22:05 +01005907 ret = copy_to_user_flock64(arg, &fl64);
ths43f238d2007-01-05 20:55:49 +00005908 }
bellard9ee1fa22007-11-11 15:11:19 +00005909 break;
bellard7775e9e2003-05-14 22:46:48 +00005910 case TARGET_F_SETLK64:
5911 case TARGET_F_SETLKW64:
Peter Maydell213d3e92016-06-13 11:22:05 +01005912 ret = copy_from_user_flock64(&fl64, arg);
5913 if (ret) {
5914 return ret;
5915 }
Peter Maydell435da5e2016-06-13 11:22:05 +01005916 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00005917 break;
5918
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02005919 case TARGET_F_GETFL:
Peter Maydell435da5e2016-06-13 11:22:05 +01005920 ret = get_errno(safe_fcntl(fd, host_cmd, arg));
bellard9ee1fa22007-11-11 15:11:19 +00005921 if (ret >= 0) {
5922 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
5923 }
bellardffa65c32004-01-04 23:57:22 +00005924 break;
5925
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02005926 case TARGET_F_SETFL:
Peter Maydell435da5e2016-06-13 11:22:05 +01005927 ret = get_errno(safe_fcntl(fd, host_cmd,
5928 target_to_host_bitmask(arg,
5929 fcntl_flags_tbl)));
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02005930 break;
5931
Andreas Schwab8d5d3002014-03-07 15:24:08 +01005932#ifdef F_GETOWN_EX
5933 case TARGET_F_GETOWN_EX:
Peter Maydell435da5e2016-06-13 11:22:05 +01005934 ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
Andreas Schwab8d5d3002014-03-07 15:24:08 +01005935 if (ret >= 0) {
5936 if (!lock_user_struct(VERIFY_WRITE, target_fox, arg, 0))
5937 return -TARGET_EFAULT;
5938 target_fox->type = tswap32(fox.type);
5939 target_fox->pid = tswap32(fox.pid);
5940 unlock_user_struct(target_fox, arg, 1);
5941 }
5942 break;
5943#endif
5944
5945#ifdef F_SETOWN_EX
5946 case TARGET_F_SETOWN_EX:
5947 if (!lock_user_struct(VERIFY_READ, target_fox, arg, 1))
5948 return -TARGET_EFAULT;
5949 fox.type = tswap32(target_fox->type);
5950 fox.pid = tswap32(target_fox->pid);
5951 unlock_user_struct(target_fox, arg, 0);
Peter Maydell435da5e2016-06-13 11:22:05 +01005952 ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
Andreas Schwab8d5d3002014-03-07 15:24:08 +01005953 break;
5954#endif
5955
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02005956 case TARGET_F_SETOWN:
5957 case TARGET_F_GETOWN:
5958 case TARGET_F_SETSIG:
5959 case TARGET_F_GETSIG:
Ulrich Hecht7e22e542009-07-24 19:10:27 +02005960 case TARGET_F_SETLEASE:
5961 case TARGET_F_GETLEASE:
Peter Maydell7e3b92e2016-06-20 15:50:37 +01005962 case TARGET_F_SETPIPE_SZ:
5963 case TARGET_F_GETPIPE_SZ:
Peter Maydell435da5e2016-06-13 11:22:05 +01005964 ret = get_errno(safe_fcntl(fd, host_cmd, arg));
bellardffa65c32004-01-04 23:57:22 +00005965 break;
5966
bellard7775e9e2003-05-14 22:46:48 +00005967 default:
Peter Maydell435da5e2016-06-13 11:22:05 +01005968 ret = get_errno(safe_fcntl(fd, cmd, arg));
bellard7775e9e2003-05-14 22:46:48 +00005969 break;
5970 }
5971 return ret;
5972}
5973
bellard67867302003-11-23 17:05:30 +00005974#ifdef USE_UID16
bellard7775e9e2003-05-14 22:46:48 +00005975
bellard67867302003-11-23 17:05:30 +00005976static inline int high2lowuid(int uid)
5977{
5978 if (uid > 65535)
5979 return 65534;
5980 else
5981 return uid;
5982}
5983
5984static inline int high2lowgid(int gid)
5985{
5986 if (gid > 65535)
5987 return 65534;
5988 else
5989 return gid;
5990}
5991
5992static inline int low2highuid(int uid)
5993{
5994 if ((int16_t)uid == -1)
5995 return -1;
5996 else
5997 return uid;
5998}
5999
6000static inline int low2highgid(int gid)
6001{
6002 if ((int16_t)gid == -1)
6003 return -1;
6004 else
6005 return gid;
6006}
Riku Voipio0c866a72011-04-18 15:23:06 +03006007static inline int tswapid(int id)
6008{
6009 return tswap16(id);
6010}
Peter Maydell76ca3102014-03-02 19:36:41 +00006011
6012#define put_user_id(x, gaddr) put_user_u16(x, gaddr)
6013
Riku Voipio0c866a72011-04-18 15:23:06 +03006014#else /* !USE_UID16 */
6015static inline int high2lowuid(int uid)
6016{
6017 return uid;
6018}
6019static inline int high2lowgid(int gid)
6020{
6021 return gid;
6022}
6023static inline int low2highuid(int uid)
6024{
6025 return uid;
6026}
6027static inline int low2highgid(int gid)
6028{
6029 return gid;
6030}
6031static inline int tswapid(int id)
6032{
6033 return tswap32(id);
6034}
Peter Maydell76ca3102014-03-02 19:36:41 +00006035
6036#define put_user_id(x, gaddr) put_user_u32(x, gaddr)
6037
bellard67867302003-11-23 17:05:30 +00006038#endif /* USE_UID16 */
bellard1b6b0292003-03-22 17:31:38 +00006039
Peter Maydellfd6f7792016-03-01 16:33:02 +00006040/* We must do direct syscalls for setting UID/GID, because we want to
6041 * implement the Linux system call semantics of "change only for this thread",
6042 * not the libc/POSIX semantics of "change for all threads in process".
6043 * (See http://ewontfix.com/17/ for more details.)
6044 * We use the 32-bit version of the syscalls if present; if it is not
6045 * then either the host architecture supports 32-bit UIDs natively with
6046 * the standard syscall, or the 16-bit UID is the best we can do.
6047 */
6048#ifdef __NR_setuid32
6049#define __NR_sys_setuid __NR_setuid32
6050#else
6051#define __NR_sys_setuid __NR_setuid
6052#endif
6053#ifdef __NR_setgid32
6054#define __NR_sys_setgid __NR_setgid32
6055#else
6056#define __NR_sys_setgid __NR_setgid
6057#endif
6058#ifdef __NR_setresuid32
6059#define __NR_sys_setresuid __NR_setresuid32
6060#else
6061#define __NR_sys_setresuid __NR_setresuid
6062#endif
6063#ifdef __NR_setresgid32
6064#define __NR_sys_setresgid __NR_setresgid32
6065#else
6066#define __NR_sys_setresgid __NR_setresgid
6067#endif
6068
6069_syscall1(int, sys_setuid, uid_t, uid)
6070_syscall1(int, sys_setgid, gid_t, gid)
6071_syscall3(int, sys_setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
6072_syscall3(int, sys_setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
6073
bellard31e31b82003-02-18 22:55:36 +00006074void syscall_init(void)
6075{
bellard2ab83ea2003-06-15 19:56:46 +00006076 IOCTLEntry *ie;
6077 const argtype *arg_type;
6078 int size;
thsb92c47c2007-11-01 00:07:38 +00006079 int i;
bellard2ab83ea2003-06-15 19:56:46 +00006080
Alexander Graf8be656b2015-05-06 23:47:32 +02006081 thunk_init(STRUCT_MAX);
6082
Blue Swirl001faf32009-05-13 17:53:17 +00006083#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
ths5fafdf22007-09-16 21:08:06 +00006084#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
bellard31e31b82003-02-18 22:55:36 +00006085#include "syscall_types.h"
6086#undef STRUCT
6087#undef STRUCT_SPECIAL
bellard2ab83ea2003-06-15 19:56:46 +00006088
Peter Maydelldd6e9572012-07-23 08:07:22 +00006089 /* Build target_to_host_errno_table[] table from
6090 * host_to_target_errno_table[]. */
6091 for (i = 0; i < ERRNO_TABLE_SIZE; i++) {
6092 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
6093 }
6094
bellard2ab83ea2003-06-15 19:56:46 +00006095 /* we patch the ioctl size if necessary. We rely on the fact that
6096 no ioctl has all the bits at '1' in the size field */
6097 ie = ioctl_entries;
6098 while (ie->target_cmd != 0) {
6099 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
6100 TARGET_IOC_SIZEMASK) {
6101 arg_type = ie->arg_type;
6102 if (arg_type[0] != TYPE_PTR) {
ths5fafdf22007-09-16 21:08:06 +00006103 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00006104 ie->target_cmd);
6105 exit(1);
6106 }
6107 arg_type++;
6108 size = thunk_type_size(arg_type, 0);
ths5fafdf22007-09-16 21:08:06 +00006109 ie->target_cmd = (ie->target_cmd &
bellard2ab83ea2003-06-15 19:56:46 +00006110 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
6111 (size << TARGET_IOC_SIZESHIFT);
6112 }
thsb92c47c2007-11-01 00:07:38 +00006113
bellard2ab83ea2003-06-15 19:56:46 +00006114 /* automatic consistency check if same arch */
balrog872ea0c2008-09-21 02:31:19 +00006115#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
6116 (defined(__x86_64__) && defined(TARGET_X86_64))
6117 if (unlikely(ie->target_cmd != ie->host_cmd)) {
6118 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
6119 ie->name, ie->target_cmd, ie->host_cmd);
bellard2ab83ea2003-06-15 19:56:46 +00006120 }
6121#endif
6122 ie++;
6123 }
bellard31e31b82003-02-18 22:55:36 +00006124}
bellardc573ff62004-01-04 15:51:36 +00006125
blueswir1992f48a2007-10-14 16:27:31 +00006126#if TARGET_ABI_BITS == 32
pbrookce4defa2006-02-09 16:49:55 +00006127static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
6128{
thsaf325d32008-06-10 15:29:15 +00006129#ifdef TARGET_WORDS_BIGENDIAN
pbrookce4defa2006-02-09 16:49:55 +00006130 return ((uint64_t)word0 << 32) | word1;
6131#else
6132 return ((uint64_t)word1 << 32) | word0;
6133#endif
6134}
blueswir1992f48a2007-10-14 16:27:31 +00006135#else /* TARGET_ABI_BITS == 32 */
j_mayer32407102007-09-26 23:01:49 +00006136static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
6137{
6138 return word0;
6139}
blueswir1992f48a2007-10-14 16:27:31 +00006140#endif /* TARGET_ABI_BITS != 32 */
pbrookce4defa2006-02-09 16:49:55 +00006141
6142#ifdef TARGET_NR_truncate64
blueswir1992f48a2007-10-14 16:27:31 +00006143static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
6144 abi_long arg2,
6145 abi_long arg3,
6146 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00006147{
James Clarke8bf8e9d2017-09-15 20:33:13 +01006148 if (regpairs_aligned(cpu_env, TARGET_NR_truncate64)) {
pbrookce4defa2006-02-09 16:49:55 +00006149 arg2 = arg3;
6150 arg3 = arg4;
Riku Voipio48e515d2011-07-12 15:40:51 +03006151 }
pbrookce4defa2006-02-09 16:49:55 +00006152 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
6153}
6154#endif
6155
6156#ifdef TARGET_NR_ftruncate64
blueswir1992f48a2007-10-14 16:27:31 +00006157static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
6158 abi_long arg2,
6159 abi_long arg3,
6160 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00006161{
James Clarke8bf8e9d2017-09-15 20:33:13 +01006162 if (regpairs_aligned(cpu_env, TARGET_NR_ftruncate64)) {
pbrookce4defa2006-02-09 16:49:55 +00006163 arg2 = arg3;
6164 arg3 = arg4;
Riku Voipio48e515d2011-07-12 15:40:51 +03006165 }
pbrookce4defa2006-02-09 16:49:55 +00006166 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
6167}
6168#endif
6169
bellard579a97f2007-11-11 14:26:47 +00006170static inline abi_long target_to_host_timespec(struct timespec *host_ts,
6171 abi_ulong target_addr)
pbrook53a59602006-03-25 19:31:22 +00006172{
6173 struct target_timespec *target_ts;
6174
bellard579a97f2007-11-11 14:26:47 +00006175 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
6176 return -TARGET_EFAULT;
Peter Maydellc7e35da2016-05-19 12:01:40 +01006177 __get_user(host_ts->tv_sec, &target_ts->tv_sec);
6178 __get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
pbrook53a59602006-03-25 19:31:22 +00006179 unlock_user_struct(target_ts, target_addr, 0);
bellardb255bfa2008-05-10 21:51:02 +00006180 return 0;
pbrook53a59602006-03-25 19:31:22 +00006181}
6182
bellard579a97f2007-11-11 14:26:47 +00006183static inline abi_long host_to_target_timespec(abi_ulong target_addr,
6184 struct timespec *host_ts)
pbrook53a59602006-03-25 19:31:22 +00006185{
6186 struct target_timespec *target_ts;
6187
bellard579a97f2007-11-11 14:26:47 +00006188 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
6189 return -TARGET_EFAULT;
Peter Maydellc7e35da2016-05-19 12:01:40 +01006190 __put_user(host_ts->tv_sec, &target_ts->tv_sec);
6191 __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
pbrook53a59602006-03-25 19:31:22 +00006192 unlock_user_struct(target_ts, target_addr, 1);
bellardb255bfa2008-05-10 21:51:02 +00006193 return 0;
pbrook53a59602006-03-25 19:31:22 +00006194}
6195
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11006196static inline abi_long target_to_host_itimerspec(struct itimerspec *host_itspec,
6197 abi_ulong target_addr)
6198{
6199 struct target_itimerspec *target_itspec;
6200
6201 if (!lock_user_struct(VERIFY_READ, target_itspec, target_addr, 1)) {
6202 return -TARGET_EFAULT;
6203 }
6204
6205 host_itspec->it_interval.tv_sec =
6206 tswapal(target_itspec->it_interval.tv_sec);
6207 host_itspec->it_interval.tv_nsec =
6208 tswapal(target_itspec->it_interval.tv_nsec);
6209 host_itspec->it_value.tv_sec = tswapal(target_itspec->it_value.tv_sec);
6210 host_itspec->it_value.tv_nsec = tswapal(target_itspec->it_value.tv_nsec);
6211
6212 unlock_user_struct(target_itspec, target_addr, 1);
6213 return 0;
6214}
6215
6216static inline abi_long host_to_target_itimerspec(abi_ulong target_addr,
6217 struct itimerspec *host_its)
6218{
6219 struct target_itimerspec *target_itspec;
6220
6221 if (!lock_user_struct(VERIFY_WRITE, target_itspec, target_addr, 0)) {
6222 return -TARGET_EFAULT;
6223 }
6224
6225 target_itspec->it_interval.tv_sec = tswapal(host_its->it_interval.tv_sec);
6226 target_itspec->it_interval.tv_nsec = tswapal(host_its->it_interval.tv_nsec);
6227
6228 target_itspec->it_value.tv_sec = tswapal(host_its->it_value.tv_sec);
6229 target_itspec->it_value.tv_nsec = tswapal(host_its->it_value.tv_nsec);
6230
6231 unlock_user_struct(target_itspec, target_addr, 0);
6232 return 0;
6233}
6234
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +02006235static inline abi_long target_to_host_timex(struct timex *host_tx,
6236 abi_long target_addr)
6237{
6238 struct target_timex *target_tx;
6239
6240 if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) {
6241 return -TARGET_EFAULT;
6242 }
6243
6244 __get_user(host_tx->modes, &target_tx->modes);
6245 __get_user(host_tx->offset, &target_tx->offset);
6246 __get_user(host_tx->freq, &target_tx->freq);
6247 __get_user(host_tx->maxerror, &target_tx->maxerror);
6248 __get_user(host_tx->esterror, &target_tx->esterror);
6249 __get_user(host_tx->status, &target_tx->status);
6250 __get_user(host_tx->constant, &target_tx->constant);
6251 __get_user(host_tx->precision, &target_tx->precision);
6252 __get_user(host_tx->tolerance, &target_tx->tolerance);
6253 __get_user(host_tx->time.tv_sec, &target_tx->time.tv_sec);
6254 __get_user(host_tx->time.tv_usec, &target_tx->time.tv_usec);
6255 __get_user(host_tx->tick, &target_tx->tick);
6256 __get_user(host_tx->ppsfreq, &target_tx->ppsfreq);
6257 __get_user(host_tx->jitter, &target_tx->jitter);
6258 __get_user(host_tx->shift, &target_tx->shift);
6259 __get_user(host_tx->stabil, &target_tx->stabil);
6260 __get_user(host_tx->jitcnt, &target_tx->jitcnt);
6261 __get_user(host_tx->calcnt, &target_tx->calcnt);
6262 __get_user(host_tx->errcnt, &target_tx->errcnt);
6263 __get_user(host_tx->stbcnt, &target_tx->stbcnt);
6264 __get_user(host_tx->tai, &target_tx->tai);
6265
6266 unlock_user_struct(target_tx, target_addr, 0);
6267 return 0;
6268}
6269
6270static inline abi_long host_to_target_timex(abi_long target_addr,
6271 struct timex *host_tx)
6272{
6273 struct target_timex *target_tx;
6274
6275 if (!lock_user_struct(VERIFY_WRITE, target_tx, target_addr, 0)) {
6276 return -TARGET_EFAULT;
6277 }
6278
6279 __put_user(host_tx->modes, &target_tx->modes);
6280 __put_user(host_tx->offset, &target_tx->offset);
6281 __put_user(host_tx->freq, &target_tx->freq);
6282 __put_user(host_tx->maxerror, &target_tx->maxerror);
6283 __put_user(host_tx->esterror, &target_tx->esterror);
6284 __put_user(host_tx->status, &target_tx->status);
6285 __put_user(host_tx->constant, &target_tx->constant);
6286 __put_user(host_tx->precision, &target_tx->precision);
6287 __put_user(host_tx->tolerance, &target_tx->tolerance);
6288 __put_user(host_tx->time.tv_sec, &target_tx->time.tv_sec);
6289 __put_user(host_tx->time.tv_usec, &target_tx->time.tv_usec);
6290 __put_user(host_tx->tick, &target_tx->tick);
6291 __put_user(host_tx->ppsfreq, &target_tx->ppsfreq);
6292 __put_user(host_tx->jitter, &target_tx->jitter);
6293 __put_user(host_tx->shift, &target_tx->shift);
6294 __put_user(host_tx->stabil, &target_tx->stabil);
6295 __put_user(host_tx->jitcnt, &target_tx->jitcnt);
6296 __put_user(host_tx->calcnt, &target_tx->calcnt);
6297 __put_user(host_tx->errcnt, &target_tx->errcnt);
6298 __put_user(host_tx->stbcnt, &target_tx->stbcnt);
6299 __put_user(host_tx->tai, &target_tx->tai);
6300
6301 unlock_user_struct(target_tx, target_addr, 1);
6302 return 0;
6303}
6304
6305
Peter Maydellc0659762014-08-09 15:42:32 +01006306static inline abi_long target_to_host_sigevent(struct sigevent *host_sevp,
6307 abi_ulong target_addr)
6308{
6309 struct target_sigevent *target_sevp;
6310
6311 if (!lock_user_struct(VERIFY_READ, target_sevp, target_addr, 1)) {
6312 return -TARGET_EFAULT;
6313 }
6314
6315 /* This union is awkward on 64 bit systems because it has a 32 bit
6316 * integer and a pointer in it; we follow the conversion approach
6317 * used for handling sigval types in signal.c so the guest should get
6318 * the correct value back even if we did a 64 bit byteswap and it's
6319 * using the 32 bit integer.
6320 */
6321 host_sevp->sigev_value.sival_ptr =
6322 (void *)(uintptr_t)tswapal(target_sevp->sigev_value.sival_ptr);
6323 host_sevp->sigev_signo =
6324 target_to_host_signal(tswap32(target_sevp->sigev_signo));
6325 host_sevp->sigev_notify = tswap32(target_sevp->sigev_notify);
6326 host_sevp->_sigev_un._tid = tswap32(target_sevp->_sigev_un._tid);
6327
6328 unlock_user_struct(target_sevp, target_addr, 1);
6329 return 0;
6330}
6331
Tom Musta6f6a4032014-08-12 13:53:42 -05006332#if defined(TARGET_NR_mlockall)
6333static inline int target_to_host_mlockall_arg(int arg)
6334{
6335 int result = 0;
6336
6337 if (arg & TARGET_MLOCKALL_MCL_CURRENT) {
6338 result |= MCL_CURRENT;
6339 }
6340 if (arg & TARGET_MLOCKALL_MCL_FUTURE) {
6341 result |= MCL_FUTURE;
6342 }
6343 return result;
6344}
6345#endif
6346
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02006347#if (defined(TARGET_NR_stat64) || defined(TARGET_NR_lstat64) || \
6348 defined(TARGET_NR_fstat64) || defined(TARGET_NR_fstatat64) || \
6349 defined(TARGET_NR_newfstatat))
balrog6a24a772008-09-20 02:23:36 +00006350static inline abi_long host_to_target_stat64(void *cpu_env,
6351 abi_ulong target_addr,
6352 struct stat *host_st)
6353{
Alexander Graf09701192013-09-03 20:12:15 +01006354#if defined(TARGET_ARM) && defined(TARGET_ABI32)
balrog6a24a772008-09-20 02:23:36 +00006355 if (((CPUARMState *)cpu_env)->eabi) {
6356 struct target_eabi_stat64 *target_st;
6357
6358 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
6359 return -TARGET_EFAULT;
6360 memset(target_st, 0, sizeof(struct target_eabi_stat64));
6361 __put_user(host_st->st_dev, &target_st->st_dev);
6362 __put_user(host_st->st_ino, &target_st->st_ino);
6363#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
6364 __put_user(host_st->st_ino, &target_st->__st_ino);
6365#endif
6366 __put_user(host_st->st_mode, &target_st->st_mode);
6367 __put_user(host_st->st_nlink, &target_st->st_nlink);
6368 __put_user(host_st->st_uid, &target_st->st_uid);
6369 __put_user(host_st->st_gid, &target_st->st_gid);
6370 __put_user(host_st->st_rdev, &target_st->st_rdev);
6371 __put_user(host_st->st_size, &target_st->st_size);
6372 __put_user(host_st->st_blksize, &target_st->st_blksize);
6373 __put_user(host_st->st_blocks, &target_st->st_blocks);
6374 __put_user(host_st->st_atime, &target_st->target_st_atime);
6375 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
6376 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
6377 unlock_user_struct(target_st, target_addr, 1);
6378 } else
6379#endif
6380 {
Stefan Weil20d155b2013-10-30 22:52:24 +01006381#if defined(TARGET_HAS_STRUCT_STAT64)
balrog6a24a772008-09-20 02:23:36 +00006382 struct target_stat64 *target_st;
Stefan Weil20d155b2013-10-30 22:52:24 +01006383#else
6384 struct target_stat *target_st;
aurel329d33b762009-04-08 23:07:05 +00006385#endif
balrog6a24a772008-09-20 02:23:36 +00006386
6387 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
6388 return -TARGET_EFAULT;
aurel329d33b762009-04-08 23:07:05 +00006389 memset(target_st, 0, sizeof(*target_st));
balrog6a24a772008-09-20 02:23:36 +00006390 __put_user(host_st->st_dev, &target_st->st_dev);
6391 __put_user(host_st->st_ino, &target_st->st_ino);
6392#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
6393 __put_user(host_st->st_ino, &target_st->__st_ino);
6394#endif
6395 __put_user(host_st->st_mode, &target_st->st_mode);
6396 __put_user(host_st->st_nlink, &target_st->st_nlink);
6397 __put_user(host_st->st_uid, &target_st->st_uid);
6398 __put_user(host_st->st_gid, &target_st->st_gid);
6399 __put_user(host_st->st_rdev, &target_st->st_rdev);
6400 /* XXX: better use of kernel struct */
6401 __put_user(host_st->st_size, &target_st->st_size);
6402 __put_user(host_st->st_blksize, &target_st->st_blksize);
6403 __put_user(host_st->st_blocks, &target_st->st_blocks);
6404 __put_user(host_st->st_atime, &target_st->target_st_atime);
6405 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
6406 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
6407 unlock_user_struct(target_st, target_addr, 1);
6408 }
6409
6410 return 0;
6411}
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02006412#endif
balrog6a24a772008-09-20 02:23:36 +00006413
pbrookbd0c5662008-05-29 14:34:11 +00006414/* ??? Using host futex calls even when target atomic operations
6415 are not really atomic probably breaks things. However implementing
6416 futexes locally would make futexes shared between multiple processes
6417 tricky. However they're probably useless because guest atomic
6418 operations won't work either. */
blueswir18fcd3692008-08-17 20:26:25 +00006419static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
6420 target_ulong uaddr2, int val3)
pbrookbd0c5662008-05-29 14:34:11 +00006421{
6422 struct timespec ts, *pts;
Nathan Froyda16aae02009-08-03 08:43:29 -07006423 int base_op;
pbrookbd0c5662008-05-29 14:34:11 +00006424
6425 /* ??? We assume FUTEX_* constants are the same on both host
6426 and target. */
Martin Mohringa29ccd62009-05-04 21:34:56 +03006427#ifdef FUTEX_CMD_MASK
Nathan Froyda16aae02009-08-03 08:43:29 -07006428 base_op = op & FUTEX_CMD_MASK;
Martin Mohringa29ccd62009-05-04 21:34:56 +03006429#else
Nathan Froyda16aae02009-08-03 08:43:29 -07006430 base_op = op;
Martin Mohringa29ccd62009-05-04 21:34:56 +03006431#endif
Nathan Froyda16aae02009-08-03 08:43:29 -07006432 switch (base_op) {
pbrookbd0c5662008-05-29 14:34:11 +00006433 case FUTEX_WAIT:
John Rigbycce246e2013-02-23 16:14:07 -07006434 case FUTEX_WAIT_BITSET:
pbrookbd0c5662008-05-29 14:34:11 +00006435 if (timeout) {
6436 pts = &ts;
6437 target_to_host_timespec(pts, timeout);
6438 } else {
6439 pts = NULL;
6440 }
Peter Maydelld509eeb2016-05-12 18:47:52 +01006441 return get_errno(safe_futex(g2h(uaddr), op, tswap32(val),
John Rigbycce246e2013-02-23 16:14:07 -07006442 pts, NULL, val3));
pbrookbd0c5662008-05-29 14:34:11 +00006443 case FUTEX_WAKE:
Peter Maydelld509eeb2016-05-12 18:47:52 +01006444 return get_errno(safe_futex(g2h(uaddr), op, val, NULL, NULL, 0));
pbrookbd0c5662008-05-29 14:34:11 +00006445 case FUTEX_FD:
Peter Maydelld509eeb2016-05-12 18:47:52 +01006446 return get_errno(safe_futex(g2h(uaddr), op, val, NULL, NULL, 0));
pbrookbd0c5662008-05-29 14:34:11 +00006447 case FUTEX_REQUEUE:
pbrookbd0c5662008-05-29 14:34:11 +00006448 case FUTEX_CMP_REQUEUE:
Nathan Froyda16aae02009-08-03 08:43:29 -07006449 case FUTEX_WAKE_OP:
6450 /* For FUTEX_REQUEUE, FUTEX_CMP_REQUEUE, and FUTEX_WAKE_OP, the
6451 TIMEOUT parameter is interpreted as a uint32_t by the kernel.
6452 But the prototype takes a `struct timespec *'; insert casts
6453 to satisfy the compiler. We do not need to tswap TIMEOUT
6454 since it's not compared to guest memory. */
6455 pts = (struct timespec *)(uintptr_t) timeout;
Peter Maydelld509eeb2016-05-12 18:47:52 +01006456 return get_errno(safe_futex(g2h(uaddr), op, val, pts,
6457 g2h(uaddr2),
6458 (base_op == FUTEX_CMP_REQUEUE
6459 ? tswap32(val3)
6460 : val3)));
pbrookbd0c5662008-05-29 14:34:11 +00006461 default:
6462 return -TARGET_ENOSYS;
6463 }
6464}
Laurent Vivier0f0426f2015-09-01 22:27:33 +02006465#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
6466static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname,
6467 abi_long handle, abi_long mount_id,
6468 abi_long flags)
6469{
6470 struct file_handle *target_fh;
6471 struct file_handle *fh;
6472 int mid = 0;
6473 abi_long ret;
6474 char *name;
6475 unsigned int size, total_size;
6476
6477 if (get_user_s32(size, handle)) {
6478 return -TARGET_EFAULT;
6479 }
6480
6481 name = lock_user_string(pathname);
6482 if (!name) {
6483 return -TARGET_EFAULT;
6484 }
6485
6486 total_size = sizeof(struct file_handle) + size;
6487 target_fh = lock_user(VERIFY_WRITE, handle, total_size, 0);
6488 if (!target_fh) {
6489 unlock_user(name, pathname, 0);
6490 return -TARGET_EFAULT;
6491 }
6492
6493 fh = g_malloc0(total_size);
6494 fh->handle_bytes = size;
6495
6496 ret = get_errno(name_to_handle_at(dirfd, path(name), fh, &mid, flags));
6497 unlock_user(name, pathname, 0);
6498
6499 /* man name_to_handle_at(2):
6500 * Other than the use of the handle_bytes field, the caller should treat
6501 * the file_handle structure as an opaque data type
6502 */
6503
6504 memcpy(target_fh, fh, total_size);
6505 target_fh->handle_bytes = tswap32(fh->handle_bytes);
6506 target_fh->handle_type = tswap32(fh->handle_type);
6507 g_free(fh);
6508 unlock_user(target_fh, handle, total_size);
6509
6510 if (put_user_s32(mid, mount_id)) {
6511 return -TARGET_EFAULT;
6512 }
6513
6514 return ret;
6515
6516}
6517#endif
6518
6519#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
6520static abi_long do_open_by_handle_at(abi_long mount_fd, abi_long handle,
6521 abi_long flags)
6522{
6523 struct file_handle *target_fh;
6524 struct file_handle *fh;
6525 unsigned int size, total_size;
6526 abi_long ret;
6527
6528 if (get_user_s32(size, handle)) {
6529 return -TARGET_EFAULT;
6530 }
6531
6532 total_size = sizeof(struct file_handle) + size;
6533 target_fh = lock_user(VERIFY_READ, handle, total_size, 1);
6534 if (!target_fh) {
6535 return -TARGET_EFAULT;
6536 }
6537
Thomas Huthe9d49d52015-10-09 17:56:38 +02006538 fh = g_memdup(target_fh, total_size);
Laurent Vivier0f0426f2015-09-01 22:27:33 +02006539 fh->handle_bytes = size;
6540 fh->handle_type = tswap32(target_fh->handle_type);
6541
6542 ret = get_errno(open_by_handle_at(mount_fd, fh,
6543 target_to_host_bitmask(flags, fcntl_flags_tbl)));
6544
6545 g_free(fh);
6546
6547 unlock_user(target_fh, handle, total_size);
6548
6549 return ret;
6550}
6551#endif
pbrookbd0c5662008-05-29 14:34:11 +00006552
Laurent Viviere36800c2015-10-02 14:48:09 +02006553#if defined(TARGET_NR_signalfd) || defined(TARGET_NR_signalfd4)
6554
Laurent Viviere36800c2015-10-02 14:48:09 +02006555static abi_long do_signalfd4(int fd, abi_long mask, int flags)
6556{
6557 int host_flags;
6558 target_sigset_t *target_mask;
6559 sigset_t host_mask;
6560 abi_long ret;
6561
6562 if (flags & ~(TARGET_O_NONBLOCK | TARGET_O_CLOEXEC)) {
6563 return -TARGET_EINVAL;
6564 }
6565 if (!lock_user_struct(VERIFY_READ, target_mask, mask, 1)) {
6566 return -TARGET_EFAULT;
6567 }
6568
6569 target_to_host_sigset(&host_mask, target_mask);
6570
6571 host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
6572
6573 ret = get_errno(signalfd(fd, &host_mask, host_flags));
6574 if (ret >= 0) {
6575 fd_trans_register(ret, &target_signalfd_trans);
6576 }
6577
6578 unlock_user_struct(target_mask, mask, 0);
6579
6580 return ret;
6581}
6582#endif
6583
pbrook1d9d8b52009-04-16 15:17:02 +00006584/* Map host to target signal numbers for the wait family of syscalls.
6585 Assume all other status bits are the same. */
Richard Hendersona05c6402012-09-15 11:34:20 -07006586int host_to_target_waitstatus(int status)
pbrook1d9d8b52009-04-16 15:17:02 +00006587{
6588 if (WIFSIGNALED(status)) {
6589 return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
6590 }
6591 if (WIFSTOPPED(status)) {
6592 return (host_to_target_signal(WSTOPSIG(status)) << 8)
6593 | (status & 0xff);
6594 }
6595 return status;
6596}
6597
Wim Vander Schelden76b94242014-06-18 11:02:39 +02006598static int open_self_cmdline(void *cpu_env, int fd)
6599{
Andreas Schwab58de8b92017-03-20 12:31:55 +01006600 CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
6601 struct linux_binprm *bprm = ((TaskState *)cpu->opaque)->bprm;
6602 int i;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02006603
Andreas Schwab58de8b92017-03-20 12:31:55 +01006604 for (i = 0; i < bprm->argc; i++) {
6605 size_t len = strlen(bprm->argv[i]) + 1;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02006606
Andreas Schwab58de8b92017-03-20 12:31:55 +01006607 if (write(fd, bprm->argv[i], len) != len) {
Wim Vander Schelden76b94242014-06-18 11:02:39 +02006608 return -1;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02006609 }
6610 }
6611
Andreas Schwab58de8b92017-03-20 12:31:55 +01006612 return 0;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02006613}
6614
Alexander Graf36c08d42011-11-02 20:23:24 +01006615static int open_self_maps(void *cpu_env, int fd)
6616{
Andreas Färber0429a972013-08-26 18:14:44 +02006617 CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
6618 TaskState *ts = cpu->opaque;
Alexander Graf1a49ef22012-05-01 16:30:28 +01006619 FILE *fp;
6620 char *line = NULL;
6621 size_t len = 0;
6622 ssize_t read;
Alexander Graf36c08d42011-11-02 20:23:24 +01006623
Alexander Graf1a49ef22012-05-01 16:30:28 +01006624 fp = fopen("/proc/self/maps", "r");
6625 if (fp == NULL) {
Peter Maydella3ca7bb2016-05-12 18:47:26 +01006626 return -1;
Alexander Graf1a49ef22012-05-01 16:30:28 +01006627 }
6628
6629 while ((read = getline(&line, &len, fp)) != -1) {
6630 int fields, dev_maj, dev_min, inode;
6631 uint64_t min, max, offset;
6632 char flag_r, flag_w, flag_x, flag_p;
6633 char path[512] = "";
6634 fields = sscanf(line, "%"PRIx64"-%"PRIx64" %c%c%c%c %"PRIx64" %x:%x %d"
6635 " %512s", &min, &max, &flag_r, &flag_w, &flag_x,
6636 &flag_p, &offset, &dev_maj, &dev_min, &inode, path);
6637
6638 if ((fields < 10) || (fields > 11)) {
6639 continue;
6640 }
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04006641 if (h2g_valid(min)) {
6642 int flags = page_get_flags(h2g(min));
Max Filippovebf9a362018-03-07 13:50:10 -08006643 max = h2g_valid(max - 1) ? max : (uintptr_t)g2h(GUEST_ADDR_MAX) + 1;
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04006644 if (page_check_range(h2g(min), max - min, flags) == -1) {
6645 continue;
6646 }
6647 if (h2g(min) == ts->info->stack_limit) {
6648 pstrcpy(path, sizeof(path), " [stack]");
6649 }
Laurent Vivier3e23de12018-08-14 19:12:17 +02006650 dprintf(fd, TARGET_ABI_FMT_ptr "-" TARGET_ABI_FMT_ptr
Christophe Lyone24fed42013-04-02 14:03:38 +02006651 " %c%c%c%c %08" PRIx64 " %02x:%02x %d %s%s\n",
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04006652 h2g(min), h2g(max - 1) + 1, flag_r, flag_w,
Alexander Graf1a49ef22012-05-01 16:30:28 +01006653 flag_x, flag_p, offset, dev_maj, dev_min, inode,
Christophe Lyone24fed42013-04-02 14:03:38 +02006654 path[0] ? " " : "", path);
Alexander Graf1a49ef22012-05-01 16:30:28 +01006655 }
6656 }
6657
6658 free(line);
6659 fclose(fp);
6660
Alexander Graf36c08d42011-11-02 20:23:24 +01006661 return 0;
6662}
6663
Alexander Graf480b8e72011-11-02 20:23:25 +01006664static int open_self_stat(void *cpu_env, int fd)
6665{
Andreas Färber0429a972013-08-26 18:14:44 +02006666 CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
6667 TaskState *ts = cpu->opaque;
Alexander Graf480b8e72011-11-02 20:23:25 +01006668 abi_ulong start_stack = ts->info->start_stack;
6669 int i;
6670
6671 for (i = 0; i < 44; i++) {
6672 char buf[128];
6673 int len;
6674 uint64_t val = 0;
6675
Fabio Erculianie0e65be2012-01-03 09:38:34 +00006676 if (i == 0) {
6677 /* pid */
6678 val = getpid();
6679 snprintf(buf, sizeof(buf), "%"PRId64 " ", val);
6680 } else if (i == 1) {
6681 /* app name */
6682 snprintf(buf, sizeof(buf), "(%s) ", ts->bprm->argv[0]);
6683 } else if (i == 27) {
6684 /* stack bottom */
6685 val = start_stack;
6686 snprintf(buf, sizeof(buf), "%"PRId64 " ", val);
6687 } else {
6688 /* for the rest, there is MasterCard */
6689 snprintf(buf, sizeof(buf), "0%c", i == 43 ? '\n' : ' ');
Alexander Graf480b8e72011-11-02 20:23:25 +01006690 }
Fabio Erculianie0e65be2012-01-03 09:38:34 +00006691
Alexander Graf480b8e72011-11-02 20:23:25 +01006692 len = strlen(buf);
6693 if (write(fd, buf, len) != len) {
6694 return -1;
6695 }
6696 }
6697
6698 return 0;
6699}
6700
Alexander Graf257450e2011-11-02 20:23:26 +01006701static int open_self_auxv(void *cpu_env, int fd)
6702{
Andreas Färber0429a972013-08-26 18:14:44 +02006703 CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
6704 TaskState *ts = cpu->opaque;
Alexander Graf257450e2011-11-02 20:23:26 +01006705 abi_ulong auxv = ts->info->saved_auxv;
6706 abi_ulong len = ts->info->auxv_len;
6707 char *ptr;
6708
6709 /*
6710 * Auxiliary vector is stored in target process stack.
6711 * read in whole auxv vector and copy it to file
6712 */
6713 ptr = lock_user(VERIFY_READ, auxv, len, 0);
6714 if (ptr != NULL) {
6715 while (len > 0) {
6716 ssize_t r;
6717 r = write(fd, ptr, len);
6718 if (r <= 0) {
6719 break;
6720 }
6721 len -= r;
6722 ptr += r;
6723 }
6724 lseek(fd, 0, SEEK_SET);
6725 unlock_user(ptr, auxv, len);
6726 }
6727
6728 return 0;
6729}
6730
Andreas Schwab463d8e72013-07-02 14:04:12 +01006731static int is_proc_myself(const char *filename, const char *entry)
6732{
6733 if (!strncmp(filename, "/proc/", strlen("/proc/"))) {
6734 filename += strlen("/proc/");
6735 if (!strncmp(filename, "self/", strlen("self/"))) {
6736 filename += strlen("self/");
6737 } else if (*filename >= '1' && *filename <= '9') {
6738 char myself[80];
6739 snprintf(myself, sizeof(myself), "%d/", getpid());
6740 if (!strncmp(filename, myself, strlen(myself))) {
6741 filename += strlen(myself);
6742 } else {
6743 return 0;
6744 }
6745 } else {
6746 return 0;
6747 }
6748 if (!strcmp(filename, entry)) {
6749 return 1;
6750 }
6751 }
6752 return 0;
6753}
6754
Laurent Vivierde6b9932013-08-30 01:46:40 +02006755#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
6756static int is_proc(const char *filename, const char *entry)
6757{
6758 return strcmp(filename, entry) == 0;
6759}
6760
6761static int open_net_route(void *cpu_env, int fd)
6762{
6763 FILE *fp;
6764 char *line = NULL;
6765 size_t len = 0;
6766 ssize_t read;
6767
6768 fp = fopen("/proc/net/route", "r");
6769 if (fp == NULL) {
Peter Maydella3ca7bb2016-05-12 18:47:26 +01006770 return -1;
Laurent Vivierde6b9932013-08-30 01:46:40 +02006771 }
6772
6773 /* read header */
6774
6775 read = getline(&line, &len, fp);
6776 dprintf(fd, "%s", line);
6777
6778 /* read routes */
6779
6780 while ((read = getline(&line, &len, fp)) != -1) {
6781 char iface[16];
6782 uint32_t dest, gw, mask;
6783 unsigned int flags, refcnt, use, metric, mtu, window, irtt;
Peter Maydell9d0bd0c2019-02-05 17:42:07 +00006784 int fields;
6785
6786 fields = sscanf(line,
6787 "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
6788 iface, &dest, &gw, &flags, &refcnt, &use, &metric,
6789 &mask, &mtu, &window, &irtt);
6790 if (fields != 11) {
6791 continue;
6792 }
Laurent Vivierde6b9932013-08-30 01:46:40 +02006793 dprintf(fd, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
6794 iface, tswap32(dest), tswap32(gw), flags, refcnt, use,
6795 metric, tswap32(mask), mtu, window, irtt);
6796 }
6797
6798 free(line);
6799 fclose(fp);
6800
6801 return 0;
6802}
6803#endif
6804
Riku Voipio0b2effd2014-08-06 10:36:37 +03006805static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags, mode_t mode)
Alexander Graf3be14d02011-11-02 20:23:23 +01006806{
6807 struct fake_open {
6808 const char *filename;
6809 int (*fill)(void *cpu_env, int fd);
Laurent Vivierde6b9932013-08-30 01:46:40 +02006810 int (*cmp)(const char *s1, const char *s2);
Alexander Graf3be14d02011-11-02 20:23:23 +01006811 };
6812 const struct fake_open *fake_open;
6813 static const struct fake_open fakes[] = {
Laurent Vivierde6b9932013-08-30 01:46:40 +02006814 { "maps", open_self_maps, is_proc_myself },
6815 { "stat", open_self_stat, is_proc_myself },
6816 { "auxv", open_self_auxv, is_proc_myself },
Wim Vander Schelden76b94242014-06-18 11:02:39 +02006817 { "cmdline", open_self_cmdline, is_proc_myself },
Laurent Vivierde6b9932013-08-30 01:46:40 +02006818#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
6819 { "/proc/net/route", open_net_route, is_proc },
6820#endif
6821 { NULL, NULL, NULL }
Alexander Graf3be14d02011-11-02 20:23:23 +01006822 };
6823
Maxim Ostapenkoaa07f5e2014-05-02 11:17:07 +03006824 if (is_proc_myself(pathname, "exe")) {
6825 int execfd = qemu_getauxval(AT_EXECFD);
Timothy E Baldwinc10a0732016-05-12 18:47:48 +01006826 return execfd ? execfd : safe_openat(dirfd, exec_path, flags, mode);
Maxim Ostapenkoaa07f5e2014-05-02 11:17:07 +03006827 }
6828
Alexander Graf3be14d02011-11-02 20:23:23 +01006829 for (fake_open = fakes; fake_open->filename; fake_open++) {
Laurent Vivierde6b9932013-08-30 01:46:40 +02006830 if (fake_open->cmp(pathname, fake_open->filename)) {
Alexander Graf3be14d02011-11-02 20:23:23 +01006831 break;
6832 }
6833 }
6834
6835 if (fake_open->filename) {
6836 const char *tmpdir;
6837 char filename[PATH_MAX];
6838 int fd, r;
6839
6840 /* create temporary file to map stat to */
6841 tmpdir = getenv("TMPDIR");
6842 if (!tmpdir)
6843 tmpdir = "/tmp";
6844 snprintf(filename, sizeof(filename), "%s/qemu-open.XXXXXX", tmpdir);
6845 fd = mkstemp(filename);
6846 if (fd < 0) {
6847 return fd;
6848 }
6849 unlink(filename);
6850
6851 if ((r = fake_open->fill(cpu_env, fd))) {
Peter Maydella3ca7bb2016-05-12 18:47:26 +01006852 int e = errno;
Alexander Graf3be14d02011-11-02 20:23:23 +01006853 close(fd);
Peter Maydella3ca7bb2016-05-12 18:47:26 +01006854 errno = e;
Alexander Graf3be14d02011-11-02 20:23:23 +01006855 return r;
6856 }
6857 lseek(fd, 0, SEEK_SET);
6858
6859 return fd;
6860 }
6861
Timothy E Baldwinc10a0732016-05-12 18:47:48 +01006862 return safe_openat(dirfd, path(pathname), flags, mode);
Alexander Graf3be14d02011-11-02 20:23:23 +01006863}
6864
Alexander Grafaecc8862014-11-10 21:33:03 +01006865#define TIMER_MAGIC 0x0caf0000
6866#define TIMER_MAGIC_MASK 0xffff0000
6867
6868/* Convert QEMU provided timer ID back to internal 16bit index format */
6869static target_timer_t get_timer_id(abi_long arg)
6870{
6871 target_timer_t timerid = arg;
6872
6873 if ((timerid & TIMER_MAGIC_MASK) != TIMER_MAGIC) {
6874 return -TARGET_EINVAL;
6875 }
6876
6877 timerid &= 0xffff;
6878
6879 if (timerid >= ARRAY_SIZE(g_posix_timers)) {
6880 return -TARGET_EINVAL;
6881 }
6882
6883 return timerid;
6884}
6885
Samuel Thibault2e0a8712018-01-09 21:16:43 +01006886static int target_to_host_cpu_mask(unsigned long *host_mask,
6887 size_t host_size,
6888 abi_ulong target_addr,
6889 size_t target_size)
6890{
6891 unsigned target_bits = sizeof(abi_ulong) * 8;
6892 unsigned host_bits = sizeof(*host_mask) * 8;
6893 abi_ulong *target_mask;
6894 unsigned i, j;
6895
6896 assert(host_size >= target_size);
6897
6898 target_mask = lock_user(VERIFY_READ, target_addr, target_size, 1);
6899 if (!target_mask) {
6900 return -TARGET_EFAULT;
6901 }
6902 memset(host_mask, 0, host_size);
6903
6904 for (i = 0 ; i < target_size / sizeof(abi_ulong); i++) {
6905 unsigned bit = i * target_bits;
6906 abi_ulong val;
6907
6908 __get_user(val, &target_mask[i]);
6909 for (j = 0; j < target_bits; j++, bit++) {
6910 if (val & (1UL << j)) {
6911 host_mask[bit / host_bits] |= 1UL << (bit % host_bits);
6912 }
6913 }
6914 }
6915
6916 unlock_user(target_mask, target_addr, 0);
6917 return 0;
6918}
6919
6920static int host_to_target_cpu_mask(const unsigned long *host_mask,
6921 size_t host_size,
6922 abi_ulong target_addr,
6923 size_t target_size)
6924{
6925 unsigned target_bits = sizeof(abi_ulong) * 8;
6926 unsigned host_bits = sizeof(*host_mask) * 8;
6927 abi_ulong *target_mask;
6928 unsigned i, j;
6929
6930 assert(host_size >= target_size);
6931
6932 target_mask = lock_user(VERIFY_WRITE, target_addr, target_size, 0);
6933 if (!target_mask) {
6934 return -TARGET_EFAULT;
6935 }
6936
6937 for (i = 0 ; i < target_size / sizeof(abi_ulong); i++) {
6938 unsigned bit = i * target_bits;
6939 abi_ulong val = 0;
6940
6941 for (j = 0; j < target_bits; j++, bit++) {
6942 if (host_mask[bit / host_bits] & (1UL << (bit % host_bits))) {
6943 val |= 1UL << j;
6944 }
6945 }
6946 __put_user(val, &target_mask[i]);
6947 }
6948
6949 unlock_user(target_mask, target_addr, target_size);
6950 return 0;
6951}
6952
Richard Hendersondc1ce182018-08-18 12:01:04 -07006953/* This is an internal helper for do_syscall so that it is easier
6954 * to have a single return point, so that actions, such as logging
6955 * of syscall results, can be performed.
6956 * All errnos that do_syscall() returns must be -TARGET_<errcode>.
6957 */
6958static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
6959 abi_long arg2, abi_long arg3, abi_long arg4,
6960 abi_long arg5, abi_long arg6, abi_long arg7,
6961 abi_long arg8)
bellard31e31b82003-02-18 22:55:36 +00006962{
Andreas Färber182735e2013-05-29 22:29:20 +02006963 CPUState *cpu = ENV_GET_CPU(cpu_env);
blueswir1992f48a2007-10-14 16:27:31 +00006964 abi_long ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02006965#if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) \
6966 || defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64) \
6967 || defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64)
bellard31e31b82003-02-18 22:55:36 +00006968 struct stat st;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02006969#endif
6970#if defined(TARGET_NR_statfs) || defined(TARGET_NR_statfs64) \
6971 || defined(TARGET_NR_fstatfs)
bellard56c8f682005-11-28 22:28:41 +00006972 struct statfs stfs;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02006973#endif
pbrook53a59602006-03-25 19:31:22 +00006974 void *p;
ths3b46e622007-09-17 08:09:54 +00006975
bellard31e31b82003-02-18 22:55:36 +00006976 switch(num) {
6977 case TARGET_NR_exit:
Andreas Färber9b056fc2013-06-24 23:53:10 +02006978 /* In old applications this may be used to implement _exit(2).
6979 However in threaded applictions it is used for thread termination,
6980 and _exit_group is used for application termination.
6981 Do thread termination if we have more then one thread. */
Timothy E Baldwina0995882016-05-27 15:51:56 +01006982
6983 if (block_signals()) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07006984 return -TARGET_ERESTARTSYS;
Timothy E Baldwina0995882016-05-27 15:51:56 +01006985 }
6986
Alex Bennéedd1f6342016-09-30 22:31:01 +01006987 cpu_list_lock();
6988
Andreas Färberbdc44642013-06-24 23:50:24 +02006989 if (CPU_NEXT(first_cpu)) {
Andreas Färber9b056fc2013-06-24 23:53:10 +02006990 TaskState *ts;
pbrookc2764712009-03-07 15:24:59 +00006991
Andreas Färber9b056fc2013-06-24 23:53:10 +02006992 /* Remove the CPU from the list. */
Emilio G. Cota068a5ea2018-08-19 05:13:35 -04006993 QTAILQ_REMOVE_RCU(&cpus, cpu, node);
Alex Bennéedd1f6342016-09-30 22:31:01 +01006994
Andreas Färber9b056fc2013-06-24 23:53:10 +02006995 cpu_list_unlock();
Alex Bennéedd1f6342016-09-30 22:31:01 +01006996
Andreas Färber0429a972013-08-26 18:14:44 +02006997 ts = cpu->opaque;
Andreas Färber9b056fc2013-06-24 23:53:10 +02006998 if (ts->child_tidptr) {
6999 put_user_u32(0, ts->child_tidptr);
7000 sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
7001 NULL, NULL, 0);
7002 }
Andreas Färbera2247f82013-06-09 19:47:04 +02007003 thread_cpu = NULL;
Andreas Färber0429a972013-08-26 18:14:44 +02007004 object_unref(OBJECT(cpu));
Andreas Färber9b056fc2013-06-24 23:53:10 +02007005 g_free(ts);
Emilio G. Cota70903762015-08-23 20:23:41 -04007006 rcu_unregister_thread();
Andreas Färber9b056fc2013-06-24 23:53:10 +02007007 pthread_exit(NULL);
7008 }
Alex Bennéedd1f6342016-09-30 22:31:01 +01007009
7010 cpu_list_unlock();
Alex Bennée708b6a62018-06-22 17:09:10 +01007011 preexit_cleanup(cpu_env, arg1);
pbrookc2764712009-03-07 15:24:59 +00007012 _exit(arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007013 return 0; /* avoid warning */
bellard31e31b82003-02-18 22:55:36 +00007014 case TARGET_NR_read:
Andreas Schwabba584f12019-03-05 17:45:05 +01007015 if (arg2 == 0 && arg3 == 0) {
7016 return get_errno(safe_read(arg1, 0, 0));
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007017 } else {
aurel3238d840e2009-01-30 19:48:17 +00007018 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007019 return -TARGET_EFAULT;
Timothy E Baldwin50afd022016-05-12 18:47:47 +01007020 ret = get_errno(safe_read(arg1, p, arg3));
Laurent Viviere36800c2015-10-02 14:48:09 +02007021 if (ret >= 0 &&
Laurent Vivier5d4d3662015-10-28 21:40:43 +01007022 fd_trans_host_to_target_data(arg1)) {
7023 ret = fd_trans_host_to_target_data(arg1)(p, ret);
Laurent Viviere36800c2015-10-02 14:48:09 +02007024 }
aurel3238d840e2009-01-30 19:48:17 +00007025 unlock_user(p, arg2, ret);
7026 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007027 return ret;
bellard31e31b82003-02-18 22:55:36 +00007028 case TARGET_NR_write:
Tony Garnock-Jones58cfa6c2018-09-08 19:22:05 +01007029 if (arg2 == 0 && arg3 == 0) {
7030 return get_errno(safe_write(arg1, 0, 0));
7031 }
bellard579a97f2007-11-11 14:26:47 +00007032 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007033 return -TARGET_EFAULT;
Laurent Vivier04b9bcf2017-03-01 10:37:47 +01007034 if (fd_trans_target_to_host_data(arg1)) {
7035 void *copy = g_malloc(arg3);
7036 memcpy(copy, p, arg3);
7037 ret = fd_trans_target_to_host_data(arg1)(copy, arg3);
7038 if (ret >= 0) {
7039 ret = get_errno(safe_write(arg1, copy, ret));
7040 }
7041 g_free(copy);
7042 } else {
7043 ret = get_errno(safe_write(arg1, p, arg3));
7044 }
pbrook53a59602006-03-25 19:31:22 +00007045 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007046 return ret;
7047
Chen Gang704eff62015-08-21 05:37:33 +08007048#ifdef TARGET_NR_open
bellard31e31b82003-02-18 22:55:36 +00007049 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00007050 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007051 return -TARGET_EFAULT;
Riku Voipio0b2effd2014-08-06 10:36:37 +03007052 ret = get_errno(do_openat(cpu_env, AT_FDCWD, p,
7053 target_to_host_bitmask(arg2, fcntl_flags_tbl),
7054 arg3));
Laurent Viviere36800c2015-10-02 14:48:09 +02007055 fd_trans_unregister(ret);
pbrook53a59602006-03-25 19:31:22 +00007056 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007057 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007058#endif
ths82424832007-09-24 09:21:55 +00007059 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00007060 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007061 return -TARGET_EFAULT;
Riku Voipio0b2effd2014-08-06 10:36:37 +03007062 ret = get_errno(do_openat(cpu_env, arg1, p,
7063 target_to_host_bitmask(arg3, fcntl_flags_tbl),
7064 arg4));
Laurent Viviere36800c2015-10-02 14:48:09 +02007065 fd_trans_unregister(ret);
bellard579a97f2007-11-11 14:26:47 +00007066 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007067 return ret;
Laurent Vivier0f0426f2015-09-01 22:27:33 +02007068#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
7069 case TARGET_NR_name_to_handle_at:
7070 ret = do_name_to_handle_at(arg1, arg2, arg3, arg4, arg5);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007071 return ret;
Laurent Vivier0f0426f2015-09-01 22:27:33 +02007072#endif
7073#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
7074 case TARGET_NR_open_by_handle_at:
7075 ret = do_open_by_handle_at(arg1, arg2, arg3);
Laurent Viviere36800c2015-10-02 14:48:09 +02007076 fd_trans_unregister(ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007077 return ret;
Laurent Vivier0f0426f2015-09-01 22:27:33 +02007078#endif
bellard31e31b82003-02-18 22:55:36 +00007079 case TARGET_NR_close:
Laurent Viviere36800c2015-10-02 14:48:09 +02007080 fd_trans_unregister(arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007081 return get_errno(close(arg1));
7082
bellard31e31b82003-02-18 22:55:36 +00007083 case TARGET_NR_brk:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007084 return do_brk(arg1);
Chen Gang704eff62015-08-21 05:37:33 +08007085#ifdef TARGET_NR_fork
bellard31e31b82003-02-18 22:55:36 +00007086 case TARGET_NR_fork:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007087 return get_errno(do_fork(cpu_env, TARGET_SIGCHLD, 0, 0, 0, 0));
Chen Gang704eff62015-08-21 05:37:33 +08007088#endif
thse5febef2007-04-01 18:31:35 +00007089#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00007090 case TARGET_NR_waitpid:
7091 {
pbrook53a59602006-03-25 19:31:22 +00007092 int status;
Timothy E Baldwin4af80a32016-05-12 18:47:49 +01007093 ret = get_errno(safe_wait4(arg1, &status, arg3, 0));
Alexander Graf53795572011-11-24 00:44:43 +01007094 if (!is_error(ret) && arg2 && ret
pbrook1d9d8b52009-04-16 15:17:02 +00007095 && put_user_s32(host_to_target_waitstatus(status), arg2))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007096 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00007097 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007098 return ret;
thse5febef2007-04-01 18:31:35 +00007099#endif
pbrookf0cbb612008-05-30 18:20:05 +00007100#ifdef TARGET_NR_waitid
7101 case TARGET_NR_waitid:
7102 {
7103 siginfo_t info;
7104 info.si_pid = 0;
Timothy E Baldwin4af80a32016-05-12 18:47:49 +01007105 ret = get_errno(safe_waitid(arg1, arg2, &info, arg4, NULL));
pbrookf0cbb612008-05-30 18:20:05 +00007106 if (!is_error(ret) && arg3 && info.si_pid != 0) {
Anthony Liguoric227f092009-10-01 16:12:16 -05007107 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007108 return -TARGET_EFAULT;
pbrookf0cbb612008-05-30 18:20:05 +00007109 host_to_target_siginfo(p, &info);
Anthony Liguoric227f092009-10-01 16:12:16 -05007110 unlock_user(p, arg3, sizeof(target_siginfo_t));
pbrookf0cbb612008-05-30 18:20:05 +00007111 }
7112 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007113 return ret;
pbrookf0cbb612008-05-30 18:20:05 +00007114#endif
j_mayer7a3148a2007-04-05 07:13:51 +00007115#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00007116 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00007117 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007118 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007119 ret = get_errno(creat(p, arg2));
Laurent Viviere36800c2015-10-02 14:48:09 +02007120 fd_trans_unregister(ret);
pbrook53a59602006-03-25 19:31:22 +00007121 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007122 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00007123#endif
Chen Gang704eff62015-08-21 05:37:33 +08007124#ifdef TARGET_NR_link
bellard31e31b82003-02-18 22:55:36 +00007125 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00007126 {
7127 void * p2;
7128 p = lock_user_string(arg1);
7129 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00007130 if (!p || !p2)
7131 ret = -TARGET_EFAULT;
7132 else
7133 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00007134 unlock_user(p2, arg2, 0);
7135 unlock_user(p, arg1, 0);
7136 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007137 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007138#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01007139#if defined(TARGET_NR_linkat)
ths64f0ce42007-09-24 09:25:06 +00007140 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00007141 {
7142 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00007143 if (!arg2 || !arg4)
Richard Henderson2852aaf2018-08-18 12:01:06 -07007144 return -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00007145 p = lock_user_string(arg2);
7146 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00007147 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00007148 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00007149 else
Peter Maydellc0d472b2013-06-12 16:20:21 +01007150 ret = get_errno(linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00007151 unlock_user(p, arg2, 0);
7152 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00007153 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007154 return ret;
ths64f0ce42007-09-24 09:25:06 +00007155#endif
Chen Gang704eff62015-08-21 05:37:33 +08007156#ifdef TARGET_NR_unlink
bellard31e31b82003-02-18 22:55:36 +00007157 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00007158 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007159 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007160 ret = get_errno(unlink(p));
7161 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007162 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007163#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01007164#if defined(TARGET_NR_unlinkat)
ths8170f562007-09-24 09:24:11 +00007165 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00007166 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007167 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01007168 ret = get_errno(unlinkat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00007169 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007170 return ret;
balrogb7d35e62007-12-12 00:40:24 +00007171#endif
bellard31e31b82003-02-18 22:55:36 +00007172 case TARGET_NR_execve:
bellard7854b052003-03-29 17:22:23 +00007173 {
7174 char **argp, **envp;
bellardf7341ff2003-03-30 21:00:25 +00007175 int argc, envc;
blueswir1992f48a2007-10-14 16:27:31 +00007176 abi_ulong gp;
7177 abi_ulong guest_argp;
7178 abi_ulong guest_envp;
7179 abi_ulong addr;
bellard7854b052003-03-29 17:22:23 +00007180 char **q;
Ulrich Hechta6f79cc2012-01-31 12:43:16 +01007181 int total_size = 0;
bellard7854b052003-03-29 17:22:23 +00007182
bellardf7341ff2003-03-30 21:00:25 +00007183 argc = 0;
pbrook53a59602006-03-25 19:31:22 +00007184 guest_argp = arg2;
pbrookda94d262008-05-30 18:24:00 +00007185 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00007186 if (get_user_ual(addr, gp))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007187 return -TARGET_EFAULT;
ths03aa1972007-12-02 06:28:08 +00007188 if (!addr)
bellard2f619692007-11-16 10:46:05 +00007189 break;
bellard7854b052003-03-29 17:22:23 +00007190 argc++;
bellard2f619692007-11-16 10:46:05 +00007191 }
bellardf7341ff2003-03-30 21:00:25 +00007192 envc = 0;
pbrook53a59602006-03-25 19:31:22 +00007193 guest_envp = arg3;
pbrookda94d262008-05-30 18:24:00 +00007194 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00007195 if (get_user_ual(addr, gp))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007196 return -TARGET_EFAULT;
ths03aa1972007-12-02 06:28:08 +00007197 if (!addr)
bellard2f619692007-11-16 10:46:05 +00007198 break;
bellard7854b052003-03-29 17:22:23 +00007199 envc++;
bellard2f619692007-11-16 10:46:05 +00007200 }
bellard7854b052003-03-29 17:22:23 +00007201
Prasad J Panditb936cb52017-03-07 12:51:47 +05307202 argp = g_new0(char *, argc + 1);
7203 envp = g_new0(char *, envc + 1);
bellard7854b052003-03-29 17:22:23 +00007204
pbrookda94d262008-05-30 18:24:00 +00007205 for (gp = guest_argp, q = argp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00007206 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00007207 if (get_user_ual(addr, gp))
7208 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00007209 if (!addr)
7210 break;
bellard2f619692007-11-16 10:46:05 +00007211 if (!(*q = lock_user_string(addr)))
7212 goto execve_efault;
Ulrich Hechta6f79cc2012-01-31 12:43:16 +01007213 total_size += strlen(*q) + 1;
pbrook53a59602006-03-25 19:31:22 +00007214 }
bellardf7341ff2003-03-30 21:00:25 +00007215 *q = NULL;
7216
pbrookda94d262008-05-30 18:24:00 +00007217 for (gp = guest_envp, q = envp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00007218 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00007219 if (get_user_ual(addr, gp))
7220 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00007221 if (!addr)
7222 break;
bellard2f619692007-11-16 10:46:05 +00007223 if (!(*q = lock_user_string(addr)))
7224 goto execve_efault;
Ulrich Hechta6f79cc2012-01-31 12:43:16 +01007225 total_size += strlen(*q) + 1;
pbrook53a59602006-03-25 19:31:22 +00007226 }
bellardf7341ff2003-03-30 21:00:25 +00007227 *q = NULL;
bellard7854b052003-03-29 17:22:23 +00007228
bellard2f619692007-11-16 10:46:05 +00007229 if (!(p = lock_user_string(arg1)))
7230 goto execve_efault;
Timothy E Baldwinffdcbe22016-05-12 18:47:50 +01007231 /* Although execve() is not an interruptible syscall it is
7232 * a special case where we must use the safe_syscall wrapper:
7233 * if we allow a signal to happen before we make the host
7234 * syscall then we will 'lose' it, because at the point of
7235 * execve the process leaves QEMU's control. So we use the
7236 * safe syscall wrapper to ensure that we either take the
7237 * signal as a guest signal, or else it does not happen
7238 * before the execve completes and makes it the other
7239 * program's problem.
7240 */
7241 ret = get_errno(safe_execve(p, argp, envp));
pbrook53a59602006-03-25 19:31:22 +00007242 unlock_user(p, arg1, 0);
7243
bellard2f619692007-11-16 10:46:05 +00007244 goto execve_end;
7245
7246 execve_efault:
7247 ret = -TARGET_EFAULT;
7248
7249 execve_end:
pbrook53a59602006-03-25 19:31:22 +00007250 for (gp = guest_argp, q = argp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00007251 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00007252 if (get_user_ual(addr, gp)
7253 || !addr)
7254 break;
pbrook53a59602006-03-25 19:31:22 +00007255 unlock_user(*q, addr, 0);
7256 }
7257 for (gp = guest_envp, q = envp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00007258 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00007259 if (get_user_ual(addr, gp)
7260 || !addr)
7261 break;
pbrook53a59602006-03-25 19:31:22 +00007262 unlock_user(*q, addr, 0);
7263 }
Prasad J Panditb936cb52017-03-07 12:51:47 +05307264
7265 g_free(argp);
7266 g_free(envp);
bellard7854b052003-03-29 17:22:23 +00007267 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007268 return ret;
bellard31e31b82003-02-18 22:55:36 +00007269 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00007270 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007271 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007272 ret = get_errno(chdir(p));
7273 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007274 return ret;
bellarda315a142005-01-30 22:59:18 +00007275#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00007276 case TARGET_NR_time:
7277 {
pbrook53a59602006-03-25 19:31:22 +00007278 time_t host_time;
7279 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00007280 if (!is_error(ret)
7281 && arg1
7282 && put_user_sal(host_time, arg1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007283 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00007284 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007285 return ret;
bellarda315a142005-01-30 22:59:18 +00007286#endif
Chen Gang704eff62015-08-21 05:37:33 +08007287#ifdef TARGET_NR_mknod
bellard31e31b82003-02-18 22:55:36 +00007288 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00007289 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007290 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007291 ret = get_errno(mknod(p, arg2, arg3));
7292 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007293 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007294#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01007295#if defined(TARGET_NR_mknodat)
ths75ac37a2007-09-24 09:23:05 +00007296 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00007297 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007298 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01007299 ret = get_errno(mknodat(arg1, p, arg3, arg4));
bellard579a97f2007-11-11 14:26:47 +00007300 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007301 return ret;
ths75ac37a2007-09-24 09:23:05 +00007302#endif
Chen Gang704eff62015-08-21 05:37:33 +08007303#ifdef TARGET_NR_chmod
bellard31e31b82003-02-18 22:55:36 +00007304 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00007305 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007306 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007307 ret = get_errno(chmod(p, arg2));
7308 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007309 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007310#endif
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02007311#ifdef TARGET_NR_lseek
bellard31e31b82003-02-18 22:55:36 +00007312 case TARGET_NR_lseek:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007313 return get_errno(lseek(arg1, arg2, arg3));
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02007314#endif
Richard Henderson92317332010-05-03 10:07:53 -07007315#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA)
7316 /* Alpha specific */
j_mayer7a3148a2007-04-05 07:13:51 +00007317 case TARGET_NR_getxpid:
Richard Henderson92317332010-05-03 10:07:53 -07007318 ((CPUAlphaState *)cpu_env)->ir[IR_A4] = getppid();
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007319 return get_errno(getpid());
Richard Henderson92317332010-05-03 10:07:53 -07007320#endif
7321#ifdef TARGET_NR_getpid
7322 case TARGET_NR_getpid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007323 return get_errno(getpid());
Richard Henderson92317332010-05-03 10:07:53 -07007324#endif
bellard31e31b82003-02-18 22:55:36 +00007325 case TARGET_NR_mount:
Paul Burton356d7712014-06-22 11:25:37 +01007326 {
7327 /* need to look at the data field */
7328 void *p2, *p3;
7329
7330 if (arg1) {
7331 p = lock_user_string(arg1);
7332 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07007333 return -TARGET_EFAULT;
Paul Burton356d7712014-06-22 11:25:37 +01007334 }
7335 } else {
7336 p = NULL;
7337 }
7338
7339 p2 = lock_user_string(arg2);
7340 if (!p2) {
7341 if (arg1) {
7342 unlock_user(p, arg1, 0);
7343 }
Richard Henderson2852aaf2018-08-18 12:01:06 -07007344 return -TARGET_EFAULT;
Paul Burton356d7712014-06-22 11:25:37 +01007345 }
7346
7347 if (arg3) {
7348 p3 = lock_user_string(arg3);
7349 if (!p3) {
7350 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00007351 unlock_user(p, arg1, 0);
Paul Burton356d7712014-06-22 11:25:37 +01007352 }
7353 unlock_user(p2, arg2, 0);
Richard Henderson2852aaf2018-08-18 12:01:06 -07007354 return -TARGET_EFAULT;
Paul Burton356d7712014-06-22 11:25:37 +01007355 }
7356 } else {
7357 p3 = NULL;
7358 }
7359
7360 /* FIXME - arg5 should be locked, but it isn't clear how to
7361 * do that since it's not guaranteed to be a NULL-terminated
7362 * string.
7363 */
7364 if (!arg5) {
7365 ret = mount(p, p2, p3, (unsigned long)arg4, NULL);
7366 } else {
7367 ret = mount(p, p2, p3, (unsigned long)arg4, g2h(arg5));
7368 }
7369 ret = get_errno(ret);
7370
7371 if (arg1) {
7372 unlock_user(p, arg1, 0);
7373 }
7374 unlock_user(p2, arg2, 0);
7375 if (arg3) {
7376 unlock_user(p3, arg3, 0);
7377 }
7378 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007379 return ret;
thse5febef2007-04-01 18:31:35 +00007380#ifdef TARGET_NR_umount
bellard31e31b82003-02-18 22:55:36 +00007381 case TARGET_NR_umount:
bellard579a97f2007-11-11 14:26:47 +00007382 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007383 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007384 ret = get_errno(umount(p));
7385 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007386 return ret;
thse5febef2007-04-01 18:31:35 +00007387#endif
j_mayer7a3148a2007-04-05 07:13:51 +00007388#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00007389 case TARGET_NR_stime:
7390 {
pbrook53a59602006-03-25 19:31:22 +00007391 time_t host_time;
bellard2f619692007-11-16 10:46:05 +00007392 if (get_user_sal(host_time, arg1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007393 return -TARGET_EFAULT;
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007394 return get_errno(stime(&host_time));
bellard31e31b82003-02-18 22:55:36 +00007395 }
j_mayer7a3148a2007-04-05 07:13:51 +00007396#endif
j_mayer7a3148a2007-04-05 07:13:51 +00007397#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00007398 case TARGET_NR_alarm:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007399 return alarm(arg1);
j_mayer7a3148a2007-04-05 07:13:51 +00007400#endif
j_mayer7a3148a2007-04-05 07:13:51 +00007401#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00007402 case TARGET_NR_pause:
Timothy E Baldwinf59ec602016-05-27 15:51:55 +01007403 if (!block_signals()) {
7404 sigsuspend(&((TaskState *)cpu->opaque)->signal_mask);
7405 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007406 return -TARGET_EINTR;
j_mayer7a3148a2007-04-05 07:13:51 +00007407#endif
thse5febef2007-04-01 18:31:35 +00007408#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00007409 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00007410 {
pbrook53a59602006-03-25 19:31:22 +00007411 struct utimbuf tbuf, *host_tbuf;
7412 struct target_utimbuf *target_tbuf;
7413 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00007414 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007415 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02007416 tbuf.actime = tswapal(target_tbuf->actime);
7417 tbuf.modtime = tswapal(target_tbuf->modtime);
pbrook53a59602006-03-25 19:31:22 +00007418 unlock_user_struct(target_tbuf, arg2, 0);
7419 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00007420 } else {
pbrook53a59602006-03-25 19:31:22 +00007421 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00007422 }
bellard579a97f2007-11-11 14:26:47 +00007423 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007424 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007425 ret = get_errno(utime(p, host_tbuf));
7426 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00007427 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007428 return ret;
thse5febef2007-04-01 18:31:35 +00007429#endif
Chen Gang704eff62015-08-21 05:37:33 +08007430#ifdef TARGET_NR_utimes
bellard978a66f2004-12-06 22:58:05 +00007431 case TARGET_NR_utimes:
7432 {
bellard978a66f2004-12-06 22:58:05 +00007433 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00007434 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00007435 if (copy_from_user_timeval(&tv[0], arg2)
7436 || copy_from_user_timeval(&tv[1],
7437 arg2 + sizeof(struct target_timeval)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007438 return -TARGET_EFAULT;
bellard978a66f2004-12-06 22:58:05 +00007439 tvp = tv;
7440 } else {
7441 tvp = NULL;
7442 }
bellard579a97f2007-11-11 14:26:47 +00007443 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007444 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007445 ret = get_errno(utimes(p, tvp));
7446 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00007447 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007448 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007449#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01007450#if defined(TARGET_NR_futimesat)
balrogac8a6552008-09-20 02:25:39 +00007451 case TARGET_NR_futimesat:
7452 {
7453 struct timeval *tvp, tv[2];
7454 if (arg3) {
7455 if (copy_from_user_timeval(&tv[0], arg3)
7456 || copy_from_user_timeval(&tv[1],
7457 arg3 + sizeof(struct target_timeval)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007458 return -TARGET_EFAULT;
balrogac8a6552008-09-20 02:25:39 +00007459 tvp = tv;
7460 } else {
7461 tvp = NULL;
7462 }
Richard Henderson2852aaf2018-08-18 12:01:06 -07007463 if (!(p = lock_user_string(arg2))) {
7464 return -TARGET_EFAULT;
7465 }
Peter Maydellc0d472b2013-06-12 16:20:21 +01007466 ret = get_errno(futimesat(arg1, path(p), tvp));
balrogac8a6552008-09-20 02:25:39 +00007467 unlock_user(p, arg2, 0);
7468 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007469 return ret;
balrogac8a6552008-09-20 02:25:39 +00007470#endif
Chen Gang704eff62015-08-21 05:37:33 +08007471#ifdef TARGET_NR_access
bellard31e31b82003-02-18 22:55:36 +00007472 case TARGET_NR_access:
Richard Henderson2852aaf2018-08-18 12:01:06 -07007473 if (!(p = lock_user_string(arg1))) {
7474 return -TARGET_EFAULT;
7475 }
Ulrich Hecht719f9082009-07-03 17:09:29 +02007476 ret = get_errno(access(path(p), arg2));
pbrook53a59602006-03-25 19:31:22 +00007477 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007478 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007479#endif
ths92a34c12007-09-24 09:27:49 +00007480#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
7481 case TARGET_NR_faccessat:
Richard Henderson2852aaf2018-08-18 12:01:06 -07007482 if (!(p = lock_user_string(arg2))) {
7483 return -TARGET_EFAULT;
7484 }
Peter Maydellc0d472b2013-06-12 16:20:21 +01007485 ret = get_errno(faccessat(arg1, p, arg3, 0));
bellard579a97f2007-11-11 14:26:47 +00007486 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007487 return ret;
ths92a34c12007-09-24 09:27:49 +00007488#endif
j_mayer7a3148a2007-04-05 07:13:51 +00007489#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00007490 case TARGET_NR_nice:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007491 return get_errno(nice(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +00007492#endif
bellard31e31b82003-02-18 22:55:36 +00007493 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00007494 sync();
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007495 return 0;
Aleksandar Markovic5a03cd02016-10-10 13:23:30 +02007496#if defined(TARGET_NR_syncfs) && defined(CONFIG_SYNCFS)
7497 case TARGET_NR_syncfs:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007498 return get_errno(syncfs(arg1));
Aleksandar Markovic5a03cd02016-10-10 13:23:30 +02007499#endif
bellard31e31b82003-02-18 22:55:36 +00007500 case TARGET_NR_kill:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007501 return get_errno(safe_kill(arg1, target_to_host_signal(arg2)));
Chen Gang704eff62015-08-21 05:37:33 +08007502#ifdef TARGET_NR_rename
bellard31e31b82003-02-18 22:55:36 +00007503 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00007504 {
7505 void *p2;
7506 p = lock_user_string(arg1);
7507 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00007508 if (!p || !p2)
7509 ret = -TARGET_EFAULT;
7510 else
7511 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00007512 unlock_user(p2, arg2, 0);
7513 unlock_user(p, arg1, 0);
7514 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007515 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007516#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01007517#if defined(TARGET_NR_renameat)
ths722183f2007-09-24 09:24:37 +00007518 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00007519 {
bellard579a97f2007-11-11 14:26:47 +00007520 void *p2;
ths722183f2007-09-24 09:24:37 +00007521 p = lock_user_string(arg2);
7522 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00007523 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00007524 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00007525 else
Peter Maydellc0d472b2013-06-12 16:20:21 +01007526 ret = get_errno(renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00007527 unlock_user(p2, arg4, 0);
7528 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00007529 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007530 return ret;
ths722183f2007-09-24 09:24:37 +00007531#endif
Andreas Schwab95d03072018-01-23 11:53:31 +01007532#if defined(TARGET_NR_renameat2)
7533 case TARGET_NR_renameat2:
7534 {
7535 void *p2;
7536 p = lock_user_string(arg2);
7537 p2 = lock_user_string(arg4);
7538 if (!p || !p2) {
7539 ret = -TARGET_EFAULT;
7540 } else {
7541 ret = get_errno(sys_renameat2(arg1, p, arg3, p2, arg5));
7542 }
7543 unlock_user(p2, arg4, 0);
7544 unlock_user(p, arg2, 0);
7545 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007546 return ret;
Andreas Schwab95d03072018-01-23 11:53:31 +01007547#endif
Chen Gang704eff62015-08-21 05:37:33 +08007548#ifdef TARGET_NR_mkdir
bellard31e31b82003-02-18 22:55:36 +00007549 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00007550 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007551 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007552 ret = get_errno(mkdir(p, arg2));
7553 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007554 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007555#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01007556#if defined(TARGET_NR_mkdirat)
ths4472ad02007-09-24 09:22:32 +00007557 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00007558 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007559 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01007560 ret = get_errno(mkdirat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00007561 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007562 return ret;
ths4472ad02007-09-24 09:22:32 +00007563#endif
Chen Gang704eff62015-08-21 05:37:33 +08007564#ifdef TARGET_NR_rmdir
bellard31e31b82003-02-18 22:55:36 +00007565 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00007566 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007567 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007568 ret = get_errno(rmdir(p));
7569 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007570 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007571#endif
bellard31e31b82003-02-18 22:55:36 +00007572 case TARGET_NR_dup:
7573 ret = get_errno(dup(arg1));
Laurent Viviere36800c2015-10-02 14:48:09 +02007574 if (ret >= 0) {
7575 fd_trans_dup(arg1, ret);
7576 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007577 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007578#ifdef TARGET_NR_pipe
bellard31e31b82003-02-18 22:55:36 +00007579 case TARGET_NR_pipe:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007580 return do_pipe(cpu_env, arg1, 0, 0);
Chen Gang704eff62015-08-21 05:37:33 +08007581#endif
Riku Voipio099d6b02009-05-05 12:10:04 +03007582#ifdef TARGET_NR_pipe2
7583 case TARGET_NR_pipe2:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007584 return do_pipe(cpu_env, arg1,
7585 target_to_host_bitmask(arg2, fcntl_flags_tbl), 1);
Riku Voipio099d6b02009-05-05 12:10:04 +03007586#endif
bellard31e31b82003-02-18 22:55:36 +00007587 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00007588 {
pbrook53a59602006-03-25 19:31:22 +00007589 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00007590 struct tms tms;
7591 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00007592 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00007593 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
7594 if (!tmsp)
Richard Henderson2852aaf2018-08-18 12:01:06 -07007595 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02007596 tmsp->tms_utime = tswapal(host_to_target_clock_t(tms.tms_utime));
7597 tmsp->tms_stime = tswapal(host_to_target_clock_t(tms.tms_stime));
7598 tmsp->tms_cutime = tswapal(host_to_target_clock_t(tms.tms_cutime));
7599 tmsp->tms_cstime = tswapal(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00007600 }
bellardc596ed12003-07-13 17:32:31 +00007601 if (!is_error(ret))
7602 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00007603 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007604 return ret;
bellard31e31b82003-02-18 22:55:36 +00007605 case TARGET_NR_acct:
aurel3238d840e2009-01-30 19:48:17 +00007606 if (arg1 == 0) {
7607 ret = get_errno(acct(NULL));
7608 } else {
Richard Henderson2852aaf2018-08-18 12:01:06 -07007609 if (!(p = lock_user_string(arg1))) {
7610 return -TARGET_EFAULT;
7611 }
aurel3238d840e2009-01-30 19:48:17 +00007612 ret = get_errno(acct(path(p)));
7613 unlock_user(p, arg1, 0);
7614 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007615 return ret;
Richard Henderson8070e7b2013-07-24 09:50:00 -10007616#ifdef TARGET_NR_umount2
bellard31e31b82003-02-18 22:55:36 +00007617 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00007618 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007619 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007620 ret = get_errno(umount2(p, arg2));
7621 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007622 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00007623#endif
bellard31e31b82003-02-18 22:55:36 +00007624 case TARGET_NR_ioctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007625 return do_ioctl(arg1, arg2, arg3);
Michael Clark47ae93c2018-03-03 01:31:11 +13007626#ifdef TARGET_NR_fcntl
bellard31e31b82003-02-18 22:55:36 +00007627 case TARGET_NR_fcntl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007628 return do_fcntl(arg1, arg2, arg3);
Michael Clark47ae93c2018-03-03 01:31:11 +13007629#endif
bellard31e31b82003-02-18 22:55:36 +00007630 case TARGET_NR_setpgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007631 return get_errno(setpgid(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00007632 case TARGET_NR_umask:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007633 return get_errno(umask(arg1));
bellard31e31b82003-02-18 22:55:36 +00007634 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00007635 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007636 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007637 ret = get_errno(chroot(p));
7638 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007639 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007640#ifdef TARGET_NR_dup2
bellard31e31b82003-02-18 22:55:36 +00007641 case TARGET_NR_dup2:
7642 ret = get_errno(dup2(arg1, arg2));
Laurent Viviere36800c2015-10-02 14:48:09 +02007643 if (ret >= 0) {
7644 fd_trans_dup(arg1, arg2);
7645 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007646 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08007647#endif
Ulrich Hechtd0927932009-09-17 20:22:14 +03007648#if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3)
7649 case TARGET_NR_dup3:
Peter Maydell10fa9932017-12-15 15:18:00 +00007650 {
7651 int host_flags;
7652
7653 if ((arg3 & ~TARGET_O_CLOEXEC) != 0) {
7654 return -EINVAL;
7655 }
7656 host_flags = target_to_host_bitmask(arg3, fcntl_flags_tbl);
7657 ret = get_errno(dup3(arg1, arg2, host_flags));
Laurent Viviere36800c2015-10-02 14:48:09 +02007658 if (ret >= 0) {
7659 fd_trans_dup(arg1, arg2);
7660 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007661 return ret;
Peter Maydell10fa9932017-12-15 15:18:00 +00007662 }
Ulrich Hechtd0927932009-09-17 20:22:14 +03007663#endif
j_mayer7a3148a2007-04-05 07:13:51 +00007664#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00007665 case TARGET_NR_getppid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007666 return get_errno(getppid());
j_mayer7a3148a2007-04-05 07:13:51 +00007667#endif
Chen Gang704eff62015-08-21 05:37:33 +08007668#ifdef TARGET_NR_getpgrp
bellard31e31b82003-02-18 22:55:36 +00007669 case TARGET_NR_getpgrp:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007670 return get_errno(getpgrp());
Chen Gang704eff62015-08-21 05:37:33 +08007671#endif
bellard31e31b82003-02-18 22:55:36 +00007672 case TARGET_NR_setsid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007673 return get_errno(setsid());
thse5febef2007-04-01 18:31:35 +00007674#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00007675 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00007676 {
Richard Henderson6049f4f2009-12-27 18:30:03 -08007677#if defined(TARGET_ALPHA)
7678 struct target_sigaction act, oact, *pact = 0;
pbrook53a59602006-03-25 19:31:22 +00007679 struct target_old_sigaction *old_act;
pbrook53a59602006-03-25 19:31:22 +00007680 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00007681 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007682 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +00007683 act._sa_handler = old_act->_sa_handler;
7684 target_siginitset(&act.sa_mask, old_act->sa_mask);
7685 act.sa_flags = old_act->sa_flags;
Richard Henderson6049f4f2009-12-27 18:30:03 -08007686 act.sa_restorer = 0;
pbrook53a59602006-03-25 19:31:22 +00007687 unlock_user_struct(old_act, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00007688 pact = &act;
bellard66fb9762003-03-23 01:06:05 +00007689 }
7690 ret = get_errno(do_sigaction(arg1, pact, &oact));
pbrook53a59602006-03-25 19:31:22 +00007691 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00007692 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007693 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007694 old_act->_sa_handler = oact._sa_handler;
7695 old_act->sa_mask = oact.sa_mask.sig[0];
7696 old_act->sa_flags = oact.sa_flags;
pbrook53a59602006-03-25 19:31:22 +00007697 unlock_user_struct(old_act, arg3, 1);
bellard66fb9762003-03-23 01:06:05 +00007698 }
Richard Henderson6049f4f2009-12-27 18:30:03 -08007699#elif defined(TARGET_MIPS)
bellard106ec872006-06-27 21:08:10 +00007700 struct target_sigaction act, oact, *pact, *old_act;
7701
7702 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00007703 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007704 return -TARGET_EFAULT;
bellard106ec872006-06-27 21:08:10 +00007705 act._sa_handler = old_act->_sa_handler;
7706 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
7707 act.sa_flags = old_act->sa_flags;
7708 unlock_user_struct(old_act, arg2, 0);
7709 pact = &act;
7710 } else {
7711 pact = NULL;
7712 }
7713
7714 ret = get_errno(do_sigaction(arg1, pact, &oact));
7715
7716 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00007717 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007718 return -TARGET_EFAULT;
bellard106ec872006-06-27 21:08:10 +00007719 old_act->_sa_handler = oact._sa_handler;
7720 old_act->sa_flags = oact.sa_flags;
7721 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
7722 old_act->sa_mask.sig[1] = 0;
7723 old_act->sa_mask.sig[2] = 0;
7724 old_act->sa_mask.sig[3] = 0;
7725 unlock_user_struct(old_act, arg3, 1);
7726 }
Richard Henderson6049f4f2009-12-27 18:30:03 -08007727#else
7728 struct target_old_sigaction *old_act;
7729 struct target_sigaction act, oact, *pact;
7730 if (arg2) {
7731 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007732 return -TARGET_EFAULT;
Richard Henderson6049f4f2009-12-27 18:30:03 -08007733 act._sa_handler = old_act->_sa_handler;
7734 target_siginitset(&act.sa_mask, old_act->sa_mask);
7735 act.sa_flags = old_act->sa_flags;
7736 act.sa_restorer = old_act->sa_restorer;
Laurent Vivier5de154e2018-04-02 12:24:52 +02007737#ifdef TARGET_ARCH_HAS_KA_RESTORER
7738 act.ka_restorer = 0;
7739#endif
Richard Henderson6049f4f2009-12-27 18:30:03 -08007740 unlock_user_struct(old_act, arg2, 0);
7741 pact = &act;
7742 } else {
7743 pact = NULL;
7744 }
7745 ret = get_errno(do_sigaction(arg1, pact, &oact));
7746 if (!is_error(ret) && arg3) {
7747 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007748 return -TARGET_EFAULT;
Richard Henderson6049f4f2009-12-27 18:30:03 -08007749 old_act->_sa_handler = oact._sa_handler;
7750 old_act->sa_mask = oact.sa_mask.sig[0];
7751 old_act->sa_flags = oact.sa_flags;
7752 old_act->sa_restorer = oact.sa_restorer;
7753 unlock_user_struct(old_act, arg3, 1);
7754 }
ths388bb212007-05-13 13:58:00 +00007755#endif
bellard31e31b82003-02-18 22:55:36 +00007756 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007757 return ret;
thse5febef2007-04-01 18:31:35 +00007758#endif
bellard66fb9762003-03-23 01:06:05 +00007759 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00007760 {
Richard Henderson6049f4f2009-12-27 18:30:03 -08007761#if defined(TARGET_ALPHA)
Peter Maydell78bfef72017-11-06 18:33:26 +00007762 /* For Alpha and SPARC this is a 5 argument syscall, with
7763 * a 'restorer' parameter which must be copied into the
7764 * sa_restorer field of the sigaction struct.
7765 * For Alpha that 'restorer' is arg5; for SPARC it is arg4,
7766 * and arg5 is the sigsetsize.
7767 * Alpha also has a separate rt_sigaction struct that it uses
7768 * here; SPARC uses the usual sigaction struct.
7769 */
Richard Henderson6049f4f2009-12-27 18:30:03 -08007770 struct target_rt_sigaction *rt_act;
Peter Maydell78bfef72017-11-06 18:33:26 +00007771 struct target_sigaction act, oact, *pact = 0;
Peter Maydellc8157012016-06-30 14:23:24 +01007772
7773 if (arg4 != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007774 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01007775 }
Richard Henderson6049f4f2009-12-27 18:30:03 -08007776 if (arg2) {
7777 if (!lock_user_struct(VERIFY_READ, rt_act, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007778 return -TARGET_EFAULT;
Richard Henderson6049f4f2009-12-27 18:30:03 -08007779 act._sa_handler = rt_act->_sa_handler;
7780 act.sa_mask = rt_act->sa_mask;
7781 act.sa_flags = rt_act->sa_flags;
7782 act.sa_restorer = arg5;
7783 unlock_user_struct(rt_act, arg2, 0);
7784 pact = &act;
7785 }
7786 ret = get_errno(do_sigaction(arg1, pact, &oact));
7787 if (!is_error(ret) && arg3) {
7788 if (!lock_user_struct(VERIFY_WRITE, rt_act, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007789 return -TARGET_EFAULT;
Richard Henderson6049f4f2009-12-27 18:30:03 -08007790 rt_act->_sa_handler = oact._sa_handler;
7791 rt_act->sa_mask = oact.sa_mask;
7792 rt_act->sa_flags = oact.sa_flags;
7793 unlock_user_struct(rt_act, arg3, 1);
7794 }
7795#else
Peter Maydell78bfef72017-11-06 18:33:26 +00007796#ifdef TARGET_SPARC
7797 target_ulong restorer = arg4;
7798 target_ulong sigsetsize = arg5;
7799#else
7800 target_ulong sigsetsize = arg4;
7801#endif
pbrook53a59602006-03-25 19:31:22 +00007802 struct target_sigaction *act;
7803 struct target_sigaction *oact;
7804
Peter Maydell78bfef72017-11-06 18:33:26 +00007805 if (sigsetsize != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007806 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01007807 }
bellard579a97f2007-11-11 14:26:47 +00007808 if (arg2) {
Peter Maydell78bfef72017-11-06 18:33:26 +00007809 if (!lock_user_struct(VERIFY_READ, act, arg2, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07007810 return -TARGET_EFAULT;
Peter Maydell78bfef72017-11-06 18:33:26 +00007811 }
Laurent Vivier5de154e2018-04-02 12:24:52 +02007812#ifdef TARGET_ARCH_HAS_KA_RESTORER
7813 act->ka_restorer = restorer;
Peter Maydell78bfef72017-11-06 18:33:26 +00007814#endif
7815 } else {
pbrook53a59602006-03-25 19:31:22 +00007816 act = NULL;
Peter Maydell78bfef72017-11-06 18:33:26 +00007817 }
bellard579a97f2007-11-11 14:26:47 +00007818 if (arg3) {
7819 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
7820 ret = -TARGET_EFAULT;
7821 goto rt_sigaction_fail;
7822 }
7823 } else
pbrook53a59602006-03-25 19:31:22 +00007824 oact = NULL;
7825 ret = get_errno(do_sigaction(arg1, act, oact));
bellard579a97f2007-11-11 14:26:47 +00007826 rt_sigaction_fail:
7827 if (act)
pbrook53a59602006-03-25 19:31:22 +00007828 unlock_user_struct(act, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +00007829 if (oact)
pbrook53a59602006-03-25 19:31:22 +00007830 unlock_user_struct(oact, arg3, 1);
Richard Henderson6049f4f2009-12-27 18:30:03 -08007831#endif
pbrook53a59602006-03-25 19:31:22 +00007832 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007833 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00007834#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00007835 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00007836 {
7837 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00007838 abi_ulong target_set;
Peter Maydell3d3efba2016-05-27 15:51:49 +01007839 ret = do_sigprocmask(0, NULL, &cur_set);
7840 if (!ret) {
7841 host_to_target_old_sigset(&target_set, &cur_set);
7842 ret = target_set;
7843 }
bellard66fb9762003-03-23 01:06:05 +00007844 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007845 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00007846#endif
7847#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00007848 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00007849 {
Miloš Stojanovića8617d82017-05-15 16:59:43 +02007850 sigset_t set, oset;
blueswir1992f48a2007-10-14 16:27:31 +00007851 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00007852 target_to_host_old_sigset(&set, &target_set);
Peter Maydell3d3efba2016-05-27 15:51:49 +01007853 ret = do_sigprocmask(SIG_SETMASK, &set, &oset);
7854 if (!ret) {
7855 host_to_target_old_sigset(&target_set, &oset);
7856 ret = target_set;
7857 }
bellard66fb9762003-03-23 01:06:05 +00007858 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007859 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00007860#endif
thse5febef2007-04-01 18:31:35 +00007861#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00007862 case TARGET_NR_sigprocmask:
7863 {
Richard Hendersona5b3b132010-05-03 10:07:55 -07007864#if defined(TARGET_ALPHA)
7865 sigset_t set, oldset;
7866 abi_ulong mask;
7867 int how;
7868
7869 switch (arg1) {
7870 case TARGET_SIG_BLOCK:
7871 how = SIG_BLOCK;
7872 break;
7873 case TARGET_SIG_UNBLOCK:
7874 how = SIG_UNBLOCK;
7875 break;
7876 case TARGET_SIG_SETMASK:
7877 how = SIG_SETMASK;
7878 break;
7879 default:
Richard Henderson259841c2018-08-18 12:01:09 -07007880 return -TARGET_EINVAL;
Richard Hendersona5b3b132010-05-03 10:07:55 -07007881 }
7882 mask = arg2;
7883 target_to_host_old_sigset(&set, &mask);
7884
Peter Maydell3d3efba2016-05-27 15:51:49 +01007885 ret = do_sigprocmask(how, &set, &oldset);
Richard Hendersona5b3b132010-05-03 10:07:55 -07007886 if (!is_error(ret)) {
7887 host_to_target_old_sigset(&mask, &oldset);
7888 ret = mask;
Richard Henderson0229f5a2012-06-07 15:02:49 -07007889 ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0; /* force no error */
Richard Hendersona5b3b132010-05-03 10:07:55 -07007890 }
7891#else
bellard66fb9762003-03-23 01:06:05 +00007892 sigset_t set, oldset, *set_ptr;
Richard Hendersona5b3b132010-05-03 10:07:55 -07007893 int how;
ths3b46e622007-09-17 08:09:54 +00007894
pbrook53a59602006-03-25 19:31:22 +00007895 if (arg2) {
Richard Hendersona5b3b132010-05-03 10:07:55 -07007896 switch (arg1) {
bellard66fb9762003-03-23 01:06:05 +00007897 case TARGET_SIG_BLOCK:
7898 how = SIG_BLOCK;
7899 break;
7900 case TARGET_SIG_UNBLOCK:
7901 how = SIG_UNBLOCK;
7902 break;
7903 case TARGET_SIG_SETMASK:
7904 how = SIG_SETMASK;
7905 break;
7906 default:
Richard Henderson259841c2018-08-18 12:01:09 -07007907 return -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00007908 }
Anthony Liguoric227f092009-10-01 16:12:16 -05007909 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007910 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007911 target_to_host_old_sigset(&set, p);
7912 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00007913 set_ptr = &set;
7914 } else {
7915 how = 0;
7916 set_ptr = NULL;
7917 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01007918 ret = do_sigprocmask(how, set_ptr, &oldset);
pbrook53a59602006-03-25 19:31:22 +00007919 if (!is_error(ret) && arg3) {
Anthony Liguoric227f092009-10-01 16:12:16 -05007920 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007921 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007922 host_to_target_old_sigset(p, &oldset);
Anthony Liguoric227f092009-10-01 16:12:16 -05007923 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00007924 }
Richard Hendersona5b3b132010-05-03 10:07:55 -07007925#endif
bellard66fb9762003-03-23 01:06:05 +00007926 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007927 return ret;
thse5febef2007-04-01 18:31:35 +00007928#endif
bellard66fb9762003-03-23 01:06:05 +00007929 case TARGET_NR_rt_sigprocmask:
7930 {
7931 int how = arg1;
7932 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00007933
Peter Maydellc8157012016-06-30 14:23:24 +01007934 if (arg4 != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007935 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01007936 }
7937
pbrook53a59602006-03-25 19:31:22 +00007938 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00007939 switch(how) {
7940 case TARGET_SIG_BLOCK:
7941 how = SIG_BLOCK;
7942 break;
7943 case TARGET_SIG_UNBLOCK:
7944 how = SIG_UNBLOCK;
7945 break;
7946 case TARGET_SIG_SETMASK:
7947 how = SIG_SETMASK;
7948 break;
7949 default:
Richard Henderson259841c2018-08-18 12:01:09 -07007950 return -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00007951 }
Anthony Liguoric227f092009-10-01 16:12:16 -05007952 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007953 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007954 target_to_host_sigset(&set, p);
7955 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00007956 set_ptr = &set;
7957 } else {
7958 how = 0;
7959 set_ptr = NULL;
7960 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01007961 ret = do_sigprocmask(how, set_ptr, &oldset);
pbrook53a59602006-03-25 19:31:22 +00007962 if (!is_error(ret) && arg3) {
Anthony Liguoric227f092009-10-01 16:12:16 -05007963 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007964 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007965 host_to_target_sigset(p, &oldset);
Anthony Liguoric227f092009-10-01 16:12:16 -05007966 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00007967 }
7968 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007969 return ret;
thse5febef2007-04-01 18:31:35 +00007970#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00007971 case TARGET_NR_sigpending:
7972 {
7973 sigset_t set;
7974 ret = get_errno(sigpending(&set));
7975 if (!is_error(ret)) {
Anthony Liguoric227f092009-10-01 16:12:16 -05007976 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07007977 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00007978 host_to_target_old_sigset(p, &set);
Anthony Liguoric227f092009-10-01 16:12:16 -05007979 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00007980 }
7981 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007982 return ret;
thse5febef2007-04-01 18:31:35 +00007983#endif
bellard66fb9762003-03-23 01:06:05 +00007984 case TARGET_NR_rt_sigpending:
7985 {
7986 sigset_t set;
Peter Maydellc8157012016-06-30 14:23:24 +01007987
7988 /* Yes, this check is >, not != like most. We follow the kernel's
7989 * logic and it does it like this because it implements
7990 * NR_sigpending through the same code path, and in that case
7991 * the old_sigset_t is smaller in size.
7992 */
7993 if (arg2 > sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07007994 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01007995 }
7996
bellard66fb9762003-03-23 01:06:05 +00007997 ret = get_errno(sigpending(&set));
7998 if (!is_error(ret)) {
Anthony Liguoric227f092009-10-01 16:12:16 -05007999 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008000 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008001 host_to_target_sigset(p, &set);
Anthony Liguoric227f092009-10-01 16:12:16 -05008002 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00008003 }
8004 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008005 return ret;
thse5febef2007-04-01 18:31:35 +00008006#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00008007 case TARGET_NR_sigsuspend:
8008 {
Peter Maydell3d3efba2016-05-27 15:51:49 +01008009 TaskState *ts = cpu->opaque;
Richard Hendersonf43ce122010-05-03 10:07:54 -07008010#if defined(TARGET_ALPHA)
8011 abi_ulong mask = arg1;
Peter Maydell3d3efba2016-05-27 15:51:49 +01008012 target_to_host_old_sigset(&ts->sigsuspend_mask, &mask);
Richard Hendersonf43ce122010-05-03 10:07:54 -07008013#else
Anthony Liguoric227f092009-10-01 16:12:16 -05008014 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008015 return -TARGET_EFAULT;
Peter Maydell3d3efba2016-05-27 15:51:49 +01008016 target_to_host_old_sigset(&ts->sigsuspend_mask, p);
pbrook53a59602006-03-25 19:31:22 +00008017 unlock_user(p, arg1, 0);
Richard Hendersonf43ce122010-05-03 10:07:54 -07008018#endif
Peter Maydell3d3efba2016-05-27 15:51:49 +01008019 ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
8020 SIGSET_T_SIZE));
8021 if (ret != -TARGET_ERESTARTSYS) {
8022 ts->in_sigsuspend = 1;
8023 }
bellard66fb9762003-03-23 01:06:05 +00008024 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008025 return ret;
thse5febef2007-04-01 18:31:35 +00008026#endif
bellard66fb9762003-03-23 01:06:05 +00008027 case TARGET_NR_rt_sigsuspend:
8028 {
Peter Maydell3d3efba2016-05-27 15:51:49 +01008029 TaskState *ts = cpu->opaque;
Peter Maydellc8157012016-06-30 14:23:24 +01008030
8031 if (arg2 != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008032 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01008033 }
Anthony Liguoric227f092009-10-01 16:12:16 -05008034 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008035 return -TARGET_EFAULT;
Peter Maydell3d3efba2016-05-27 15:51:49 +01008036 target_to_host_sigset(&ts->sigsuspend_mask, p);
pbrook53a59602006-03-25 19:31:22 +00008037 unlock_user(p, arg1, 0);
Peter Maydell3d3efba2016-05-27 15:51:49 +01008038 ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
8039 SIGSET_T_SIZE));
8040 if (ret != -TARGET_ERESTARTSYS) {
8041 ts->in_sigsuspend = 1;
8042 }
bellard66fb9762003-03-23 01:06:05 +00008043 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008044 return ret;
bellard66fb9762003-03-23 01:06:05 +00008045 case TARGET_NR_rt_sigtimedwait:
8046 {
bellard66fb9762003-03-23 01:06:05 +00008047 sigset_t set;
8048 struct timespec uts, *puts;
8049 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00008050
Peter Maydellc8157012016-06-30 14:23:24 +01008051 if (arg4 != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008052 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01008053 }
8054
Anthony Liguoric227f092009-10-01 16:12:16 -05008055 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008056 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008057 target_to_host_sigset(&set, p);
8058 unlock_user(p, arg1, 0);
8059 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00008060 puts = &uts;
pbrook53a59602006-03-25 19:31:22 +00008061 target_to_host_timespec(puts, arg3);
bellard66fb9762003-03-23 01:06:05 +00008062 } else {
8063 puts = NULL;
8064 }
Peter Maydellb3f82332016-06-06 19:58:08 +01008065 ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts,
8066 SIGSET_T_SIZE));
Petar Jovanovic974a1962014-03-03 15:07:41 +01008067 if (!is_error(ret)) {
8068 if (arg2) {
8069 p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t),
8070 0);
8071 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008072 return -TARGET_EFAULT;
Petar Jovanovic974a1962014-03-03 15:07:41 +01008073 }
8074 host_to_target_siginfo(p, &uinfo);
8075 unlock_user(p, arg2, sizeof(target_siginfo_t));
8076 }
8077 ret = host_to_target_signal(ret);
bellard66fb9762003-03-23 01:06:05 +00008078 }
8079 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008080 return ret;
bellard66fb9762003-03-23 01:06:05 +00008081 case TARGET_NR_rt_sigqueueinfo:
8082 {
8083 siginfo_t uinfo;
Peter Maydell4debae62016-06-20 15:50:36 +01008084
8085 p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
8086 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008087 return -TARGET_EFAULT;
Peter Maydell4debae62016-06-20 15:50:36 +01008088 }
pbrook53a59602006-03-25 19:31:22 +00008089 target_to_host_siginfo(&uinfo, p);
Miloš Stojanovićd8b6d892017-05-15 16:59:44 +02008090 unlock_user(p, arg3, 0);
bellard66fb9762003-03-23 01:06:05 +00008091 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
8092 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008093 return ret;
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +02008094 case TARGET_NR_rt_tgsigqueueinfo:
8095 {
8096 siginfo_t uinfo;
8097
8098 p = lock_user(VERIFY_READ, arg4, sizeof(target_siginfo_t), 1);
8099 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008100 return -TARGET_EFAULT;
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +02008101 }
8102 target_to_host_siginfo(&uinfo, p);
8103 unlock_user(p, arg4, 0);
8104 ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, arg3, &uinfo));
8105 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008106 return ret;
thse5febef2007-04-01 18:31:35 +00008107#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00008108 case TARGET_NR_sigreturn:
Peter Maydell3d3efba2016-05-27 15:51:49 +01008109 if (block_signals()) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008110 return -TARGET_ERESTARTSYS;
Peter Maydell3d3efba2016-05-27 15:51:49 +01008111 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008112 return do_sigreturn(cpu_env);
thse5febef2007-04-01 18:31:35 +00008113#endif
bellard66fb9762003-03-23 01:06:05 +00008114 case TARGET_NR_rt_sigreturn:
Peter Maydell3d3efba2016-05-27 15:51:49 +01008115 if (block_signals()) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008116 return -TARGET_ERESTARTSYS;
Peter Maydell3d3efba2016-05-27 15:51:49 +01008117 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008118 return do_rt_sigreturn(cpu_env);
bellard31e31b82003-02-18 22:55:36 +00008119 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00008120 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008121 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008122 ret = get_errno(sethostname(p, arg2));
8123 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008124 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008125#ifdef TARGET_NR_setrlimit
bellard31e31b82003-02-18 22:55:36 +00008126 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +00008127 {
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03008128 int resource = target_to_host_resource(arg1);
pbrook53a59602006-03-25 19:31:22 +00008129 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00008130 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +00008131 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008132 return -TARGET_EFAULT;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09008133 rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
8134 rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00008135 unlock_user_struct(target_rlim, arg2, 0);
Max Filippov5dfa88f2018-09-17 11:13:14 -07008136 /*
8137 * If we just passed through resource limit settings for memory then
8138 * they would also apply to QEMU's own allocations, and QEMU will
8139 * crash or hang or die if its allocations fail. Ideally we would
8140 * track the guest allocations in QEMU and apply the limits ourselves.
8141 * For now, just tell the guest the call succeeded but don't actually
8142 * limit anything.
8143 */
8144 if (resource != RLIMIT_AS &&
8145 resource != RLIMIT_DATA &&
8146 resource != RLIMIT_STACK) {
8147 return get_errno(setrlimit(resource, &rlim));
8148 } else {
8149 return 0;
8150 }
bellard9de5e442003-03-23 16:49:39 +00008151 }
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008152#endif
8153#ifdef TARGET_NR_getrlimit
bellard31e31b82003-02-18 22:55:36 +00008154 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00008155 {
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03008156 int resource = target_to_host_resource(arg1);
pbrook53a59602006-03-25 19:31:22 +00008157 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00008158 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00008159
bellard9de5e442003-03-23 16:49:39 +00008160 ret = get_errno(getrlimit(resource, &rlim));
8161 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00008162 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008163 return -TARGET_EFAULT;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09008164 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
8165 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00008166 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00008167 }
8168 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008169 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008170#endif
bellard31e31b82003-02-18 22:55:36 +00008171 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00008172 {
8173 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00008174 ret = get_errno(getrusage(arg1, &rusage));
8175 if (!is_error(ret)) {
Petar Jovanovica39fb272014-04-08 19:24:30 +02008176 ret = host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00008177 }
8178 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008179 return ret;
bellard31e31b82003-02-18 22:55:36 +00008180 case TARGET_NR_gettimeofday:
8181 {
bellard31e31b82003-02-18 22:55:36 +00008182 struct timeval tv;
8183 ret = get_errno(gettimeofday(&tv, NULL));
8184 if (!is_error(ret)) {
ths788f5ec2007-12-09 02:37:05 +00008185 if (copy_to_user_timeval(arg1, &tv))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008186 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00008187 }
8188 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008189 return ret;
bellard31e31b82003-02-18 22:55:36 +00008190 case TARGET_NR_settimeofday:
8191 {
Paul Burtonb67d8032014-06-22 11:25:41 +01008192 struct timeval tv, *ptv = NULL;
Paul Burtonef4467e2014-06-22 11:25:40 +01008193 struct timezone tz, *ptz = NULL;
8194
Paul Burtonb67d8032014-06-22 11:25:41 +01008195 if (arg1) {
8196 if (copy_from_user_timeval(&tv, arg1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008197 return -TARGET_EFAULT;
Paul Burtonb67d8032014-06-22 11:25:41 +01008198 }
8199 ptv = &tv;
8200 }
Paul Burtonef4467e2014-06-22 11:25:40 +01008201
8202 if (arg2) {
8203 if (copy_from_user_timezone(&tz, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008204 return -TARGET_EFAULT;
Paul Burtonef4467e2014-06-22 11:25:40 +01008205 }
8206 ptz = &tz;
8207 }
8208
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008209 return get_errno(settimeofday(ptv, ptz));
bellard31e31b82003-02-18 22:55:36 +00008210 }
Laurent Vivier9468a5d2013-01-10 22:30:50 +01008211#if defined(TARGET_NR_select)
bellard31e31b82003-02-18 22:55:36 +00008212 case TARGET_NR_select:
Laurent Vivier5457dc92016-07-08 01:17:27 +02008213#if defined(TARGET_WANT_NI_OLD_SELECT)
8214 /* some architectures used to have old_select here
8215 * but now ENOSYS it.
8216 */
8217 ret = -TARGET_ENOSYS;
8218#elif defined(TARGET_WANT_OLD_SYS_SELECT)
8219 ret = do_old_select(arg1);
Laurent Vivier9468a5d2013-01-10 22:30:50 +01008220#else
Laurent Vivier5457dc92016-07-08 01:17:27 +02008221 ret = do_select(arg1, arg2, arg3, arg4, arg5);
Laurent Vivier9468a5d2013-01-10 22:30:50 +01008222#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008223 return ret;
bellard048f6b42005-11-26 18:47:20 +00008224#endif
Riku Voipio9e423822010-05-07 12:28:05 +00008225#ifdef TARGET_NR_pselect6
8226 case TARGET_NR_pselect6:
Mike Frysinger055e0902011-06-03 17:01:49 -04008227 {
8228 abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr;
8229 fd_set rfds, wfds, efds;
8230 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
8231 struct timespec ts, *ts_ptr;
8232
8233 /*
8234 * The 6th arg is actually two args smashed together,
8235 * so we cannot use the C library.
8236 */
8237 sigset_t set;
8238 struct {
8239 sigset_t *set;
8240 size_t size;
8241 } sig, *sig_ptr;
8242
8243 abi_ulong arg_sigset, arg_sigsize, *arg7;
8244 target_sigset_t *target_sigset;
8245
8246 n = arg1;
8247 rfd_addr = arg2;
8248 wfd_addr = arg3;
8249 efd_addr = arg4;
8250 ts_addr = arg5;
8251
8252 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
8253 if (ret) {
Richard Henderson259841c2018-08-18 12:01:09 -07008254 return ret;
Mike Frysinger055e0902011-06-03 17:01:49 -04008255 }
8256 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
8257 if (ret) {
Richard Henderson259841c2018-08-18 12:01:09 -07008258 return ret;
Mike Frysinger055e0902011-06-03 17:01:49 -04008259 }
8260 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
8261 if (ret) {
Richard Henderson259841c2018-08-18 12:01:09 -07008262 return ret;
Mike Frysinger055e0902011-06-03 17:01:49 -04008263 }
8264
8265 /*
8266 * This takes a timespec, and not a timeval, so we cannot
8267 * use the do_select() helper ...
8268 */
8269 if (ts_addr) {
8270 if (target_to_host_timespec(&ts, ts_addr)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008271 return -TARGET_EFAULT;
Mike Frysinger055e0902011-06-03 17:01:49 -04008272 }
8273 ts_ptr = &ts;
8274 } else {
8275 ts_ptr = NULL;
8276 }
8277
8278 /* Extract the two packed args for the sigset */
8279 if (arg6) {
8280 sig_ptr = &sig;
Peter Maydellb28a1f32016-05-27 15:51:47 +01008281 sig.size = SIGSET_T_SIZE;
Mike Frysinger055e0902011-06-03 17:01:49 -04008282
8283 arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1);
8284 if (!arg7) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008285 return -TARGET_EFAULT;
Mike Frysinger055e0902011-06-03 17:01:49 -04008286 }
Matthias Brauncbb21ee2011-08-12 19:57:41 +02008287 arg_sigset = tswapal(arg7[0]);
8288 arg_sigsize = tswapal(arg7[1]);
Mike Frysinger055e0902011-06-03 17:01:49 -04008289 unlock_user(arg7, arg6, 0);
8290
8291 if (arg_sigset) {
8292 sig.set = &set;
Peter Maydell8f04eeb2011-06-28 12:21:57 +01008293 if (arg_sigsize != sizeof(*target_sigset)) {
8294 /* Like the kernel, we enforce correct size sigsets */
Richard Henderson259841c2018-08-18 12:01:09 -07008295 return -TARGET_EINVAL;
Peter Maydell8f04eeb2011-06-28 12:21:57 +01008296 }
Mike Frysinger055e0902011-06-03 17:01:49 -04008297 target_sigset = lock_user(VERIFY_READ, arg_sigset,
8298 sizeof(*target_sigset), 1);
8299 if (!target_sigset) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008300 return -TARGET_EFAULT;
Mike Frysinger055e0902011-06-03 17:01:49 -04008301 }
8302 target_to_host_sigset(&set, target_sigset);
8303 unlock_user(target_sigset, arg_sigset, 0);
8304 } else {
8305 sig.set = NULL;
8306 }
8307 } else {
8308 sig_ptr = NULL;
8309 }
8310
Peter Maydell6df9d382016-05-12 18:47:51 +01008311 ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
8312 ts_ptr, sig_ptr));
Mike Frysinger055e0902011-06-03 17:01:49 -04008313
8314 if (!is_error(ret)) {
8315 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008316 return -TARGET_EFAULT;
Mike Frysinger055e0902011-06-03 17:01:49 -04008317 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008318 return -TARGET_EFAULT;
Mike Frysinger055e0902011-06-03 17:01:49 -04008319 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008320 return -TARGET_EFAULT;
Mike Frysinger055e0902011-06-03 17:01:49 -04008321
8322 if (ts_addr && host_to_target_timespec(ts_addr, &ts))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008323 return -TARGET_EFAULT;
Mike Frysinger055e0902011-06-03 17:01:49 -04008324 }
8325 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008326 return ret;
Riku Voipio9e423822010-05-07 12:28:05 +00008327#endif
Chen Gang704eff62015-08-21 05:37:33 +08008328#ifdef TARGET_NR_symlink
bellard31e31b82003-02-18 22:55:36 +00008329 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00008330 {
8331 void *p2;
8332 p = lock_user_string(arg1);
8333 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00008334 if (!p || !p2)
8335 ret = -TARGET_EFAULT;
8336 else
8337 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00008338 unlock_user(p2, arg2, 0);
8339 unlock_user(p, arg1, 0);
8340 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008341 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008342#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01008343#if defined(TARGET_NR_symlinkat)
thsf0b62432007-09-24 09:25:40 +00008344 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00008345 {
bellard579a97f2007-11-11 14:26:47 +00008346 void *p2;
thsf0b62432007-09-24 09:25:40 +00008347 p = lock_user_string(arg1);
8348 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00008349 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00008350 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00008351 else
Peter Maydellc0d472b2013-06-12 16:20:21 +01008352 ret = get_errno(symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00008353 unlock_user(p2, arg3, 0);
8354 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00008355 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008356 return ret;
thsf0b62432007-09-24 09:25:40 +00008357#endif
Chen Gang704eff62015-08-21 05:37:33 +08008358#ifdef TARGET_NR_readlink
bellard31e31b82003-02-18 22:55:36 +00008359 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00008360 {
Andreas Schwab463d8e72013-07-02 14:04:12 +01008361 void *p2;
pbrook53a59602006-03-25 19:31:22 +00008362 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00008363 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
Andreas Schwab463d8e72013-07-02 14:04:12 +01008364 if (!p || !p2) {
bellard579a97f2007-11-11 14:26:47 +00008365 ret = -TARGET_EFAULT;
Mike Frysingerf17f4982014-08-08 09:40:25 +09008366 } else if (!arg3) {
8367 /* Short circuit this for the magic exe check. */
8368 ret = -TARGET_EINVAL;
Andreas Schwab463d8e72013-07-02 14:04:12 +01008369 } else if (is_proc_myself((const char *)p, "exe")) {
8370 char real[PATH_MAX], *temp;
8371 temp = realpath(exec_path, real);
Mike Frysingerf17f4982014-08-08 09:40:25 +09008372 /* Return value is # of bytes that we wrote to the buffer. */
8373 if (temp == NULL) {
8374 ret = get_errno(-1);
8375 } else {
8376 /* Don't worry about sign mismatch as earlier mapping
8377 * logic would have thrown a bad address error. */
8378 ret = MIN(strlen(real), arg3);
8379 /* We cannot NUL terminate the string. */
8380 memcpy(p2, real, ret);
8381 }
Andreas Schwab463d8e72013-07-02 14:04:12 +01008382 } else {
8383 ret = get_errno(readlink(path(p), p2, arg3));
aurel32d088d662009-01-30 20:09:01 +00008384 }
pbrook53a59602006-03-25 19:31:22 +00008385 unlock_user(p2, arg2, ret);
8386 unlock_user(p, arg1, 0);
8387 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008388 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008389#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01008390#if defined(TARGET_NR_readlinkat)
ths5e0ccb12007-09-24 09:26:10 +00008391 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +00008392 {
bellard579a97f2007-11-11 14:26:47 +00008393 void *p2;
ths5e0ccb12007-09-24 09:26:10 +00008394 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00008395 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
Andreas Schwab463d8e72013-07-02 14:04:12 +01008396 if (!p || !p2) {
8397 ret = -TARGET_EFAULT;
8398 } else if (is_proc_myself((const char *)p, "exe")) {
8399 char real[PATH_MAX], *temp;
8400 temp = realpath(exec_path, real);
8401 ret = temp == NULL ? get_errno(-1) : strlen(real) ;
8402 snprintf((char *)p2, arg4, "%s", real);
8403 } else {
Peter Maydellc0d472b2013-06-12 16:20:21 +01008404 ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
Andreas Schwab463d8e72013-07-02 14:04:12 +01008405 }
bellard579a97f2007-11-11 14:26:47 +00008406 unlock_user(p2, arg3, ret);
8407 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +00008408 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008409 return ret;
ths5e0ccb12007-09-24 09:26:10 +00008410#endif
thse5febef2007-04-01 18:31:35 +00008411#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +00008412 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +00008413 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008414 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008415 ret = get_errno(swapon(p, arg2));
8416 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008417 return ret;
thse5febef2007-04-01 18:31:35 +00008418#endif
bellard31e31b82003-02-18 22:55:36 +00008419 case TARGET_NR_reboot:
Laurent Vivierc07ecc62013-01-07 11:40:06 +00008420 if (arg3 == LINUX_REBOOT_CMD_RESTART2) {
8421 /* arg4 must be ignored in all other cases */
8422 p = lock_user_string(arg4);
8423 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008424 return -TARGET_EFAULT;
Laurent Vivierc07ecc62013-01-07 11:40:06 +00008425 }
8426 ret = get_errno(reboot(arg1, arg2, arg3, p));
8427 unlock_user(p, arg4, 0);
8428 } else {
8429 ret = get_errno(reboot(arg1, arg2, arg3, NULL));
8430 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008431 return ret;
thse5febef2007-04-01 18:31:35 +00008432#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +00008433 case TARGET_NR_mmap:
Alexander Graf09701192013-09-03 20:12:15 +01008434#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
8435 (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
Ulrich Hechta4c075f2009-07-24 16:57:31 +02008436 defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \
8437 || defined(TARGET_S390X)
bellard31e31b82003-02-18 22:55:36 +00008438 {
blueswir1992f48a2007-10-14 16:27:31 +00008439 abi_ulong *v;
8440 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +00008441 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008442 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02008443 v1 = tswapal(v[0]);
8444 v2 = tswapal(v[1]);
8445 v3 = tswapal(v[2]);
8446 v4 = tswapal(v[3]);
8447 v5 = tswapal(v[4]);
8448 v6 = tswapal(v[5]);
pbrook53a59602006-03-25 19:31:22 +00008449 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +00008450 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +00008451 target_to_host_bitmask(v4, mmap_flags_tbl),
8452 v5, v6));
bellard31e31b82003-02-18 22:55:36 +00008453 }
bellard31e31b82003-02-18 22:55:36 +00008454#else
ths5fafdf22007-09-16 21:08:06 +00008455 ret = get_errno(target_mmap(arg1, arg2, arg3,
8456 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +00008457 arg5,
8458 arg6));
bellard31e31b82003-02-18 22:55:36 +00008459#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008460 return ret;
thse5febef2007-04-01 18:31:35 +00008461#endif
bellarda315a142005-01-30 22:59:18 +00008462#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +00008463 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +00008464#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +00008465#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +00008466#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008467 ret = target_mmap(arg1, arg2, arg3,
8468 target_to_host_bitmask(arg4, mmap_flags_tbl),
8469 arg5, arg6 << MMAP_SHIFT);
8470 return get_errno(ret);
bellarda315a142005-01-30 22:59:18 +00008471#endif
bellard31e31b82003-02-18 22:55:36 +00008472 case TARGET_NR_munmap:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008473 return get_errno(target_munmap(arg1, arg2));
bellard9de5e442003-03-23 16:49:39 +00008474 case TARGET_NR_mprotect:
Paul Brook97374d32010-06-16 13:03:51 +01008475 {
Andreas Färber0429a972013-08-26 18:14:44 +02008476 TaskState *ts = cpu->opaque;
Paul Brook97374d32010-06-16 13:03:51 +01008477 /* Special hack to detect libc making the stack executable. */
8478 if ((arg3 & PROT_GROWSDOWN)
8479 && arg1 >= ts->info->stack_limit
8480 && arg1 <= ts->info->start_stack) {
8481 arg3 &= ~PROT_GROWSDOWN;
8482 arg2 = arg2 + arg1 - ts->info->stack_limit;
8483 arg1 = ts->info->stack_limit;
8484 }
8485 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008486 return get_errno(target_mprotect(arg1, arg2, arg3));
thse5febef2007-04-01 18:31:35 +00008487#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +00008488 case TARGET_NR_mremap:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008489 return get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
thse5febef2007-04-01 18:31:35 +00008490#endif
pbrook53a59602006-03-25 19:31:22 +00008491 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +00008492#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +00008493 case TARGET_NR_msync:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008494 return get_errno(msync(g2h(arg1), arg2, arg3));
thse5febef2007-04-01 18:31:35 +00008495#endif
8496#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +00008497 case TARGET_NR_mlock:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008498 return get_errno(mlock(g2h(arg1), arg2));
thse5febef2007-04-01 18:31:35 +00008499#endif
8500#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +00008501 case TARGET_NR_munlock:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008502 return get_errno(munlock(g2h(arg1), arg2));
thse5febef2007-04-01 18:31:35 +00008503#endif
8504#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +00008505 case TARGET_NR_mlockall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008506 return get_errno(mlockall(target_to_host_mlockall_arg(arg1)));
thse5febef2007-04-01 18:31:35 +00008507#endif
8508#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +00008509 case TARGET_NR_munlockall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008510 return get_errno(munlockall());
thse5febef2007-04-01 18:31:35 +00008511#endif
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008512#ifdef TARGET_NR_truncate
bellard31e31b82003-02-18 22:55:36 +00008513 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +00008514 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008515 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008516 ret = get_errno(truncate(p, arg2));
8517 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008518 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008519#endif
8520#ifdef TARGET_NR_ftruncate
bellard31e31b82003-02-18 22:55:36 +00008521 case TARGET_NR_ftruncate:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008522 return get_errno(ftruncate(arg1, arg2));
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008523#endif
bellard31e31b82003-02-18 22:55:36 +00008524 case TARGET_NR_fchmod:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008525 return get_errno(fchmod(arg1, arg2));
Peter Maydellc0d472b2013-06-12 16:20:21 +01008526#if defined(TARGET_NR_fchmodat)
ths814d7972007-09-24 09:26:51 +00008527 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +00008528 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008529 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01008530 ret = get_errno(fchmodat(arg1, p, arg3, 0));
bellard579a97f2007-11-11 14:26:47 +00008531 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008532 return ret;
ths814d7972007-09-24 09:26:51 +00008533#endif
bellard31e31b82003-02-18 22:55:36 +00008534 case TARGET_NR_getpriority:
Richard Henderson95c09822012-06-07 15:14:50 -07008535 /* Note that negative values are valid for getpriority, so we must
8536 differentiate based on errno settings. */
8537 errno = 0;
8538 ret = getpriority(arg1, arg2);
8539 if (ret == -1 && errno != 0) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008540 return -host_to_target_errno(errno);
Richard Henderson95c09822012-06-07 15:14:50 -07008541 }
8542#ifdef TARGET_ALPHA
8543 /* Return value is the unbiased priority. Signal no error. */
8544 ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0;
8545#else
8546 /* Return value is a biased priority to avoid negative numbers. */
8547 ret = 20 - ret;
8548#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008549 return ret;
bellard31e31b82003-02-18 22:55:36 +00008550 case TARGET_NR_setpriority:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008551 return get_errno(setpriority(arg1, arg2, arg3));
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008552#ifdef TARGET_NR_statfs
bellard31e31b82003-02-18 22:55:36 +00008553 case TARGET_NR_statfs:
Richard Henderson2852aaf2018-08-18 12:01:06 -07008554 if (!(p = lock_user_string(arg1))) {
8555 return -TARGET_EFAULT;
8556 }
pbrook53a59602006-03-25 19:31:22 +00008557 ret = get_errno(statfs(path(p), &stfs));
8558 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00008559 convert_statfs:
8560 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00008561 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +00008562
bellard579a97f2007-11-11 14:26:47 +00008563 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008564 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00008565 __put_user(stfs.f_type, &target_stfs->f_type);
8566 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
8567 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
8568 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
8569 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
8570 __put_user(stfs.f_files, &target_stfs->f_files);
8571 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
8572 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
8573 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
8574 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
Alexander Graf229d3372012-09-19 04:39:53 +02008575 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
Shea Levyd4247ec2018-03-01 06:15:00 -05008576#ifdef _STATFS_F_FLAGS
8577 __put_user(stfs.f_flags, &target_stfs->f_flags);
8578#else
8579 __put_user(0, &target_stfs->f_flags);
8580#endif
Alexander Graf229d3372012-09-19 04:39:53 +02008581 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
pbrook53a59602006-03-25 19:31:22 +00008582 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00008583 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008584 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008585#endif
8586#ifdef TARGET_NR_fstatfs
bellard31e31b82003-02-18 22:55:36 +00008587 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +00008588 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +00008589 goto convert_statfs;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008590#endif
bellard56c8f682005-11-28 22:28:41 +00008591#ifdef TARGET_NR_statfs64
8592 case TARGET_NR_statfs64:
Richard Henderson2852aaf2018-08-18 12:01:06 -07008593 if (!(p = lock_user_string(arg1))) {
8594 return -TARGET_EFAULT;
8595 }
pbrook53a59602006-03-25 19:31:22 +00008596 ret = get_errno(statfs(path(p), &stfs));
8597 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +00008598 convert_statfs64:
8599 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00008600 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +00008601
bellard579a97f2007-11-11 14:26:47 +00008602 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008603 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00008604 __put_user(stfs.f_type, &target_stfs->f_type);
8605 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
8606 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
8607 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
8608 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
8609 __put_user(stfs.f_files, &target_stfs->f_files);
8610 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
8611 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
8612 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
8613 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
Alexander Graf229d3372012-09-19 04:39:53 +02008614 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
8615 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
bellard579a97f2007-11-11 14:26:47 +00008616 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +00008617 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008618 return ret;
bellard56c8f682005-11-28 22:28:41 +00008619 case TARGET_NR_fstatfs64:
8620 ret = get_errno(fstatfs(arg1, &stfs));
8621 goto convert_statfs64;
8622#endif
thse5febef2007-04-01 18:31:35 +00008623#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +00008624 case TARGET_NR_socketcall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008625 return do_socketcall(arg1, arg2);
thse5febef2007-04-01 18:31:35 +00008626#endif
bellard3532fa72006-06-24 15:06:03 +00008627#ifdef TARGET_NR_accept
8628 case TARGET_NR_accept:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008629 return do_accept4(arg1, arg2, arg3, 0);
Peter Maydella94b4982013-02-08 04:35:04 +00008630#endif
8631#ifdef TARGET_NR_accept4
8632 case TARGET_NR_accept4:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008633 return do_accept4(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00008634#endif
8635#ifdef TARGET_NR_bind
8636 case TARGET_NR_bind:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008637 return do_bind(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00008638#endif
8639#ifdef TARGET_NR_connect
8640 case TARGET_NR_connect:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008641 return do_connect(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00008642#endif
8643#ifdef TARGET_NR_getpeername
8644 case TARGET_NR_getpeername:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008645 return do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00008646#endif
8647#ifdef TARGET_NR_getsockname
8648 case TARGET_NR_getsockname:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008649 return do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00008650#endif
8651#ifdef TARGET_NR_getsockopt
8652 case TARGET_NR_getsockopt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008653 return do_getsockopt(arg1, arg2, arg3, arg4, arg5);
bellard3532fa72006-06-24 15:06:03 +00008654#endif
8655#ifdef TARGET_NR_listen
8656 case TARGET_NR_listen:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008657 return get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00008658#endif
8659#ifdef TARGET_NR_recv
8660 case TARGET_NR_recv:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008661 return do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00008662#endif
8663#ifdef TARGET_NR_recvfrom
8664 case TARGET_NR_recvfrom:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008665 return do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00008666#endif
8667#ifdef TARGET_NR_recvmsg
8668 case TARGET_NR_recvmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008669 return do_sendrecvmsg(arg1, arg2, arg3, 0);
bellard3532fa72006-06-24 15:06:03 +00008670#endif
8671#ifdef TARGET_NR_send
8672 case TARGET_NR_send:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008673 return do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00008674#endif
8675#ifdef TARGET_NR_sendmsg
8676 case TARGET_NR_sendmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008677 return do_sendrecvmsg(arg1, arg2, arg3, 1);
bellard3532fa72006-06-24 15:06:03 +00008678#endif
Alexander Graff19e00d2014-03-02 19:36:42 +00008679#ifdef TARGET_NR_sendmmsg
8680 case TARGET_NR_sendmmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008681 return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1);
Alexander Graff19e00d2014-03-02 19:36:42 +00008682 case TARGET_NR_recvmmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008683 return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0);
Alexander Graff19e00d2014-03-02 19:36:42 +00008684#endif
bellard3532fa72006-06-24 15:06:03 +00008685#ifdef TARGET_NR_sendto
8686 case TARGET_NR_sendto:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008687 return do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00008688#endif
8689#ifdef TARGET_NR_shutdown
8690 case TARGET_NR_shutdown:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008691 return get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00008692#endif
Laurent Vivierf894efd2016-02-21 10:56:23 +01008693#if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
8694 case TARGET_NR_getrandom:
8695 p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
8696 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008697 return -TARGET_EFAULT;
Laurent Vivierf894efd2016-02-21 10:56:23 +01008698 }
8699 ret = get_errno(getrandom(p, arg2, arg3));
8700 unlock_user(p, arg1, ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008701 return ret;
Laurent Vivierf894efd2016-02-21 10:56:23 +01008702#endif
bellard3532fa72006-06-24 15:06:03 +00008703#ifdef TARGET_NR_socket
8704 case TARGET_NR_socket:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008705 return do_socket(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00008706#endif
8707#ifdef TARGET_NR_socketpair
8708 case TARGET_NR_socketpair:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008709 return do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00008710#endif
8711#ifdef TARGET_NR_setsockopt
8712 case TARGET_NR_setsockopt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008713 return do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
bellard3532fa72006-06-24 15:06:03 +00008714#endif
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02008715#if defined(TARGET_NR_syslog)
bellard31e31b82003-02-18 22:55:36 +00008716 case TARGET_NR_syslog:
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02008717 {
8718 int len = arg2;
ths7494b0f2007-02-11 18:26:53 +00008719
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02008720 switch (arg1) {
8721 case TARGET_SYSLOG_ACTION_CLOSE: /* Close log */
8722 case TARGET_SYSLOG_ACTION_OPEN: /* Open log */
8723 case TARGET_SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
8724 case TARGET_SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging */
8725 case TARGET_SYSLOG_ACTION_CONSOLE_ON: /* Enable logging */
8726 case TARGET_SYSLOG_ACTION_CONSOLE_LEVEL: /* Set messages level */
8727 case TARGET_SYSLOG_ACTION_SIZE_UNREAD: /* Number of chars */
8728 case TARGET_SYSLOG_ACTION_SIZE_BUFFER: /* Size of the buffer */
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008729 return get_errno(sys_syslog((int)arg1, NULL, (int)arg3));
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02008730 case TARGET_SYSLOG_ACTION_READ: /* Read from log */
8731 case TARGET_SYSLOG_ACTION_READ_CLEAR: /* Read/clear msgs */
8732 case TARGET_SYSLOG_ACTION_READ_ALL: /* Read last messages */
8733 {
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02008734 if (len < 0) {
Richard Henderson259841c2018-08-18 12:01:09 -07008735 return -TARGET_EINVAL;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02008736 }
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02008737 if (len == 0) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008738 return 0;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02008739 }
8740 p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
8741 if (!p) {
Richard Henderson259841c2018-08-18 12:01:09 -07008742 return -TARGET_EFAULT;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02008743 }
8744 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
8745 unlock_user(p, arg2, arg3);
8746 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008747 return ret;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02008748 default:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008749 return -TARGET_EINVAL;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +02008750 }
8751 }
8752 break;
8753#endif
bellard31e31b82003-02-18 22:55:36 +00008754 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +00008755 {
bellard66fb9762003-03-23 01:06:05 +00008756 struct itimerval value, ovalue, *pvalue;
8757
pbrook53a59602006-03-25 19:31:22 +00008758 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00008759 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +00008760 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
8761 || copy_from_user_timeval(&pvalue->it_value,
8762 arg2 + sizeof(struct target_timeval)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008763 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +00008764 } else {
8765 pvalue = NULL;
8766 }
8767 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +00008768 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +00008769 if (copy_to_user_timeval(arg3,
8770 &ovalue.it_interval)
8771 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
8772 &ovalue.it_value))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008773 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +00008774 }
8775 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008776 return ret;
bellard31e31b82003-02-18 22:55:36 +00008777 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +00008778 {
bellard66fb9762003-03-23 01:06:05 +00008779 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +00008780
bellard66fb9762003-03-23 01:06:05 +00008781 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +00008782 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +00008783 if (copy_to_user_timeval(arg2,
8784 &value.it_interval)
8785 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
8786 &value.it_value))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008787 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +00008788 }
8789 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008790 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008791#ifdef TARGET_NR_stat
bellard31e31b82003-02-18 22:55:36 +00008792 case TARGET_NR_stat:
Richard Henderson2852aaf2018-08-18 12:01:06 -07008793 if (!(p = lock_user_string(arg1))) {
8794 return -TARGET_EFAULT;
8795 }
pbrook53a59602006-03-25 19:31:22 +00008796 ret = get_errno(stat(path(p), &st));
8797 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00008798 goto do_stat;
Chen Gang704eff62015-08-21 05:37:33 +08008799#endif
8800#ifdef TARGET_NR_lstat
bellard31e31b82003-02-18 22:55:36 +00008801 case TARGET_NR_lstat:
Richard Henderson2852aaf2018-08-18 12:01:06 -07008802 if (!(p = lock_user_string(arg1))) {
8803 return -TARGET_EFAULT;
8804 }
pbrook53a59602006-03-25 19:31:22 +00008805 ret = get_errno(lstat(path(p), &st));
8806 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00008807 goto do_stat;
Chen Gang704eff62015-08-21 05:37:33 +08008808#endif
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008809#ifdef TARGET_NR_fstat
bellard31e31b82003-02-18 22:55:36 +00008810 case TARGET_NR_fstat:
8811 {
8812 ret = get_errno(fstat(arg1, &st));
Chen Gang704eff62015-08-21 05:37:33 +08008813#if defined(TARGET_NR_stat) || defined(TARGET_NR_lstat)
bellard31e31b82003-02-18 22:55:36 +00008814 do_stat:
Chen Gang704eff62015-08-21 05:37:33 +08008815#endif
bellard31e31b82003-02-18 22:55:36 +00008816 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00008817 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +00008818
bellard579a97f2007-11-11 14:26:47 +00008819 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008820 return -TARGET_EFAULT;
Ulrich Hecht12727912009-07-24 19:10:32 +02008821 memset(target_st, 0, sizeof(*target_st));
bellardd2fd1af2007-11-14 18:08:56 +00008822 __put_user(st.st_dev, &target_st->st_dev);
8823 __put_user(st.st_ino, &target_st->st_ino);
8824 __put_user(st.st_mode, &target_st->st_mode);
8825 __put_user(st.st_uid, &target_st->st_uid);
8826 __put_user(st.st_gid, &target_st->st_gid);
8827 __put_user(st.st_nlink, &target_st->st_nlink);
8828 __put_user(st.st_rdev, &target_st->st_rdev);
8829 __put_user(st.st_size, &target_st->st_size);
8830 __put_user(st.st_blksize, &target_st->st_blksize);
8831 __put_user(st.st_blocks, &target_st->st_blocks);
8832 __put_user(st.st_atime, &target_st->target_st_atime);
8833 __put_user(st.st_mtime, &target_st->target_st_mtime);
8834 __put_user(st.st_ctime, &target_st->target_st_ctime);
pbrook53a59602006-03-25 19:31:22 +00008835 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00008836 }
8837 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008838 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008839#endif
bellard31e31b82003-02-18 22:55:36 +00008840 case TARGET_NR_vhangup:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008841 return get_errno(vhangup());
bellard42ad6ae2005-01-03 22:48:11 +00008842#ifdef TARGET_NR_syscall
8843 case TARGET_NR_syscall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008844 return do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5,
8845 arg6, arg7, arg8, 0);
bellard42ad6ae2005-01-03 22:48:11 +00008846#endif
bellard31e31b82003-02-18 22:55:36 +00008847 case TARGET_NR_wait4:
8848 {
8849 int status;
blueswir1992f48a2007-10-14 16:27:31 +00008850 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +00008851 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00008852 abi_ulong target_rusage = arg4;
Petar Jovanovica39fb272014-04-08 19:24:30 +02008853 abi_long rusage_err;
bellard31e31b82003-02-18 22:55:36 +00008854 if (target_rusage)
8855 rusage_ptr = &rusage;
8856 else
8857 rusage_ptr = NULL;
Timothy E Baldwin4af80a32016-05-12 18:47:49 +01008858 ret = get_errno(safe_wait4(arg1, &status, arg3, rusage_ptr));
bellard31e31b82003-02-18 22:55:36 +00008859 if (!is_error(ret)) {
Alexander Graf53795572011-11-24 00:44:43 +01008860 if (status_ptr && ret) {
pbrook1d9d8b52009-04-16 15:17:02 +00008861 status = host_to_target_waitstatus(status);
bellard2f619692007-11-16 10:46:05 +00008862 if (put_user_s32(status, status_ptr))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008863 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00008864 }
Petar Jovanovica39fb272014-04-08 19:24:30 +02008865 if (target_rusage) {
8866 rusage_err = host_to_target_rusage(target_rusage, &rusage);
8867 if (rusage_err) {
8868 ret = rusage_err;
8869 }
8870 }
bellard31e31b82003-02-18 22:55:36 +00008871 }
8872 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008873 return ret;
thse5febef2007-04-01 18:31:35 +00008874#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +00008875 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +00008876 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008877 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008878 ret = get_errno(swapoff(p));
8879 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008880 return ret;
thse5febef2007-04-01 18:31:35 +00008881#endif
bellard31e31b82003-02-18 22:55:36 +00008882 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +00008883 {
pbrook53a59602006-03-25 19:31:22 +00008884 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +00008885 struct sysinfo value;
8886 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +00008887 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +00008888 {
bellard579a97f2007-11-11 14:26:47 +00008889 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008890 return -TARGET_EFAULT;
bellarda5448a72004-06-19 16:59:03 +00008891 __put_user(value.uptime, &target_value->uptime);
8892 __put_user(value.loads[0], &target_value->loads[0]);
8893 __put_user(value.loads[1], &target_value->loads[1]);
8894 __put_user(value.loads[2], &target_value->loads[2]);
8895 __put_user(value.totalram, &target_value->totalram);
8896 __put_user(value.freeram, &target_value->freeram);
8897 __put_user(value.sharedram, &target_value->sharedram);
8898 __put_user(value.bufferram, &target_value->bufferram);
8899 __put_user(value.totalswap, &target_value->totalswap);
8900 __put_user(value.freeswap, &target_value->freeswap);
8901 __put_user(value.procs, &target_value->procs);
8902 __put_user(value.totalhigh, &target_value->totalhigh);
8903 __put_user(value.freehigh, &target_value->freehigh);
8904 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +00008905 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +00008906 }
8907 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008908 return ret;
thse5febef2007-04-01 18:31:35 +00008909#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +00008910 case TARGET_NR_ipc:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008911 return do_ipc(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
thse5febef2007-04-01 18:31:35 +00008912#endif
aurel32e5289082009-04-18 16:16:12 +00008913#ifdef TARGET_NR_semget
8914 case TARGET_NR_semget:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008915 return get_errno(semget(arg1, arg2, arg3));
aurel32e5289082009-04-18 16:16:12 +00008916#endif
8917#ifdef TARGET_NR_semop
8918 case TARGET_NR_semop:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008919 return do_semop(arg1, arg2, arg3);
aurel32e5289082009-04-18 16:16:12 +00008920#endif
8921#ifdef TARGET_NR_semctl
8922 case TARGET_NR_semctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008923 return do_semctl(arg1, arg2, arg3, arg4);
aurel32e5289082009-04-18 16:16:12 +00008924#endif
aurel32eeb438c2008-10-13 21:08:55 +00008925#ifdef TARGET_NR_msgctl
8926 case TARGET_NR_msgctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008927 return do_msgctl(arg1, arg2, arg3);
aurel32eeb438c2008-10-13 21:08:55 +00008928#endif
8929#ifdef TARGET_NR_msgget
8930 case TARGET_NR_msgget:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008931 return get_errno(msgget(arg1, arg2));
aurel32eeb438c2008-10-13 21:08:55 +00008932#endif
8933#ifdef TARGET_NR_msgrcv
8934 case TARGET_NR_msgrcv:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008935 return do_msgrcv(arg1, arg2, arg3, arg4, arg5);
aurel32eeb438c2008-10-13 21:08:55 +00008936#endif
8937#ifdef TARGET_NR_msgsnd
8938 case TARGET_NR_msgsnd:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008939 return do_msgsnd(arg1, arg2, arg3, arg4);
aurel32eeb438c2008-10-13 21:08:55 +00008940#endif
Riku Voipio88a8c982009-04-03 10:42:00 +03008941#ifdef TARGET_NR_shmget
8942 case TARGET_NR_shmget:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008943 return get_errno(shmget(arg1, arg2, arg3));
Riku Voipio88a8c982009-04-03 10:42:00 +03008944#endif
8945#ifdef TARGET_NR_shmctl
8946 case TARGET_NR_shmctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008947 return do_shmctl(arg1, arg2, arg3);
Riku Voipio88a8c982009-04-03 10:42:00 +03008948#endif
8949#ifdef TARGET_NR_shmat
8950 case TARGET_NR_shmat:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008951 return do_shmat(cpu_env, arg1, arg2, arg3);
Riku Voipio88a8c982009-04-03 10:42:00 +03008952#endif
8953#ifdef TARGET_NR_shmdt
8954 case TARGET_NR_shmdt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008955 return do_shmdt(arg1);
Riku Voipio88a8c982009-04-03 10:42:00 +03008956#endif
bellard31e31b82003-02-18 22:55:36 +00008957 case TARGET_NR_fsync:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008958 return get_errno(fsync(arg1));
bellard31e31b82003-02-18 22:55:36 +00008959 case TARGET_NR_clone:
Peter Maydell4ce62432013-07-16 18:44:57 +01008960 /* Linux manages to have three different orderings for its
8961 * arguments to clone(); the BACKWARDS and BACKWARDS2 defines
8962 * match the kernel's CONFIG_CLONE_* settings.
8963 * Microblaze is further special in that it uses a sixth
8964 * implicit argument to clone for the TLS pointer.
8965 */
8966#if defined(TARGET_MICROBLAZE)
Edgar E. Iglesiasa5b3bdc2012-04-26 14:17:41 +02008967 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5));
Peter Maydell4ce62432013-07-16 18:44:57 +01008968#elif defined(TARGET_CLONE_BACKWARDS)
8969 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
8970#elif defined(TARGET_CLONE_BACKWARDS2)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02008971 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
aurel320b6d3ae2008-09-15 07:43:43 +00008972#else
Peter Maydell4ce62432013-07-16 18:44:57 +01008973 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
aurel320b6d3ae2008-09-15 07:43:43 +00008974#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008975 return ret;
bellardec86b0f2003-04-11 00:15:04 +00008976#ifdef __NR_exit_group
8977 /* new thread calls */
8978 case TARGET_NR_exit_group:
Alex Bennée708b6a62018-06-22 17:09:10 +01008979 preexit_cleanup(cpu_env, arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008980 return get_errno(exit_group(arg1));
bellardec86b0f2003-04-11 00:15:04 +00008981#endif
bellard31e31b82003-02-18 22:55:36 +00008982 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +00008983 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008984 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008985 ret = get_errno(setdomainname(p, arg2));
8986 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008987 return ret;
bellard31e31b82003-02-18 22:55:36 +00008988 case TARGET_NR_uname:
8989 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +00008990 {
8991 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +00008992
bellard579a97f2007-11-11 14:26:47 +00008993 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008994 return -TARGET_EFAULT;
bellard29e619b2004-09-13 21:41:04 +00008995 ret = get_errno(sys_uname(buf));
8996 if (!is_error(ret)) {
Peter Maydell332c9782016-07-12 13:02:16 +01008997 /* Overwrite the native machine name with whatever is being
bellard29e619b2004-09-13 21:41:04 +00008998 emulated. */
Philippe Mathieu-Daudé871f95c2017-07-24 15:27:47 -03008999 g_strlcpy(buf->machine, cpu_to_uname_machine(cpu_env),
9000 sizeof(buf->machine));
pbrookc5937222006-05-14 11:30:38 +00009001 /* Allow the user to override the reported release. */
Peter Maydell332c9782016-07-12 13:02:16 +01009002 if (qemu_uname_release && *qemu_uname_release) {
9003 g_strlcpy(buf->release, qemu_uname_release,
9004 sizeof(buf->release));
9005 }
bellard29e619b2004-09-13 21:41:04 +00009006 }
pbrook53a59602006-03-25 19:31:22 +00009007 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +00009008 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009009 return ret;
bellard6dbad632003-03-16 18:05:05 +00009010#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +00009011 case TARGET_NR_modify_ldt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009012 return do_modify_ldt(cpu_env, arg1, arg2, arg3);
j_mayer84409dd2007-04-06 08:56:50 +00009013#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +00009014 case TARGET_NR_vm86:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009015 return do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +00009016#endif
j_mayer84409dd2007-04-06 08:56:50 +00009017#endif
bellard31e31b82003-02-18 22:55:36 +00009018 case TARGET_NR_adjtimex:
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +02009019 {
9020 struct timex host_buf;
9021
9022 if (target_to_host_timex(&host_buf, arg1) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009023 return -TARGET_EFAULT;
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +02009024 }
9025 ret = get_errno(adjtimex(&host_buf));
9026 if (!is_error(ret)) {
9027 if (host_to_target_timex(arg1, &host_buf) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009028 return -TARGET_EFAULT;
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +02009029 }
9030 }
9031 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009032 return ret;
Aleksandar Markovic38860a02016-10-10 13:23:29 +02009033#if defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME)
9034 case TARGET_NR_clock_adjtime:
9035 {
9036 struct timex htx, *phtx = &htx;
9037
9038 if (target_to_host_timex(phtx, arg2) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009039 return -TARGET_EFAULT;
Aleksandar Markovic38860a02016-10-10 13:23:29 +02009040 }
9041 ret = get_errno(clock_adjtime(arg1, phtx));
9042 if (!is_error(ret) && phtx) {
9043 if (host_to_target_timex(arg2, phtx) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009044 return -TARGET_EFAULT;
Aleksandar Markovic38860a02016-10-10 13:23:29 +02009045 }
9046 }
9047 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009048 return ret;
Aleksandar Markovic38860a02016-10-10 13:23:29 +02009049#endif
bellard31e31b82003-02-18 22:55:36 +00009050 case TARGET_NR_getpgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009051 return get_errno(getpgid(arg1));
bellard31e31b82003-02-18 22:55:36 +00009052 case TARGET_NR_fchdir:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009053 return get_errno(fchdir(arg1));
bellard31e31b82003-02-18 22:55:36 +00009054 case TARGET_NR_personality:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009055 return get_errno(personality(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +00009056#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009057 case TARGET_NR__llseek:
9058 {
9059 int64_t res;
Peter Maydell0c1592d2011-02-22 13:02:26 +00009060#if !defined(__NR_llseek)
Peter Maydell9fea2732016-08-11 18:59:39 +01009061 res = lseek(arg1, ((uint64_t)arg2 << 32) | (abi_ulong)arg3, arg5);
Peter Maydell0c1592d2011-02-22 13:02:26 +00009062 if (res == -1) {
9063 ret = get_errno(res);
9064 } else {
9065 ret = 0;
9066 }
9067#else
bellard31e31b82003-02-18 22:55:36 +00009068 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard4f2ac232004-04-26 19:44:02 +00009069#endif
Peter Maydell0c1592d2011-02-22 13:02:26 +00009070 if ((ret == 0) && put_user_s64(res, arg4)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009071 return -TARGET_EFAULT;
Peter Maydell0c1592d2011-02-22 13:02:26 +00009072 }
bellard31e31b82003-02-18 22:55:36 +00009073 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009074 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00009075#endif
Chen Gang704eff62015-08-21 05:37:33 +08009076#ifdef TARGET_NR_getdents
bellard31e31b82003-02-18 22:55:36 +00009077 case TARGET_NR_getdents:
Peter Maydell2b3f64c2018-04-19 13:57:40 +01009078#ifdef EMULATE_GETDENTS_WITH_GETDENTS
Ulrich Hechtd83c8732009-07-24 19:10:28 +02009079#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
bellard4add45b2003-06-05 01:52:59 +00009080 {
pbrook53a59602006-03-25 19:31:22 +00009081 struct target_dirent *target_dirp;
aurel326556a832008-10-13 21:08:17 +00009082 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00009083 abi_long count = arg3;
bellard4add45b2003-06-05 01:52:59 +00009084
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05309085 dirp = g_try_malloc(count);
9086 if (!dirp) {
Richard Henderson259841c2018-08-18 12:01:09 -07009087 return -TARGET_ENOMEM;
ths0da46a62007-10-20 20:23:07 +00009088 }
ths3b46e622007-09-17 08:09:54 +00009089
bellard4add45b2003-06-05 01:52:59 +00009090 ret = get_errno(sys_getdents(arg1, dirp, count));
9091 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00009092 struct linux_dirent *de;
bellard4add45b2003-06-05 01:52:59 +00009093 struct target_dirent *tde;
9094 int len = ret;
9095 int reclen, treclen;
9096 int count1, tnamelen;
9097
9098 count1 = 0;
9099 de = dirp;
bellard579a97f2007-11-11 14:26:47 +00009100 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009101 return -TARGET_EFAULT;
bellard4add45b2003-06-05 01:52:59 +00009102 tde = target_dirp;
9103 while (len > 0) {
9104 reclen = de->d_reclen;
Dmitry V. Levin333858b2012-08-21 02:13:12 +04009105 tnamelen = reclen - offsetof(struct linux_dirent, d_name);
9106 assert(tnamelen >= 0);
9107 treclen = tnamelen + offsetof(struct target_dirent, d_name);
9108 assert(count1 + treclen <= count);
bellard4add45b2003-06-05 01:52:59 +00009109 tde->d_reclen = tswap16(treclen);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02009110 tde->d_ino = tswapal(de->d_ino);
9111 tde->d_off = tswapal(de->d_off);
Dmitry V. Levin333858b2012-08-21 02:13:12 +04009112 memcpy(tde->d_name, de->d_name, tnamelen);
aurel326556a832008-10-13 21:08:17 +00009113 de = (struct linux_dirent *)((char *)de + reclen);
bellard4add45b2003-06-05 01:52:59 +00009114 len -= reclen;
j_mayer1c5bf3b2007-04-14 12:17:59 +00009115 tde = (struct target_dirent *)((char *)tde + treclen);
bellard4add45b2003-06-05 01:52:59 +00009116 count1 += treclen;
9117 }
9118 ret = count1;
bellard579a97f2007-11-11 14:26:47 +00009119 unlock_user(target_dirp, arg2, ret);
bellard4add45b2003-06-05 01:52:59 +00009120 }
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05309121 g_free(dirp);
bellard4add45b2003-06-05 01:52:59 +00009122 }
9123#else
bellard31e31b82003-02-18 22:55:36 +00009124 {
aurel326556a832008-10-13 21:08:17 +00009125 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00009126 abi_long count = arg3;
bellarddab2ed92003-03-22 15:23:14 +00009127
bellard579a97f2007-11-11 14:26:47 +00009128 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009129 return -TARGET_EFAULT;
bellard72f03902003-02-18 23:33:18 +00009130 ret = get_errno(sys_getdents(arg1, dirp, count));
bellard31e31b82003-02-18 22:55:36 +00009131 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00009132 struct linux_dirent *de;
bellard31e31b82003-02-18 22:55:36 +00009133 int len = ret;
9134 int reclen;
9135 de = dirp;
9136 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00009137 reclen = de->d_reclen;
bellard31e31b82003-02-18 22:55:36 +00009138 if (reclen > len)
9139 break;
bellard8083a3e2003-03-24 23:12:16 +00009140 de->d_reclen = tswap16(reclen);
bellard31e31b82003-02-18 22:55:36 +00009141 tswapls(&de->d_ino);
9142 tswapls(&de->d_off);
aurel326556a832008-10-13 21:08:17 +00009143 de = (struct linux_dirent *)((char *)de + reclen);
bellard31e31b82003-02-18 22:55:36 +00009144 len -= reclen;
9145 }
9146 }
pbrook53a59602006-03-25 19:31:22 +00009147 unlock_user(dirp, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00009148 }
bellard4add45b2003-06-05 01:52:59 +00009149#endif
Peter Maydell3307e232013-06-12 16:20:21 +01009150#else
9151 /* Implement getdents in terms of getdents64 */
9152 {
9153 struct linux_dirent64 *dirp;
9154 abi_long count = arg3;
9155
9156 dirp = lock_user(VERIFY_WRITE, arg2, count, 0);
9157 if (!dirp) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009158 return -TARGET_EFAULT;
Peter Maydell3307e232013-06-12 16:20:21 +01009159 }
9160 ret = get_errno(sys_getdents64(arg1, dirp, count));
9161 if (!is_error(ret)) {
9162 /* Convert the dirent64 structs to target dirent. We do this
9163 * in-place, since we can guarantee that a target_dirent is no
9164 * larger than a dirent64; however this means we have to be
9165 * careful to read everything before writing in the new format.
9166 */
9167 struct linux_dirent64 *de;
9168 struct target_dirent *tde;
9169 int len = ret;
9170 int tlen = 0;
9171
9172 de = dirp;
9173 tde = (struct target_dirent *)dirp;
9174 while (len > 0) {
9175 int namelen, treclen;
9176 int reclen = de->d_reclen;
9177 uint64_t ino = de->d_ino;
9178 int64_t off = de->d_off;
9179 uint8_t type = de->d_type;
9180
9181 namelen = strlen(de->d_name);
9182 treclen = offsetof(struct target_dirent, d_name)
9183 + namelen + 2;
9184 treclen = QEMU_ALIGN_UP(treclen, sizeof(abi_long));
9185
9186 memmove(tde->d_name, de->d_name, namelen + 1);
9187 tde->d_ino = tswapal(ino);
9188 tde->d_off = tswapal(off);
9189 tde->d_reclen = tswap16(treclen);
9190 /* The target_dirent type is in what was formerly a padding
9191 * byte at the end of the structure:
9192 */
9193 *(((char *)tde) + treclen - 1) = type;
9194
9195 de = (struct linux_dirent64 *)((char *)de + reclen);
9196 tde = (struct target_dirent *)((char *)tde + treclen);
9197 len -= reclen;
9198 tlen += treclen;
9199 }
9200 ret = tlen;
9201 }
9202 unlock_user(dirp, arg2, ret);
9203 }
9204#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009205 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009206#endif /* TARGET_NR_getdents */
ths3ae43202007-09-16 21:39:48 +00009207#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +00009208 case TARGET_NR_getdents64:
9209 {
aurel326556a832008-10-13 21:08:17 +00009210 struct linux_dirent64 *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00009211 abi_long count = arg3;
bellard579a97f2007-11-11 14:26:47 +00009212 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009213 return -TARGET_EFAULT;
bellarddab2ed92003-03-22 15:23:14 +00009214 ret = get_errno(sys_getdents64(arg1, dirp, count));
9215 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00009216 struct linux_dirent64 *de;
bellarddab2ed92003-03-22 15:23:14 +00009217 int len = ret;
9218 int reclen;
9219 de = dirp;
9220 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00009221 reclen = de->d_reclen;
bellarddab2ed92003-03-22 15:23:14 +00009222 if (reclen > len)
9223 break;
bellard8083a3e2003-03-24 23:12:16 +00009224 de->d_reclen = tswap16(reclen);
bellard8582a532007-11-11 23:11:36 +00009225 tswap64s((uint64_t *)&de->d_ino);
9226 tswap64s((uint64_t *)&de->d_off);
aurel326556a832008-10-13 21:08:17 +00009227 de = (struct linux_dirent64 *)((char *)de + reclen);
bellarddab2ed92003-03-22 15:23:14 +00009228 len -= reclen;
9229 }
9230 }
pbrook53a59602006-03-25 19:31:22 +00009231 unlock_user(dirp, arg2, ret);
bellarddab2ed92003-03-22 15:23:14 +00009232 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009233 return ret;
bellarda541f292004-04-12 20:39:29 +00009234#endif /* TARGET_NR_getdents64 */
Laurent Vivier9468a5d2013-01-10 22:30:50 +01009235#if defined(TARGET_NR__newselect)
bellard31e31b82003-02-18 22:55:36 +00009236 case TARGET_NR__newselect:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009237 return do_select(arg1, arg2, arg3, arg4, arg5);
thse5febef2007-04-01 18:31:35 +00009238#endif
Mike Frysingerd8035d42011-02-07 01:05:51 -05009239#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll)
9240# ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +00009241 case TARGET_NR_poll:
Mike Frysingerd8035d42011-02-07 01:05:51 -05009242# endif
9243# ifdef TARGET_NR_ppoll
9244 case TARGET_NR_ppoll:
9245# endif
bellard9de5e442003-03-23 16:49:39 +00009246 {
pbrook53a59602006-03-25 19:31:22 +00009247 struct target_pollfd *target_pfd;
bellard9de5e442003-03-23 16:49:39 +00009248 unsigned int nfds = arg2;
bellard9de5e442003-03-23 16:49:39 +00009249 struct pollfd *pfd;
bellard7854b052003-03-29 17:22:23 +00009250 unsigned int i;
bellard9de5e442003-03-23 16:49:39 +00009251
Laurent Vivier3e24bb32015-10-06 01:20:48 +02009252 pfd = NULL;
9253 target_pfd = NULL;
9254 if (nfds) {
Peter Maydellce9c1392016-07-18 16:30:36 +01009255 if (nfds > (INT_MAX / sizeof(struct target_pollfd))) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009256 return -TARGET_EINVAL;
Peter Maydellce9c1392016-07-18 16:30:36 +01009257 }
9258
Laurent Vivier3e24bb32015-10-06 01:20:48 +02009259 target_pfd = lock_user(VERIFY_WRITE, arg1,
9260 sizeof(struct target_pollfd) * nfds, 1);
9261 if (!target_pfd) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009262 return -TARGET_EFAULT;
Laurent Vivier3e24bb32015-10-06 01:20:48 +02009263 }
Mike Frysingerd8035d42011-02-07 01:05:51 -05009264
Laurent Vivier3e24bb32015-10-06 01:20:48 +02009265 pfd = alloca(sizeof(struct pollfd) * nfds);
9266 for (i = 0; i < nfds; i++) {
9267 pfd[i].fd = tswap32(target_pfd[i].fd);
9268 pfd[i].events = tswap16(target_pfd[i].events);
9269 }
bellard9de5e442003-03-23 16:49:39 +00009270 }
Mike Frysingerd8035d42011-02-07 01:05:51 -05009271
Peter Maydella6130232016-06-06 19:58:10 +01009272 switch (num) {
Mike Frysingerd8035d42011-02-07 01:05:51 -05009273# ifdef TARGET_NR_ppoll
Peter Maydella6130232016-06-06 19:58:10 +01009274 case TARGET_NR_ppoll:
9275 {
Mike Frysingerd8035d42011-02-07 01:05:51 -05009276 struct timespec _timeout_ts, *timeout_ts = &_timeout_ts;
9277 target_sigset_t *target_set;
9278 sigset_t _set, *set = &_set;
9279
9280 if (arg3) {
9281 if (target_to_host_timespec(timeout_ts, arg3)) {
9282 unlock_user(target_pfd, arg1, 0);
Richard Henderson2852aaf2018-08-18 12:01:06 -07009283 return -TARGET_EFAULT;
Mike Frysingerd8035d42011-02-07 01:05:51 -05009284 }
9285 } else {
9286 timeout_ts = NULL;
9287 }
9288
9289 if (arg4) {
Peter Maydellc8157012016-06-30 14:23:24 +01009290 if (arg5 != sizeof(target_sigset_t)) {
9291 unlock_user(target_pfd, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009292 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01009293 }
9294
Mike Frysingerd8035d42011-02-07 01:05:51 -05009295 target_set = lock_user(VERIFY_READ, arg4, sizeof(target_sigset_t), 1);
9296 if (!target_set) {
9297 unlock_user(target_pfd, arg1, 0);
Richard Henderson2852aaf2018-08-18 12:01:06 -07009298 return -TARGET_EFAULT;
Mike Frysingerd8035d42011-02-07 01:05:51 -05009299 }
9300 target_to_host_sigset(set, target_set);
9301 } else {
9302 set = NULL;
9303 }
9304
Peter Maydella6130232016-06-06 19:58:10 +01009305 ret = get_errno(safe_ppoll(pfd, nfds, timeout_ts,
9306 set, SIGSET_T_SIZE));
Mike Frysingerd8035d42011-02-07 01:05:51 -05009307
9308 if (!is_error(ret) && arg3) {
9309 host_to_target_timespec(arg3, timeout_ts);
9310 }
9311 if (arg4) {
9312 unlock_user(target_set, arg4, 0);
9313 }
Peter Maydella6130232016-06-06 19:58:10 +01009314 break;
9315 }
Mike Frysingerd8035d42011-02-07 01:05:51 -05009316# endif
Peter Maydella6130232016-06-06 19:58:10 +01009317# ifdef TARGET_NR_poll
9318 case TARGET_NR_poll:
9319 {
9320 struct timespec ts, *pts;
9321
9322 if (arg3 >= 0) {
9323 /* Convert ms to secs, ns */
9324 ts.tv_sec = arg3 / 1000;
9325 ts.tv_nsec = (arg3 % 1000) * 1000000LL;
9326 pts = &ts;
9327 } else {
9328 /* -ve poll() timeout means "infinite" */
9329 pts = NULL;
9330 }
9331 ret = get_errno(safe_ppoll(pfd, nfds, pts, NULL, 0));
9332 break;
9333 }
9334# endif
9335 default:
9336 g_assert_not_reached();
9337 }
Mike Frysingerd8035d42011-02-07 01:05:51 -05009338
bellard9de5e442003-03-23 16:49:39 +00009339 if (!is_error(ret)) {
9340 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00009341 target_pfd[i].revents = tswap16(pfd[i].revents);
bellard9de5e442003-03-23 16:49:39 +00009342 }
9343 }
Peter Maydell30cb4cd2011-02-25 10:27:40 +00009344 unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds);
bellard9de5e442003-03-23 16:49:39 +00009345 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009346 return ret;
thse5febef2007-04-01 18:31:35 +00009347#endif
bellard31e31b82003-02-18 22:55:36 +00009348 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +00009349 /* NOTE: the flock constant seems to be the same for every
9350 Linux platform */
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009351 return get_errno(safe_flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00009352 case TARGET_NR_readv:
9353 {
Richard Hendersonf287b2c2012-09-15 13:20:25 -07009354 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
9355 if (vec != NULL) {
Peter Maydell918c03e2016-06-06 19:58:02 +01009356 ret = get_errno(safe_readv(arg1, vec, arg3));
Richard Hendersonf287b2c2012-09-15 13:20:25 -07009357 unlock_iovec(vec, arg2, arg3, 1);
9358 } else {
9359 ret = -host_to_target_errno(errno);
9360 }
bellard31e31b82003-02-18 22:55:36 +00009361 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009362 return ret;
bellard31e31b82003-02-18 22:55:36 +00009363 case TARGET_NR_writev:
9364 {
Richard Hendersonf287b2c2012-09-15 13:20:25 -07009365 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
9366 if (vec != NULL) {
Peter Maydell918c03e2016-06-06 19:58:02 +01009367 ret = get_errno(safe_writev(arg1, vec, arg3));
Richard Hendersonf287b2c2012-09-15 13:20:25 -07009368 unlock_iovec(vec, arg2, arg3, 0);
9369 } else {
9370 ret = -host_to_target_errno(errno);
9371 }
bellard31e31b82003-02-18 22:55:36 +00009372 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009373 return ret;
Dejan Jovicevic0f263862016-10-11 11:52:46 +02009374#if defined(TARGET_NR_preadv)
9375 case TARGET_NR_preadv:
9376 {
9377 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
9378 if (vec != NULL) {
Max Filippov9ac22512018-04-04 17:30:41 -07009379 unsigned long low, high;
9380
9381 target_to_host_low_high(arg4, arg5, &low, &high);
9382 ret = get_errno(safe_preadv(arg1, vec, arg3, low, high));
Dejan Jovicevic0f263862016-10-11 11:52:46 +02009383 unlock_iovec(vec, arg2, arg3, 1);
9384 } else {
9385 ret = -host_to_target_errno(errno);
9386 }
9387 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009388 return ret;
Dejan Jovicevic0f263862016-10-11 11:52:46 +02009389#endif
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +02009390#if defined(TARGET_NR_pwritev)
9391 case TARGET_NR_pwritev:
9392 {
9393 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
9394 if (vec != NULL) {
Max Filippov9ac22512018-04-04 17:30:41 -07009395 unsigned long low, high;
9396
9397 target_to_host_low_high(arg4, arg5, &low, &high);
9398 ret = get_errno(safe_pwritev(arg1, vec, arg3, low, high));
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +02009399 unlock_iovec(vec, arg2, arg3, 0);
9400 } else {
9401 ret = -host_to_target_errno(errno);
9402 }
9403 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009404 return ret;
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +02009405#endif
bellard31e31b82003-02-18 22:55:36 +00009406 case TARGET_NR_getsid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009407 return get_errno(getsid(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +00009408#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +00009409 case TARGET_NR_fdatasync:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009410 return get_errno(fdatasync(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +00009411#endif
Chen Gang704eff62015-08-21 05:37:33 +08009412#ifdef TARGET_NR__sysctl
bellard31e31b82003-02-18 22:55:36 +00009413 case TARGET_NR__sysctl:
ths0da46a62007-10-20 20:23:07 +00009414 /* We don't implement this, but ENOTDIR is always a safe
bellard29e619b2004-09-13 21:41:04 +00009415 return value. */
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009416 return -TARGET_ENOTDIR;
Chen Gang704eff62015-08-21 05:37:33 +08009417#endif
Mike Frysinger737de1d2011-02-07 01:05:55 -05009418 case TARGET_NR_sched_getaffinity:
9419 {
9420 unsigned int mask_size;
9421 unsigned long *mask;
9422
9423 /*
9424 * sched_getaffinity needs multiples of ulong, so need to take
9425 * care of mismatches between target ulong and host ulong sizes.
9426 */
9427 if (arg2 & (sizeof(abi_ulong) - 1)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009428 return -TARGET_EINVAL;
Mike Frysinger737de1d2011-02-07 01:05:55 -05009429 }
9430 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
9431
9432 mask = alloca(mask_size);
Samuel Thibault2e0a8712018-01-09 21:16:43 +01009433 memset(mask, 0, mask_size);
Mike Frysinger737de1d2011-02-07 01:05:55 -05009434 ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
9435
9436 if (!is_error(ret)) {
Peter Maydellbe3bd282014-05-15 14:40:23 +01009437 if (ret > arg2) {
9438 /* More data returned than the caller's buffer will fit.
9439 * This only happens if sizeof(abi_long) < sizeof(long)
9440 * and the caller passed us a buffer holding an odd number
9441 * of abi_longs. If the host kernel is actually using the
9442 * extra 4 bytes then fail EINVAL; otherwise we can just
9443 * ignore them and only copy the interesting part.
9444 */
9445 int numcpus = sysconf(_SC_NPROCESSORS_CONF);
9446 if (numcpus > arg2 * 8) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009447 return -TARGET_EINVAL;
Peter Maydellbe3bd282014-05-15 14:40:23 +01009448 }
9449 ret = arg2;
9450 }
9451
Samuel Thibault5fdefcf2018-02-11 18:47:04 +01009452 if (host_to_target_cpu_mask(mask, mask_size, arg3, ret)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009453 return -TARGET_EFAULT;
Samuel Thibault5fdefcf2018-02-11 18:47:04 +01009454 }
Mike Frysinger737de1d2011-02-07 01:05:55 -05009455 }
9456 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009457 return ret;
Mike Frysinger737de1d2011-02-07 01:05:55 -05009458 case TARGET_NR_sched_setaffinity:
9459 {
9460 unsigned int mask_size;
9461 unsigned long *mask;
9462
9463 /*
9464 * sched_setaffinity needs multiples of ulong, so need to take
9465 * care of mismatches between target ulong and host ulong sizes.
9466 */
9467 if (arg2 & (sizeof(abi_ulong) - 1)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009468 return -TARGET_EINVAL;
Mike Frysinger737de1d2011-02-07 01:05:55 -05009469 }
9470 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
Mike Frysinger737de1d2011-02-07 01:05:55 -05009471 mask = alloca(mask_size);
Samuel Thibault2e0a8712018-01-09 21:16:43 +01009472
9473 ret = target_to_host_cpu_mask(mask, mask_size, arg3, arg2);
9474 if (ret) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009475 return ret;
Mike Frysinger737de1d2011-02-07 01:05:55 -05009476 }
Mike Frysinger737de1d2011-02-07 01:05:55 -05009477
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009478 return get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
Mike Frysinger737de1d2011-02-07 01:05:55 -05009479 }
Samuel Thibaultb827c3e2018-01-12 09:14:35 +01009480 case TARGET_NR_getcpu:
9481 {
9482 unsigned cpu, node;
9483 ret = get_errno(sys_getcpu(arg1 ? &cpu : NULL,
9484 arg2 ? &node : NULL,
9485 NULL));
9486 if (is_error(ret)) {
Richard Henderson259841c2018-08-18 12:01:09 -07009487 return ret;
Samuel Thibaultb827c3e2018-01-12 09:14:35 +01009488 }
9489 if (arg1 && put_user_u32(cpu, arg1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009490 return -TARGET_EFAULT;
Samuel Thibaultb827c3e2018-01-12 09:14:35 +01009491 }
9492 if (arg2 && put_user_u32(node, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009493 return -TARGET_EFAULT;
Samuel Thibaultb827c3e2018-01-12 09:14:35 +01009494 }
9495 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009496 return ret;
bellard31e31b82003-02-18 22:55:36 +00009497 case TARGET_NR_sched_setparam:
bellard5cd43932003-03-29 16:54:36 +00009498 {
pbrook53a59602006-03-25 19:31:22 +00009499 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00009500 struct sched_param schp;
pbrook53a59602006-03-25 19:31:22 +00009501
Tom Mustaa1d5c5b2014-08-12 13:53:38 -05009502 if (arg2 == 0) {
9503 return -TARGET_EINVAL;
9504 }
bellard579a97f2007-11-11 14:26:47 +00009505 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009506 return -TARGET_EFAULT;
bellard5cd43932003-03-29 16:54:36 +00009507 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00009508 unlock_user_struct(target_schp, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009509 return get_errno(sched_setparam(arg1, &schp));
bellard5cd43932003-03-29 16:54:36 +00009510 }
bellard31e31b82003-02-18 22:55:36 +00009511 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +00009512 {
pbrook53a59602006-03-25 19:31:22 +00009513 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00009514 struct sched_param schp;
Tom Mustaa1d5c5b2014-08-12 13:53:38 -05009515
9516 if (arg2 == 0) {
9517 return -TARGET_EINVAL;
9518 }
bellard5cd43932003-03-29 16:54:36 +00009519 ret = get_errno(sched_getparam(arg1, &schp));
9520 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00009521 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009522 return -TARGET_EFAULT;
bellard5cd43932003-03-29 16:54:36 +00009523 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +00009524 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +00009525 }
9526 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009527 return ret;
bellard31e31b82003-02-18 22:55:36 +00009528 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +00009529 {
pbrook53a59602006-03-25 19:31:22 +00009530 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00009531 struct sched_param schp;
Tom Mustaa1d5c5b2014-08-12 13:53:38 -05009532 if (arg3 == 0) {
9533 return -TARGET_EINVAL;
9534 }
bellard579a97f2007-11-11 14:26:47 +00009535 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009536 return -TARGET_EFAULT;
bellard5cd43932003-03-29 16:54:36 +00009537 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00009538 unlock_user_struct(target_schp, arg3, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009539 return get_errno(sched_setscheduler(arg1, arg2, &schp));
bellard5cd43932003-03-29 16:54:36 +00009540 }
bellard31e31b82003-02-18 22:55:36 +00009541 case TARGET_NR_sched_getscheduler:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009542 return get_errno(sched_getscheduler(arg1));
bellard31e31b82003-02-18 22:55:36 +00009543 case TARGET_NR_sched_yield:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009544 return get_errno(sched_yield());
bellard31e31b82003-02-18 22:55:36 +00009545 case TARGET_NR_sched_get_priority_max:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009546 return get_errno(sched_get_priority_max(arg1));
bellard31e31b82003-02-18 22:55:36 +00009547 case TARGET_NR_sched_get_priority_min:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009548 return get_errno(sched_get_priority_min(arg1));
bellard31e31b82003-02-18 22:55:36 +00009549 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +00009550 {
bellard5cd43932003-03-29 16:54:36 +00009551 struct timespec ts;
9552 ret = get_errno(sched_rr_get_interval(arg1, &ts));
9553 if (!is_error(ret)) {
Tom Mustad4290c42014-08-12 13:53:39 -05009554 ret = host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +00009555 }
9556 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009557 return ret;
bellard31e31b82003-02-18 22:55:36 +00009558 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +00009559 {
bellard1b6b0292003-03-22 17:31:38 +00009560 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +00009561 target_to_host_timespec(&req, arg1);
Peter Maydell9e518222016-06-06 19:58:09 +01009562 ret = get_errno(safe_nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +00009563 if (is_error(ret) && arg2) {
9564 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +00009565 }
9566 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009567 return ret;
bellard31e31b82003-02-18 22:55:36 +00009568 case TARGET_NR_prctl:
Peter Maydell1e6722f2012-02-03 14:48:03 +00009569 switch (arg1) {
9570 case PR_GET_PDEATHSIG:
9571 {
9572 int deathsig;
9573 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
9574 if (!is_error(ret) && arg2
9575 && put_user_ual(deathsig, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009576 return -TARGET_EFAULT;
thse5574482007-02-11 20:03:13 +00009577 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009578 return ret;
Peter Maydell1e6722f2012-02-03 14:48:03 +00009579 }
Peter Maydelldb9526b2012-02-03 14:48:03 +00009580#ifdef PR_GET_NAME
9581 case PR_GET_NAME:
9582 {
9583 void *name = lock_user(VERIFY_WRITE, arg2, 16, 1);
9584 if (!name) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009585 return -TARGET_EFAULT;
Peter Maydelldb9526b2012-02-03 14:48:03 +00009586 }
9587 ret = get_errno(prctl(arg1, (unsigned long)name,
9588 arg3, arg4, arg5));
9589 unlock_user(name, arg2, 16);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009590 return ret;
Peter Maydelldb9526b2012-02-03 14:48:03 +00009591 }
9592 case PR_SET_NAME:
9593 {
9594 void *name = lock_user(VERIFY_READ, arg2, 16, 1);
9595 if (!name) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009596 return -TARGET_EFAULT;
Peter Maydelldb9526b2012-02-03 14:48:03 +00009597 }
9598 ret = get_errno(prctl(arg1, (unsigned long)name,
9599 arg3, arg4, arg5));
9600 unlock_user(name, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009601 return ret;
Peter Maydelldb9526b2012-02-03 14:48:03 +00009602 }
9603#endif
Stefan Markovic5b702ff2018-10-12 12:57:35 +02009604#ifdef TARGET_MIPS
9605 case TARGET_PR_GET_FP_MODE:
Stefan Markovic64ea3d62018-10-26 13:17:43 +02009606 {
9607 CPUMIPSState *env = ((CPUMIPSState *)cpu_env);
9608 ret = 0;
9609 if (env->CP0_Status & (1 << CP0St_FR)) {
9610 ret |= TARGET_PR_FP_MODE_FR;
9611 }
9612 if (env->CP0_Config5 & (1 << CP0C5_FRE)) {
9613 ret |= TARGET_PR_FP_MODE_FRE;
9614 }
9615 return ret;
9616 }
Stefan Markovic5b702ff2018-10-12 12:57:35 +02009617 case TARGET_PR_SET_FP_MODE:
Stefan Markovic64ea3d62018-10-26 13:17:43 +02009618 {
9619 CPUMIPSState *env = ((CPUMIPSState *)cpu_env);
9620 bool old_fr = env->CP0_Status & (1 << CP0St_FR);
Stefan Markovic6456c512018-11-14 14:37:08 +01009621 bool old_fre = env->CP0_Config5 & (1 << CP0C5_FRE);
Stefan Markovic64ea3d62018-10-26 13:17:43 +02009622 bool new_fr = arg2 & TARGET_PR_FP_MODE_FR;
9623 bool new_fre = arg2 & TARGET_PR_FP_MODE_FRE;
9624
Stefan Markovic6456c512018-11-14 14:37:08 +01009625 const unsigned int known_bits = TARGET_PR_FP_MODE_FR |
9626 TARGET_PR_FP_MODE_FRE;
9627
9628 /* If nothing to change, return right away, successfully. */
9629 if (old_fr == new_fr && old_fre == new_fre) {
9630 return 0;
9631 }
9632 /* Check the value is valid */
9633 if (arg2 & ~known_bits) {
9634 return -TARGET_EOPNOTSUPP;
9635 }
9636 /* Setting FRE without FR is not supported. */
9637 if (new_fre && !new_fr) {
9638 return -TARGET_EOPNOTSUPP;
9639 }
Stefan Markovic64ea3d62018-10-26 13:17:43 +02009640 if (new_fr && !(env->active_fpu.fcr0 & (1 << FCR0_F64))) {
9641 /* FR1 is not supported */
9642 return -TARGET_EOPNOTSUPP;
9643 }
9644 if (!new_fr && (env->active_fpu.fcr0 & (1 << FCR0_F64))
9645 && !(env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
9646 /* cannot set FR=0 */
9647 return -TARGET_EOPNOTSUPP;
9648 }
9649 if (new_fre && !(env->active_fpu.fcr0 & (1 << FCR0_FREP))) {
9650 /* Cannot set FRE=1 */
9651 return -TARGET_EOPNOTSUPP;
9652 }
9653
9654 int i;
9655 fpr_t *fpr = env->active_fpu.fpr;
9656 for (i = 0; i < 32 ; i += 2) {
9657 if (!old_fr && new_fr) {
9658 fpr[i].w[!FP_ENDIAN_IDX] = fpr[i + 1].w[FP_ENDIAN_IDX];
9659 } else if (old_fr && !new_fr) {
9660 fpr[i + 1].w[FP_ENDIAN_IDX] = fpr[i].w[!FP_ENDIAN_IDX];
9661 }
9662 }
9663
9664 if (new_fr) {
9665 env->CP0_Status |= (1 << CP0St_FR);
9666 env->hflags |= MIPS_HFLAG_F64;
9667 } else {
9668 env->CP0_Status &= ~(1 << CP0St_FR);
Stefan Markovic6456c512018-11-14 14:37:08 +01009669 env->hflags &= ~MIPS_HFLAG_F64;
Stefan Markovic64ea3d62018-10-26 13:17:43 +02009670 }
9671 if (new_fre) {
9672 env->CP0_Config5 |= (1 << CP0C5_FRE);
9673 if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
9674 env->hflags |= MIPS_HFLAG_FRE;
9675 }
9676 } else {
9677 env->CP0_Config5 &= ~(1 << CP0C5_FRE);
Stefan Markovic6456c512018-11-14 14:37:08 +01009678 env->hflags &= ~MIPS_HFLAG_FRE;
Stefan Markovic64ea3d62018-10-26 13:17:43 +02009679 }
9680
9681 return 0;
9682 }
Stefan Markovic5b702ff2018-10-12 12:57:35 +02009683#endif /* MIPS */
Richard Henderson85fc7162018-03-09 17:09:43 +00009684#ifdef TARGET_AARCH64
9685 case TARGET_PR_SVE_SET_VL:
Richard Hendersonadf92ea2018-08-16 14:05:28 +01009686 /*
9687 * We cannot support either PR_SVE_SET_VL_ONEXEC or
9688 * PR_SVE_VL_INHERIT. Note the kernel definition
9689 * of sve_vl_valid allows for VQ=512, i.e. VL=8192,
9690 * even though the current architectural maximum is VQ=16.
9691 */
Richard Henderson85fc7162018-03-09 17:09:43 +00009692 ret = -TARGET_EINVAL;
Richard Hendersoncd208a12018-10-24 07:50:17 +01009693 if (cpu_isar_feature(aa64_sve, arm_env_get_cpu(cpu_env))
Richard Hendersonadf92ea2018-08-16 14:05:28 +01009694 && arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
Richard Henderson85fc7162018-03-09 17:09:43 +00009695 CPUARMState *env = cpu_env;
Richard Hendersonadf92ea2018-08-16 14:05:28 +01009696 ARMCPU *cpu = arm_env_get_cpu(env);
9697 uint32_t vq, old_vq;
9698
9699 old_vq = (env->vfp.zcr_el[1] & 0xf) + 1;
9700 vq = MAX(arg2 / 16, 1);
9701 vq = MIN(vq, cpu->sve_max_vq);
Richard Henderson85fc7162018-03-09 17:09:43 +00009702
9703 if (vq < old_vq) {
9704 aarch64_sve_narrow_vq(env, vq);
9705 }
9706 env->vfp.zcr_el[1] = vq - 1;
9707 ret = vq * 16;
9708 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009709 return ret;
Richard Henderson85fc7162018-03-09 17:09:43 +00009710 case TARGET_PR_SVE_GET_VL:
9711 ret = -TARGET_EINVAL;
Richard Hendersoncd208a12018-10-24 07:50:17 +01009712 {
9713 ARMCPU *cpu = arm_env_get_cpu(cpu_env);
9714 if (cpu_isar_feature(aa64_sve, cpu)) {
9715 ret = ((cpu->env.vfp.zcr_el[1] & 0xf) + 1) * 16;
9716 }
Richard Henderson85fc7162018-03-09 17:09:43 +00009717 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009718 return ret;
Richard Hendersonbff63fb2019-02-05 16:52:39 +00009719 case TARGET_PR_PAC_RESET_KEYS:
9720 {
9721 CPUARMState *env = cpu_env;
9722 ARMCPU *cpu = arm_env_get_cpu(env);
9723
9724 if (arg3 || arg4 || arg5) {
9725 return -TARGET_EINVAL;
9726 }
9727 if (cpu_isar_feature(aa64_pauth, cpu)) {
9728 int all = (TARGET_PR_PAC_APIAKEY | TARGET_PR_PAC_APIBKEY |
9729 TARGET_PR_PAC_APDAKEY | TARGET_PR_PAC_APDBKEY |
9730 TARGET_PR_PAC_APGAKEY);
9731 if (arg2 == 0) {
9732 arg2 = all;
9733 } else if (arg2 & ~all) {
9734 return -TARGET_EINVAL;
9735 }
9736 if (arg2 & TARGET_PR_PAC_APIAKEY) {
9737 arm_init_pauth_key(&env->apia_key);
9738 }
9739 if (arg2 & TARGET_PR_PAC_APIBKEY) {
9740 arm_init_pauth_key(&env->apib_key);
9741 }
9742 if (arg2 & TARGET_PR_PAC_APDAKEY) {
9743 arm_init_pauth_key(&env->apda_key);
9744 }
9745 if (arg2 & TARGET_PR_PAC_APDBKEY) {
9746 arm_init_pauth_key(&env->apdb_key);
9747 }
9748 if (arg2 & TARGET_PR_PAC_APGAKEY) {
9749 arm_init_pauth_key(&env->apga_key);
9750 }
9751 return 0;
9752 }
9753 }
9754 return -TARGET_EINVAL;
Richard Henderson85fc7162018-03-09 17:09:43 +00009755#endif /* AARCH64 */
James Cowgilla8b154a2017-11-06 18:03:51 +00009756 case PR_GET_SECCOMP:
9757 case PR_SET_SECCOMP:
9758 /* Disable seccomp to prevent the target disabling syscalls we
9759 * need. */
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009760 return -TARGET_EINVAL;
Peter Maydell1e6722f2012-02-03 14:48:03 +00009761 default:
9762 /* Most prctl options have no pointer arguments */
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009763 return get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
Peter Maydell1e6722f2012-02-03 14:48:03 +00009764 }
ths39b9aae2007-02-11 18:36:44 +00009765 break;
bellardd2fd1af2007-11-14 18:08:56 +00009766#ifdef TARGET_NR_arch_prctl
9767 case TARGET_NR_arch_prctl:
9768#if defined(TARGET_I386) && !defined(TARGET_ABI32)
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009769 return do_arch_prctl(cpu_env, arg1, arg2);
bellardd2fd1af2007-11-14 18:08:56 +00009770#else
Richard Henderson1a7b2b12018-08-18 12:01:08 -07009771#error unreachable
bellardd2fd1af2007-11-14 18:08:56 +00009772#endif
9773#endif
aurel32f2c7ba12008-03-28 22:32:06 +00009774#ifdef TARGET_NR_pread64
9775 case TARGET_NR_pread64:
James Clarke8bf8e9d2017-09-15 20:33:13 +01009776 if (regpairs_aligned(cpu_env, num)) {
Alexander Grafae017a52012-09-29 15:32:39 +00009777 arg4 = arg5;
9778 arg5 = arg6;
9779 }
Peter Maydell2bd3f892019-01-08 18:49:00 +00009780 if (arg2 == 0 && arg3 == 0) {
9781 /* Special-case NULL buffer and zero length, which should succeed */
9782 p = 0;
9783 } else {
9784 p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
9785 if (!p) {
9786 return -TARGET_EFAULT;
9787 }
9788 }
aurel32f2c7ba12008-03-28 22:32:06 +00009789 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
9790 unlock_user(p, arg2, ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009791 return ret;
aurel32f2c7ba12008-03-28 22:32:06 +00009792 case TARGET_NR_pwrite64:
James Clarke8bf8e9d2017-09-15 20:33:13 +01009793 if (regpairs_aligned(cpu_env, num)) {
Alexander Grafae017a52012-09-29 15:32:39 +00009794 arg4 = arg5;
9795 arg5 = arg6;
9796 }
Peter Maydell2bd3f892019-01-08 18:49:00 +00009797 if (arg2 == 0 && arg3 == 0) {
9798 /* Special-case NULL buffer and zero length, which should succeed */
9799 p = 0;
9800 } else {
9801 p = lock_user(VERIFY_READ, arg2, arg3, 1);
9802 if (!p) {
9803 return -TARGET_EFAULT;
9804 }
9805 }
aurel32f2c7ba12008-03-28 22:32:06 +00009806 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
9807 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009808 return ret;
aurel32f2c7ba12008-03-28 22:32:06 +00009809#endif
bellard31e31b82003-02-18 22:55:36 +00009810 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +00009811 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009812 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009813 ret = get_errno(sys_getcwd1(p, arg2));
9814 unlock_user(p, arg1, ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009815 return ret;
bellard31e31b82003-02-18 22:55:36 +00009816 case TARGET_NR_capget:
9817 case TARGET_NR_capset:
Peter Maydelle0eb2102014-03-17 12:15:35 +00009818 {
9819 struct target_user_cap_header *target_header;
9820 struct target_user_cap_data *target_data = NULL;
9821 struct __user_cap_header_struct header;
9822 struct __user_cap_data_struct data[2];
9823 struct __user_cap_data_struct *dataptr = NULL;
9824 int i, target_datalen;
9825 int data_items = 1;
9826
9827 if (!lock_user_struct(VERIFY_WRITE, target_header, arg1, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009828 return -TARGET_EFAULT;
Peter Maydelle0eb2102014-03-17 12:15:35 +00009829 }
9830 header.version = tswap32(target_header->version);
9831 header.pid = tswap32(target_header->pid);
9832
Peter Maydellec864872014-03-19 16:07:30 +00009833 if (header.version != _LINUX_CAPABILITY_VERSION) {
Peter Maydelle0eb2102014-03-17 12:15:35 +00009834 /* Version 2 and up takes pointer to two user_data structs */
9835 data_items = 2;
9836 }
9837
9838 target_datalen = sizeof(*target_data) * data_items;
9839
9840 if (arg2) {
9841 if (num == TARGET_NR_capget) {
9842 target_data = lock_user(VERIFY_WRITE, arg2, target_datalen, 0);
9843 } else {
9844 target_data = lock_user(VERIFY_READ, arg2, target_datalen, 1);
9845 }
9846 if (!target_data) {
9847 unlock_user_struct(target_header, arg1, 0);
Richard Henderson2852aaf2018-08-18 12:01:06 -07009848 return -TARGET_EFAULT;
Peter Maydelle0eb2102014-03-17 12:15:35 +00009849 }
9850
9851 if (num == TARGET_NR_capset) {
9852 for (i = 0; i < data_items; i++) {
9853 data[i].effective = tswap32(target_data[i].effective);
9854 data[i].permitted = tswap32(target_data[i].permitted);
9855 data[i].inheritable = tswap32(target_data[i].inheritable);
9856 }
9857 }
9858
9859 dataptr = data;
9860 }
9861
9862 if (num == TARGET_NR_capget) {
9863 ret = get_errno(capget(&header, dataptr));
9864 } else {
9865 ret = get_errno(capset(&header, dataptr));
9866 }
9867
9868 /* The kernel always updates version for both capget and capset */
9869 target_header->version = tswap32(header.version);
9870 unlock_user_struct(target_header, arg1, 1);
9871
9872 if (arg2) {
9873 if (num == TARGET_NR_capget) {
9874 for (i = 0; i < data_items; i++) {
9875 target_data[i].effective = tswap32(data[i].effective);
9876 target_data[i].permitted = tswap32(data[i].permitted);
9877 target_data[i].inheritable = tswap32(data[i].inheritable);
9878 }
9879 unlock_user(target_data, arg2, target_datalen);
9880 } else {
9881 unlock_user(target_data, arg2, 0);
9882 }
9883 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009884 return ret;
Peter Maydelle0eb2102014-03-17 12:15:35 +00009885 }
bellard31e31b82003-02-18 22:55:36 +00009886 case TARGET_NR_sigaltstack:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009887 return do_sigaltstack(arg1, arg2,
9888 get_sp_from_cpustate((CPUArchState *)cpu_env));
Peter Maydella8fd1ab2013-02-08 07:31:55 +00009889
9890#ifdef CONFIG_SENDFILE
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009891#ifdef TARGET_NR_sendfile
bellard31e31b82003-02-18 22:55:36 +00009892 case TARGET_NR_sendfile:
Peter Maydella8fd1ab2013-02-08 07:31:55 +00009893 {
9894 off_t *offp = NULL;
9895 off_t off;
9896 if (arg3) {
9897 ret = get_user_sal(off, arg3);
9898 if (is_error(ret)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009899 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +00009900 }
9901 offp = &off;
9902 }
9903 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
9904 if (!is_error(ret) && arg3) {
9905 abi_long ret2 = put_user_sal(off, arg3);
9906 if (is_error(ret2)) {
9907 ret = ret2;
9908 }
9909 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009910 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +00009911 }
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009912#endif
Peter Maydella8fd1ab2013-02-08 07:31:55 +00009913#ifdef TARGET_NR_sendfile64
9914 case TARGET_NR_sendfile64:
9915 {
9916 off_t *offp = NULL;
9917 off_t off;
9918 if (arg3) {
9919 ret = get_user_s64(off, arg3);
9920 if (is_error(ret)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009921 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +00009922 }
9923 offp = &off;
9924 }
9925 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
9926 if (!is_error(ret) && arg3) {
9927 abi_long ret2 = put_user_s64(off, arg3);
9928 if (is_error(ret2)) {
9929 ret = ret2;
9930 }
9931 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009932 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +00009933 }
9934#endif
bellardebc05482003-09-30 21:08:41 +00009935#endif
bellard048f6b42005-11-26 18:47:20 +00009936#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +00009937 case TARGET_NR_vfork:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009938 return get_errno(do_fork(cpu_env,
9939 CLONE_VFORK | CLONE_VM | TARGET_SIGCHLD,
9940 0, 0, 0, 0));
bellard048f6b42005-11-26 18:47:20 +00009941#endif
bellardebc05482003-09-30 21:08:41 +00009942#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +00009943 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +00009944 {
9945 struct rlimit rlim;
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03009946 int resource = target_to_host_resource(arg1);
9947 ret = get_errno(getrlimit(resource, &rlim));
bellard728584b2003-04-29 20:43:36 +00009948 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00009949 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +00009950 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009951 return -TARGET_EFAULT;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09009952 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
9953 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00009954 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +00009955 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009956 return ret;
bellard728584b2003-04-29 20:43:36 +00009957 }
bellardebc05482003-09-30 21:08:41 +00009958#endif
bellarda315a142005-01-30 22:59:18 +00009959#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +00009960 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +00009961 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009962 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009963 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
9964 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009965 return ret;
bellarda315a142005-01-30 22:59:18 +00009966#endif
9967#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +00009968 case TARGET_NR_ftruncate64:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009969 return target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellarda315a142005-01-30 22:59:18 +00009970#endif
9971#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +00009972 case TARGET_NR_stat64:
Richard Henderson2852aaf2018-08-18 12:01:06 -07009973 if (!(p = lock_user_string(arg1))) {
9974 return -TARGET_EFAULT;
9975 }
pbrook53a59602006-03-25 19:31:22 +00009976 ret = get_errno(stat(path(p), &st));
9977 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00009978 if (!is_error(ret))
9979 ret = host_to_target_stat64(cpu_env, arg2, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009980 return ret;
bellarda315a142005-01-30 22:59:18 +00009981#endif
9982#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +00009983 case TARGET_NR_lstat64:
Richard Henderson2852aaf2018-08-18 12:01:06 -07009984 if (!(p = lock_user_string(arg1))) {
9985 return -TARGET_EFAULT;
9986 }
pbrook53a59602006-03-25 19:31:22 +00009987 ret = get_errno(lstat(path(p), &st));
9988 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00009989 if (!is_error(ret))
9990 ret = host_to_target_stat64(cpu_env, arg2, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009991 return ret;
bellarda315a142005-01-30 22:59:18 +00009992#endif
9993#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +00009994 case TARGET_NR_fstat64:
balrog6a24a772008-09-20 02:23:36 +00009995 ret = get_errno(fstat(arg1, &st));
9996 if (!is_error(ret))
9997 ret = host_to_target_stat64(cpu_env, arg2, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009998 return ret;
bellardec86b0f2003-04-11 00:15:04 +00009999#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +010010000#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat))
aurel329d33b762009-04-08 23:07:05 +000010001#ifdef TARGET_NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +000010002 case TARGET_NR_fstatat64:
aurel329d33b762009-04-08 23:07:05 +000010003#endif
10004#ifdef TARGET_NR_newfstatat
10005 case TARGET_NR_newfstatat:
10006#endif
Richard Henderson2852aaf2018-08-18 12:01:06 -070010007 if (!(p = lock_user_string(arg2))) {
10008 return -TARGET_EFAULT;
10009 }
Peter Maydellc0d472b2013-06-12 16:20:21 +010010010 ret = get_errno(fstatat(arg1, path(p), &st, arg4));
Richard Henderson2852aaf2018-08-18 12:01:06 -070010011 unlock_user(p, arg2, 0);
balrog6a24a772008-09-20 02:23:36 +000010012 if (!is_error(ret))
10013 ret = host_to_target_stat64(cpu_env, arg3, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010014 return ret;
bellarda315a142005-01-30 22:59:18 +000010015#endif
Chen Gang704eff62015-08-21 05:37:33 +080010016#ifdef TARGET_NR_lchown
bellard67867302003-11-23 17:05:30 +000010017 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +000010018 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010019 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010020 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
10021 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010022 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080010023#endif
Riku Voipio0c866a72011-04-18 15:23:06 +030010024#ifdef TARGET_NR_getuid
bellard67867302003-11-23 17:05:30 +000010025 case TARGET_NR_getuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010026 return get_errno(high2lowuid(getuid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030010027#endif
10028#ifdef TARGET_NR_getgid
bellard67867302003-11-23 17:05:30 +000010029 case TARGET_NR_getgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010030 return get_errno(high2lowgid(getgid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030010031#endif
10032#ifdef TARGET_NR_geteuid
bellard67867302003-11-23 17:05:30 +000010033 case TARGET_NR_geteuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010034 return get_errno(high2lowuid(geteuid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030010035#endif
10036#ifdef TARGET_NR_getegid
bellard67867302003-11-23 17:05:30 +000010037 case TARGET_NR_getegid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010038 return get_errno(high2lowgid(getegid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030010039#endif
bellard67867302003-11-23 17:05:30 +000010040 case TARGET_NR_setreuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010041 return get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
bellard67867302003-11-23 17:05:30 +000010042 case TARGET_NR_setregid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010043 return get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
bellard67867302003-11-23 17:05:30 +000010044 case TARGET_NR_getgroups:
10045 {
10046 int gidsetsize = arg1;
Riku Voipio0c866a72011-04-18 15:23:06 +030010047 target_id *target_grouplist;
bellard67867302003-11-23 17:05:30 +000010048 gid_t *grouplist;
10049 int i;
10050
10051 grouplist = alloca(gidsetsize * sizeof(gid_t));
10052 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +000010053 if (gidsetsize == 0)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010054 return ret;
bellard67867302003-11-23 17:05:30 +000010055 if (!is_error(ret)) {
Andreas Schwab03903ff2013-04-09 05:41:33 +000010056 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * sizeof(target_id), 0);
bellard579a97f2007-11-11 14:26:47 +000010057 if (!target_grouplist)
Richard Henderson2852aaf2018-08-18 12:01:06 -070010058 return -TARGET_EFAULT;
balroga2155fc2008-09-20 02:12:08 +000010059 for(i = 0;i < ret; i++)
Riku Voipio0c866a72011-04-18 15:23:06 +030010060 target_grouplist[i] = tswapid(high2lowgid(grouplist[i]));
Andreas Schwab03903ff2013-04-09 05:41:33 +000010061 unlock_user(target_grouplist, arg2, gidsetsize * sizeof(target_id));
bellard67867302003-11-23 17:05:30 +000010062 }
10063 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010064 return ret;
bellard67867302003-11-23 17:05:30 +000010065 case TARGET_NR_setgroups:
10066 {
10067 int gidsetsize = arg1;
Riku Voipio0c866a72011-04-18 15:23:06 +030010068 target_id *target_grouplist;
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050010069 gid_t *grouplist = NULL;
bellard67867302003-11-23 17:05:30 +000010070 int i;
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050010071 if (gidsetsize) {
10072 grouplist = alloca(gidsetsize * sizeof(gid_t));
Andreas Schwab03903ff2013-04-09 05:41:33 +000010073 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * sizeof(target_id), 1);
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050010074 if (!target_grouplist) {
Richard Henderson259841c2018-08-18 12:01:09 -070010075 return -TARGET_EFAULT;
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050010076 }
10077 for (i = 0; i < gidsetsize; i++) {
10078 grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
10079 }
10080 unlock_user(target_grouplist, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +000010081 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010082 return get_errno(setgroups(gidsetsize, grouplist));
bellard67867302003-11-23 17:05:30 +000010083 }
bellard67867302003-11-23 17:05:30 +000010084 case TARGET_NR_fchown:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010085 return get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
Peter Maydellc0d472b2013-06-12 16:20:21 +010010086#if defined(TARGET_NR_fchownat)
thsccfa72b2007-09-24 09:23:34 +000010087 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +000010088 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010089 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +010010090 ret = get_errno(fchownat(arg1, p, low2highuid(arg3),
10091 low2highgid(arg4), arg5));
bellard579a97f2007-11-11 14:26:47 +000010092 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010093 return ret;
thsccfa72b2007-09-24 09:23:34 +000010094#endif
bellard67867302003-11-23 17:05:30 +000010095#ifdef TARGET_NR_setresuid
10096 case TARGET_NR_setresuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010097 return get_errno(sys_setresuid(low2highuid(arg1),
10098 low2highuid(arg2),
10099 low2highuid(arg3)));
bellard67867302003-11-23 17:05:30 +000010100#endif
10101#ifdef TARGET_NR_getresuid
10102 case TARGET_NR_getresuid:
10103 {
pbrook53a59602006-03-25 19:31:22 +000010104 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +000010105 ret = get_errno(getresuid(&ruid, &euid, &suid));
10106 if (!is_error(ret)) {
Peter Maydell76ca3102014-03-02 19:36:41 +000010107 if (put_user_id(high2lowuid(ruid), arg1)
10108 || put_user_id(high2lowuid(euid), arg2)
10109 || put_user_id(high2lowuid(suid), arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010110 return -TARGET_EFAULT;
bellard67867302003-11-23 17:05:30 +000010111 }
10112 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010113 return ret;
bellard67867302003-11-23 17:05:30 +000010114#endif
10115#ifdef TARGET_NR_getresgid
10116 case TARGET_NR_setresgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010117 return get_errno(sys_setresgid(low2highgid(arg1),
10118 low2highgid(arg2),
10119 low2highgid(arg3)));
bellard67867302003-11-23 17:05:30 +000010120#endif
10121#ifdef TARGET_NR_getresgid
10122 case TARGET_NR_getresgid:
10123 {
pbrook53a59602006-03-25 19:31:22 +000010124 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +000010125 ret = get_errno(getresgid(&rgid, &egid, &sgid));
10126 if (!is_error(ret)) {
Peter Maydell76ca3102014-03-02 19:36:41 +000010127 if (put_user_id(high2lowgid(rgid), arg1)
10128 || put_user_id(high2lowgid(egid), arg2)
10129 || put_user_id(high2lowgid(sgid), arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010130 return -TARGET_EFAULT;
bellard67867302003-11-23 17:05:30 +000010131 }
10132 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010133 return ret;
bellard67867302003-11-23 17:05:30 +000010134#endif
Chen Gang704eff62015-08-21 05:37:33 +080010135#ifdef TARGET_NR_chown
bellard67867302003-11-23 17:05:30 +000010136 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +000010137 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010138 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010139 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
10140 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010141 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080010142#endif
bellard67867302003-11-23 17:05:30 +000010143 case TARGET_NR_setuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010144 return get_errno(sys_setuid(low2highuid(arg1)));
bellard67867302003-11-23 17:05:30 +000010145 case TARGET_NR_setgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010146 return get_errno(sys_setgid(low2highgid(arg1)));
bellard67867302003-11-23 17:05:30 +000010147 case TARGET_NR_setfsuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010148 return get_errno(setfsuid(arg1));
bellard67867302003-11-23 17:05:30 +000010149 case TARGET_NR_setfsgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010150 return get_errno(setfsgid(arg1));
bellard67867302003-11-23 17:05:30 +000010151
bellarda315a142005-01-30 22:59:18 +000010152#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +000010153 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +000010154 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010155 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010156 ret = get_errno(lchown(p, arg2, arg3));
10157 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010158 return ret;
bellarda315a142005-01-30 22:59:18 +000010159#endif
10160#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +000010161 case TARGET_NR_getuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010162 return get_errno(getuid());
bellarda315a142005-01-30 22:59:18 +000010163#endif
aurel3264b4d282008-11-14 17:20:15 +000010164
10165#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
10166 /* Alpha specific */
10167 case TARGET_NR_getxuid:
Richard Hendersonba0e2762009-12-09 15:56:29 -080010168 {
10169 uid_t euid;
10170 euid=geteuid();
10171 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
10172 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010173 return get_errno(getuid());
aurel3264b4d282008-11-14 17:20:15 +000010174#endif
10175#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
10176 /* Alpha specific */
10177 case TARGET_NR_getxgid:
Richard Hendersonba0e2762009-12-09 15:56:29 -080010178 {
10179 uid_t egid;
10180 egid=getegid();
10181 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
10182 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010183 return get_errno(getgid());
aurel3264b4d282008-11-14 17:20:15 +000010184#endif
Richard Hendersonba0e2762009-12-09 15:56:29 -080010185#if defined(TARGET_NR_osf_getsysinfo) && defined(TARGET_ALPHA)
10186 /* Alpha specific */
10187 case TARGET_NR_osf_getsysinfo:
10188 ret = -TARGET_EOPNOTSUPP;
10189 switch (arg1) {
10190 case TARGET_GSI_IEEE_FP_CONTROL:
10191 {
10192 uint64_t swcr, fpcr = cpu_alpha_load_fpcr (cpu_env);
10193
10194 /* Copied from linux ieee_fpcr_to_swcr. */
10195 swcr = (fpcr >> 35) & SWCR_STATUS_MASK;
10196 swcr |= (fpcr >> 36) & SWCR_MAP_DMZ;
10197 swcr |= (~fpcr >> 48) & (SWCR_TRAP_ENABLE_INV
10198 | SWCR_TRAP_ENABLE_DZE
10199 | SWCR_TRAP_ENABLE_OVF);
10200 swcr |= (~fpcr >> 57) & (SWCR_TRAP_ENABLE_UNF
10201 | SWCR_TRAP_ENABLE_INE);
10202 swcr |= (fpcr >> 47) & SWCR_MAP_UMZ;
10203 swcr |= (~fpcr >> 41) & SWCR_TRAP_ENABLE_DNO;
10204
10205 if (put_user_u64 (swcr, arg2))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010206 return -TARGET_EFAULT;
Richard Hendersonba0e2762009-12-09 15:56:29 -080010207 ret = 0;
10208 }
10209 break;
10210
10211 /* case GSI_IEEE_STATE_AT_SIGNAL:
10212 -- Not implemented in linux kernel.
10213 case GSI_UACPROC:
10214 -- Retrieves current unaligned access state; not much used.
10215 case GSI_PROC_TYPE:
10216 -- Retrieves implver information; surely not used.
10217 case GSI_GET_HWRPB:
10218 -- Grabs a copy of the HWRPB; surely not used.
10219 */
10220 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010221 return ret;
Richard Hendersonba0e2762009-12-09 15:56:29 -080010222#endif
10223#if defined(TARGET_NR_osf_setsysinfo) && defined(TARGET_ALPHA)
10224 /* Alpha specific */
10225 case TARGET_NR_osf_setsysinfo:
10226 ret = -TARGET_EOPNOTSUPP;
10227 switch (arg1) {
10228 case TARGET_SSI_IEEE_FP_CONTROL:
Richard Hendersonba0e2762009-12-09 15:56:29 -080010229 {
10230 uint64_t swcr, fpcr, orig_fpcr;
10231
Richard Henderson6e06d512012-06-01 09:08:21 -070010232 if (get_user_u64 (swcr, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010233 return -TARGET_EFAULT;
Richard Henderson6e06d512012-06-01 09:08:21 -070010234 }
10235 orig_fpcr = cpu_alpha_load_fpcr(cpu_env);
Richard Hendersonba0e2762009-12-09 15:56:29 -080010236 fpcr = orig_fpcr & FPCR_DYN_MASK;
10237
10238 /* Copied from linux ieee_swcr_to_fpcr. */
10239 fpcr |= (swcr & SWCR_STATUS_MASK) << 35;
10240 fpcr |= (swcr & SWCR_MAP_DMZ) << 36;
10241 fpcr |= (~swcr & (SWCR_TRAP_ENABLE_INV
10242 | SWCR_TRAP_ENABLE_DZE
10243 | SWCR_TRAP_ENABLE_OVF)) << 48;
10244 fpcr |= (~swcr & (SWCR_TRAP_ENABLE_UNF
10245 | SWCR_TRAP_ENABLE_INE)) << 57;
10246 fpcr |= (swcr & SWCR_MAP_UMZ ? FPCR_UNDZ | FPCR_UNFD : 0);
10247 fpcr |= (~swcr & SWCR_TRAP_ENABLE_DNO) << 41;
10248
Richard Henderson6e06d512012-06-01 09:08:21 -070010249 cpu_alpha_store_fpcr(cpu_env, fpcr);
10250 ret = 0;
10251 }
10252 break;
10253
10254 case TARGET_SSI_IEEE_RAISE_EXCEPTION:
10255 {
10256 uint64_t exc, fpcr, orig_fpcr;
10257 int si_code;
10258
10259 if (get_user_u64(exc, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010260 return -TARGET_EFAULT;
Richard Henderson6e06d512012-06-01 09:08:21 -070010261 }
10262
10263 orig_fpcr = cpu_alpha_load_fpcr(cpu_env);
10264
10265 /* We only add to the exception status here. */
10266 fpcr = orig_fpcr | ((exc & SWCR_STATUS_MASK) << 35);
10267
10268 cpu_alpha_store_fpcr(cpu_env, fpcr);
Richard Hendersonba0e2762009-12-09 15:56:29 -080010269 ret = 0;
10270
Richard Henderson6e06d512012-06-01 09:08:21 -070010271 /* Old exceptions are not signaled. */
10272 fpcr &= ~(orig_fpcr & FPCR_STATUS_MASK);
Richard Hendersonba0e2762009-12-09 15:56:29 -080010273
Richard Henderson6e06d512012-06-01 09:08:21 -070010274 /* If any exceptions set by this call,
10275 and are unmasked, send a signal. */
10276 si_code = 0;
10277 if ((fpcr & (FPCR_INE | FPCR_INED)) == FPCR_INE) {
10278 si_code = TARGET_FPE_FLTRES;
10279 }
10280 if ((fpcr & (FPCR_UNF | FPCR_UNFD)) == FPCR_UNF) {
10281 si_code = TARGET_FPE_FLTUND;
10282 }
10283 if ((fpcr & (FPCR_OVF | FPCR_OVFD)) == FPCR_OVF) {
10284 si_code = TARGET_FPE_FLTOVF;
10285 }
10286 if ((fpcr & (FPCR_DZE | FPCR_DZED)) == FPCR_DZE) {
10287 si_code = TARGET_FPE_FLTDIV;
10288 }
10289 if ((fpcr & (FPCR_INV | FPCR_INVD)) == FPCR_INV) {
10290 si_code = TARGET_FPE_FLTINV;
10291 }
10292 if (si_code != 0) {
10293 target_siginfo_t info;
10294 info.si_signo = SIGFPE;
10295 info.si_errno = 0;
10296 info.si_code = si_code;
10297 info._sifields._sigfault._addr
10298 = ((CPUArchState *)cpu_env)->pc;
Peter Maydell9d2803f2016-07-28 16:44:46 +010010299 queue_signal((CPUArchState *)cpu_env, info.si_signo,
10300 QEMU_SI_FAULT, &info);
Richard Hendersonba0e2762009-12-09 15:56:29 -080010301 }
10302 }
10303 break;
10304
10305 /* case SSI_NVPAIRS:
10306 -- Used with SSIN_UACPROC to enable unaligned accesses.
10307 case SSI_IEEE_STATE_AT_SIGNAL:
10308 case SSI_IEEE_IGNORE_STATE_AT_SIGNAL:
10309 -- Not implemented in linux kernel
10310 */
10311 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010312 return ret;
Richard Hendersonba0e2762009-12-09 15:56:29 -080010313#endif
10314#ifdef TARGET_NR_osf_sigprocmask
10315 /* Alpha specific. */
10316 case TARGET_NR_osf_sigprocmask:
10317 {
10318 abi_ulong mask;
Juan Quintelabc088ba2011-06-16 17:37:10 +010010319 int how;
Richard Hendersonba0e2762009-12-09 15:56:29 -080010320 sigset_t set, oldset;
10321
10322 switch(arg1) {
10323 case TARGET_SIG_BLOCK:
10324 how = SIG_BLOCK;
10325 break;
10326 case TARGET_SIG_UNBLOCK:
10327 how = SIG_UNBLOCK;
10328 break;
10329 case TARGET_SIG_SETMASK:
10330 how = SIG_SETMASK;
10331 break;
10332 default:
Richard Henderson259841c2018-08-18 12:01:09 -070010333 return -TARGET_EINVAL;
Richard Hendersonba0e2762009-12-09 15:56:29 -080010334 }
10335 mask = arg2;
10336 target_to_host_old_sigset(&set, &mask);
Peter Maydell3d3efba2016-05-27 15:51:49 +010010337 ret = do_sigprocmask(how, &set, &oldset);
10338 if (!ret) {
10339 host_to_target_old_sigset(&mask, &oldset);
10340 ret = mask;
10341 }
Richard Hendersonba0e2762009-12-09 15:56:29 -080010342 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010343 return ret;
Richard Hendersonba0e2762009-12-09 15:56:29 -080010344#endif
aurel3264b4d282008-11-14 17:20:15 +000010345
bellarda315a142005-01-30 22:59:18 +000010346#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +000010347 case TARGET_NR_getgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010348 return get_errno(getgid());
bellarda315a142005-01-30 22:59:18 +000010349#endif
10350#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +000010351 case TARGET_NR_geteuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010352 return get_errno(geteuid());
bellarda315a142005-01-30 22:59:18 +000010353#endif
10354#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +000010355 case TARGET_NR_getegid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010356 return get_errno(getegid());
bellarda315a142005-01-30 22:59:18 +000010357#endif
10358#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +000010359 case TARGET_NR_setreuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010360 return get_errno(setreuid(arg1, arg2));
bellarda315a142005-01-30 22:59:18 +000010361#endif
10362#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +000010363 case TARGET_NR_setregid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010364 return get_errno(setregid(arg1, arg2));
bellarda315a142005-01-30 22:59:18 +000010365#endif
10366#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +000010367 case TARGET_NR_getgroups32:
bellard99c475a2005-01-31 20:45:13 +000010368 {
10369 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +000010370 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +000010371 gid_t *grouplist;
10372 int i;
10373
10374 grouplist = alloca(gidsetsize * sizeof(gid_t));
10375 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +000010376 if (gidsetsize == 0)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010377 return ret;
bellard99c475a2005-01-31 20:45:13 +000010378 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +000010379 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
10380 if (!target_grouplist) {
Richard Henderson259841c2018-08-18 12:01:09 -070010381 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000010382 }
balroga2155fc2008-09-20 02:12:08 +000010383 for(i = 0;i < ret; i++)
pbrook53a59602006-03-25 19:31:22 +000010384 target_grouplist[i] = tswap32(grouplist[i]);
10385 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +000010386 }
10387 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010388 return ret;
bellarda315a142005-01-30 22:59:18 +000010389#endif
10390#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +000010391 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +000010392 {
10393 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +000010394 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +000010395 gid_t *grouplist;
10396 int i;
ths3b46e622007-09-17 08:09:54 +000010397
bellard99c475a2005-01-31 20:45:13 +000010398 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +000010399 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
10400 if (!target_grouplist) {
Richard Henderson259841c2018-08-18 12:01:09 -070010401 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000010402 }
bellard99c475a2005-01-31 20:45:13 +000010403 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +000010404 grouplist[i] = tswap32(target_grouplist[i]);
10405 unlock_user(target_grouplist, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010406 return get_errno(setgroups(gidsetsize, grouplist));
bellard99c475a2005-01-31 20:45:13 +000010407 }
bellarda315a142005-01-30 22:59:18 +000010408#endif
10409#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +000010410 case TARGET_NR_fchown32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010411 return get_errno(fchown(arg1, arg2, arg3));
bellarda315a142005-01-30 22:59:18 +000010412#endif
10413#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +000010414 case TARGET_NR_setresuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010415 return get_errno(sys_setresuid(arg1, arg2, arg3));
bellarda315a142005-01-30 22:59:18 +000010416#endif
10417#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +000010418 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +000010419 {
pbrook53a59602006-03-25 19:31:22 +000010420 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +000010421 ret = get_errno(getresuid(&ruid, &euid, &suid));
10422 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +000010423 if (put_user_u32(ruid, arg1)
10424 || put_user_u32(euid, arg2)
10425 || put_user_u32(suid, arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010426 return -TARGET_EFAULT;
bellardb03c60f2003-03-23 17:19:56 +000010427 }
10428 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010429 return ret;
bellarda315a142005-01-30 22:59:18 +000010430#endif
10431#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +000010432 case TARGET_NR_setresgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010433 return get_errno(sys_setresgid(arg1, arg2, arg3));
bellarda315a142005-01-30 22:59:18 +000010434#endif
10435#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +000010436 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +000010437 {
pbrook53a59602006-03-25 19:31:22 +000010438 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +000010439 ret = get_errno(getresgid(&rgid, &egid, &sgid));
10440 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +000010441 if (put_user_u32(rgid, arg1)
10442 || put_user_u32(egid, arg2)
10443 || put_user_u32(sgid, arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010444 return -TARGET_EFAULT;
bellardb03c60f2003-03-23 17:19:56 +000010445 }
10446 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010447 return ret;
bellarda315a142005-01-30 22:59:18 +000010448#endif
10449#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +000010450 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +000010451 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010452 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010453 ret = get_errno(chown(p, arg2, arg3));
10454 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010455 return ret;
bellarda315a142005-01-30 22:59:18 +000010456#endif
10457#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +000010458 case TARGET_NR_setuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010459 return get_errno(sys_setuid(arg1));
bellarda315a142005-01-30 22:59:18 +000010460#endif
10461#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +000010462 case TARGET_NR_setgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010463 return get_errno(sys_setgid(arg1));
bellarda315a142005-01-30 22:59:18 +000010464#endif
10465#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +000010466 case TARGET_NR_setfsuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010467 return get_errno(setfsuid(arg1));
bellarda315a142005-01-30 22:59:18 +000010468#endif
10469#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +000010470 case TARGET_NR_setfsgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010471 return get_errno(setfsgid(arg1));
bellarda315a142005-01-30 22:59:18 +000010472#endif
bellardffa65c32004-01-04 23:57:22 +000010473#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +000010474 case TARGET_NR_mincore:
aurel3204bb9ac2008-10-01 21:46:41 +000010475 {
Richard Henderson259841c2018-08-18 12:01:09 -070010476 void *a = lock_user(VERIFY_READ, arg1, arg2, 0);
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000010477 if (!a) {
Richard Henderson259841c2018-08-18 12:01:09 -070010478 return -TARGET_ENOMEM;
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000010479 }
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000010480 p = lock_user_string(arg3);
10481 if (!p) {
Richard Henderson259841c2018-08-18 12:01:09 -070010482 ret = -TARGET_EFAULT;
10483 } else {
10484 ret = get_errno(mincore(a, arg2, p));
10485 unlock_user(p, arg3, ret);
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000010486 }
aurel3204bb9ac2008-10-01 21:46:41 +000010487 unlock_user(a, arg1, 0);
10488 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010489 return ret;
bellardffa65c32004-01-04 23:57:22 +000010490#endif
aurel32408321b2008-10-01 21:46:32 +000010491#ifdef TARGET_NR_arm_fadvise64_64
10492 case TARGET_NR_arm_fadvise64_64:
Peter Maydelle0156a92016-05-31 15:45:09 +010010493 /* arm_fadvise64_64 looks like fadvise64_64 but
10494 * with different argument order: fd, advice, offset, len
10495 * rather than the usual fd, offset, len, advice.
10496 * Note that offset and len are both 64-bit so appear as
10497 * pairs of 32-bit registers.
10498 */
10499 ret = posix_fadvise(arg1, target_offset64(arg3, arg4),
10500 target_offset64(arg5, arg6), arg2);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010501 return -host_to_target_errno(ret);
aurel32408321b2008-10-01 21:46:32 +000010502#endif
Peter Maydellbadd3cd2016-05-31 15:45:10 +010010503
10504#if TARGET_ABI_BITS == 32
10505
10506#ifdef TARGET_NR_fadvise64_64
10507 case TARGET_NR_fadvise64_64:
Max Filippov64a563d2018-04-01 15:02:34 -070010508#if defined(TARGET_PPC) || defined(TARGET_XTENSA)
Laurent Vivier43046b52017-03-02 01:11:45 +010010509 /* 6 args: fd, advice, offset (high, low), len (high, low) */
10510 ret = arg2;
10511 arg2 = arg3;
10512 arg3 = arg4;
10513 arg4 = arg5;
10514 arg5 = arg6;
10515 arg6 = ret;
10516#else
Peter Maydellbadd3cd2016-05-31 15:45:10 +010010517 /* 6 args: fd, offset (high, low), len (high, low), advice */
James Clarke8bf8e9d2017-09-15 20:33:13 +010010518 if (regpairs_aligned(cpu_env, num)) {
Peter Maydellbadd3cd2016-05-31 15:45:10 +010010519 /* offset is in (3,4), len in (5,6) and advice in 7 */
10520 arg2 = arg3;
10521 arg3 = arg4;
10522 arg4 = arg5;
10523 arg5 = arg6;
10524 arg6 = arg7;
10525 }
Laurent Vivier43046b52017-03-02 01:11:45 +010010526#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010527 ret = posix_fadvise(arg1, target_offset64(arg2, arg3),
10528 target_offset64(arg4, arg5), arg6);
10529 return -host_to_target_errno(ret);
Peter Maydellbadd3cd2016-05-31 15:45:10 +010010530#endif
10531
10532#ifdef TARGET_NR_fadvise64
10533 case TARGET_NR_fadvise64:
10534 /* 5 args: fd, offset (high, low), len, advice */
James Clarke8bf8e9d2017-09-15 20:33:13 +010010535 if (regpairs_aligned(cpu_env, num)) {
Peter Maydellbadd3cd2016-05-31 15:45:10 +010010536 /* offset is in (3,4), len in 5 and advice in 6 */
10537 arg2 = arg3;
10538 arg3 = arg4;
10539 arg4 = arg5;
10540 arg5 = arg6;
10541 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010542 ret = posix_fadvise(arg1, target_offset64(arg2, arg3), arg4, arg5);
10543 return -host_to_target_errno(ret);
Peter Maydellbadd3cd2016-05-31 15:45:10 +010010544#endif
10545
10546#else /* not a 32-bit ABI */
Peter Maydelle0156a92016-05-31 15:45:09 +010010547#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_fadvise64)
aurel32408321b2008-10-01 21:46:32 +000010548#ifdef TARGET_NR_fadvise64_64
10549 case TARGET_NR_fadvise64_64:
10550#endif
Ulrich Hechte72d2cc2009-07-24 19:10:31 +020010551#ifdef TARGET_NR_fadvise64
10552 case TARGET_NR_fadvise64:
10553#endif
10554#ifdef TARGET_S390X
10555 switch (arg4) {
10556 case 4: arg4 = POSIX_FADV_NOREUSE + 1; break; /* make sure it's an invalid value */
10557 case 5: arg4 = POSIX_FADV_NOREUSE + 2; break; /* ditto */
10558 case 6: arg4 = POSIX_FADV_DONTNEED; break;
10559 case 7: arg4 = POSIX_FADV_NOREUSE; break;
10560 default: break;
10561 }
10562#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010563 return -host_to_target_errno(posix_fadvise(arg1, arg2, arg3, arg4));
aurel32408321b2008-10-01 21:46:32 +000010564#endif
Peter Maydellbadd3cd2016-05-31 15:45:10 +010010565#endif /* end of 64-bit ABI fadvise handling */
10566
bellardffa65c32004-01-04 23:57:22 +000010567#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +000010568 case TARGET_NR_madvise:
pbrook24836682006-04-16 14:14:53 +000010569 /* A straight passthrough may not be safe because qemu sometimes
Lei Lid2d6b852013-05-20 17:20:50 +080010570 turns private file-backed mappings into anonymous mappings.
pbrook24836682006-04-16 14:14:53 +000010571 This will break MADV_DONTNEED.
10572 This is a hint, so ignoring and returning success is ok. */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010573 return 0;
bellardffa65c32004-01-04 23:57:22 +000010574#endif
blueswir1992f48a2007-10-14 16:27:31 +000010575#if TARGET_ABI_BITS == 32
bellard31e31b82003-02-18 22:55:36 +000010576 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +000010577 {
thsb1e341e2007-03-20 21:50:52 +000010578 int cmd;
bellard77e46722003-04-29 20:39:06 +000010579 struct flock64 fl;
Peter Maydell213d3e92016-06-13 11:22:05 +010010580 from_flock64_fn *copyfrom = copy_from_user_flock64;
10581 to_flock64_fn *copyto = copy_to_user_flock64;
10582
pbrookce4defa2006-02-09 16:49:55 +000010583#ifdef TARGET_ARM
Laurent Vivier7f254c52018-05-02 23:57:30 +020010584 if (!((CPUARMState *)cpu_env)->eabi) {
10585 copyfrom = copy_from_user_oabi_flock64;
10586 copyto = copy_to_user_oabi_flock64;
Peter Maydell213d3e92016-06-13 11:22:05 +010010587 }
pbrookce4defa2006-02-09 16:49:55 +000010588#endif
bellard77e46722003-04-29 20:39:06 +000010589
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +020010590 cmd = target_to_host_fcntl_cmd(arg2);
Peter Maydell31b63192011-12-05 23:11:50 +000010591 if (cmd == -TARGET_EINVAL) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010592 return cmd;
Peter Maydell31b63192011-12-05 23:11:50 +000010593 }
thsb1e341e2007-03-20 21:50:52 +000010594
bellard60cd49d2003-03-16 22:53:56 +000010595 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +000010596 case TARGET_F_GETLK64:
Peter Maydell213d3e92016-06-13 11:22:05 +010010597 ret = copyfrom(&fl, arg3);
10598 if (ret) {
10599 break;
ths58134272007-03-31 18:59:32 +000010600 }
Laurent Vivieraf8ab2b2018-07-13 14:58:05 +020010601 ret = get_errno(safe_fcntl(arg1, cmd, &fl));
Peter Maydell213d3e92016-06-13 11:22:05 +010010602 if (ret == 0) {
10603 ret = copyto(arg3, &fl);
10604 }
bellard77e46722003-04-29 20:39:06 +000010605 break;
10606
thsb1e341e2007-03-20 21:50:52 +000010607 case TARGET_F_SETLK64:
10608 case TARGET_F_SETLKW64:
Peter Maydell213d3e92016-06-13 11:22:05 +010010609 ret = copyfrom(&fl, arg3);
10610 if (ret) {
10611 break;
pbrookce4defa2006-02-09 16:49:55 +000010612 }
Peter Maydell435da5e2016-06-13 11:22:05 +010010613 ret = get_errno(safe_fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +000010614 break;
bellard60cd49d2003-03-16 22:53:56 +000010615 default:
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +020010616 ret = do_fcntl(arg1, arg2, arg3);
bellard60cd49d2003-03-16 22:53:56 +000010617 break;
10618 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010619 return ret;
bellard77e46722003-04-29 20:39:06 +000010620 }
bellard60cd49d2003-03-16 22:53:56 +000010621#endif
ths7d600c82006-12-08 01:32:58 +000010622#ifdef TARGET_NR_cacheflush
10623 case TARGET_NR_cacheflush:
10624 /* self-modifying code is handled automatically, so nothing needed */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010625 return 0;
ths7d600c82006-12-08 01:32:58 +000010626#endif
bellardc573ff62004-01-04 15:51:36 +000010627#ifdef TARGET_NR_getpagesize
10628 case TARGET_NR_getpagesize:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010629 return TARGET_PAGE_SIZE;
bellardc573ff62004-01-04 15:51:36 +000010630#endif
bellard31e31b82003-02-18 22:55:36 +000010631 case TARGET_NR_gettid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010632 return get_errno(gettid());
thse5febef2007-04-01 18:31:35 +000010633#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +000010634 case TARGET_NR_readahead:
aurel322054ac92008-10-13 21:08:07 +000010635#if TARGET_ABI_BITS == 32
James Clarke8bf8e9d2017-09-15 20:33:13 +010010636 if (regpairs_aligned(cpu_env, num)) {
aurel322054ac92008-10-13 21:08:07 +000010637 arg2 = arg3;
10638 arg3 = arg4;
10639 arg4 = arg5;
10640 }
Lena Djokic77c68502016-11-24 17:08:56 +010010641 ret = get_errno(readahead(arg1, target_offset64(arg2, arg3) , arg4));
aurel322054ac92008-10-13 21:08:07 +000010642#else
10643 ret = get_errno(readahead(arg1, arg2, arg3));
10644#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010645 return ret;
thse5febef2007-04-01 18:31:35 +000010646#endif
An-Cheng Huanga790ae32011-08-09 12:34:06 -070010647#ifdef CONFIG_ATTR
bellardebc05482003-09-30 21:08:41 +000010648#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +000010649 case TARGET_NR_listxattr:
10650 case TARGET_NR_llistxattr:
Peter Maydellfb5590f2011-12-14 15:37:19 +000010651 {
10652 void *p, *b = 0;
10653 if (arg2) {
10654 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
10655 if (!b) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010656 return -TARGET_EFAULT;
Peter Maydellfb5590f2011-12-14 15:37:19 +000010657 }
10658 }
10659 p = lock_user_string(arg1);
10660 if (p) {
10661 if (num == TARGET_NR_listxattr) {
10662 ret = get_errno(listxattr(p, b, arg3));
10663 } else {
10664 ret = get_errno(llistxattr(p, b, arg3));
10665 }
10666 } else {
10667 ret = -TARGET_EFAULT;
10668 }
10669 unlock_user(p, arg1, 0);
10670 unlock_user(b, arg2, arg3);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010671 return ret;
Peter Maydellfb5590f2011-12-14 15:37:19 +000010672 }
10673 case TARGET_NR_flistxattr:
10674 {
10675 void *b = 0;
10676 if (arg2) {
10677 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
10678 if (!b) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010679 return -TARGET_EFAULT;
Peter Maydellfb5590f2011-12-14 15:37:19 +000010680 }
10681 }
10682 ret = get_errno(flistxattr(arg1, b, arg3));
10683 unlock_user(b, arg2, arg3);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010684 return ret;
Peter Maydellfb5590f2011-12-14 15:37:19 +000010685 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070010686 case TARGET_NR_setxattr:
Peter Maydell30297b52011-12-14 15:37:18 +000010687 case TARGET_NR_lsetxattr:
An-Cheng Huanga790ae32011-08-09 12:34:06 -070010688 {
Peter Maydelle3c33ec2011-12-14 15:37:17 +000010689 void *p, *n, *v = 0;
10690 if (arg3) {
10691 v = lock_user(VERIFY_READ, arg3, arg4, 1);
10692 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010693 return -TARGET_EFAULT;
Peter Maydelle3c33ec2011-12-14 15:37:17 +000010694 }
10695 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070010696 p = lock_user_string(arg1);
10697 n = lock_user_string(arg2);
Peter Maydelle3c33ec2011-12-14 15:37:17 +000010698 if (p && n) {
Peter Maydell30297b52011-12-14 15:37:18 +000010699 if (num == TARGET_NR_setxattr) {
10700 ret = get_errno(setxattr(p, n, v, arg4, arg5));
10701 } else {
10702 ret = get_errno(lsetxattr(p, n, v, arg4, arg5));
10703 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070010704 } else {
10705 ret = -TARGET_EFAULT;
10706 }
10707 unlock_user(p, arg1, 0);
10708 unlock_user(n, arg2, 0);
10709 unlock_user(v, arg3, 0);
10710 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010711 return ret;
Peter Maydell30297b52011-12-14 15:37:18 +000010712 case TARGET_NR_fsetxattr:
10713 {
10714 void *n, *v = 0;
10715 if (arg3) {
10716 v = lock_user(VERIFY_READ, arg3, arg4, 1);
10717 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010718 return -TARGET_EFAULT;
Peter Maydell30297b52011-12-14 15:37:18 +000010719 }
10720 }
10721 n = lock_user_string(arg2);
10722 if (n) {
10723 ret = get_errno(fsetxattr(arg1, n, v, arg4, arg5));
10724 } else {
10725 ret = -TARGET_EFAULT;
10726 }
10727 unlock_user(n, arg2, 0);
10728 unlock_user(v, arg3, 0);
10729 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010730 return ret;
An-Cheng Huanga790ae32011-08-09 12:34:06 -070010731 case TARGET_NR_getxattr:
Peter Maydell30297b52011-12-14 15:37:18 +000010732 case TARGET_NR_lgetxattr:
An-Cheng Huanga790ae32011-08-09 12:34:06 -070010733 {
Peter Maydelle3c33ec2011-12-14 15:37:17 +000010734 void *p, *n, *v = 0;
10735 if (arg3) {
10736 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
10737 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010738 return -TARGET_EFAULT;
Peter Maydelle3c33ec2011-12-14 15:37:17 +000010739 }
10740 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070010741 p = lock_user_string(arg1);
10742 n = lock_user_string(arg2);
Peter Maydelle3c33ec2011-12-14 15:37:17 +000010743 if (p && n) {
Peter Maydell30297b52011-12-14 15:37:18 +000010744 if (num == TARGET_NR_getxattr) {
10745 ret = get_errno(getxattr(p, n, v, arg4));
10746 } else {
10747 ret = get_errno(lgetxattr(p, n, v, arg4));
10748 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070010749 } else {
10750 ret = -TARGET_EFAULT;
10751 }
10752 unlock_user(p, arg1, 0);
10753 unlock_user(n, arg2, 0);
10754 unlock_user(v, arg3, arg4);
10755 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010756 return ret;
Peter Maydell30297b52011-12-14 15:37:18 +000010757 case TARGET_NR_fgetxattr:
10758 {
10759 void *n, *v = 0;
10760 if (arg3) {
10761 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
10762 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010763 return -TARGET_EFAULT;
Peter Maydell30297b52011-12-14 15:37:18 +000010764 }
10765 }
10766 n = lock_user_string(arg2);
10767 if (n) {
10768 ret = get_errno(fgetxattr(arg1, n, v, arg4));
10769 } else {
10770 ret = -TARGET_EFAULT;
10771 }
10772 unlock_user(n, arg2, 0);
10773 unlock_user(v, arg3, arg4);
10774 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010775 return ret;
An-Cheng Huanga790ae32011-08-09 12:34:06 -070010776 case TARGET_NR_removexattr:
Peter Maydell30297b52011-12-14 15:37:18 +000010777 case TARGET_NR_lremovexattr:
An-Cheng Huanga790ae32011-08-09 12:34:06 -070010778 {
10779 void *p, *n;
10780 p = lock_user_string(arg1);
10781 n = lock_user_string(arg2);
10782 if (p && n) {
Peter Maydell30297b52011-12-14 15:37:18 +000010783 if (num == TARGET_NR_removexattr) {
10784 ret = get_errno(removexattr(p, n));
10785 } else {
10786 ret = get_errno(lremovexattr(p, n));
10787 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070010788 } else {
10789 ret = -TARGET_EFAULT;
10790 }
10791 unlock_user(p, arg1, 0);
10792 unlock_user(n, arg2, 0);
10793 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010794 return ret;
Peter Maydell30297b52011-12-14 15:37:18 +000010795 case TARGET_NR_fremovexattr:
10796 {
10797 void *n;
10798 n = lock_user_string(arg2);
10799 if (n) {
10800 ret = get_errno(fremovexattr(arg1, n));
10801 } else {
10802 ret = -TARGET_EFAULT;
10803 }
10804 unlock_user(n, arg2, 0);
10805 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010806 return ret;
bellardebc05482003-09-30 21:08:41 +000010807#endif
An-Cheng Huanga790ae32011-08-09 12:34:06 -070010808#endif /* CONFIG_ATTR */
bellardebc05482003-09-30 21:08:41 +000010809#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +000010810 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +000010811#if defined(TARGET_MIPS)
Petar Jovanovicd2792792014-06-18 17:48:20 +020010812 ((CPUMIPSState *) cpu_env)->active_tc.CP0_UserLocal = arg1;
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010813 return 0;
edgar_iglef967792009-01-07 14:19:38 +000010814#elif defined(TARGET_CRIS)
10815 if (arg1 & 0xff)
10816 ret = -TARGET_EINVAL;
10817 else {
10818 ((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1;
10819 ret = 0;
10820 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010821 return ret;
bellard8d18e892007-11-14 15:18:40 +000010822#elif defined(TARGET_I386) && defined(TARGET_ABI32)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010823 return do_set_thread_area(cpu_env, arg1);
Peter Maydell1ccd9372013-07-16 18:44:55 +010010824#elif defined(TARGET_M68K)
10825 {
Andreas Färber0429a972013-08-26 18:14:44 +020010826 TaskState *ts = cpu->opaque;
Peter Maydell1ccd9372013-07-16 18:44:55 +010010827 ts->tp_value = arg1;
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010828 return 0;
Peter Maydell1ccd9372013-07-16 18:44:55 +010010829 }
ths6f5b89a2007-03-02 20:48:00 +000010830#else
Richard Henderson10f45d92018-08-18 12:01:07 -070010831 return -TARGET_ENOSYS;
ths6f5b89a2007-03-02 20:48:00 +000010832#endif
10833#endif
10834#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +000010835 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +000010836#if defined(TARGET_I386) && defined(TARGET_ABI32)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010837 return do_get_thread_area(cpu_env, arg1);
Peter Maydell1ccd9372013-07-16 18:44:55 +010010838#elif defined(TARGET_M68K)
10839 {
Andreas Färber0429a972013-08-26 18:14:44 +020010840 TaskState *ts = cpu->opaque;
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010841 return ts->tp_value;
Peter Maydell1ccd9372013-07-16 18:44:55 +010010842 }
bellard8d18e892007-11-14 15:18:40 +000010843#else
Richard Henderson10f45d92018-08-18 12:01:07 -070010844 return -TARGET_ENOSYS;
bellardebc05482003-09-30 21:08:41 +000010845#endif
bellard8d18e892007-11-14 15:18:40 +000010846#endif
bellard48dc41e2006-06-21 18:15:50 +000010847#ifdef TARGET_NR_getdomainname
10848 case TARGET_NR_getdomainname:
Richard Henderson10f45d92018-08-18 12:01:07 -070010849 return -TARGET_ENOSYS;
bellard48dc41e2006-06-21 18:15:50 +000010850#endif
ths6f5b89a2007-03-02 20:48:00 +000010851
Max Filippov12e33402018-04-01 13:13:49 -070010852#ifdef TARGET_NR_clock_settime
10853 case TARGET_NR_clock_settime:
10854 {
10855 struct timespec ts;
10856
10857 ret = target_to_host_timespec(&ts, arg2);
10858 if (!is_error(ret)) {
10859 ret = get_errno(clock_settime(arg1, &ts));
10860 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010861 return ret;
Max Filippov12e33402018-04-01 13:13:49 -070010862 }
10863#endif
thsb5906f92007-03-19 13:32:45 +000010864#ifdef TARGET_NR_clock_gettime
10865 case TARGET_NR_clock_gettime:
10866 {
10867 struct timespec ts;
10868 ret = get_errno(clock_gettime(arg1, &ts));
10869 if (!is_error(ret)) {
Max Filippovb9f99082018-04-01 13:14:04 -070010870 ret = host_to_target_timespec(arg2, &ts);
thsb5906f92007-03-19 13:32:45 +000010871 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010872 return ret;
thsb5906f92007-03-19 13:32:45 +000010873 }
10874#endif
10875#ifdef TARGET_NR_clock_getres
10876 case TARGET_NR_clock_getres:
10877 {
10878 struct timespec ts;
10879 ret = get_errno(clock_getres(arg1, &ts));
10880 if (!is_error(ret)) {
10881 host_to_target_timespec(arg2, &ts);
10882 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010883 return ret;
thsb5906f92007-03-19 13:32:45 +000010884 }
10885#endif
pbrook63d76512008-05-29 13:43:29 +000010886#ifdef TARGET_NR_clock_nanosleep
10887 case TARGET_NR_clock_nanosleep:
10888 {
10889 struct timespec ts;
10890 target_to_host_timespec(&ts, arg3);
Peter Maydell9e518222016-06-06 19:58:09 +010010891 ret = get_errno(safe_clock_nanosleep(arg1, arg2,
10892 &ts, arg4 ? &ts : NULL));
pbrook63d76512008-05-29 13:43:29 +000010893 if (arg4)
10894 host_to_target_timespec(arg4, &ts);
Tom Musta8fbe8fd2014-08-12 13:53:41 -050010895
10896#if defined(TARGET_PPC)
10897 /* clock_nanosleep is odd in that it returns positive errno values.
10898 * On PPC, CR0 bit 3 should be set in such a situation. */
Peter Maydell9e518222016-06-06 19:58:09 +010010899 if (ret && ret != -TARGET_ERESTARTSYS) {
Tom Musta8fbe8fd2014-08-12 13:53:41 -050010900 ((CPUPPCState *)cpu_env)->crf[0] |= 1;
10901 }
10902#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010903 return ret;
pbrook63d76512008-05-29 13:43:29 +000010904 }
10905#endif
thsb5906f92007-03-19 13:32:45 +000010906
ths6f5b89a2007-03-02 20:48:00 +000010907#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
10908 case TARGET_NR_set_tid_address:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010909 return get_errno(set_tid_address((int *)g2h(arg1)));
ths6f5b89a2007-03-02 20:48:00 +000010910#endif
10911
ths4cae1d12007-07-12 11:06:53 +000010912 case TARGET_NR_tkill:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010913 return get_errno(safe_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +000010914
ths71455572007-06-21 21:45:30 +000010915 case TARGET_NR_tgkill:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010916 return get_errno(safe_tgkill((int)arg1, (int)arg2,
10917 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +000010918
ths4f2b1fe2007-06-21 21:57:12 +000010919#ifdef TARGET_NR_set_robust_list
10920 case TARGET_NR_set_robust_list:
Peter Maydelle9a970a2013-02-08 04:34:54 +000010921 case TARGET_NR_get_robust_list:
10922 /* The ABI for supporting robust futexes has userspace pass
10923 * the kernel a pointer to a linked list which is updated by
10924 * userspace after the syscall; the list is walked by the kernel
10925 * when the thread exits. Since the linked list in QEMU guest
10926 * memory isn't a valid linked list for the host and we have
10927 * no way to reliably intercept the thread-death event, we can't
10928 * support these. Silently return ENOSYS so that guest userspace
10929 * falls back to a non-robust futex implementation (which should
10930 * be OK except in the corner case of the guest crashing while
10931 * holding a mutex that is shared with another process via
10932 * shared memory).
10933 */
Richard Henderson10f45d92018-08-18 12:01:07 -070010934 return -TARGET_ENOSYS;
ths4f2b1fe2007-06-21 21:57:12 +000010935#endif
10936
Peter Maydell1acae9f2013-07-02 14:04:12 +010010937#if defined(TARGET_NR_utimensat)
ths9007f0e2007-09-25 17:50:37 +000010938 case TARGET_NR_utimensat:
10939 {
Riku Voipioebc996f2009-04-21 15:01:51 +030010940 struct timespec *tsp, ts[2];
10941 if (!arg3) {
10942 tsp = NULL;
10943 } else {
10944 target_to_host_timespec(ts, arg3);
10945 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
10946 tsp = ts;
10947 }
ths9007f0e2007-09-25 17:50:37 +000010948 if (!arg2)
Riku Voipioebc996f2009-04-21 15:01:51 +030010949 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
ths9007f0e2007-09-25 17:50:37 +000010950 else {
bellard579a97f2007-11-11 14:26:47 +000010951 if (!(p = lock_user_string(arg2))) {
Richard Henderson259841c2018-08-18 12:01:09 -070010952 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000010953 }
Riku Voipioebc996f2009-04-21 15:01:51 +030010954 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
bellard579a97f2007-11-11 14:26:47 +000010955 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +000010956 }
10957 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010958 return ret;
ths9007f0e2007-09-25 17:50:37 +000010959#endif
pbrookbd0c5662008-05-29 14:34:11 +000010960 case TARGET_NR_futex:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010961 return do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
aurel32dbfe4c32009-04-08 21:29:30 +000010962#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
aurel3239b59762008-10-01 21:46:50 +000010963 case TARGET_NR_inotify_init:
10964 ret = get_errno(sys_inotify_init());
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030010965 if (ret >= 0) {
10966 fd_trans_register(ret, &target_inotify_trans);
10967 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010968 return ret;
aurel3239b59762008-10-01 21:46:50 +000010969#endif
Stefan Weila1606b02010-03-28 11:44:41 +020010970#ifdef CONFIG_INOTIFY1
Riku Voipioc05c7a72010-03-26 15:25:11 +000010971#if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1)
10972 case TARGET_NR_inotify_init1:
Lena Djokicfea243e2016-11-24 17:08:53 +010010973 ret = get_errno(sys_inotify_init1(target_to_host_bitmask(arg1,
10974 fcntl_flags_tbl)));
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030010975 if (ret >= 0) {
10976 fd_trans_register(ret, &target_inotify_trans);
10977 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010978 return ret;
Riku Voipioc05c7a72010-03-26 15:25:11 +000010979#endif
Stefan Weila1606b02010-03-28 11:44:41 +020010980#endif
aurel32dbfe4c32009-04-08 21:29:30 +000010981#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
aurel3239b59762008-10-01 21:46:50 +000010982 case TARGET_NR_inotify_add_watch:
10983 p = lock_user_string(arg2);
10984 ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3));
10985 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010986 return ret;
aurel3239b59762008-10-01 21:46:50 +000010987#endif
aurel32dbfe4c32009-04-08 21:29:30 +000010988#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
aurel3239b59762008-10-01 21:46:50 +000010989 case TARGET_NR_inotify_rm_watch:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010990 return get_errno(sys_inotify_rm_watch(arg1, arg2));
aurel3239b59762008-10-01 21:46:50 +000010991#endif
ths9007f0e2007-09-25 17:50:37 +000010992
Nathan Froyd8ec9cf82009-07-22 09:14:36 -070010993#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
aurel3224e10032009-04-15 16:11:43 +000010994 case TARGET_NR_mq_open:
10995 {
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020010996 struct mq_attr posix_mq_attr;
Lena Djokic26400772016-11-24 17:08:58 +010010997 struct mq_attr *pposix_mq_attr;
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020010998 int host_flags;
aurel3224e10032009-04-15 16:11:43 +000010999
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020011000 host_flags = target_to_host_bitmask(arg2, fcntl_flags_tbl);
Lena Djokic26400772016-11-24 17:08:58 +010011001 pposix_mq_attr = NULL;
11002 if (arg4) {
11003 if (copy_from_user_mq_attr(&posix_mq_attr, arg4) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011004 return -TARGET_EFAULT;
Lena Djokic26400772016-11-24 17:08:58 +010011005 }
11006 pposix_mq_attr = &posix_mq_attr;
Tom Mustab6ce1f62014-08-12 13:53:36 -050011007 }
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020011008 p = lock_user_string(arg1 - 1);
11009 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011010 return -TARGET_EFAULT;
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020011011 }
Lena Djokic26400772016-11-24 17:08:58 +010011012 ret = get_errno(mq_open(p, host_flags, arg3, pposix_mq_attr));
aurel3224e10032009-04-15 16:11:43 +000011013 unlock_user (p, arg1, 0);
11014 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011015 return ret;
aurel3224e10032009-04-15 16:11:43 +000011016
11017 case TARGET_NR_mq_unlink:
11018 p = lock_user_string(arg1 - 1);
Peter Maydell32112152016-07-12 13:02:13 +010011019 if (!p) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011020 return -TARGET_EFAULT;
Peter Maydell32112152016-07-12 13:02:13 +010011021 }
aurel3224e10032009-04-15 16:11:43 +000011022 ret = get_errno(mq_unlink(p));
11023 unlock_user (p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011024 return ret;
aurel3224e10032009-04-15 16:11:43 +000011025
11026 case TARGET_NR_mq_timedsend:
11027 {
11028 struct timespec ts;
11029
11030 p = lock_user (VERIFY_READ, arg2, arg3, 1);
11031 if (arg5 != 0) {
11032 target_to_host_timespec(&ts, arg5);
Peter Maydelld40ecd62016-06-06 19:58:06 +010011033 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts));
aurel3224e10032009-04-15 16:11:43 +000011034 host_to_target_timespec(arg5, &ts);
Peter Maydelld40ecd62016-06-06 19:58:06 +010011035 } else {
11036 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL));
aurel3224e10032009-04-15 16:11:43 +000011037 }
aurel3224e10032009-04-15 16:11:43 +000011038 unlock_user (p, arg2, arg3);
11039 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011040 return ret;
aurel3224e10032009-04-15 16:11:43 +000011041
11042 case TARGET_NR_mq_timedreceive:
11043 {
11044 struct timespec ts;
11045 unsigned int prio;
11046
11047 p = lock_user (VERIFY_READ, arg2, arg3, 1);
11048 if (arg5 != 0) {
11049 target_to_host_timespec(&ts, arg5);
Peter Maydelld40ecd62016-06-06 19:58:06 +010011050 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
11051 &prio, &ts));
aurel3224e10032009-04-15 16:11:43 +000011052 host_to_target_timespec(arg5, &ts);
Peter Maydelld40ecd62016-06-06 19:58:06 +010011053 } else {
11054 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
11055 &prio, NULL));
aurel3224e10032009-04-15 16:11:43 +000011056 }
aurel3224e10032009-04-15 16:11:43 +000011057 unlock_user (p, arg2, arg3);
11058 if (arg4 != 0)
11059 put_user_u32(prio, arg4);
11060 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011061 return ret;
aurel3224e10032009-04-15 16:11:43 +000011062
11063 /* Not implemented for now... */
11064/* case TARGET_NR_mq_notify: */
11065/* break; */
11066
11067 case TARGET_NR_mq_getsetattr:
11068 {
11069 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
11070 ret = 0;
aurel3224e10032009-04-15 16:11:43 +000011071 if (arg2 != 0) {
11072 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
Max Filippova23ea402018-03-31 08:20:15 -070011073 ret = get_errno(mq_setattr(arg1, &posix_mq_attr_in,
11074 &posix_mq_attr_out));
11075 } else if (arg3 != 0) {
11076 ret = get_errno(mq_getattr(arg1, &posix_mq_attr_out));
aurel3224e10032009-04-15 16:11:43 +000011077 }
Max Filippova23ea402018-03-31 08:20:15 -070011078 if (ret == 0 && arg3 != 0) {
11079 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
11080 }
aurel3224e10032009-04-15 16:11:43 +000011081 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011082 return ret;
aurel3224e10032009-04-15 16:11:43 +000011083#endif
11084
vibisreenivasan3ce34df2009-05-16 18:32:41 +053011085#ifdef CONFIG_SPLICE
11086#ifdef TARGET_NR_tee
11087 case TARGET_NR_tee:
11088 {
11089 ret = get_errno(tee(arg1,arg2,arg3,arg4));
11090 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011091 return ret;
vibisreenivasan3ce34df2009-05-16 18:32:41 +053011092#endif
11093#ifdef TARGET_NR_splice
11094 case TARGET_NR_splice:
11095 {
11096 loff_t loff_in, loff_out;
11097 loff_t *ploff_in = NULL, *ploff_out = NULL;
Andreas Schwab17644b32015-03-10 17:11:35 +010011098 if (arg2) {
11099 if (get_user_u64(loff_in, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011100 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010011101 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053011102 ploff_in = &loff_in;
11103 }
Andreas Schwab17644b32015-03-10 17:11:35 +010011104 if (arg4) {
11105 if (get_user_u64(loff_out, arg4)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011106 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010011107 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053011108 ploff_out = &loff_out;
11109 }
11110 ret = get_errno(splice(arg1, ploff_in, arg3, ploff_out, arg5, arg6));
Andreas Schwab17644b32015-03-10 17:11:35 +010011111 if (arg2) {
11112 if (put_user_u64(loff_in, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011113 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010011114 }
11115 }
11116 if (arg4) {
11117 if (put_user_u64(loff_out, arg4)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011118 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010011119 }
11120 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053011121 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011122 return ret;
vibisreenivasan3ce34df2009-05-16 18:32:41 +053011123#endif
11124#ifdef TARGET_NR_vmsplice
11125 case TARGET_NR_vmsplice:
11126 {
Richard Hendersonf287b2c2012-09-15 13:20:25 -070011127 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
11128 if (vec != NULL) {
11129 ret = get_errno(vmsplice(arg1, vec, arg3, arg4));
11130 unlock_iovec(vec, arg2, arg3, 0);
11131 } else {
11132 ret = -host_to_target_errno(errno);
11133 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053011134 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011135 return ret;
vibisreenivasan3ce34df2009-05-16 18:32:41 +053011136#endif
11137#endif /* CONFIG_SPLICE */
Riku Voipioc2882b92009-08-12 15:08:24 +030011138#ifdef CONFIG_EVENTFD
11139#if defined(TARGET_NR_eventfd)
11140 case TARGET_NR_eventfd:
11141 ret = get_errno(eventfd(arg1, 0));
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030011142 if (ret >= 0) {
11143 fd_trans_register(ret, &target_eventfd_trans);
11144 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011145 return ret;
Riku Voipioc2882b92009-08-12 15:08:24 +030011146#endif
11147#if defined(TARGET_NR_eventfd2)
11148 case TARGET_NR_eventfd2:
Petar Jovanovic5947c692013-04-08 20:26:10 +020011149 {
11150 int host_flags = arg2 & (~(TARGET_O_NONBLOCK | TARGET_O_CLOEXEC));
11151 if (arg2 & TARGET_O_NONBLOCK) {
11152 host_flags |= O_NONBLOCK;
11153 }
11154 if (arg2 & TARGET_O_CLOEXEC) {
11155 host_flags |= O_CLOEXEC;
11156 }
11157 ret = get_errno(eventfd(arg1, host_flags));
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030011158 if (ret >= 0) {
11159 fd_trans_register(ret, &target_eventfd_trans);
11160 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011161 return ret;
Petar Jovanovic5947c692013-04-08 20:26:10 +020011162 }
Riku Voipioc2882b92009-08-12 15:08:24 +030011163#endif
11164#endif /* CONFIG_EVENTFD */
Ulrich Hechtd0927932009-09-17 20:22:14 +030011165#if defined(CONFIG_FALLOCATE) && defined(TARGET_NR_fallocate)
11166 case TARGET_NR_fallocate:
Alexander Graf20249ae2012-02-06 21:37:07 +010011167#if TARGET_ABI_BITS == 32
11168 ret = get_errno(fallocate(arg1, arg2, target_offset64(arg3, arg4),
11169 target_offset64(arg5, arg6)));
11170#else
Ulrich Hechtd0927932009-09-17 20:22:14 +030011171 ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
Alexander Graf20249ae2012-02-06 21:37:07 +010011172#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011173 return ret;
Ulrich Hechtd0927932009-09-17 20:22:14 +030011174#endif
Peter Maydellc727f472011-01-06 11:05:10 +000011175#if defined(CONFIG_SYNC_FILE_RANGE)
11176#if defined(TARGET_NR_sync_file_range)
11177 case TARGET_NR_sync_file_range:
11178#if TARGET_ABI_BITS == 32
Riku Voipiobfcedc52011-06-20 16:24:39 +030011179#if defined(TARGET_MIPS)
11180 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
11181 target_offset64(arg5, arg6), arg7));
11182#else
Peter Maydellc727f472011-01-06 11:05:10 +000011183 ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3),
11184 target_offset64(arg4, arg5), arg6));
Riku Voipiobfcedc52011-06-20 16:24:39 +030011185#endif /* !TARGET_MIPS */
Peter Maydellc727f472011-01-06 11:05:10 +000011186#else
11187 ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4));
11188#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011189 return ret;
Peter Maydellc727f472011-01-06 11:05:10 +000011190#endif
11191#if defined(TARGET_NR_sync_file_range2)
11192 case TARGET_NR_sync_file_range2:
11193 /* This is like sync_file_range but the arguments are reordered */
11194#if TARGET_ABI_BITS == 32
11195 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
11196 target_offset64(arg5, arg6), arg2));
11197#else
11198 ret = get_errno(sync_file_range(arg1, arg3, arg4, arg2));
11199#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011200 return ret;
Peter Maydellc727f472011-01-06 11:05:10 +000011201#endif
11202#endif
Laurent Viviere36800c2015-10-02 14:48:09 +020011203#if defined(TARGET_NR_signalfd4)
11204 case TARGET_NR_signalfd4:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011205 return do_signalfd4(arg1, arg2, arg4);
Laurent Viviere36800c2015-10-02 14:48:09 +020011206#endif
11207#if defined(TARGET_NR_signalfd)
11208 case TARGET_NR_signalfd:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011209 return do_signalfd4(arg1, arg2, 0);
Laurent Viviere36800c2015-10-02 14:48:09 +020011210#endif
Peter Maydell3b6edd12011-02-15 18:35:05 +000011211#if defined(CONFIG_EPOLL)
11212#if defined(TARGET_NR_epoll_create)
11213 case TARGET_NR_epoll_create:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011214 return get_errno(epoll_create(arg1));
Peter Maydell3b6edd12011-02-15 18:35:05 +000011215#endif
11216#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1)
11217 case TARGET_NR_epoll_create1:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011218 return get_errno(epoll_create1(arg1));
Peter Maydell3b6edd12011-02-15 18:35:05 +000011219#endif
11220#if defined(TARGET_NR_epoll_ctl)
11221 case TARGET_NR_epoll_ctl:
11222 {
11223 struct epoll_event ep;
11224 struct epoll_event *epp = 0;
11225 if (arg4) {
11226 struct target_epoll_event *target_ep;
11227 if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011228 return -TARGET_EFAULT;
Peter Maydell3b6edd12011-02-15 18:35:05 +000011229 }
11230 ep.events = tswap32(target_ep->events);
11231 /* The epoll_data_t union is just opaque data to the kernel,
11232 * so we transfer all 64 bits across and need not worry what
11233 * actual data type it is.
11234 */
11235 ep.data.u64 = tswap64(target_ep->data.u64);
11236 unlock_user_struct(target_ep, arg4, 0);
11237 epp = &ep;
11238 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011239 return get_errno(epoll_ctl(arg1, arg2, arg3, epp));
Peter Maydell3b6edd12011-02-15 18:35:05 +000011240 }
11241#endif
11242
Peter Maydell227f0212016-06-06 19:58:11 +010011243#if defined(TARGET_NR_epoll_wait) || defined(TARGET_NR_epoll_pwait)
Peter Maydell3b6edd12011-02-15 18:35:05 +000011244#if defined(TARGET_NR_epoll_wait)
11245 case TARGET_NR_epoll_wait:
11246#endif
Peter Maydell227f0212016-06-06 19:58:11 +010011247#if defined(TARGET_NR_epoll_pwait)
Peter Maydell3b6edd12011-02-15 18:35:05 +000011248 case TARGET_NR_epoll_pwait:
11249#endif
11250 {
11251 struct target_epoll_event *target_ep;
11252 struct epoll_event *ep;
11253 int epfd = arg1;
11254 int maxevents = arg3;
11255 int timeout = arg4;
11256
Peter Maydell2ba7fae32016-07-18 15:35:59 +010011257 if (maxevents <= 0 || maxevents > TARGET_EP_MAX_EVENTS) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011258 return -TARGET_EINVAL;
Peter Maydell2ba7fae32016-07-18 15:35:59 +010011259 }
11260
Peter Maydell3b6edd12011-02-15 18:35:05 +000011261 target_ep = lock_user(VERIFY_WRITE, arg2,
11262 maxevents * sizeof(struct target_epoll_event), 1);
11263 if (!target_ep) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011264 return -TARGET_EFAULT;
Peter Maydell3b6edd12011-02-15 18:35:05 +000011265 }
11266
Peter Maydell04c95f42016-07-18 15:36:00 +010011267 ep = g_try_new(struct epoll_event, maxevents);
11268 if (!ep) {
11269 unlock_user(target_ep, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011270 return -TARGET_ENOMEM;
Peter Maydell04c95f42016-07-18 15:36:00 +010011271 }
Peter Maydell3b6edd12011-02-15 18:35:05 +000011272
11273 switch (num) {
Peter Maydell227f0212016-06-06 19:58:11 +010011274#if defined(TARGET_NR_epoll_pwait)
Peter Maydell3b6edd12011-02-15 18:35:05 +000011275 case TARGET_NR_epoll_pwait:
11276 {
11277 target_sigset_t *target_set;
11278 sigset_t _set, *set = &_set;
11279
11280 if (arg5) {
Peter Maydellc8157012016-06-30 14:23:24 +010011281 if (arg6 != sizeof(target_sigset_t)) {
11282 ret = -TARGET_EINVAL;
11283 break;
11284 }
11285
Peter Maydell3b6edd12011-02-15 18:35:05 +000011286 target_set = lock_user(VERIFY_READ, arg5,
11287 sizeof(target_sigset_t), 1);
11288 if (!target_set) {
Peter Maydell04c95f42016-07-18 15:36:00 +010011289 ret = -TARGET_EFAULT;
11290 break;
Peter Maydell3b6edd12011-02-15 18:35:05 +000011291 }
11292 target_to_host_sigset(set, target_set);
11293 unlock_user(target_set, arg5, 0);
11294 } else {
11295 set = NULL;
11296 }
11297
Peter Maydell227f0212016-06-06 19:58:11 +010011298 ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
11299 set, SIGSET_T_SIZE));
Peter Maydell3b6edd12011-02-15 18:35:05 +000011300 break;
11301 }
11302#endif
11303#if defined(TARGET_NR_epoll_wait)
11304 case TARGET_NR_epoll_wait:
Peter Maydell227f0212016-06-06 19:58:11 +010011305 ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
11306 NULL, 0));
Peter Maydell3b6edd12011-02-15 18:35:05 +000011307 break;
11308#endif
11309 default:
11310 ret = -TARGET_ENOSYS;
11311 }
11312 if (!is_error(ret)) {
11313 int i;
11314 for (i = 0; i < ret; i++) {
11315 target_ep[i].events = tswap32(ep[i].events);
11316 target_ep[i].data.u64 = tswap64(ep[i].data.u64);
11317 }
Peter Maydell04c95f42016-07-18 15:36:00 +010011318 unlock_user(target_ep, arg2,
11319 ret * sizeof(struct target_epoll_event));
11320 } else {
11321 unlock_user(target_ep, arg2, 0);
Peter Maydell3b6edd12011-02-15 18:35:05 +000011322 }
Peter Maydell04c95f42016-07-18 15:36:00 +010011323 g_free(ep);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011324 return ret;
Peter Maydell3b6edd12011-02-15 18:35:05 +000011325 }
11326#endif
11327#endif
Peter Maydell163a05a2011-06-27 17:44:52 +010011328#ifdef TARGET_NR_prlimit64
11329 case TARGET_NR_prlimit64:
11330 {
11331 /* args: pid, resource number, ptr to new rlimit, ptr to old rlimit */
11332 struct target_rlimit64 *target_rnew, *target_rold;
11333 struct host_rlimit64 rnew, rold, *rnewp = 0;
Felix Janda95018012014-12-02 22:11:17 +010011334 int resource = target_to_host_resource(arg2);
Peter Maydell163a05a2011-06-27 17:44:52 +010011335 if (arg3) {
11336 if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011337 return -TARGET_EFAULT;
Peter Maydell163a05a2011-06-27 17:44:52 +010011338 }
11339 rnew.rlim_cur = tswap64(target_rnew->rlim_cur);
11340 rnew.rlim_max = tswap64(target_rnew->rlim_max);
11341 unlock_user_struct(target_rnew, arg3, 0);
11342 rnewp = &rnew;
11343 }
11344
Felix Janda95018012014-12-02 22:11:17 +010011345 ret = get_errno(sys_prlimit64(arg1, resource, rnewp, arg4 ? &rold : 0));
Peter Maydell163a05a2011-06-27 17:44:52 +010011346 if (!is_error(ret) && arg4) {
11347 if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011348 return -TARGET_EFAULT;
Peter Maydell163a05a2011-06-27 17:44:52 +010011349 }
11350 target_rold->rlim_cur = tswap64(rold.rlim_cur);
11351 target_rold->rlim_max = tswap64(rold.rlim_max);
11352 unlock_user_struct(target_rold, arg4, 1);
11353 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011354 return ret;
Peter Maydell163a05a2011-06-27 17:44:52 +010011355 }
11356#endif
Richard Henderson3d21d292012-09-15 13:20:46 -070011357#ifdef TARGET_NR_gethostname
11358 case TARGET_NR_gethostname:
11359 {
11360 char *name = lock_user(VERIFY_WRITE, arg1, arg2, 0);
11361 if (name) {
11362 ret = get_errno(gethostname(name, arg2));
11363 unlock_user(name, arg1, arg2);
11364 } else {
11365 ret = -TARGET_EFAULT;
11366 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011367 return ret;
Richard Henderson3d21d292012-09-15 13:20:46 -070011368 }
11369#endif
Riku Voipio89aaf1a2013-07-24 09:44:26 +030011370#ifdef TARGET_NR_atomic_cmpxchg_32
11371 case TARGET_NR_atomic_cmpxchg_32:
11372 {
11373 /* should use start_exclusive from main.c */
11374 abi_ulong mem_value;
11375 if (get_user_u32(mem_value, arg6)) {
11376 target_siginfo_t info;
11377 info.si_signo = SIGSEGV;
11378 info.si_errno = 0;
11379 info.si_code = TARGET_SEGV_MAPERR;
11380 info._sifields._sigfault._addr = arg6;
Peter Maydell9d2803f2016-07-28 16:44:46 +010011381 queue_signal((CPUArchState *)cpu_env, info.si_signo,
11382 QEMU_SI_FAULT, &info);
Riku Voipio89aaf1a2013-07-24 09:44:26 +030011383 ret = 0xdeadbeef;
11384
11385 }
11386 if (mem_value == arg2)
11387 put_user_u32(arg1, arg6);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011388 return mem_value;
Riku Voipio89aaf1a2013-07-24 09:44:26 +030011389 }
11390#endif
11391#ifdef TARGET_NR_atomic_barrier
11392 case TARGET_NR_atomic_barrier:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011393 /* Like the kernel implementation and the
11394 qemu arm barrier, no-op this? */
11395 return 0;
Riku Voipio89aaf1a2013-07-24 09:44:26 +030011396#endif
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011397
11398#ifdef TARGET_NR_timer_create
11399 case TARGET_NR_timer_create:
11400 {
11401 /* args: clockid_t clockid, struct sigevent *sevp, timer_t *timerid */
11402
11403 struct sigevent host_sevp = { {0}, }, *phost_sevp = NULL;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011404
11405 int clkid = arg1;
11406 int timer_index = next_free_host_timer();
11407
11408 if (timer_index < 0) {
11409 ret = -TARGET_EAGAIN;
11410 } else {
11411 timer_t *phtimer = g_posix_timers + timer_index;
11412
11413 if (arg2) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011414 phost_sevp = &host_sevp;
Peter Maydellc0659762014-08-09 15:42:32 +010011415 ret = target_to_host_sigevent(phost_sevp, arg2);
11416 if (ret != 0) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011417 return ret;
Peter Maydellc0659762014-08-09 15:42:32 +010011418 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011419 }
11420
11421 ret = get_errno(timer_create(clkid, phost_sevp, phtimer));
11422 if (ret) {
11423 phtimer = NULL;
11424 } else {
Alexander Grafaecc8862014-11-10 21:33:03 +010011425 if (put_user(TIMER_MAGIC | timer_index, arg3, target_timer_t)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011426 return -TARGET_EFAULT;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011427 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011428 }
11429 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011430 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011431 }
11432#endif
11433
11434#ifdef TARGET_NR_timer_settime
11435 case TARGET_NR_timer_settime:
11436 {
11437 /* args: timer_t timerid, int flags, const struct itimerspec *new_value,
11438 * struct itimerspec * old_value */
Alexander Grafaecc8862014-11-10 21:33:03 +010011439 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020011440
Alexander Grafaecc8862014-11-10 21:33:03 +010011441 if (timerid < 0) {
11442 ret = timerid;
11443 } else if (arg3 == 0) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011444 ret = -TARGET_EINVAL;
11445 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020011446 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011447 struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
11448
Marc-André Lureau40c80b52017-01-19 10:15:32 -050011449 if (target_to_host_itimerspec(&hspec_new, arg3)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011450 return -TARGET_EFAULT;
Marc-André Lureau40c80b52017-01-19 10:15:32 -050011451 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011452 ret = get_errno(
11453 timer_settime(htimer, arg2, &hspec_new, &hspec_old));
Marc-André Lureau40c80b52017-01-19 10:15:32 -050011454 if (arg4 && host_to_target_itimerspec(arg4, &hspec_old)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011455 return -TARGET_EFAULT;
Marc-André Lureau40c80b52017-01-19 10:15:32 -050011456 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011457 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011458 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011459 }
11460#endif
11461
11462#ifdef TARGET_NR_timer_gettime
11463 case TARGET_NR_timer_gettime:
11464 {
11465 /* args: timer_t timerid, struct itimerspec *curr_value */
Alexander Grafaecc8862014-11-10 21:33:03 +010011466 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020011467
Alexander Grafaecc8862014-11-10 21:33:03 +010011468 if (timerid < 0) {
11469 ret = timerid;
11470 } else if (!arg2) {
11471 ret = -TARGET_EFAULT;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011472 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020011473 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011474 struct itimerspec hspec;
11475 ret = get_errno(timer_gettime(htimer, &hspec));
11476
11477 if (host_to_target_itimerspec(arg2, &hspec)) {
11478 ret = -TARGET_EFAULT;
11479 }
11480 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011481 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011482 }
11483#endif
11484
11485#ifdef TARGET_NR_timer_getoverrun
11486 case TARGET_NR_timer_getoverrun:
11487 {
11488 /* args: timer_t timerid */
Alexander Grafaecc8862014-11-10 21:33:03 +010011489 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020011490
Alexander Grafaecc8862014-11-10 21:33:03 +010011491 if (timerid < 0) {
11492 ret = timerid;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011493 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020011494 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011495 ret = get_errno(timer_getoverrun(htimer));
11496 }
Laurent Viviere36800c2015-10-02 14:48:09 +020011497 fd_trans_unregister(ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011498 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011499 }
11500#endif
11501
11502#ifdef TARGET_NR_timer_delete
11503 case TARGET_NR_timer_delete:
11504 {
11505 /* args: timer_t timerid */
Alexander Grafaecc8862014-11-10 21:33:03 +010011506 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020011507
Alexander Grafaecc8862014-11-10 21:33:03 +010011508 if (timerid < 0) {
11509 ret = timerid;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011510 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020011511 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011512 ret = get_errno(timer_delete(htimer));
Alexander Grafe52a99f2014-08-22 13:56:18 +020011513 g_posix_timers[timerid] = 0;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011514 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011515 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110011516 }
11517#endif
11518
Riku Voipio51834342014-06-22 11:25:42 +010011519#if defined(TARGET_NR_timerfd_create) && defined(CONFIG_TIMERFD)
11520 case TARGET_NR_timerfd_create:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011521 return get_errno(timerfd_create(arg1,
11522 target_to_host_bitmask(arg2, fcntl_flags_tbl)));
Riku Voipio51834342014-06-22 11:25:42 +010011523#endif
11524
11525#if defined(TARGET_NR_timerfd_gettime) && defined(CONFIG_TIMERFD)
11526 case TARGET_NR_timerfd_gettime:
11527 {
11528 struct itimerspec its_curr;
11529
11530 ret = get_errno(timerfd_gettime(arg1, &its_curr));
11531
11532 if (arg2 && host_to_target_itimerspec(arg2, &its_curr)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011533 return -TARGET_EFAULT;
Riku Voipio51834342014-06-22 11:25:42 +010011534 }
11535 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011536 return ret;
Riku Voipio51834342014-06-22 11:25:42 +010011537#endif
11538
11539#if defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD)
11540 case TARGET_NR_timerfd_settime:
11541 {
11542 struct itimerspec its_new, its_old, *p_new;
11543
11544 if (arg3) {
11545 if (target_to_host_itimerspec(&its_new, arg3)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011546 return -TARGET_EFAULT;
Riku Voipio51834342014-06-22 11:25:42 +010011547 }
11548 p_new = &its_new;
11549 } else {
11550 p_new = NULL;
11551 }
11552
11553 ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
11554
11555 if (arg4 && host_to_target_itimerspec(arg4, &its_old)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011556 return -TARGET_EFAULT;
Riku Voipio51834342014-06-22 11:25:42 +010011557 }
11558 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011559 return ret;
Riku Voipio51834342014-06-22 11:25:42 +010011560#endif
11561
Paul Burtonab31cda2014-06-22 11:25:43 +010011562#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
11563 case TARGET_NR_ioprio_get:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011564 return get_errno(ioprio_get(arg1, arg2));
Paul Burtonab31cda2014-06-22 11:25:43 +010011565#endif
11566
11567#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
11568 case TARGET_NR_ioprio_set:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011569 return get_errno(ioprio_set(arg1, arg2, arg3));
Paul Burtonab31cda2014-06-22 11:25:43 +010011570#endif
11571
Riku Voipio9af5c902014-08-12 15:58:57 +030011572#if defined(TARGET_NR_setns) && defined(CONFIG_SETNS)
11573 case TARGET_NR_setns:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011574 return get_errno(setns(arg1, arg2));
Riku Voipio9af5c902014-08-12 15:58:57 +030011575#endif
11576#if defined(TARGET_NR_unshare) && defined(CONFIG_SETNS)
11577 case TARGET_NR_unshare:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011578 return get_errno(unshare(arg1));
Riku Voipio9af5c902014-08-12 15:58:57 +030011579#endif
Laurent Vivier2f147882016-09-25 22:20:20 +020011580#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
11581 case TARGET_NR_kcmp:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011582 return get_errno(kcmp(arg1, arg2, arg3, arg4, arg5));
Laurent Vivier2f147882016-09-25 22:20:20 +020011583#endif
Richard Hendersonfa97e382018-07-18 13:06:48 -070011584#ifdef TARGET_NR_swapcontext
11585 case TARGET_NR_swapcontext:
11586 /* PowerPC specific. */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011587 return do_swapcontext(cpu_env, arg1, arg2, arg3);
Richard Hendersonfa97e382018-07-18 13:06:48 -070011588#endif
Riku Voipio9af5c902014-08-12 15:58:57 +030011589
bellard31e31b82003-02-18 22:55:36 +000011590 default:
Philippe Mathieu-Daudé122f9c82018-07-06 12:51:25 -030011591 qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011592 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +000011593 }
bellard31e31b82003-02-18 22:55:36 +000011594 return ret;
11595}
Richard Hendersondc1ce182018-08-18 12:01:04 -070011596
11597abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
11598 abi_long arg2, abi_long arg3, abi_long arg4,
11599 abi_long arg5, abi_long arg6, abi_long arg7,
11600 abi_long arg8)
11601{
11602 CPUState *cpu = ENV_GET_CPU(cpu_env);
11603 abi_long ret;
11604
11605#ifdef DEBUG_ERESTARTSYS
11606 /* Debug-only code for exercising the syscall-restart code paths
11607 * in the per-architecture cpu main loops: restart every syscall
11608 * the guest makes once before letting it through.
11609 */
11610 {
11611 static bool flag;
11612 flag = !flag;
11613 if (flag) {
11614 return -TARGET_ERESTARTSYS;
11615 }
11616 }
11617#endif
11618
11619 trace_guest_user_syscall(cpu, num, arg1, arg2, arg3, arg4,
11620 arg5, arg6, arg7, arg8);
11621
11622 if (unlikely(do_strace)) {
11623 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
11624 ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4,
11625 arg5, arg6, arg7, arg8);
11626 print_syscall_ret(num, ret);
11627 } else {
11628 ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4,
11629 arg5, arg6, arg7, arg8);
11630 }
11631
11632 trace_guest_user_syscall_ret(cpu, num, ret);
11633 return ret;
11634}