blob: d499cac1d5d1b975be077951c31c18c03fc8d6d9 [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/*
2 * Linux syscalls
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard31e31b82003-02-18 22:55:36 +00004 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * along with this program; if not, see <http://www.gnu.org/licenses/>.
bellard31e31b82003-02-18 22:55:36 +000018 */
Eduardo Habkostd5b3a9b2009-06-09 18:26:31 -030019#define _ATFILE_SOURCE
Peter Maydelld39594e2016-01-26 18:17:02 +000020#include "qemu/osdep.h"
Veronia Bahaaf348b6d2016-03-20 19:16:19 +020021#include "qemu/cutils.h"
22#include "qemu/path.h"
Shu-Chun Weng9bdfa4d2019-08-19 11:09:47 -070023#include "qemu/memfd.h"
Markus Armbrusterdc5e9ac2019-08-12 07:23:49 +020024#include "qemu/queue.h"
bellard31e31b82003-02-18 22:55:36 +000025#include <elf.h>
26#include <endian.h>
John Spencerc56dc772012-12-10 07:59:46 +010027#include <grp.h>
thsd08d3bb2007-03-19 13:09:22 +000028#include <sys/ipc.h>
29#include <sys/msg.h>
bellard31e31b82003-02-18 22:55:36 +000030#include <sys/wait.h>
bellard31e31b82003-02-18 22:55:36 +000031#include <sys/mount.h>
John Spencer586b0be2012-12-26 00:49:49 +010032#include <sys/file.h>
33#include <sys/fsuid.h>
34#include <sys/personality.h>
ths39b9aae2007-02-11 18:36:44 +000035#include <sys/prctl.h>
bellard31e31b82003-02-18 22:55:36 +000036#include <sys/resource.h>
bellard31e31b82003-02-18 22:55:36 +000037#include <sys/swap.h>
Peter Maydelle0eb2102014-03-17 12:15:35 +000038#include <linux/capability.h>
bellard31e31b82003-02-18 22:55:36 +000039#include <sched.h>
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +020040#include <sys/timex.h>
bellard31e31b82003-02-18 22:55:36 +000041#include <sys/socket.h>
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +020042#include <linux/sockios.h>
aurel32607175e2009-04-15 16:11:59 +000043#include <sys/un.h>
bellard31e31b82003-02-18 22:55:36 +000044#include <sys/uio.h>
Felix Janda0839f112016-09-30 19:40:21 -040045#include <poll.h>
bellard32f36bc2003-03-30 21:29:48 +000046#include <sys/times.h>
bellard8853f862004-02-22 14:57:26 +000047#include <sys/shm.h>
thsfa294812007-02-02 22:05:00 +000048#include <sys/sem.h>
bellard56c8f682005-11-28 22:28:41 +000049#include <sys/statfs.h>
bellardebc05482003-09-30 21:08:41 +000050#include <utime.h>
bellarda5448a72004-06-19 16:59:03 +000051#include <sys/sysinfo.h>
Laurent Viviere36800c2015-10-02 14:48:09 +020052#include <sys/signalfd.h>
bellard72f03902003-02-18 23:33:18 +000053//#include <sys/user.h>
Shu-Chun Weng22db1212020-12-18 11:32:12 -080054#include <netinet/in.h>
bellard8853f862004-02-22 14:57:26 +000055#include <netinet/ip.h>
bellard7854b052003-03-29 17:22:23 +000056#include <netinet/tcp.h>
Shu-Chun Wengfe51b0a2020-12-18 11:32:11 -080057#include <netinet/udp.h>
Laurent Vivier86fcd942011-03-30 01:35:23 +020058#include <linux/wireless.h>
Jing Huang920394d2012-07-24 13:59:23 +000059#include <linux/icmp.h>
Helge Delleree1ac3a2017-02-18 23:31:30 +010060#include <linux/icmpv6.h>
Shu-Chun Weng6addf062020-09-28 18:48:01 -070061#include <linux/if_tun.h>
Shu-Chun Weng22db1212020-12-18 11:32:12 -080062#include <linux/in6.h>
Helge Delleree1ac3a2017-02-18 23:31:30 +010063#include <linux/errqueue.h>
Marco A L Barbosad6d6d6f2017-10-05 10:55:30 -030064#include <linux/random.h>
Riku Voipiod80a1902014-10-01 16:05:46 +030065#ifdef CONFIG_TIMERFD
66#include <sys/timerfd.h>
67#endif
Riku Voipioc2882b92009-08-12 15:08:24 +030068#ifdef CONFIG_EVENTFD
69#include <sys/eventfd.h>
70#endif
Peter Maydell3b6edd12011-02-15 18:35:05 +000071#ifdef CONFIG_EPOLL
72#include <sys/epoll.h>
73#endif
An-Cheng Huanga790ae32011-08-09 12:34:06 -070074#ifdef CONFIG_ATTR
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010075#include "qemu/xattr.h"
An-Cheng Huanga790ae32011-08-09 12:34:06 -070076#endif
Peter Maydella8fd1ab2013-02-08 07:31:55 +000077#ifdef CONFIG_SENDFILE
78#include <sys/sendfile.h>
79#endif
Thomas Huth4a9d5f82020-11-18 18:10:51 +010080#ifdef HAVE_SYS_KCOV_H
Aleksandar Markovicbd27e672020-01-16 23:49:50 +010081#include <sys/kcov.h>
82#endif
bellard31e31b82003-02-18 22:55:36 +000083
84#define termios host_termios
85#define winsize host_winsize
86#define termio host_termio
bellard04369ff2003-03-20 22:33:23 +000087#define sgttyb host_sgttyb /* same as target */
88#define tchars host_tchars /* same as target */
89#define ltchars host_ltchars /* same as target */
bellard31e31b82003-02-18 22:55:36 +000090
91#include <linux/termios.h>
92#include <linux/unistd.h>
bellard31e31b82003-02-18 22:55:36 +000093#include <linux/cdrom.h>
94#include <linux/hdreg.h>
95#include <linux/soundcard.h>
bellard19b84f32003-05-08 15:41:49 +000096#include <linux/kd.h>
balrog8fbd6b52008-09-20 03:03:09 +000097#include <linux/mtio.h>
Daniel P. Berrangé3cd3df22022-08-02 12:41:34 -040098
99#ifdef HAVE_SYS_MOUNT_FSCONFIG
100/*
101 * glibc >= 2.36 linux/mount.h conflicts with sys/mount.h,
102 * which in turn prevents use of linux/fs.h. So we have to
103 * define the constants ourselves for now.
104 */
105#define FS_IOC_GETFLAGS _IOR('f', 1, long)
106#define FS_IOC_SETFLAGS _IOW('f', 2, long)
107#define FS_IOC_GETVERSION _IOR('v', 1, long)
108#define FS_IOC_SETVERSION _IOW('v', 2, long)
109#define FS_IOC_FIEMAP _IOWR('f', 11, struct fiemap)
110#define FS_IOC32_GETFLAGS _IOR('f', 1, int)
111#define FS_IOC32_SETFLAGS _IOW('f', 2, int)
112#define FS_IOC32_GETVERSION _IOR('v', 1, int)
113#define FS_IOC32_SETVERSION _IOW('v', 2, int)
Daniel P. Berrangéc5495f42022-10-04 10:32:03 +0100114
115#define BLKGETSIZE64 _IOR(0x12,114,size_t)
116#define BLKDISCARD _IO(0x12,119)
117#define BLKIOMIN _IO(0x12,120)
118#define BLKIOOPT _IO(0x12,121)
119#define BLKALIGNOFF _IO(0x12,122)
120#define BLKPBSZGET _IO(0x12,123)
121#define BLKDISCARDZEROES _IO(0x12,124)
122#define BLKSECDISCARD _IO(0x12,125)
123#define BLKROTATIONAL _IO(0x12,126)
124#define BLKZEROOUT _IO(0x12,127)
125
126#define FIBMAP _IO(0x00,1)
127#define FIGETBSZ _IO(0x00,2)
128
129struct file_clone_range {
130 __s64 src_fd;
131 __u64 src_offset;
132 __u64 src_length;
133 __u64 dest_offset;
134};
135
136#define FICLONE _IOW(0x94, 9, int)
137#define FICLONERANGE _IOW(0x94, 13, struct file_clone_range)
138
Daniel P. Berrangé3cd3df22022-08-02 12:41:34 -0400139#else
Martin Mohring350d1772009-05-04 21:21:41 +0300140#include <linux/fs.h>
Daniel P. Berrangé3cd3df22022-08-02 12:41:34 -0400141#endif
Yunqiang Suab22b4d2019-09-04 14:59:24 +0200142#include <linux/fd.h>
Peter Maydelldace20d2011-01-10 13:11:24 +0000143#if defined(CONFIG_FIEMAP)
Peter Maydell285da2b2011-01-06 15:04:18 +0000144#include <linux/fiemap.h>
Peter Maydelldace20d2011-01-10 13:11:24 +0000145#endif
Ulrich Hechtf7680a52009-10-16 17:00:44 +0200146#include <linux/fb.h>
Cortland Tölva6c753a62018-10-08 09:35:20 -0700147#if defined(CONFIG_USBFS)
148#include <linux/usbdevice_fs.h>
Cortland Tölvaa1333672018-10-08 09:35:21 -0700149#include <linux/usb/ch9.h>
Cortland Tölva6c753a62018-10-08 09:35:20 -0700150#endif
Ulrich Hechtf7680a52009-10-16 17:00:44 +0200151#include <linux/vt.h>
Alexander Graf56e904e2012-01-31 18:42:06 +0100152#include <linux/dm-ioctl.h>
Laurent Vivierc07ecc62013-01-07 11:40:06 +0000153#include <linux/reboot.h>
Laurent Vivier7ff7b662013-07-02 14:04:12 +0100154#include <linux/route.h>
Laurent Vivierf57d4192013-08-30 01:46:41 +0200155#include <linux/filter.h>
Andreas Färberfff8c532014-01-18 07:38:30 +0100156#include <linux/blkpg.h>
Laurent Viviera82ea932016-06-27 00:18:22 +0200157#include <netpacket/packet.h>
Laurent Vivier6c5b5642016-05-22 18:56:19 +0200158#include <linux/netlink.h>
Yunqiang Suf31dddd2019-06-19 16:17:11 +0200159#include <linux/if_alg.h>
Filip Bozuta68365f92020-01-15 20:36:35 +0100160#include <linux/rtc.h>
Filip Bozuta1c4c6fc2020-01-15 20:36:41 +0100161#include <sound/asound.h>
Thomas Huth48f670e2020-11-18 18:10:52 +0100162#ifdef HAVE_BTRFS_H
Filip Bozutad6092e02020-08-23 21:50:07 +0200163#include <linux/btrfs.h>
164#endif
Chen Gange865b972020-06-05 09:32:21 +0800165#ifdef HAVE_DRM_H
166#include <libdrm/drm.h>
Chen Gang913b03c2020-08-02 21:39:38 +0800167#include <libdrm/i915_drm.h>
Chen Gange865b972020-06-05 09:32:21 +0800168#endif
pbrookd7e40362008-05-23 16:06:43 +0000169#include "linux_loop.h"
Riku Voipio18cb0082014-02-19 12:59:58 +0200170#include "uname.h"
bellard31e31b82003-02-18 22:55:36 +0000171
bellard3ef693a2003-03-23 20:17:16 +0000172#include "qemu.h"
Peter Maydell3b249d22021-09-08 16:44:03 +0100173#include "user-internals.h"
Peter Maydella44d57a2021-09-08 16:43:58 +0100174#include "strace.h"
Peter Maydell2113aed2021-09-08 16:43:59 +0100175#include "signal-common.h"
Peter Maydell3ad0a762021-09-08 16:44:00 +0100176#include "loader.h"
Peter Maydell5423e6d2021-09-08 16:44:01 +0100177#include "user-mmap.h"
Richard Hendersonbbf15aa2021-11-17 16:14:00 +0100178#include "user/safe-syscall.h"
Richard Henderson5ebdd772019-03-14 13:10:53 -0700179#include "qemu/guest-random.h"
Alex Bennée01ef6b92020-04-03 20:11:46 +0100180#include "qemu/selfmap.h"
Emilio G. Cotac36f7a62018-10-21 13:27:44 -0400181#include "user/syscall-trace.h"
Richard Henderson5da40632021-11-17 15:46:05 +0100182#include "special-errno.h"
Richard Henderson51977e22019-03-12 19:22:20 -0700183#include "qapi/error.h"
Laurent Vivierf7e6a402018-08-24 00:22:15 +0200184#include "fd-trans.h"
Philippe Mathieu-Daudédcb32f12020-01-01 12:23:00 +0100185#include "tcg/tcg.h"
bellard31e31b82003-02-18 22:55:36 +0000186
Peter Maydell5ea2fc82016-08-02 18:41:27 +0100187#ifndef CLONE_IO
188#define CLONE_IO 0x80000000 /* Clone io context */
189#endif
190
191/* We can't directly call the host clone syscall, because this will
192 * badly confuse libc (breaking mutexes, for example). So we must
193 * divide clone flags into:
194 * * flag combinations that look like pthread_create()
195 * * flag combinations that look like fork()
196 * * flags we can implement within QEMU itself
197 * * flags we can't support and will return an error for
198 */
199/* For thread creation, all these flags must be present; for
200 * fork, none must be present.
201 */
202#define CLONE_THREAD_FLAGS \
203 (CLONE_VM | CLONE_FS | CLONE_FILES | \
204 CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM)
205
206/* These flags are ignored:
207 * CLONE_DETACHED is now ignored by the kernel;
208 * CLONE_IO is just an optimisation hint to the I/O scheduler
209 */
210#define CLONE_IGNORED_FLAGS \
211 (CLONE_DETACHED | CLONE_IO)
212
213/* Flags for fork which we can implement within QEMU itself */
214#define CLONE_OPTIONAL_FORK_FLAGS \
215 (CLONE_SETTLS | CLONE_PARENT_SETTID | \
216 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID)
217
218/* Flags for thread creation which we can implement within QEMU itself */
219#define CLONE_OPTIONAL_THREAD_FLAGS \
220 (CLONE_SETTLS | CLONE_PARENT_SETTID | \
221 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | CLONE_PARENT)
222
223#define CLONE_INVALID_FORK_FLAGS \
224 (~(CSIGNAL | CLONE_OPTIONAL_FORK_FLAGS | CLONE_IGNORED_FLAGS))
225
226#define CLONE_INVALID_THREAD_FLAGS \
227 (~(CSIGNAL | CLONE_THREAD_FLAGS | CLONE_OPTIONAL_THREAD_FLAGS | \
228 CLONE_IGNORED_FLAGS))
229
230/* CLONE_VFORK is special cased early in do_fork(). The other flag bits
231 * have almost all been allocated. We cannot support any of
232 * CLONE_NEWNS, CLONE_NEWCGROUP, CLONE_NEWUTS, CLONE_NEWIPC,
233 * CLONE_NEWUSER, CLONE_NEWPID, CLONE_NEWNET, CLONE_PTRACE, CLONE_UNTRACED.
234 * The checks against the invalid thread masks above will catch these.
235 * (The one remaining unallocated bit is 0x1000 which used to be CLONE_PID.)
236 */
pbrook30813ce2008-06-02 15:45:44 +0000237
Timothy E Baldwin71a8f7f2016-05-12 18:47:45 +0100238/* Define DEBUG_ERESTARTSYS to force every syscall to be restarted
239 * once. This exercises the codepaths for restart.
240 */
241//#define DEBUG_ERESTARTSYS
bellard31e31b82003-02-18 22:55:36 +0000242
bellard1a9353d2003-03-16 20:28:50 +0000243//#include <linux/msdos_fs.h>
Richard Henderson540a7362021-11-14 11:35:37 +0100244#define VFAT_IOCTL_READDIR_BOTH \
245 _IOC(_IOC_READ, 'r', 1, (sizeof(struct linux_dirent) + 256) * 2)
246#define VFAT_IOCTL_READDIR_SHORT \
247 _IOC(_IOC_READ, 'r', 2, (sizeof(struct linux_dirent) + 256) * 2)
bellard1a9353d2003-03-16 20:28:50 +0000248
bellard70a194b2003-08-11 22:20:16 +0000249#undef _syscall0
250#undef _syscall1
251#undef _syscall2
252#undef _syscall3
253#undef _syscall4
254#undef _syscall5
bellard83fcb512006-06-14 13:37:16 +0000255#undef _syscall6
bellard70a194b2003-08-11 22:20:16 +0000256
bellard83fcb512006-06-14 13:37:16 +0000257#define _syscall0(type,name) \
blueswir18fcd3692008-08-17 20:26:25 +0000258static type name (void) \
bellard83fcb512006-06-14 13:37:16 +0000259{ \
260 return syscall(__NR_##name); \
bellard70a194b2003-08-11 22:20:16 +0000261}
262
bellard83fcb512006-06-14 13:37:16 +0000263#define _syscall1(type,name,type1,arg1) \
blueswir18fcd3692008-08-17 20:26:25 +0000264static type name (type1 arg1) \
bellard83fcb512006-06-14 13:37:16 +0000265{ \
266 return syscall(__NR_##name, arg1); \
bellard70a194b2003-08-11 22:20:16 +0000267}
268
bellard83fcb512006-06-14 13:37:16 +0000269#define _syscall2(type,name,type1,arg1,type2,arg2) \
blueswir18fcd3692008-08-17 20:26:25 +0000270static type name (type1 arg1,type2 arg2) \
bellard83fcb512006-06-14 13:37:16 +0000271{ \
272 return syscall(__NR_##name, arg1, arg2); \
bellard70a194b2003-08-11 22:20:16 +0000273}
274
bellard83fcb512006-06-14 13:37:16 +0000275#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
blueswir18fcd3692008-08-17 20:26:25 +0000276static type name (type1 arg1,type2 arg2,type3 arg3) \
bellard83fcb512006-06-14 13:37:16 +0000277{ \
278 return syscall(__NR_##name, arg1, arg2, arg3); \
bellard70a194b2003-08-11 22:20:16 +0000279}
280
bellard83fcb512006-06-14 13:37:16 +0000281#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
blueswir18fcd3692008-08-17 20:26:25 +0000282static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
bellard83fcb512006-06-14 13:37:16 +0000283{ \
284 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
bellard70a194b2003-08-11 22:20:16 +0000285}
286
bellard83fcb512006-06-14 13:37:16 +0000287#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
288 type5,arg5) \
blueswir18fcd3692008-08-17 20:26:25 +0000289static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
bellard83fcb512006-06-14 13:37:16 +0000290{ \
291 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
bellard70a194b2003-08-11 22:20:16 +0000292}
bellard83fcb512006-06-14 13:37:16 +0000293
294
295#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
296 type5,arg5,type6,arg6) \
blueswir18fcd3692008-08-17 20:26:25 +0000297static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
298 type6 arg6) \
bellard83fcb512006-06-14 13:37:16 +0000299{ \
300 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
301}
302
bellard70a194b2003-08-11 22:20:16 +0000303
bellard31e31b82003-02-18 22:55:36 +0000304#define __NR_sys_uname __NR_uname
bellard72f03902003-02-18 23:33:18 +0000305#define __NR_sys_getcwd1 __NR_getcwd
bellard72f03902003-02-18 23:33:18 +0000306#define __NR_sys_getdents __NR_getdents
bellarddab2ed92003-03-22 15:23:14 +0000307#define __NR_sys_getdents64 __NR_getdents64
thsc6cda172007-10-09 03:42:34 +0000308#define __NR_sys_getpriority __NR_getpriority
bellard66fb9762003-03-23 01:06:05 +0000309#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +0200310#define __NR_sys_rt_tgsigqueueinfo __NR_rt_tgsigqueueinfo
ths7494b0f2007-02-11 18:26:53 +0000311#define __NR_sys_syslog __NR_syslog
Alistair Francis14690292020-03-18 15:47:01 -0700312#if defined(__NR_futex)
313# define __NR_sys_futex __NR_futex
314#endif
315#if defined(__NR_futex_time64)
316# define __NR_sys_futex_time64 __NR_futex_time64
317#endif
Aleksandar Rikaloefa92182019-06-28 12:43:34 +0200318#define __NR_sys_statx __NR_statx
bellard31e31b82003-02-18 22:55:36 +0000319
Peter Maydellb1cef6d2018-01-25 16:19:49 +0000320#if defined(__alpha__) || defined(__x86_64__) || defined(__s390x__)
bellard9af9eaa2003-04-07 21:34:41 +0000321#define __NR__llseek __NR_lseek
322#endif
323
James Hogana29e5ba2014-03-25 21:51:08 +0000324/* Newer kernel ports have llseek() instead of _llseek() */
325#if defined(TARGET_NR_llseek) && !defined(TARGET_NR__llseek)
326#define TARGET_NR__llseek TARGET_NR_llseek
327#endif
328
Helge Deller78721302021-02-10 07:12:14 +0100329/* some platforms need to mask more bits than just TARGET_O_NONBLOCK */
330#ifndef TARGET_O_NONBLOCK_MASK
331#define TARGET_O_NONBLOCK_MASK TARGET_O_NONBLOCK
332#endif
333
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +0000334#define __NR_sys_gettid __NR_gettid
335_syscall0(int, sys_gettid)
Peter Maydell2b3f64c2018-04-19 13:57:40 +0100336
337/* For the 64-bit guest on 32-bit host case we must emulate
338 * getdents using getdents64, because otherwise the host
339 * might hand us back more dirent records than we can fit
340 * into the guest buffer after structure format conversion.
341 * Otherwise we emulate getdents with getdents if the host has it.
342 */
343#if defined(__NR_getdents) && HOST_LONG_BITS >= TARGET_ABI_BITS
344#define EMULATE_GETDENTS_WITH_GETDENTS
345#endif
346
347#if defined(TARGET_NR_getdents) && defined(EMULATE_GETDENTS_WITH_GETDENTS)
aurel323b3f24a2009-04-15 16:12:13 +0000348_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
Peter Maydell3307e232013-06-12 16:20:21 +0100349#endif
Peter Maydell2b3f64c2018-04-19 13:57:40 +0100350#if (defined(TARGET_NR_getdents) && \
351 !defined(EMULATE_GETDENTS_WITH_GETDENTS)) || \
Peter Maydell3307e232013-06-12 16:20:21 +0100352 (defined(TARGET_NR_getdents64) && defined(__NR_getdents64))
aurel323b3f24a2009-04-15 16:12:13 +0000353_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
354#endif
Richard Hendersond35b2612010-06-04 12:14:10 -0700355#if defined(TARGET_NR__llseek) && defined(__NR_llseek)
aurel323b3f24a2009-04-15 16:12:13 +0000356_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
357 loff_t *, res, uint, wh);
358#endif
Miloš Stojanovićc1a402a2017-05-15 16:59:45 +0200359_syscall3(int, sys_rt_sigqueueinfo, pid_t, pid, int, sig, siginfo_t *, uinfo)
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +0200360_syscall4(int, sys_rt_tgsigqueueinfo, pid_t, pid, pid_t, tid, int, sig,
361 siginfo_t *, uinfo)
aurel323b3f24a2009-04-15 16:12:13 +0000362_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
aurel323b3f24a2009-04-15 16:12:13 +0000363#ifdef __NR_exit_group
364_syscall1(int,exit_group,int,error_code)
365#endif
Alistair Francis14690292020-03-18 15:47:01 -0700366#if defined(__NR_futex)
aurel323b3f24a2009-04-15 16:12:13 +0000367_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
368 const struct timespec *,timeout,int *,uaddr2,int,val3)
369#endif
Alistair Francis14690292020-03-18 15:47:01 -0700370#if defined(__NR_futex_time64)
371_syscall6(int,sys_futex_time64,int *,uaddr,int,op,int,val,
372 const struct timespec *,timeout,int *,uaddr2,int,val3)
373#endif
Helge Dellercc054c62022-09-18 21:45:46 +0200374#if defined(__NR_pidfd_open) && defined(TARGET_NR_pidfd_open)
375_syscall2(int, pidfd_open, pid_t, pid, unsigned int, flags);
376#endif
377#if defined(__NR_pidfd_send_signal) && defined(TARGET_NR_pidfd_send_signal)
378_syscall4(int, pidfd_send_signal, int, pidfd, int, sig, siginfo_t *, info,
379 unsigned int, flags);
380#endif
381#if defined(__NR_pidfd_getfd) && defined(TARGET_NR_pidfd_getfd)
382_syscall3(int, pidfd_getfd, int, pidfd, int, targetfd, unsigned int, flags);
383#endif
Mike Frysinger737de1d2011-02-07 01:05:55 -0500384#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
385_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
386 unsigned long *, user_mask_ptr);
387#define __NR_sys_sched_setaffinity __NR_sched_setaffinity
388_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
389 unsigned long *, user_mask_ptr);
Tonis Tiigi45ad7612022-01-04 20:18:18 -0800390/* sched_attr is not defined in glibc */
391struct sched_attr {
392 uint32_t size;
393 uint32_t sched_policy;
394 uint64_t sched_flags;
395 int32_t sched_nice;
396 uint32_t sched_priority;
397 uint64_t sched_runtime;
398 uint64_t sched_deadline;
399 uint64_t sched_period;
400 uint32_t sched_util_min;
401 uint32_t sched_util_max;
402};
403#define __NR_sys_sched_getattr __NR_sched_getattr
404_syscall4(int, sys_sched_getattr, pid_t, pid, struct sched_attr *, attr,
405 unsigned int, size, unsigned int, flags);
406#define __NR_sys_sched_setattr __NR_sched_setattr
407_syscall3(int, sys_sched_setattr, pid_t, pid, struct sched_attr *, attr,
408 unsigned int, flags);
Tonis Tiigi407a1192022-01-04 20:18:19 -0800409#define __NR_sys_sched_getscheduler __NR_sched_getscheduler
410_syscall1(int, sys_sched_getscheduler, pid_t, pid);
411#define __NR_sys_sched_setscheduler __NR_sched_setscheduler
412_syscall3(int, sys_sched_setscheduler, pid_t, pid, int, policy,
413 const struct sched_param *, param);
414#define __NR_sys_sched_getparam __NR_sched_getparam
415_syscall2(int, sys_sched_getparam, pid_t, pid,
416 struct sched_param *, param);
417#define __NR_sys_sched_setparam __NR_sched_setparam
418_syscall2(int, sys_sched_setparam, pid_t, pid,
419 const struct sched_param *, param);
Samuel Thibaultb827c3e2018-01-12 09:14:35 +0100420#define __NR_sys_getcpu __NR_getcpu
421_syscall3(int, sys_getcpu, unsigned *, cpu, unsigned *, node, void *, tcache);
Alexander Graf0f6b4d22011-09-27 14:39:42 +0200422_syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd,
423 void *, arg);
Peter Maydelle0eb2102014-03-17 12:15:35 +0000424_syscall2(int, capget, struct __user_cap_header_struct *, header,
425 struct __user_cap_data_struct *, data);
426_syscall2(int, capset, struct __user_cap_header_struct *, header,
427 struct __user_cap_data_struct *, data);
Paul Burtonab31cda2014-06-22 11:25:43 +0100428#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
429_syscall2(int, ioprio_get, int, which, int, who)
430#endif
431#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
432_syscall3(int, ioprio_set, int, which, int, who, int, ioprio)
433#endif
Laurent Vivierf894efd2016-02-21 10:56:23 +0100434#if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
435_syscall3(int, getrandom, void *, buf, size_t, buflen, unsigned int, flags)
436#endif
aurel323b3f24a2009-04-15 16:12:13 +0000437
Laurent Vivier2f147882016-09-25 22:20:20 +0200438#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
439_syscall5(int, kcmp, pid_t, pid1, pid_t, pid2, int, type,
440 unsigned long, idx1, unsigned long, idx2)
441#endif
442
Aleksandar Rikaloefa92182019-06-28 12:43:34 +0200443/*
444 * It is assumed that struct statx is architecture independent.
445 */
446#if defined(TARGET_NR_statx) && defined(__NR_statx)
447_syscall5(int, sys_statx, int, dirfd, const char *, pathname, int, flags,
448 unsigned int, mask, struct target_statx *, statxbuf)
449#endif
Andreas Schwab85004762019-05-13 11:02:53 +0200450#if defined(TARGET_NR_membarrier) && defined(__NR_membarrier)
451_syscall2(int, membarrier, int, cmd, int, flags)
452#endif
Aleksandar Rikaloefa92182019-06-28 12:43:34 +0200453
Philippe Mathieu-Daudé180d4ef2021-05-17 07:52:43 +0200454static const bitmask_transtbl fcntl_flags_tbl[] = {
aurel323b3f24a2009-04-15 16:12:13 +0000455 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
456 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
457 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
458 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
459 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
460 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
461 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
462 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
Richard Hendersonafc87632012-07-25 14:30:34 -0700463 { TARGET_O_SYNC, TARGET_O_DSYNC, O_SYNC, O_DSYNC, },
aurel323b3f24a2009-04-15 16:12:13 +0000464 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
465 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
466 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
467 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
aurel323b3f24a2009-04-15 16:12:13 +0000468#if defined(O_DIRECT)
469 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
470#endif
Richard Hendersonafc87632012-07-25 14:30:34 -0700471#if defined(O_NOATIME)
472 { TARGET_O_NOATIME, TARGET_O_NOATIME, O_NOATIME, O_NOATIME },
473#endif
474#if defined(O_CLOEXEC)
475 { TARGET_O_CLOEXEC, TARGET_O_CLOEXEC, O_CLOEXEC, O_CLOEXEC },
476#endif
477#if defined(O_PATH)
478 { TARGET_O_PATH, TARGET_O_PATH, O_PATH, O_PATH },
479#endif
Riku Voipio5f9cee42017-08-08 16:01:19 +0300480#if defined(O_TMPFILE)
481 { TARGET_O_TMPFILE, TARGET_O_TMPFILE, O_TMPFILE, O_TMPFILE },
482#endif
Richard Hendersonafc87632012-07-25 14:30:34 -0700483 /* Don't terminate the list prematurely on 64-bit host+guest. */
484#if TARGET_O_LARGEFILE != 0 || O_LARGEFILE != 0
485 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
486#endif
aurel323b3f24a2009-04-15 16:12:13 +0000487 { 0, 0, 0, 0 }
488};
489
Andreas Schwab0f6bb192020-07-23 12:27:13 +0200490_syscall2(int, sys_getcwd1, char *, buf, size_t, size)
aurel323b3f24a2009-04-15 16:12:13 +0000491
Filip Bozutacac46eb2020-08-25 00:30:50 +0200492#if defined(TARGET_NR_utimensat) || defined(TARGET_NR_utimensat_time64)
Peter Maydell700fa582016-07-18 11:47:55 +0100493#if defined(__NR_utimensat)
Peter Maydell1acae9f2013-07-02 14:04:12 +0100494#define __NR_sys_utimensat __NR_utimensat
ths9007f0e2007-09-25 17:50:37 +0000495_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
496 const struct timespec *,tsp,int,flags)
Peter Maydell1acae9f2013-07-02 14:04:12 +0100497#else
498static int sys_utimensat(int dirfd, const char *pathname,
499 const struct timespec times[2], int flags)
500{
501 errno = ENOSYS;
502 return -1;
503}
ths9007f0e2007-09-25 17:50:37 +0000504#endif
Peter Maydell1acae9f2013-07-02 14:04:12 +0100505#endif /* TARGET_NR_utimensat */
aurel323b3f24a2009-04-15 16:12:13 +0000506
Andreas Schwab95d03072018-01-23 11:53:31 +0100507#ifdef TARGET_NR_renameat2
508#if defined(__NR_renameat2)
509#define __NR_sys_renameat2 __NR_renameat2
510_syscall5(int, sys_renameat2, int, oldfd, const char *, old, int, newfd,
511 const char *, new, unsigned int, flags)
512#else
513static int sys_renameat2(int oldfd, const char *old,
514 int newfd, const char *new, int flags)
515{
516 if (flags == 0) {
517 return renameat(oldfd, old, newfd, new);
518 }
519 errno = ENOSYS;
520 return -1;
521}
522#endif
523#endif /* TARGET_NR_renameat2 */
524
aurel323b3f24a2009-04-15 16:12:13 +0000525#ifdef CONFIG_INOTIFY
aurel328690e422009-04-17 13:50:32 +0000526#include <sys/inotify.h>
aurel323b3f24a2009-04-15 16:12:13 +0000527#else
528/* Userspace can usually survive runtime without inotify */
529#undef TARGET_NR_inotify_init
Riku Voipioc05c7a72010-03-26 15:25:11 +0000530#undef TARGET_NR_inotify_init1
aurel323b3f24a2009-04-15 16:12:13 +0000531#undef TARGET_NR_inotify_add_watch
532#undef TARGET_NR_inotify_rm_watch
533#endif /* CONFIG_INOTIFY */
534
Peter Maydell163a05a2011-06-27 17:44:52 +0100535#if defined(TARGET_NR_prlimit64)
536#ifndef __NR_prlimit64
537# define __NR_prlimit64 -1
538#endif
539#define __NR_sys_prlimit64 __NR_prlimit64
540/* The glibc rlimit structure may not be that used by the underlying syscall */
541struct host_rlimit64 {
542 uint64_t rlim_cur;
543 uint64_t rlim_max;
544};
545_syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
546 const struct host_rlimit64 *, new_limit,
547 struct host_rlimit64 *, old_limit)
548#endif
549
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +1100550
551#if defined(TARGET_NR_timer_create)
zhaolichang6f9ff552020-09-17 15:50:25 +0800552/* Maximum of 32 active POSIX timers allowed at any one time. */
Peter Maydell9e598992022-07-25 12:00:35 +0100553#define GUEST_TIMER_MAX 32
554static timer_t g_posix_timers[GUEST_TIMER_MAX];
555static int g_posix_timer_allocated[GUEST_TIMER_MAX];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +1100556
557static inline int next_free_host_timer(void)
558{
Peter Maydell9e598992022-07-25 12:00:35 +0100559 int k;
560 for (k = 0; k < ARRAY_SIZE(g_posix_timer_allocated); k++) {
561 if (qatomic_xchg(g_posix_timer_allocated + k, 1) == 0) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +1100562 return k;
563 }
564 }
565 return -1;
566}
Peter Maydell9e598992022-07-25 12:00:35 +0100567
568static inline void free_host_timer_slot(int id)
569{
570 qatomic_store_release(g_posix_timer_allocated + id, 0);
571}
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +1100572#endif
573
Philippe Mathieu-Daudé3ffe3262021-07-08 19:05:49 +0200574static inline int host_to_target_errno(int host_errno)
ths637947f2007-06-01 12:09:19 +0000575{
Philippe Mathieu-Daudé3ffe3262021-07-08 19:05:49 +0200576 switch (host_errno) {
577#define E(X) case X: return TARGET_##X;
578#include "errnos.c.inc"
579#undef E
580 default:
581 return host_errno;
Timothy E Baldwin24661192016-05-12 18:47:25 +0100582 }
ths637947f2007-06-01 12:09:19 +0000583}
584
Philippe Mathieu-Daudé3ffe3262021-07-08 19:05:49 +0200585static inline int target_to_host_errno(int target_errno)
thsb92c47c2007-11-01 00:07:38 +0000586{
Philippe Mathieu-Daudé3ffe3262021-07-08 19:05:49 +0200587 switch (target_errno) {
588#define E(X) case TARGET_##X: return X;
589#include "errnos.c.inc"
590#undef E
591 default:
592 return target_errno;
Timothy E Baldwin24661192016-05-12 18:47:25 +0100593 }
thsb92c47c2007-11-01 00:07:38 +0000594}
595
Ilya Leoshkevich892a4f62022-06-21 16:42:05 +0200596abi_long get_errno(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000597{
598 if (ret == -1)
ths637947f2007-06-01 12:09:19 +0000599 return -host_to_target_errno(errno);
bellard31e31b82003-02-18 22:55:36 +0000600 else
601 return ret;
602}
603
Peter Maydell7dcdaea2016-06-06 19:58:18 +0100604const char *target_strerror(int err)
thsb92c47c2007-11-01 00:07:38 +0000605{
Richard Hendersonaf254a22021-11-22 19:47:33 +0100606 if (err == QEMU_ERESTARTSYS) {
Peter Maydellda2a34f2016-06-06 19:58:19 +0100607 return "To be restarted";
608 }
Richard Henderson57a0c932021-11-17 05:14:52 -0800609 if (err == QEMU_ESIGRETURN) {
Peter Maydellda2a34f2016-06-06 19:58:19 +0100610 return "Successful exit from sigreturn";
611 }
612
thsb92c47c2007-11-01 00:07:38 +0000613 return strerror(target_to_host_errno(err));
614}
615
Tonis Tiigi45ad7612022-01-04 20:18:18 -0800616static int check_zeroed_user(abi_long addr, size_t ksize, size_t usize)
617{
618 int i;
619 uint8_t b;
620 if (usize <= ksize) {
621 return 1;
622 }
623 for (i = ksize; i < usize; i++) {
624 if (get_user_u8(b, addr + i)) {
625 return -TARGET_EFAULT;
626 }
627 if (b != 0) {
628 return 0;
629 }
630 }
631 return 1;
632}
633
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100634#define safe_syscall0(type, name) \
635static type safe_##name(void) \
636{ \
637 return safe_syscall(__NR_##name); \
638}
639
640#define safe_syscall1(type, name, type1, arg1) \
641static type safe_##name(type1 arg1) \
642{ \
643 return safe_syscall(__NR_##name, arg1); \
644}
645
646#define safe_syscall2(type, name, type1, arg1, type2, arg2) \
647static type safe_##name(type1 arg1, type2 arg2) \
648{ \
649 return safe_syscall(__NR_##name, arg1, arg2); \
650}
651
652#define safe_syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
653static type safe_##name(type1 arg1, type2 arg2, type3 arg3) \
654{ \
655 return safe_syscall(__NR_##name, arg1, arg2, arg3); \
656}
657
658#define safe_syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
659 type4, arg4) \
660static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
661{ \
662 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4); \
663}
664
665#define safe_syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \
666 type4, arg4, type5, arg5) \
667static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
668 type5 arg5) \
669{ \
670 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
671}
672
673#define safe_syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \
674 type4, arg4, type5, arg5, type6, arg6) \
675static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
676 type5 arg5, type6 arg6) \
677{ \
678 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
679}
680
Timothy E Baldwin50afd022016-05-12 18:47:47 +0100681safe_syscall3(ssize_t, read, int, fd, void *, buff, size_t, count)
682safe_syscall3(ssize_t, write, int, fd, const void *, buff, size_t, count)
Timothy E Baldwinc10a0732016-05-12 18:47:48 +0100683safe_syscall4(int, openat, int, dirfd, const char *, pathname, \
684 int, flags, mode_t, mode)
Alistair Francis859e8a82020-03-12 15:13:49 -0700685#if defined(TARGET_NR_wait4) || defined(TARGET_NR_waitpid)
Timothy E Baldwin4af80a32016-05-12 18:47:49 +0100686safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \
687 struct rusage *, rusage)
Alistair Francis859e8a82020-03-12 15:13:49 -0700688#endif
Timothy E Baldwin4af80a32016-05-12 18:47:49 +0100689safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \
690 int, options, struct rusage *, rusage)
Timothy E Baldwinffdcbe22016-05-12 18:47:50 +0100691safe_syscall3(int, execve, const char *, filename, char **, argv, char **, envp)
Alistair Francis859e8a82020-03-12 15:13:49 -0700692#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \
Filip Bozutae5ce9682020-08-25 00:30:49 +0200693 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
Peter Maydell6df9d382016-05-12 18:47:51 +0100694safe_syscall6(int, pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, \
695 fd_set *, exceptfds, struct timespec *, timeout, void *, sig)
Alistair Francis859e8a82020-03-12 15:13:49 -0700696#endif
Filip Bozutae5ce9682020-08-25 00:30:49 +0200697#if defined(TARGET_NR_ppoll) || defined(TARGET_NR_ppoll_time64)
Peter Maydella6130232016-06-06 19:58:10 +0100698safe_syscall5(int, ppoll, struct pollfd *, ufds, unsigned int, nfds,
699 struct timespec *, tsp, const sigset_t *, sigmask,
700 size_t, sigsetsize)
Alistair Francis859e8a82020-03-12 15:13:49 -0700701#endif
Peter Maydell227f0212016-06-06 19:58:11 +0100702safe_syscall6(int, epoll_pwait, int, epfd, struct epoll_event *, events,
703 int, maxevents, int, timeout, const sigset_t *, sigmask,
704 size_t, sigsetsize)
Alistair Francis14690292020-03-18 15:47:01 -0700705#if defined(__NR_futex)
Peter Maydelld509eeb2016-05-12 18:47:52 +0100706safe_syscall6(int,futex,int *,uaddr,int,op,int,val, \
707 const struct timespec *,timeout,int *,uaddr2,int,val3)
Alistair Francis859e8a82020-03-12 15:13:49 -0700708#endif
Alistair Francis14690292020-03-18 15:47:01 -0700709#if defined(__NR_futex_time64)
710safe_syscall6(int,futex_time64,int *,uaddr,int,op,int,val, \
711 const struct timespec *,timeout,int *,uaddr2,int,val3)
712#endif
Peter Maydell2fe4fba2016-05-27 15:51:48 +0100713safe_syscall2(int, rt_sigsuspend, sigset_t *, newset, size_t, sigsetsize)
Peter Maydellbef653d2016-05-27 15:51:57 +0100714safe_syscall2(int, kill, pid_t, pid, int, sig)
715safe_syscall2(int, tkill, int, tid, int, sig)
716safe_syscall3(int, tgkill, int, tgid, int, pid, int, sig)
Peter Maydell918c03e2016-06-06 19:58:02 +0100717safe_syscall3(ssize_t, readv, int, fd, const struct iovec *, iov, int, iovcnt)
718safe_syscall3(ssize_t, writev, int, fd, const struct iovec *, iov, int, iovcnt)
Dejan Jovicevic0f263862016-10-11 11:52:46 +0200719safe_syscall5(ssize_t, preadv, int, fd, const struct iovec *, iov, int, iovcnt,
720 unsigned long, pos_l, unsigned long, pos_h)
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +0200721safe_syscall5(ssize_t, pwritev, int, fd, const struct iovec *, iov, int, iovcnt,
722 unsigned long, pos_l, unsigned long, pos_h)
Peter Maydell2a3c7612016-06-06 19:58:03 +0100723safe_syscall3(int, connect, int, fd, const struct sockaddr *, addr,
724 socklen_t, addrlen)
Peter Maydell66687532016-06-06 19:58:04 +0100725safe_syscall6(ssize_t, sendto, int, fd, const void *, buf, size_t, len,
726 int, flags, const struct sockaddr *, addr, socklen_t, addrlen)
727safe_syscall6(ssize_t, recvfrom, int, fd, void *, buf, size_t, len,
728 int, flags, struct sockaddr *, addr, socklen_t *, addrlen)
729safe_syscall3(ssize_t, sendmsg, int, fd, const struct msghdr *, msg, int, flags)
730safe_syscall3(ssize_t, recvmsg, int, fd, struct msghdr *, msg, int, flags)
Peter Maydell2a845982016-06-06 19:58:07 +0100731safe_syscall2(int, flock, int, fd, int, operation)
Filip Bozutaddcbde12020-08-24 21:21:16 +0200732#if defined(TARGET_NR_rt_sigtimedwait) || defined(TARGET_NR_rt_sigtimedwait_time64)
Peter Maydellb3f82332016-06-06 19:58:08 +0100733safe_syscall4(int, rt_sigtimedwait, const sigset_t *, these, siginfo_t *, uinfo,
734 const struct timespec *, uts, size_t, sigsetsize)
Alistair Francis859e8a82020-03-12 15:13:49 -0700735#endif
Peter Maydellff6dc132016-06-06 19:58:13 +0100736safe_syscall4(int, accept4, int, fd, struct sockaddr *, addr, socklen_t *, len,
737 int, flags)
Alistair Francis859e8a82020-03-12 15:13:49 -0700738#if defined(TARGET_NR_nanosleep)
Peter Maydell9e518222016-06-06 19:58:09 +0100739safe_syscall2(int, nanosleep, const struct timespec *, req,
740 struct timespec *, rem)
Alistair Francis859e8a82020-03-12 15:13:49 -0700741#endif
Filip Bozuta6ac03b22020-08-24 21:21:15 +0200742#if defined(TARGET_NR_clock_nanosleep) || \
743 defined(TARGET_NR_clock_nanosleep_time64)
Peter Maydell9e518222016-06-06 19:58:09 +0100744safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags,
745 const struct timespec *, req, struct timespec *, rem)
746#endif
Laurent Vivier524fa342019-05-29 10:48:04 +0200747#ifdef __NR_ipc
Matus Kyseld8c08b12020-06-26 14:46:11 +0200748#ifdef __s390x__
749safe_syscall5(int, ipc, int, call, long, first, long, second, long, third,
750 void *, ptr)
751#else
Peter Maydell89f9fe42016-06-06 19:58:05 +0100752safe_syscall6(int, ipc, int, call, long, first, long, second, long, third,
753 void *, ptr, long, fifth)
Laurent Vivier86e63692019-05-23 19:54:13 +0200754#endif
Matus Kyseld8c08b12020-06-26 14:46:11 +0200755#endif
Laurent Vivier86e63692019-05-23 19:54:13 +0200756#ifdef __NR_msgsnd
757safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz,
758 int, flags)
Laurent Vivier86e63692019-05-23 19:54:13 +0200759#endif
760#ifdef __NR_msgrcv
761safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz,
762 long, msgtype, int, flags)
Laurent Vivier86e63692019-05-23 19:54:13 +0200763#endif
764#ifdef __NR_semtimedop
765safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops,
766 unsigned, nsops, const struct timespec *, timeout)
Peter Maydell89f9fe42016-06-06 19:58:05 +0100767#endif
Filip Bozutad107e372020-08-24 21:37:52 +0200768#if defined(TARGET_NR_mq_timedsend) || \
769 defined(TARGET_NR_mq_timedsend_time64)
Peter Maydelld40ecd62016-06-06 19:58:06 +0100770safe_syscall5(int, mq_timedsend, int, mqdes, const char *, msg_ptr,
771 size_t, len, unsigned, prio, const struct timespec *, timeout)
Alistair Francis859e8a82020-03-12 15:13:49 -0700772#endif
Filip Bozutad107e372020-08-24 21:37:52 +0200773#if defined(TARGET_NR_mq_timedreceive) || \
774 defined(TARGET_NR_mq_timedreceive_time64)
Peter Maydelld40ecd62016-06-06 19:58:06 +0100775safe_syscall5(int, mq_timedreceive, int, mqdes, char *, msg_ptr,
776 size_t, len, unsigned *, prio, const struct timespec *, timeout)
777#endif
Andreas Schwab84946452020-11-12 12:45:16 +0100778#if defined(TARGET_NR_copy_file_range) && defined(__NR_copy_file_range)
779safe_syscall6(ssize_t, copy_file_range, int, infd, loff_t *, pinoff,
780 int, outfd, loff_t *, poutoff, size_t, length,
781 unsigned int, flags)
782#endif
783
Peter Maydell49ca6f32016-06-06 19:58:14 +0100784/* We do ioctl like this rather than via safe_syscall3 to preserve the
785 * "third argument might be integer or pointer or not present" behaviour of
786 * the libc function.
787 */
788#define safe_ioctl(...) safe_syscall(__NR_ioctl, __VA_ARGS__)
Peter Maydell435da5e2016-06-13 11:22:05 +0100789/* Similarly for fcntl. Note that callers must always:
790 * pass the F_GETLK64 etc constants rather than the unsuffixed F_GETLK
791 * use the flock64 struct rather than unsuffixed flock
792 * This will then work and use a 64-bit offset for both 32-bit and 64-bit hosts.
793 */
794#ifdef __NR_fcntl64
795#define safe_fcntl(...) safe_syscall(__NR_fcntl64, __VA_ARGS__)
796#else
797#define safe_fcntl(...) safe_syscall(__NR_fcntl, __VA_ARGS__)
798#endif
Timothy E Baldwin50afd022016-05-12 18:47:47 +0100799
Paul Burton8289d112014-06-22 11:25:33 +0100800static inline int host_to_target_sock_type(int host_type)
801{
802 int target_type;
803
804 switch (host_type & 0xf /* SOCK_TYPE_MASK */) {
805 case SOCK_DGRAM:
806 target_type = TARGET_SOCK_DGRAM;
807 break;
808 case SOCK_STREAM:
809 target_type = TARGET_SOCK_STREAM;
810 break;
811 default:
812 target_type = host_type & 0xf /* SOCK_TYPE_MASK */;
813 break;
814 }
815
816#if defined(SOCK_CLOEXEC)
817 if (host_type & SOCK_CLOEXEC) {
818 target_type |= TARGET_SOCK_CLOEXEC;
819 }
820#endif
821
822#if defined(SOCK_NONBLOCK)
823 if (host_type & SOCK_NONBLOCK) {
824 target_type |= TARGET_SOCK_NONBLOCK;
825 }
826#endif
827
828 return target_type;
829}
830
blueswir1992f48a2007-10-14 16:27:31 +0000831static abi_ulong target_brk;
832static abi_ulong target_original_brk;
vincent4d1de872011-06-14 21:56:33 +0000833static abi_ulong brk_page;
bellard31e31b82003-02-18 22:55:36 +0000834
blueswir1992f48a2007-10-14 16:27:31 +0000835void target_set_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000836{
blueswir14c1de732007-07-07 20:45:44 +0000837 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
vincent4d1de872011-06-14 21:56:33 +0000838 brk_page = HOST_PAGE_ALIGN(target_brk);
bellard31e31b82003-02-18 22:55:36 +0000839}
840
vincent4d1de872011-06-14 21:56:33 +0000841//#define DEBUGF_BRK(message, args...) do { fprintf(stderr, (message), ## args); } while (0)
842#define DEBUGF_BRK(message, args...)
843
ths0da46a62007-10-20 20:23:07 +0000844/* do_brk() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000845abi_long do_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000846{
blueswir1992f48a2007-10-14 16:27:31 +0000847 abi_long mapped_addr;
Peter Maydellef4330c2016-07-22 13:41:52 +0100848 abi_ulong new_alloc_size;
bellard31e31b82003-02-18 22:55:36 +0000849
Richard Hendersonee1bf832021-02-12 10:48:44 -0800850 /* brk pointers are always untagged */
851
Paul Brook3a0c6c42012-02-09 19:04:27 +0000852 DEBUGF_BRK("do_brk(" TARGET_ABI_FMT_lx ") -> ", new_brk);
ths3b46e622007-09-17 08:09:54 +0000853
vincent4d1de872011-06-14 21:56:33 +0000854 if (!new_brk) {
Paul Brook3a0c6c42012-02-09 19:04:27 +0000855 DEBUGF_BRK(TARGET_ABI_FMT_lx " (!new_brk)\n", target_brk);
vincent4d1de872011-06-14 21:56:33 +0000856 return target_brk;
857 }
858 if (new_brk < target_original_brk) {
Paul Brook3a0c6c42012-02-09 19:04:27 +0000859 DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk < target_original_brk)\n",
860 target_brk);
vincent4d1de872011-06-14 21:56:33 +0000861 return target_brk;
862 }
bellard31e31b82003-02-18 22:55:36 +0000863
vincent4d1de872011-06-14 21:56:33 +0000864 /* If the new brk is less than the highest page reserved to the
865 * target heap allocation, set it and we're almost done... */
866 if (new_brk <= brk_page) {
867 /* Heap contents are initialized to zero, as for anonymous
868 * mapped pages. */
869 if (new_brk > target_brk) {
Richard Henderson3e8f1622021-02-12 10:48:43 -0800870 memset(g2h_untagged(target_brk), 0, new_brk - target_brk);
vincent4d1de872011-06-14 21:56:33 +0000871 }
bellard31e31b82003-02-18 22:55:36 +0000872 target_brk = new_brk;
Paul Brook3a0c6c42012-02-09 19:04:27 +0000873 DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk <= brk_page)\n", target_brk);
Paolo Bonzini72e21db2018-12-13 23:37:36 +0100874 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000875 }
876
Peter Maydell00faf082011-04-18 16:34:24 +0100877 /* We need to allocate more memory after the brk... Note that
878 * we don't use MAP_FIXED because that will map over the top of
879 * any existing mapping (like the one with the host libc or qemu
880 * itself); instead we treat "mapped but at wrong address" as
881 * a failure and unmap again.
882 */
vincent4d1de872011-06-14 21:56:33 +0000883 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page);
ths5fafdf22007-09-16 21:08:06 +0000884 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
bellard54936002003-05-13 00:25:15 +0000885 PROT_READ|PROT_WRITE,
Peter Maydell00faf082011-04-18 16:34:24 +0100886 MAP_ANON|MAP_PRIVATE, 0, 0));
887
888 if (mapped_addr == brk_page) {
Cédric VINCENT70afc342011-08-26 10:56:50 +0200889 /* Heap contents are initialized to zero, as for anonymous
890 * mapped pages. Technically the new pages are already
891 * initialized to zero since they *are* anonymous mapped
892 * pages, however we have to take care with the contents that
893 * come from the remaining part of the previous page: it may
894 * contains garbage data due to a previous heap usage (grown
895 * then shrunken). */
Richard Henderson3e8f1622021-02-12 10:48:43 -0800896 memset(g2h_untagged(target_brk), 0, brk_page - target_brk);
Cédric VINCENT70afc342011-08-26 10:56:50 +0200897
Peter Maydell00faf082011-04-18 16:34:24 +0100898 target_brk = new_brk;
vincent4d1de872011-06-14 21:56:33 +0000899 brk_page = HOST_PAGE_ALIGN(target_brk);
Paul Brook3a0c6c42012-02-09 19:04:27 +0000900 DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr == brk_page)\n",
901 target_brk);
Peter Maydell00faf082011-04-18 16:34:24 +0100902 return target_brk;
903 } else if (mapped_addr != -1) {
904 /* Mapped but at wrong address, meaning there wasn't actually
905 * enough space for this brk.
906 */
907 target_munmap(mapped_addr, new_alloc_size);
908 mapped_addr = -1;
Paul Brook3a0c6c42012-02-09 19:04:27 +0000909 DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr != -1)\n", target_brk);
vincent4d1de872011-06-14 21:56:33 +0000910 }
911 else {
Paul Brook3a0c6c42012-02-09 19:04:27 +0000912 DEBUGF_BRK(TARGET_ABI_FMT_lx " (otherwise)\n", target_brk);
Peter Maydell00faf082011-04-18 16:34:24 +0100913 }
balrog7ab240a2008-04-26 12:17:34 +0000914
Richard Henderson7dd46c02010-05-03 10:07:49 -0700915#if defined(TARGET_ALPHA)
916 /* We (partially) emulate OSF/1 on Alpha, which requires we
917 return a proper errno, not an unchanged brk value. */
Peter Maydell00faf082011-04-18 16:34:24 +0100918 return -TARGET_ENOMEM;
Richard Henderson7dd46c02010-05-03 10:07:49 -0700919#endif
Peter Maydell00faf082011-04-18 16:34:24 +0100920 /* For everything else, return the previous break. */
balrog7ab240a2008-04-26 12:17:34 +0000921 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000922}
923
Alistair Francis859e8a82020-03-12 15:13:49 -0700924#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \
Filip Bozutae5ce9682020-08-25 00:30:49 +0200925 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
ths26edcf42007-12-09 02:25:24 +0000926static inline abi_long copy_from_user_fdset(fd_set *fds,
927 abi_ulong target_fds_addr,
928 int n)
bellard31e31b82003-02-18 22:55:36 +0000929{
ths26edcf42007-12-09 02:25:24 +0000930 int i, nw, j, k;
931 abi_ulong b, *target_fds;
932
Laurent Vivierb1b2db22016-05-31 18:36:02 +0200933 nw = DIV_ROUND_UP(n, TARGET_ABI_BITS);
ths26edcf42007-12-09 02:25:24 +0000934 if (!(target_fds = lock_user(VERIFY_READ,
935 target_fds_addr,
936 sizeof(abi_ulong) * nw,
937 1)))
938 return -TARGET_EFAULT;
939
940 FD_ZERO(fds);
941 k = 0;
942 for (i = 0; i < nw; i++) {
943 /* grab the abi_ulong */
944 __get_user(b, &target_fds[i]);
945 for (j = 0; j < TARGET_ABI_BITS; j++) {
946 /* check the bit inside the abi_ulong */
947 if ((b >> j) & 1)
948 FD_SET(k, fds);
949 k++;
bellard31e31b82003-02-18 22:55:36 +0000950 }
bellard31e31b82003-02-18 22:55:36 +0000951 }
ths26edcf42007-12-09 02:25:24 +0000952
953 unlock_user(target_fds, target_fds_addr, 0);
954
955 return 0;
bellard31e31b82003-02-18 22:55:36 +0000956}
957
Mike Frysinger055e0902011-06-03 17:01:49 -0400958static inline abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr,
959 abi_ulong target_fds_addr,
960 int n)
961{
962 if (target_fds_addr) {
963 if (copy_from_user_fdset(fds, target_fds_addr, n))
964 return -TARGET_EFAULT;
965 *fds_ptr = fds;
966 } else {
967 *fds_ptr = NULL;
968 }
969 return 0;
970}
971
ths26edcf42007-12-09 02:25:24 +0000972static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
973 const fd_set *fds,
974 int n)
bellard31e31b82003-02-18 22:55:36 +0000975{
bellard31e31b82003-02-18 22:55:36 +0000976 int i, nw, j, k;
blueswir1992f48a2007-10-14 16:27:31 +0000977 abi_long v;
ths26edcf42007-12-09 02:25:24 +0000978 abi_ulong *target_fds;
bellard31e31b82003-02-18 22:55:36 +0000979
Laurent Vivierb1b2db22016-05-31 18:36:02 +0200980 nw = DIV_ROUND_UP(n, TARGET_ABI_BITS);
ths26edcf42007-12-09 02:25:24 +0000981 if (!(target_fds = lock_user(VERIFY_WRITE,
982 target_fds_addr,
983 sizeof(abi_ulong) * nw,
984 0)))
985 return -TARGET_EFAULT;
986
987 k = 0;
988 for (i = 0; i < nw; i++) {
989 v = 0;
990 for (j = 0; j < TARGET_ABI_BITS; j++) {
Andreas Schwab9ab709b2013-04-09 01:02:34 +0000991 v |= ((abi_ulong)(FD_ISSET(k, fds) != 0) << j);
ths26edcf42007-12-09 02:25:24 +0000992 k++;
bellard31e31b82003-02-18 22:55:36 +0000993 }
ths26edcf42007-12-09 02:25:24 +0000994 __put_user(v, &target_fds[i]);
bellard31e31b82003-02-18 22:55:36 +0000995 }
ths26edcf42007-12-09 02:25:24 +0000996
997 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
998
999 return 0;
bellard31e31b82003-02-18 22:55:36 +00001000}
Alistair Francis859e8a82020-03-12 15:13:49 -07001001#endif
bellard31e31b82003-02-18 22:55:36 +00001002
bellardc596ed12003-07-13 17:32:31 +00001003#if defined(__alpha__)
1004#define HOST_HZ 1024
1005#else
1006#define HOST_HZ 100
1007#endif
1008
blueswir1992f48a2007-10-14 16:27:31 +00001009static inline abi_long host_to_target_clock_t(long ticks)
bellardc596ed12003-07-13 17:32:31 +00001010{
1011#if HOST_HZ == TARGET_HZ
1012 return ticks;
1013#else
1014 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
1015#endif
1016}
1017
bellard579a97f2007-11-11 14:26:47 +00001018static inline abi_long host_to_target_rusage(abi_ulong target_addr,
1019 const struct rusage *rusage)
bellardb4091862003-05-16 15:39:34 +00001020{
pbrook53a59602006-03-25 19:31:22 +00001021 struct target_rusage *target_rusage;
1022
bellard579a97f2007-11-11 14:26:47 +00001023 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
1024 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001025 target_rusage->ru_utime.tv_sec = tswapal(rusage->ru_utime.tv_sec);
1026 target_rusage->ru_utime.tv_usec = tswapal(rusage->ru_utime.tv_usec);
1027 target_rusage->ru_stime.tv_sec = tswapal(rusage->ru_stime.tv_sec);
1028 target_rusage->ru_stime.tv_usec = tswapal(rusage->ru_stime.tv_usec);
1029 target_rusage->ru_maxrss = tswapal(rusage->ru_maxrss);
1030 target_rusage->ru_ixrss = tswapal(rusage->ru_ixrss);
1031 target_rusage->ru_idrss = tswapal(rusage->ru_idrss);
1032 target_rusage->ru_isrss = tswapal(rusage->ru_isrss);
1033 target_rusage->ru_minflt = tswapal(rusage->ru_minflt);
1034 target_rusage->ru_majflt = tswapal(rusage->ru_majflt);
1035 target_rusage->ru_nswap = tswapal(rusage->ru_nswap);
1036 target_rusage->ru_inblock = tswapal(rusage->ru_inblock);
1037 target_rusage->ru_oublock = tswapal(rusage->ru_oublock);
1038 target_rusage->ru_msgsnd = tswapal(rusage->ru_msgsnd);
1039 target_rusage->ru_msgrcv = tswapal(rusage->ru_msgrcv);
1040 target_rusage->ru_nsignals = tswapal(rusage->ru_nsignals);
1041 target_rusage->ru_nvcsw = tswapal(rusage->ru_nvcsw);
1042 target_rusage->ru_nivcsw = tswapal(rusage->ru_nivcsw);
pbrook53a59602006-03-25 19:31:22 +00001043 unlock_user_struct(target_rusage, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001044
1045 return 0;
bellardb4091862003-05-16 15:39:34 +00001046}
1047
Alistair Francis859e8a82020-03-12 15:13:49 -07001048#ifdef TARGET_NR_setrlimit
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001049static inline rlim_t target_to_host_rlim(abi_ulong target_rlim)
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001050{
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001051 abi_ulong target_rlim_swap;
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001052 rlim_t result;
1053
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001054 target_rlim_swap = tswapal(target_rlim);
1055 if (target_rlim_swap == TARGET_RLIM_INFINITY)
1056 return RLIM_INFINITY;
1057
1058 result = target_rlim_swap;
1059 if (target_rlim_swap != (rlim_t)result)
1060 return RLIM_INFINITY;
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001061
1062 return result;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001063}
Alistair Francis859e8a82020-03-12 15:13:49 -07001064#endif
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001065
Alistair Francis859e8a82020-03-12 15:13:49 -07001066#if defined(TARGET_NR_getrlimit) || defined(TARGET_NR_ugetrlimit)
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001067static inline abi_ulong host_to_target_rlim(rlim_t rlim)
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001068{
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001069 abi_ulong target_rlim_swap;
1070 abi_ulong result;
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001071
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001072 if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim)
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001073 target_rlim_swap = TARGET_RLIM_INFINITY;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001074 else
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001075 target_rlim_swap = rlim;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001076 result = tswapal(target_rlim_swap);
Wesley W. Terpstra95b33b22011-07-12 14:38:22 +03001077
1078 return result;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001079}
Alistair Francis859e8a82020-03-12 15:13:49 -07001080#endif
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09001081
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03001082static inline int target_to_host_resource(int code)
1083{
1084 switch (code) {
1085 case TARGET_RLIMIT_AS:
1086 return RLIMIT_AS;
1087 case TARGET_RLIMIT_CORE:
1088 return RLIMIT_CORE;
1089 case TARGET_RLIMIT_CPU:
1090 return RLIMIT_CPU;
1091 case TARGET_RLIMIT_DATA:
1092 return RLIMIT_DATA;
1093 case TARGET_RLIMIT_FSIZE:
1094 return RLIMIT_FSIZE;
1095 case TARGET_RLIMIT_LOCKS:
1096 return RLIMIT_LOCKS;
1097 case TARGET_RLIMIT_MEMLOCK:
1098 return RLIMIT_MEMLOCK;
1099 case TARGET_RLIMIT_MSGQUEUE:
1100 return RLIMIT_MSGQUEUE;
1101 case TARGET_RLIMIT_NICE:
1102 return RLIMIT_NICE;
1103 case TARGET_RLIMIT_NOFILE:
1104 return RLIMIT_NOFILE;
1105 case TARGET_RLIMIT_NPROC:
1106 return RLIMIT_NPROC;
1107 case TARGET_RLIMIT_RSS:
1108 return RLIMIT_RSS;
1109 case TARGET_RLIMIT_RTPRIO:
1110 return RLIMIT_RTPRIO;
Fabrice Fontainec3a28d72022-05-23 12:52:39 +02001111#ifdef RLIMIT_RTTIME
Serge Belyshev244fd082022-01-29 22:48:23 +03001112 case TARGET_RLIMIT_RTTIME:
1113 return RLIMIT_RTTIME;
Fabrice Fontainec3a28d72022-05-23 12:52:39 +02001114#endif
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03001115 case TARGET_RLIMIT_SIGPENDING:
1116 return RLIMIT_SIGPENDING;
1117 case TARGET_RLIMIT_STACK:
1118 return RLIMIT_STACK;
1119 default:
1120 return code;
1121 }
1122}
1123
ths788f5ec2007-12-09 02:37:05 +00001124static inline abi_long copy_from_user_timeval(struct timeval *tv,
1125 abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +00001126{
pbrook53a59602006-03-25 19:31:22 +00001127 struct target_timeval *target_tv;
1128
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001129 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) {
bellard579a97f2007-11-11 14:26:47 +00001130 return -TARGET_EFAULT;
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001131 }
ths788f5ec2007-12-09 02:37:05 +00001132
1133 __get_user(tv->tv_sec, &target_tv->tv_sec);
1134 __get_user(tv->tv_usec, &target_tv->tv_usec);
1135
1136 unlock_user_struct(target_tv, target_tv_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001137
1138 return 0;
bellard31e31b82003-02-18 22:55:36 +00001139}
1140
ths788f5ec2007-12-09 02:37:05 +00001141static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
1142 const struct timeval *tv)
bellard31e31b82003-02-18 22:55:36 +00001143{
pbrook53a59602006-03-25 19:31:22 +00001144 struct target_timeval *target_tv;
1145
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001146 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
bellard579a97f2007-11-11 14:26:47 +00001147 return -TARGET_EFAULT;
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001148 }
ths788f5ec2007-12-09 02:37:05 +00001149
1150 __put_user(tv->tv_sec, &target_tv->tv_sec);
1151 __put_user(tv->tv_usec, &target_tv->tv_usec);
1152
1153 unlock_user_struct(target_tv, target_tv_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001154
1155 return 0;
bellard31e31b82003-02-18 22:55:36 +00001156}
1157
Filip Bozuta6ac03b22020-08-24 21:21:15 +02001158#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
1159static inline abi_long copy_from_user_timeval64(struct timeval *tv,
1160 abi_ulong target_tv_addr)
1161{
1162 struct target__kernel_sock_timeval *target_tv;
1163
1164 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) {
1165 return -TARGET_EFAULT;
1166 }
1167
1168 __get_user(tv->tv_sec, &target_tv->tv_sec);
1169 __get_user(tv->tv_usec, &target_tv->tv_usec);
1170
1171 unlock_user_struct(target_tv, target_tv_addr, 0);
1172
1173 return 0;
1174}
1175#endif
1176
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001177static inline abi_long copy_to_user_timeval64(abi_ulong target_tv_addr,
Filip Bozuta6ac03b22020-08-24 21:21:15 +02001178 const struct timeval *tv)
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001179{
1180 struct target__kernel_sock_timeval *target_tv;
1181
1182 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
1183 return -TARGET_EFAULT;
1184 }
1185
1186 __put_user(tv->tv_sec, &target_tv->tv_sec);
1187 __put_user(tv->tv_usec, &target_tv->tv_usec);
1188
1189 unlock_user_struct(target_tv, target_tv_addr, 1);
1190
1191 return 0;
1192}
1193
Alistair Francis859e8a82020-03-12 15:13:49 -07001194#if defined(TARGET_NR_futex) || \
1195 defined(TARGET_NR_rt_sigtimedwait) || \
1196 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6) || \
1197 defined(TARGET_NR_nanosleep) || defined(TARGET_NR_clock_settime) || \
1198 defined(TARGET_NR_utimensat) || defined(TARGET_NR_mq_timedsend) || \
Matus Kyseld8c08b12020-06-26 14:46:11 +02001199 defined(TARGET_NR_mq_timedreceive) || defined(TARGET_NR_ipc) || \
Filip Bozuta2c86c902020-07-22 17:34:20 +02001200 defined(TARGET_NR_semop) || defined(TARGET_NR_semtimedop) || \
1201 defined(TARGET_NR_timer_settime) || \
1202 (defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD))
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001203static inline abi_long target_to_host_timespec(struct timespec *host_ts,
1204 abi_ulong target_addr)
1205{
1206 struct target_timespec *target_ts;
1207
1208 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) {
1209 return -TARGET_EFAULT;
1210 }
1211 __get_user(host_ts->tv_sec, &target_ts->tv_sec);
1212 __get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1213 unlock_user_struct(target_ts, target_addr, 0);
1214 return 0;
1215}
Alistair Francis859e8a82020-03-12 15:13:49 -07001216#endif
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001217
Filip Bozuta828cb3a2020-07-22 17:34:21 +02001218#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) || \
1219 defined(TARGET_NR_timer_settime64) || \
Filip Bozutad107e372020-08-24 21:37:52 +02001220 defined(TARGET_NR_mq_timedsend_time64) || \
1221 defined(TARGET_NR_mq_timedreceive_time64) || \
Filip Bozuta6ac03b22020-08-24 21:21:15 +02001222 (defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)) || \
Filip Bozutaddcbde12020-08-24 21:21:16 +02001223 defined(TARGET_NR_clock_nanosleep_time64) || \
Filip Bozutacac46eb2020-08-25 00:30:50 +02001224 defined(TARGET_NR_rt_sigtimedwait_time64) || \
1225 defined(TARGET_NR_utimensat) || \
1226 defined(TARGET_NR_utimensat_time64) || \
Filip Bozutae5ce9682020-08-25 00:30:49 +02001227 defined(TARGET_NR_semtimedop_time64) || \
1228 defined(TARGET_NR_pselect6_time64) || defined(TARGET_NR_ppoll_time64)
Alistair Francisc6c8d102020-03-12 15:13:53 -07001229static inline abi_long target_to_host_timespec64(struct timespec *host_ts,
1230 abi_ulong target_addr)
1231{
1232 struct target__kernel_timespec *target_ts;
1233
1234 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) {
1235 return -TARGET_EFAULT;
1236 }
1237 __get_user(host_ts->tv_sec, &target_ts->tv_sec);
1238 __get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
Laurent Vivier00576752020-08-27 09:04:49 +02001239 /* in 32bit mode, this drops the padding */
1240 host_ts->tv_nsec = (long)(abi_long)host_ts->tv_nsec;
Alistair Francisc6c8d102020-03-12 15:13:53 -07001241 unlock_user_struct(target_ts, target_addr, 0);
1242 return 0;
1243}
1244#endif
1245
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02001246static inline abi_long host_to_target_timespec(abi_ulong target_addr,
1247 struct timespec *host_ts)
1248{
1249 struct target_timespec *target_ts;
1250
1251 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) {
1252 return -TARGET_EFAULT;
1253 }
1254 __put_user(host_ts->tv_sec, &target_ts->tv_sec);
1255 __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1256 unlock_user_struct(target_ts, target_addr, 1);
1257 return 0;
1258}
1259
1260static inline abi_long host_to_target_timespec64(abi_ulong target_addr,
1261 struct timespec *host_ts)
1262{
1263 struct target__kernel_timespec *target_ts;
1264
1265 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) {
1266 return -TARGET_EFAULT;
1267 }
1268 __put_user(host_ts->tv_sec, &target_ts->tv_sec);
1269 __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1270 unlock_user_struct(target_ts, target_addr, 1);
1271 return 0;
1272}
1273
Richard Hendersona52f5f82020-02-12 19:22:23 -08001274#if defined(TARGET_NR_gettimeofday)
1275static inline abi_long copy_to_user_timezone(abi_ulong target_tz_addr,
1276 struct timezone *tz)
1277{
1278 struct target_timezone *target_tz;
1279
1280 if (!lock_user_struct(VERIFY_WRITE, target_tz, target_tz_addr, 1)) {
1281 return -TARGET_EFAULT;
1282 }
1283
1284 __put_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
1285 __put_user(tz->tz_dsttime, &target_tz->tz_dsttime);
1286
1287 unlock_user_struct(target_tz, target_tz_addr, 1);
1288
1289 return 0;
1290}
1291#endif
1292
Alistair Francis859e8a82020-03-12 15:13:49 -07001293#if defined(TARGET_NR_settimeofday)
Paul Burtonef4467e2014-06-22 11:25:40 +01001294static inline abi_long copy_from_user_timezone(struct timezone *tz,
1295 abi_ulong target_tz_addr)
1296{
1297 struct target_timezone *target_tz;
1298
1299 if (!lock_user_struct(VERIFY_READ, target_tz, target_tz_addr, 1)) {
1300 return -TARGET_EFAULT;
1301 }
1302
1303 __get_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
1304 __get_user(tz->tz_dsttime, &target_tz->tz_dsttime);
1305
1306 unlock_user_struct(target_tz, target_tz_addr, 0);
1307
1308 return 0;
1309}
Alistair Francis859e8a82020-03-12 15:13:49 -07001310#endif
Paul Burtonef4467e2014-06-22 11:25:40 +01001311
Nathan Froyd8ec9cf82009-07-22 09:14:36 -07001312#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
1313#include <mqueue.h>
1314
aurel3224e10032009-04-15 16:11:43 +00001315static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr,
1316 abi_ulong target_mq_attr_addr)
1317{
1318 struct target_mq_attr *target_mq_attr;
1319
1320 if (!lock_user_struct(VERIFY_READ, target_mq_attr,
1321 target_mq_attr_addr, 1))
1322 return -TARGET_EFAULT;
1323
1324 __get_user(attr->mq_flags, &target_mq_attr->mq_flags);
1325 __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
1326 __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
1327 __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
1328
1329 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0);
1330
1331 return 0;
1332}
1333
1334static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
1335 const struct mq_attr *attr)
1336{
1337 struct target_mq_attr *target_mq_attr;
1338
1339 if (!lock_user_struct(VERIFY_WRITE, target_mq_attr,
1340 target_mq_attr_addr, 0))
1341 return -TARGET_EFAULT;
1342
1343 __put_user(attr->mq_flags, &target_mq_attr->mq_flags);
1344 __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
1345 __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
1346 __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
1347
1348 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1);
1349
1350 return 0;
1351}
Nathan Froyd8ec9cf82009-07-22 09:14:36 -07001352#endif
bellard31e31b82003-02-18 22:55:36 +00001353
Mike Frysinger055e0902011-06-03 17:01:49 -04001354#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect)
ths0da46a62007-10-20 20:23:07 +00001355/* do_select() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001356static abi_long do_select(int n,
ths26edcf42007-12-09 02:25:24 +00001357 abi_ulong rfd_addr, abi_ulong wfd_addr,
1358 abi_ulong efd_addr, abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +00001359{
1360 fd_set rfds, wfds, efds;
1361 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
Peter Maydell6df9d382016-05-12 18:47:51 +01001362 struct timeval tv;
1363 struct timespec ts, *ts_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00001364 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00001365
Mike Frysinger055e0902011-06-03 17:01:49 -04001366 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
1367 if (ret) {
1368 return ret;
pbrook53a59602006-03-25 19:31:22 +00001369 }
Mike Frysinger055e0902011-06-03 17:01:49 -04001370 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
1371 if (ret) {
1372 return ret;
pbrook53a59602006-03-25 19:31:22 +00001373 }
Mike Frysinger055e0902011-06-03 17:01:49 -04001374 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
1375 if (ret) {
1376 return ret;
pbrook53a59602006-03-25 19:31:22 +00001377 }
ths3b46e622007-09-17 08:09:54 +00001378
ths26edcf42007-12-09 02:25:24 +00001379 if (target_tv_addr) {
ths788f5ec2007-12-09 02:37:05 +00001380 if (copy_from_user_timeval(&tv, target_tv_addr))
1381 return -TARGET_EFAULT;
Peter Maydell6df9d382016-05-12 18:47:51 +01001382 ts.tv_sec = tv.tv_sec;
1383 ts.tv_nsec = tv.tv_usec * 1000;
1384 ts_ptr = &ts;
bellard31e31b82003-02-18 22:55:36 +00001385 } else {
Peter Maydell6df9d382016-05-12 18:47:51 +01001386 ts_ptr = NULL;
bellard31e31b82003-02-18 22:55:36 +00001387 }
ths26edcf42007-12-09 02:25:24 +00001388
Peter Maydell6df9d382016-05-12 18:47:51 +01001389 ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
1390 ts_ptr, NULL));
pbrook53a59602006-03-25 19:31:22 +00001391
ths26edcf42007-12-09 02:25:24 +00001392 if (!is_error(ret)) {
1393 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
1394 return -TARGET_EFAULT;
1395 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
1396 return -TARGET_EFAULT;
1397 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
1398 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00001399
Peter Maydell6df9d382016-05-12 18:47:51 +01001400 if (target_tv_addr) {
1401 tv.tv_sec = ts.tv_sec;
1402 tv.tv_usec = ts.tv_nsec / 1000;
1403 if (copy_to_user_timeval(target_tv_addr, &tv)) {
1404 return -TARGET_EFAULT;
1405 }
1406 }
bellard31e31b82003-02-18 22:55:36 +00001407 }
bellard579a97f2007-11-11 14:26:47 +00001408
bellard31e31b82003-02-18 22:55:36 +00001409 return ret;
1410}
Laurent Vivier5457dc92016-07-08 01:17:27 +02001411
1412#if defined(TARGET_WANT_OLD_SYS_SELECT)
1413static abi_long do_old_select(abi_ulong arg1)
1414{
1415 struct target_sel_arg_struct *sel;
1416 abi_ulong inp, outp, exp, tvp;
1417 long nsel;
1418
1419 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1)) {
1420 return -TARGET_EFAULT;
1421 }
1422
1423 nsel = tswapal(sel->n);
1424 inp = tswapal(sel->inp);
1425 outp = tswapal(sel->outp);
1426 exp = tswapal(sel->exp);
1427 tvp = tswapal(sel->tvp);
1428
1429 unlock_user_struct(sel, arg1, 0);
1430
1431 return do_select(nsel, inp, outp, exp, tvp);
1432}
1433#endif
Mike Frysinger055e0902011-06-03 17:01:49 -04001434#endif
bellard31e31b82003-02-18 22:55:36 +00001435
Filip Bozutae5ce9682020-08-25 00:30:49 +02001436#if defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
1437static abi_long do_pselect6(abi_long arg1, abi_long arg2, abi_long arg3,
1438 abi_long arg4, abi_long arg5, abi_long arg6,
1439 bool time64)
1440{
1441 abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr;
1442 fd_set rfds, wfds, efds;
1443 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
1444 struct timespec ts, *ts_ptr;
1445 abi_long ret;
1446
1447 /*
1448 * The 6th arg is actually two args smashed together,
1449 * so we cannot use the C library.
1450 */
Filip Bozutae5ce9682020-08-25 00:30:49 +02001451 struct {
1452 sigset_t *set;
1453 size_t size;
1454 } sig, *sig_ptr;
1455
1456 abi_ulong arg_sigset, arg_sigsize, *arg7;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001457
1458 n = arg1;
1459 rfd_addr = arg2;
1460 wfd_addr = arg3;
1461 efd_addr = arg4;
1462 ts_addr = arg5;
1463
1464 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
1465 if (ret) {
1466 return ret;
1467 }
1468 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
1469 if (ret) {
1470 return ret;
1471 }
1472 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
1473 if (ret) {
1474 return ret;
1475 }
1476
1477 /*
1478 * This takes a timespec, and not a timeval, so we cannot
1479 * use the do_select() helper ...
1480 */
1481 if (ts_addr) {
1482 if (time64) {
1483 if (target_to_host_timespec64(&ts, ts_addr)) {
1484 return -TARGET_EFAULT;
1485 }
1486 } else {
1487 if (target_to_host_timespec(&ts, ts_addr)) {
1488 return -TARGET_EFAULT;
1489 }
1490 }
1491 ts_ptr = &ts;
1492 } else {
1493 ts_ptr = NULL;
1494 }
1495
1496 /* Extract the two packed args for the sigset */
Richard Hendersoncb226032022-03-15 01:43:06 -07001497 sig_ptr = NULL;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001498 if (arg6) {
Filip Bozutae5ce9682020-08-25 00:30:49 +02001499 arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1);
1500 if (!arg7) {
1501 return -TARGET_EFAULT;
1502 }
1503 arg_sigset = tswapal(arg7[0]);
1504 arg_sigsize = tswapal(arg7[1]);
1505 unlock_user(arg7, arg6, 0);
1506
1507 if (arg_sigset) {
Richard Hendersoncb226032022-03-15 01:43:06 -07001508 ret = process_sigsuspend_mask(&sig.set, arg_sigset, arg_sigsize);
1509 if (ret != 0) {
1510 return ret;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001511 }
Richard Hendersoncb226032022-03-15 01:43:06 -07001512 sig_ptr = &sig;
1513 sig.size = SIGSET_T_SIZE;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001514 }
Filip Bozutae5ce9682020-08-25 00:30:49 +02001515 }
1516
1517 ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
1518 ts_ptr, sig_ptr));
1519
Richard Hendersoncb226032022-03-15 01:43:06 -07001520 if (sig_ptr) {
1521 finish_sigsuspend_mask(ret);
1522 }
1523
Filip Bozutae5ce9682020-08-25 00:30:49 +02001524 if (!is_error(ret)) {
1525 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n)) {
1526 return -TARGET_EFAULT;
1527 }
1528 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n)) {
1529 return -TARGET_EFAULT;
1530 }
1531 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n)) {
1532 return -TARGET_EFAULT;
1533 }
1534 if (time64) {
1535 if (ts_addr && host_to_target_timespec64(ts_addr, &ts)) {
1536 return -TARGET_EFAULT;
1537 }
1538 } else {
1539 if (ts_addr && host_to_target_timespec(ts_addr, &ts)) {
1540 return -TARGET_EFAULT;
1541 }
1542 }
1543 }
1544 return ret;
1545}
1546#endif
1547
1548#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll) || \
1549 defined(TARGET_NR_ppoll_time64)
1550static abi_long do_ppoll(abi_long arg1, abi_long arg2, abi_long arg3,
1551 abi_long arg4, abi_long arg5, bool ppoll, bool time64)
1552{
1553 struct target_pollfd *target_pfd;
1554 unsigned int nfds = arg2;
1555 struct pollfd *pfd;
1556 unsigned int i;
1557 abi_long ret;
1558
1559 pfd = NULL;
1560 target_pfd = NULL;
1561 if (nfds) {
1562 if (nfds > (INT_MAX / sizeof(struct target_pollfd))) {
1563 return -TARGET_EINVAL;
1564 }
1565 target_pfd = lock_user(VERIFY_WRITE, arg1,
1566 sizeof(struct target_pollfd) * nfds, 1);
1567 if (!target_pfd) {
1568 return -TARGET_EFAULT;
1569 }
1570
1571 pfd = alloca(sizeof(struct pollfd) * nfds);
1572 for (i = 0; i < nfds; i++) {
1573 pfd[i].fd = tswap32(target_pfd[i].fd);
1574 pfd[i].events = tswap16(target_pfd[i].events);
1575 }
1576 }
1577 if (ppoll) {
1578 struct timespec _timeout_ts, *timeout_ts = &_timeout_ts;
Richard Hendersondb36aa72022-03-15 01:43:08 -07001579 sigset_t *set = NULL;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001580
1581 if (arg3) {
1582 if (time64) {
1583 if (target_to_host_timespec64(timeout_ts, arg3)) {
1584 unlock_user(target_pfd, arg1, 0);
1585 return -TARGET_EFAULT;
1586 }
1587 } else {
1588 if (target_to_host_timespec(timeout_ts, arg3)) {
1589 unlock_user(target_pfd, arg1, 0);
1590 return -TARGET_EFAULT;
1591 }
1592 }
1593 } else {
1594 timeout_ts = NULL;
1595 }
1596
1597 if (arg4) {
Richard Hendersondb36aa72022-03-15 01:43:08 -07001598 ret = process_sigsuspend_mask(&set, arg4, arg5);
1599 if (ret != 0) {
Filip Bozutae5ce9682020-08-25 00:30:49 +02001600 unlock_user(target_pfd, arg1, 0);
Richard Hendersondb36aa72022-03-15 01:43:08 -07001601 return ret;
Filip Bozutae5ce9682020-08-25 00:30:49 +02001602 }
Filip Bozutae5ce9682020-08-25 00:30:49 +02001603 }
1604
1605 ret = get_errno(safe_ppoll(pfd, nfds, timeout_ts,
1606 set, SIGSET_T_SIZE));
1607
Richard Hendersondb36aa72022-03-15 01:43:08 -07001608 if (set) {
1609 finish_sigsuspend_mask(ret);
1610 }
Filip Bozutae5ce9682020-08-25 00:30:49 +02001611 if (!is_error(ret) && arg3) {
1612 if (time64) {
1613 if (host_to_target_timespec64(arg3, timeout_ts)) {
1614 return -TARGET_EFAULT;
1615 }
1616 } else {
1617 if (host_to_target_timespec(arg3, timeout_ts)) {
1618 return -TARGET_EFAULT;
1619 }
1620 }
1621 }
Filip Bozutae5ce9682020-08-25 00:30:49 +02001622 } else {
1623 struct timespec ts, *pts;
1624
1625 if (arg3 >= 0) {
1626 /* Convert ms to secs, ns */
1627 ts.tv_sec = arg3 / 1000;
1628 ts.tv_nsec = (arg3 % 1000) * 1000000LL;
1629 pts = &ts;
1630 } else {
1631 /* -ve poll() timeout means "infinite" */
1632 pts = NULL;
1633 }
1634 ret = get_errno(safe_ppoll(pfd, nfds, pts, NULL, 0));
1635 }
1636
1637 if (!is_error(ret)) {
1638 for (i = 0; i < nfds; i++) {
1639 target_pfd[i].revents = tswap16(pfd[i].revents);
1640 }
1641 }
1642 unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds);
1643 return ret;
1644}
1645#endif
1646
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02001647static abi_long do_pipe(CPUArchState *cpu_env, abi_ulong pipedes,
Richard Hendersonfb41a662010-05-03 10:07:52 -07001648 int flags, int is_pipe2)
Riku Voipio099d6b02009-05-05 12:10:04 +03001649{
1650 int host_pipe[2];
1651 abi_long ret;
Helge Deller499d8052022-07-19 18:20:42 +02001652 ret = pipe2(host_pipe, flags);
Riku Voipio099d6b02009-05-05 12:10:04 +03001653
1654 if (is_error(ret))
1655 return get_errno(ret);
Richard Hendersonfb41a662010-05-03 10:07:52 -07001656
1657 /* Several targets have special calling conventions for the original
1658 pipe syscall, but didn't replicate this into the pipe2 syscall. */
1659 if (!is_pipe2) {
1660#if defined(TARGET_ALPHA)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02001661 cpu_env->ir[IR_A4] = host_pipe[1];
Richard Hendersonfb41a662010-05-03 10:07:52 -07001662 return host_pipe[0];
1663#elif defined(TARGET_MIPS)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02001664 cpu_env->active_tc.gpr[3] = host_pipe[1];
Richard Hendersonfb41a662010-05-03 10:07:52 -07001665 return host_pipe[0];
1666#elif defined(TARGET_SH4)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02001667 cpu_env->gregs[1] = host_pipe[1];
Richard Hendersonfb41a662010-05-03 10:07:52 -07001668 return host_pipe[0];
Peter Maydell82f05b62013-07-06 17:39:48 +01001669#elif defined(TARGET_SPARC)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02001670 cpu_env->regwptr[1] = host_pipe[1];
Peter Maydell82f05b62013-07-06 17:39:48 +01001671 return host_pipe[0];
takasi-y@ops.dti.ne.jp597c0212010-02-18 00:35:03 +09001672#endif
Richard Hendersonfb41a662010-05-03 10:07:52 -07001673 }
1674
Riku Voipio099d6b02009-05-05 12:10:04 +03001675 if (put_user_s32(host_pipe[0], pipedes)
Helge Deller6f200f52022-07-17 18:21:53 +02001676 || put_user_s32(host_pipe[1], pipedes + sizeof(abi_int)))
Riku Voipio099d6b02009-05-05 12:10:04 +03001677 return -TARGET_EFAULT;
Riku Voipio099d6b02009-05-05 12:10:04 +03001678 return get_errno(ret);
1679}
1680
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001681static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
1682 abi_ulong target_addr,
1683 socklen_t len)
1684{
1685 struct target_ip_mreqn *target_smreqn;
1686
1687 target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
1688 if (!target_smreqn)
1689 return -TARGET_EFAULT;
1690 mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
1691 mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
1692 if (len == sizeof(struct target_ip_mreqn))
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001693 mreqn->imr_ifindex = tswapal(target_smreqn->imr_ifindex);
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001694 unlock_user(target_smreqn, target_addr, 0);
1695
1696 return 0;
1697}
1698
Laurent Vivier7b36f782015-10-28 21:40:44 +01001699static inline abi_long target_to_host_sockaddr(int fd, struct sockaddr *addr,
bellard579a97f2007-11-11 14:26:47 +00001700 abi_ulong target_addr,
1701 socklen_t len)
bellard7854b052003-03-29 17:22:23 +00001702{
aurel32607175e2009-04-15 16:11:59 +00001703 const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
1704 sa_family_t sa_family;
pbrook53a59602006-03-25 19:31:22 +00001705 struct target_sockaddr *target_saddr;
1706
Laurent Vivier7b36f782015-10-28 21:40:44 +01001707 if (fd_trans_target_to_host_addr(fd)) {
1708 return fd_trans_target_to_host_addr(fd)(addr, target_addr, len);
1709 }
1710
bellard579a97f2007-11-11 14:26:47 +00001711 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
1712 if (!target_saddr)
1713 return -TARGET_EFAULT;
aurel32607175e2009-04-15 16:11:59 +00001714
1715 sa_family = tswap16(target_saddr->sa_family);
1716
1717 /* Oops. The caller might send a incomplete sun_path; sun_path
1718 * must be terminated by \0 (see the manual page), but
1719 * unfortunately it is quite common to specify sockaddr_un
1720 * length as "strlen(x->sun_path)" while it should be
1721 * "strlen(...) + 1". We'll fix that here if needed.
1722 * Linux kernel has a similar feature.
1723 */
1724
1725 if (sa_family == AF_UNIX) {
1726 if (len < unix_maxlen && len > 0) {
1727 char *cp = (char*)target_saddr;
1728
1729 if ( cp[len-1] && !cp[len] )
1730 len++;
1731 }
1732 if (len > unix_maxlen)
1733 len = unix_maxlen;
1734 }
1735
pbrook53a59602006-03-25 19:31:22 +00001736 memcpy(addr, target_saddr, len);
aurel32607175e2009-04-15 16:11:59 +00001737 addr->sa_family = sa_family;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02001738 if (sa_family == AF_NETLINK) {
1739 struct sockaddr_nl *nladdr;
1740
1741 nladdr = (struct sockaddr_nl *)addr;
1742 nladdr->nl_pid = tswap32(nladdr->nl_pid);
1743 nladdr->nl_groups = tswap32(nladdr->nl_groups);
1744 } else if (sa_family == AF_PACKET) {
Joakim Tjernlund33a29b52014-07-12 15:47:07 +02001745 struct target_sockaddr_ll *lladdr;
1746
1747 lladdr = (struct target_sockaddr_ll *)addr;
1748 lladdr->sll_ifindex = tswap32(lladdr->sll_ifindex);
1749 lladdr->sll_hatype = tswap16(lladdr->sll_hatype);
1750 }
pbrook53a59602006-03-25 19:31:22 +00001751 unlock_user(target_saddr, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001752
1753 return 0;
bellard7854b052003-03-29 17:22:23 +00001754}
1755
bellard579a97f2007-11-11 14:26:47 +00001756static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
1757 struct sockaddr *addr,
1758 socklen_t len)
bellard7854b052003-03-29 17:22:23 +00001759{
pbrook53a59602006-03-25 19:31:22 +00001760 struct target_sockaddr *target_saddr;
1761
Peter Maydella1e22192016-07-07 15:44:43 +01001762 if (len == 0) {
1763 return 0;
1764 }
Philippe Mathieu-Daudé68607102017-07-26 23:42:18 -03001765 assert(addr);
Peter Maydella1e22192016-07-07 15:44:43 +01001766
bellard579a97f2007-11-11 14:26:47 +00001767 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
1768 if (!target_saddr)
1769 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001770 memcpy(target_saddr, addr, len);
Peter Maydella1e22192016-07-07 15:44:43 +01001771 if (len >= offsetof(struct target_sockaddr, sa_family) +
1772 sizeof(target_saddr->sa_family)) {
1773 target_saddr->sa_family = tswap16(addr->sa_family);
1774 }
Philippe Mathieu-Daudéa47401b2019-10-21 13:48:52 +02001775 if (addr->sa_family == AF_NETLINK &&
1776 len >= sizeof(struct target_sockaddr_nl)) {
1777 struct target_sockaddr_nl *target_nl =
1778 (struct target_sockaddr_nl *)target_saddr;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02001779 target_nl->nl_pid = tswap32(target_nl->nl_pid);
1780 target_nl->nl_groups = tswap32(target_nl->nl_groups);
Laurent Viviera82ea932016-06-27 00:18:22 +02001781 } else if (addr->sa_family == AF_PACKET) {
1782 struct sockaddr_ll *target_ll = (struct sockaddr_ll *)target_saddr;
1783 target_ll->sll_ifindex = tswap32(target_ll->sll_ifindex);
1784 target_ll->sll_hatype = tswap16(target_ll->sll_hatype);
Helge Delleree1ac3a2017-02-18 23:31:30 +01001785 } else if (addr->sa_family == AF_INET6 &&
1786 len >= sizeof(struct target_sockaddr_in6)) {
1787 struct target_sockaddr_in6 *target_in6 =
1788 (struct target_sockaddr_in6 *)target_saddr;
1789 target_in6->sin6_scope_id = tswap16(target_in6->sin6_scope_id);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02001790 }
pbrook53a59602006-03-25 19:31:22 +00001791 unlock_user(target_saddr, target_addr, len);
bellard579a97f2007-11-11 14:26:47 +00001792
1793 return 0;
bellard7854b052003-03-29 17:22:23 +00001794}
1795
bellard5a4a8982007-11-11 17:39:18 +00001796static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
1797 struct target_msghdr *target_msgh)
bellard7854b052003-03-29 17:22:23 +00001798{
1799 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001800 abi_long msg_controllen;
1801 abi_ulong target_cmsg_addr;
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001802 struct target_cmsghdr *target_cmsg, *target_cmsg_start;
bellard7854b052003-03-29 17:22:23 +00001803 socklen_t space = 0;
bellard5a4a8982007-11-11 17:39:18 +00001804
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001805 msg_controllen = tswapal(target_msgh->msg_controllen);
bellard5a4a8982007-11-11 17:39:18 +00001806 if (msg_controllen < sizeof (struct target_cmsghdr))
1807 goto the_end;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001808 target_cmsg_addr = tswapal(target_msgh->msg_control);
bellard5a4a8982007-11-11 17:39:18 +00001809 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001810 target_cmsg_start = target_cmsg;
bellard5a4a8982007-11-11 17:39:18 +00001811 if (!target_cmsg)
1812 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001813
1814 while (cmsg && target_cmsg) {
1815 void *data = CMSG_DATA(cmsg);
1816 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1817
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001818 int len = tswapal(target_cmsg->cmsg_len)
Peter Maydellad762b92017-12-15 13:52:56 +00001819 - sizeof(struct target_cmsghdr);
bellard7854b052003-03-29 17:22:23 +00001820
1821 space += CMSG_SPACE(len);
1822 if (space > msgh->msg_controllen) {
1823 space -= CMSG_SPACE(len);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001824 /* This is a QEMU bug, since we allocated the payload
1825 * area ourselves (unlike overflow in host-to-target
1826 * conversion, which is just the guest giving us a buffer
1827 * that's too small). It can't happen for the payload types
1828 * we currently support; if it becomes an issue in future
1829 * we would need to improve our allocation strategy to
1830 * something more intelligent than "twice the size of the
1831 * target buffer we're reading from".
1832 */
Josh Kunz39be5352020-02-03 18:54:13 -08001833 qemu_log_mask(LOG_UNIMP,
1834 ("Unsupported ancillary data %d/%d: "
1835 "unhandled msg size\n"),
1836 tswap32(target_cmsg->cmsg_level),
1837 tswap32(target_cmsg->cmsg_type));
bellard7854b052003-03-29 17:22:23 +00001838 break;
1839 }
1840
Petar Jovanovicdbf4f792013-09-13 19:27:29 +02001841 if (tswap32(target_cmsg->cmsg_level) == TARGET_SOL_SOCKET) {
1842 cmsg->cmsg_level = SOL_SOCKET;
1843 } else {
1844 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
1845 }
bellard7854b052003-03-29 17:22:23 +00001846 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
1847 cmsg->cmsg_len = CMSG_LEN(len);
1848
Alex Suykov30b8b682014-12-23 07:52:58 +02001849 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +00001850 int *fd = (int *)data;
1851 int *target_fd = (int *)target_data;
1852 int i, numfds = len / sizeof(int);
1853
Peter Maydell876e23c2015-05-26 19:46:32 +01001854 for (i = 0; i < numfds; i++) {
1855 __get_user(fd[i], target_fd + i);
1856 }
Alex Suykov30b8b682014-12-23 07:52:58 +02001857 } else if (cmsg->cmsg_level == SOL_SOCKET
1858 && cmsg->cmsg_type == SCM_CREDENTIALS) {
1859 struct ucred *cred = (struct ucred *)data;
1860 struct target_ucred *target_cred =
1861 (struct target_ucred *)target_data;
1862
Peter Maydell876e23c2015-05-26 19:46:32 +01001863 __get_user(cred->pid, &target_cred->pid);
1864 __get_user(cred->uid, &target_cred->uid);
1865 __get_user(cred->gid, &target_cred->gid);
Alex Suykov30b8b682014-12-23 07:52:58 +02001866 } else {
Josh Kunz39be5352020-02-03 18:54:13 -08001867 qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n",
1868 cmsg->cmsg_level, cmsg->cmsg_type);
Alex Suykov30b8b682014-12-23 07:52:58 +02001869 memcpy(data, target_data, len);
bellard7854b052003-03-29 17:22:23 +00001870 }
1871
1872 cmsg = CMSG_NXTHDR(msgh, cmsg);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001873 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg,
1874 target_cmsg_start);
bellard7854b052003-03-29 17:22:23 +00001875 }
bellard5a4a8982007-11-11 17:39:18 +00001876 unlock_user(target_cmsg, target_cmsg_addr, 0);
1877 the_end:
bellard7854b052003-03-29 17:22:23 +00001878 msgh->msg_controllen = space;
bellard5a4a8982007-11-11 17:39:18 +00001879 return 0;
bellard7854b052003-03-29 17:22:23 +00001880}
1881
bellard5a4a8982007-11-11 17:39:18 +00001882static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
1883 struct msghdr *msgh)
bellard7854b052003-03-29 17:22:23 +00001884{
1885 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001886 abi_long msg_controllen;
1887 abi_ulong target_cmsg_addr;
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001888 struct target_cmsghdr *target_cmsg, *target_cmsg_start;
bellard7854b052003-03-29 17:22:23 +00001889 socklen_t space = 0;
1890
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001891 msg_controllen = tswapal(target_msgh->msg_controllen);
bellard5a4a8982007-11-11 17:39:18 +00001892 if (msg_controllen < sizeof (struct target_cmsghdr))
1893 goto the_end;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02001894 target_cmsg_addr = tswapal(target_msgh->msg_control);
bellard5a4a8982007-11-11 17:39:18 +00001895 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02001896 target_cmsg_start = target_cmsg;
bellard5a4a8982007-11-11 17:39:18 +00001897 if (!target_cmsg)
1898 return -TARGET_EFAULT;
1899
bellard7854b052003-03-29 17:22:23 +00001900 while (cmsg && target_cmsg) {
1901 void *data = CMSG_DATA(cmsg);
1902 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1903
Peter Maydellad762b92017-12-15 13:52:56 +00001904 int len = cmsg->cmsg_len - sizeof(struct cmsghdr);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001905 int tgt_len, tgt_space;
bellard7854b052003-03-29 17:22:23 +00001906
Peter Maydellc2aeb252015-05-26 19:46:31 +01001907 /* We never copy a half-header but may copy half-data;
1908 * this is Linux's behaviour in put_cmsg(). Note that
1909 * truncation here is a guest problem (which we report
1910 * to the guest via the CTRUNC bit), unlike truncation
1911 * in target_to_host_cmsg, which is a QEMU bug.
1912 */
Peter Maydell71749702017-12-15 13:52:55 +00001913 if (msg_controllen < sizeof(struct target_cmsghdr)) {
Peter Maydellc2aeb252015-05-26 19:46:31 +01001914 target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
bellard7854b052003-03-29 17:22:23 +00001915 break;
1916 }
1917
Petar Jovanovicdbf4f792013-09-13 19:27:29 +02001918 if (cmsg->cmsg_level == SOL_SOCKET) {
1919 target_cmsg->cmsg_level = tswap32(TARGET_SOL_SOCKET);
1920 } else {
1921 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
1922 }
bellard7854b052003-03-29 17:22:23 +00001923 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
bellard7854b052003-03-29 17:22:23 +00001924
Peter Maydellc2aeb252015-05-26 19:46:31 +01001925 /* Payload types which need a different size of payload on
1926 * the target must adjust tgt_len here.
1927 */
Peter Maydell309786c2018-05-18 19:47:15 +01001928 tgt_len = len;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001929 switch (cmsg->cmsg_level) {
1930 case SOL_SOCKET:
1931 switch (cmsg->cmsg_type) {
1932 case SO_TIMESTAMP:
1933 tgt_len = sizeof(struct target_timeval);
1934 break;
1935 default:
1936 break;
1937 }
Peter Maydell309786c2018-05-18 19:47:15 +01001938 break;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001939 default:
1940 break;
1941 }
1942
Peter Maydell71749702017-12-15 13:52:55 +00001943 if (msg_controllen < TARGET_CMSG_LEN(tgt_len)) {
Peter Maydellc2aeb252015-05-26 19:46:31 +01001944 target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
Peter Maydell71749702017-12-15 13:52:55 +00001945 tgt_len = msg_controllen - sizeof(struct target_cmsghdr);
Peter Maydellc2aeb252015-05-26 19:46:31 +01001946 }
1947
1948 /* We must now copy-and-convert len bytes of payload
1949 * into tgt_len bytes of destination space. Bear in mind
1950 * that in both source and destination we may be dealing
1951 * with a truncated value!
1952 */
Huw Davies52b65492014-04-17 14:02:47 +01001953 switch (cmsg->cmsg_level) {
1954 case SOL_SOCKET:
1955 switch (cmsg->cmsg_type) {
1956 case SCM_RIGHTS:
1957 {
1958 int *fd = (int *)data;
1959 int *target_fd = (int *)target_data;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001960 int i, numfds = tgt_len / sizeof(int);
bellard7854b052003-03-29 17:22:23 +00001961
Peter Maydell876e23c2015-05-26 19:46:32 +01001962 for (i = 0; i < numfds; i++) {
1963 __put_user(fd[i], target_fd + i);
1964 }
Huw Davies52b65492014-04-17 14:02:47 +01001965 break;
1966 }
1967 case SO_TIMESTAMP:
1968 {
1969 struct timeval *tv = (struct timeval *)data;
1970 struct target_timeval *target_tv =
1971 (struct target_timeval *)target_data;
Jing Huangaebf5bc2012-07-24 14:01:42 +00001972
Peter Maydellc2aeb252015-05-26 19:46:31 +01001973 if (len != sizeof(struct timeval) ||
1974 tgt_len != sizeof(struct target_timeval)) {
Huw Davies52b65492014-04-17 14:02:47 +01001975 goto unimplemented;
Peter Maydellc2aeb252015-05-26 19:46:31 +01001976 }
Huw Davies52b65492014-04-17 14:02:47 +01001977
1978 /* copy struct timeval to target */
Peter Maydell876e23c2015-05-26 19:46:32 +01001979 __put_user(tv->tv_sec, &target_tv->tv_sec);
1980 __put_user(tv->tv_usec, &target_tv->tv_usec);
Huw Davies52b65492014-04-17 14:02:47 +01001981 break;
1982 }
Huw Davies4bc29752014-04-17 14:02:48 +01001983 case SCM_CREDENTIALS:
1984 {
1985 struct ucred *cred = (struct ucred *)data;
1986 struct target_ucred *target_cred =
1987 (struct target_ucred *)target_data;
1988
1989 __put_user(cred->pid, &target_cred->pid);
1990 __put_user(cred->uid, &target_cred->uid);
1991 __put_user(cred->gid, &target_cred->gid);
1992 break;
1993 }
Huw Davies52b65492014-04-17 14:02:47 +01001994 default:
1995 goto unimplemented;
1996 }
1997 break;
1998
Helge Delleree1ac3a2017-02-18 23:31:30 +01001999 case SOL_IP:
2000 switch (cmsg->cmsg_type) {
2001 case IP_TTL:
2002 {
2003 uint32_t *v = (uint32_t *)data;
2004 uint32_t *t_int = (uint32_t *)target_data;
2005
Peter Maydell71749702017-12-15 13:52:55 +00002006 if (len != sizeof(uint32_t) ||
2007 tgt_len != sizeof(uint32_t)) {
2008 goto unimplemented;
2009 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01002010 __put_user(*v, t_int);
2011 break;
2012 }
2013 case IP_RECVERR:
2014 {
2015 struct errhdr_t {
2016 struct sock_extended_err ee;
2017 struct sockaddr_in offender;
2018 };
2019 struct errhdr_t *errh = (struct errhdr_t *)data;
2020 struct errhdr_t *target_errh =
2021 (struct errhdr_t *)target_data;
2022
Peter Maydell71749702017-12-15 13:52:55 +00002023 if (len != sizeof(struct errhdr_t) ||
2024 tgt_len != sizeof(struct errhdr_t)) {
2025 goto unimplemented;
2026 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01002027 __put_user(errh->ee.ee_errno, &target_errh->ee.ee_errno);
2028 __put_user(errh->ee.ee_origin, &target_errh->ee.ee_origin);
2029 __put_user(errh->ee.ee_type, &target_errh->ee.ee_type);
2030 __put_user(errh->ee.ee_code, &target_errh->ee.ee_code);
2031 __put_user(errh->ee.ee_pad, &target_errh->ee.ee_pad);
2032 __put_user(errh->ee.ee_info, &target_errh->ee.ee_info);
2033 __put_user(errh->ee.ee_data, &target_errh->ee.ee_data);
2034 host_to_target_sockaddr((unsigned long) &target_errh->offender,
2035 (void *) &errh->offender, sizeof(errh->offender));
2036 break;
2037 }
2038 default:
2039 goto unimplemented;
2040 }
2041 break;
2042
2043 case SOL_IPV6:
2044 switch (cmsg->cmsg_type) {
2045 case IPV6_HOPLIMIT:
2046 {
2047 uint32_t *v = (uint32_t *)data;
2048 uint32_t *t_int = (uint32_t *)target_data;
2049
Peter Maydell71749702017-12-15 13:52:55 +00002050 if (len != sizeof(uint32_t) ||
2051 tgt_len != sizeof(uint32_t)) {
2052 goto unimplemented;
2053 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01002054 __put_user(*v, t_int);
2055 break;
2056 }
2057 case IPV6_RECVERR:
2058 {
2059 struct errhdr6_t {
2060 struct sock_extended_err ee;
2061 struct sockaddr_in6 offender;
2062 };
2063 struct errhdr6_t *errh = (struct errhdr6_t *)data;
2064 struct errhdr6_t *target_errh =
2065 (struct errhdr6_t *)target_data;
2066
Peter Maydell71749702017-12-15 13:52:55 +00002067 if (len != sizeof(struct errhdr6_t) ||
2068 tgt_len != sizeof(struct errhdr6_t)) {
2069 goto unimplemented;
2070 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01002071 __put_user(errh->ee.ee_errno, &target_errh->ee.ee_errno);
2072 __put_user(errh->ee.ee_origin, &target_errh->ee.ee_origin);
2073 __put_user(errh->ee.ee_type, &target_errh->ee.ee_type);
2074 __put_user(errh->ee.ee_code, &target_errh->ee.ee_code);
2075 __put_user(errh->ee.ee_pad, &target_errh->ee.ee_pad);
2076 __put_user(errh->ee.ee_info, &target_errh->ee.ee_info);
2077 __put_user(errh->ee.ee_data, &target_errh->ee.ee_data);
2078 host_to_target_sockaddr((unsigned long) &target_errh->offender,
2079 (void *) &errh->offender, sizeof(errh->offender));
2080 break;
2081 }
2082 default:
2083 goto unimplemented;
2084 }
2085 break;
2086
Huw Davies52b65492014-04-17 14:02:47 +01002087 default:
2088 unimplemented:
Josh Kunz39be5352020-02-03 18:54:13 -08002089 qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n",
2090 cmsg->cmsg_level, cmsg->cmsg_type);
Peter Maydellc2aeb252015-05-26 19:46:31 +01002091 memcpy(target_data, data, MIN(len, tgt_len));
2092 if (tgt_len > len) {
2093 memset(target_data + len, 0, tgt_len - len);
2094 }
bellard7854b052003-03-29 17:22:23 +00002095 }
2096
Peter Maydell71749702017-12-15 13:52:55 +00002097 target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(tgt_len));
2098 tgt_space = TARGET_CMSG_SPACE(tgt_len);
Peter Maydellc2aeb252015-05-26 19:46:31 +01002099 if (msg_controllen < tgt_space) {
2100 tgt_space = msg_controllen;
2101 }
2102 msg_controllen -= tgt_space;
2103 space += tgt_space;
bellard7854b052003-03-29 17:22:23 +00002104 cmsg = CMSG_NXTHDR(msgh, cmsg);
Jonathan Neuschäferee104582015-09-03 07:27:26 +02002105 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg,
2106 target_cmsg_start);
bellard7854b052003-03-29 17:22:23 +00002107 }
bellard5a4a8982007-11-11 17:39:18 +00002108 unlock_user(target_cmsg, target_cmsg_addr, space);
2109 the_end:
Matthias Brauncbb21ee2011-08-12 19:57:41 +02002110 target_msgh->msg_controllen = tswapal(space);
bellard5a4a8982007-11-11 17:39:18 +00002111 return 0;
bellard7854b052003-03-29 17:22:23 +00002112}
2113
ths0da46a62007-10-20 20:23:07 +00002114/* do_setsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002115static abi_long do_setsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00002116 abi_ulong optval_addr, socklen_t optlen)
bellard7854b052003-03-29 17:22:23 +00002117{
blueswir1992f48a2007-10-14 16:27:31 +00002118 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +00002119 int val;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02002120 struct ip_mreqn *ip_mreq;
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02002121 struct ip_mreq_source *ip_mreq_source;
ths3b46e622007-09-17 08:09:54 +00002122
bellard8853f862004-02-22 14:57:26 +00002123 switch(level) {
2124 case SOL_TCP:
Shu-Chun Wengfe51b0a2020-12-18 11:32:11 -08002125 case SOL_UDP:
2126 /* TCP and UDP options all take an 'int' value. */
bellard7854b052003-03-29 17:22:23 +00002127 if (optlen < sizeof(uint32_t))
ths0da46a62007-10-20 20:23:07 +00002128 return -TARGET_EINVAL;
ths3b46e622007-09-17 08:09:54 +00002129
bellard2f619692007-11-16 10:46:05 +00002130 if (get_user_u32(val, optval_addr))
2131 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00002132 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
2133 break;
2134 case SOL_IP:
2135 switch(optname) {
bellard2efbe912005-07-23 15:10:20 +00002136 case IP_TOS:
2137 case IP_TTL:
bellard8853f862004-02-22 14:57:26 +00002138 case IP_HDRINCL:
bellard2efbe912005-07-23 15:10:20 +00002139 case IP_ROUTER_ALERT:
2140 case IP_RECVOPTS:
2141 case IP_RETOPTS:
2142 case IP_PKTINFO:
2143 case IP_MTU_DISCOVER:
2144 case IP_RECVERR:
Helge Delleree1ac3a2017-02-18 23:31:30 +01002145 case IP_RECVTTL:
bellard2efbe912005-07-23 15:10:20 +00002146 case IP_RECVTOS:
2147#ifdef IP_FREEBIND
2148 case IP_FREEBIND:
2149#endif
2150 case IP_MULTICAST_TTL:
2151 case IP_MULTICAST_LOOP:
bellard8853f862004-02-22 14:57:26 +00002152 val = 0;
2153 if (optlen >= sizeof(uint32_t)) {
bellard2f619692007-11-16 10:46:05 +00002154 if (get_user_u32(val, optval_addr))
2155 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00002156 } else if (optlen >= 1) {
bellard2f619692007-11-16 10:46:05 +00002157 if (get_user_u8(val, optval_addr))
2158 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00002159 }
2160 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
2161 break;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02002162 case IP_ADD_MEMBERSHIP:
2163 case IP_DROP_MEMBERSHIP:
2164 if (optlen < sizeof (struct target_ip_mreq) ||
2165 optlen > sizeof (struct target_ip_mreqn))
2166 return -TARGET_EINVAL;
2167
2168 ip_mreq = (struct ip_mreqn *) alloca(optlen);
2169 target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
2170 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen));
2171 break;
2172
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02002173 case IP_BLOCK_SOURCE:
2174 case IP_UNBLOCK_SOURCE:
2175 case IP_ADD_SOURCE_MEMBERSHIP:
2176 case IP_DROP_SOURCE_MEMBERSHIP:
2177 if (optlen != sizeof (struct target_ip_mreq_source))
2178 return -TARGET_EINVAL;
2179
2180 ip_mreq_source = lock_user(VERIFY_READ, optval_addr, optlen, 1);
Peter Maydell74e43b02021-08-09 16:54:24 +01002181 if (!ip_mreq_source) {
2182 return -TARGET_EFAULT;
2183 }
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02002184 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen));
2185 unlock_user (ip_mreq_source, optval_addr, 0);
2186 break;
2187
bellard8853f862004-02-22 14:57:26 +00002188 default:
2189 goto unimplemented;
2190 }
2191 break;
Laurent Vivier0d78b3b2013-08-30 01:46:43 +02002192 case SOL_IPV6:
2193 switch (optname) {
2194 case IPV6_MTU_DISCOVER:
2195 case IPV6_MTU:
2196 case IPV6_V6ONLY:
2197 case IPV6_RECVPKTINFO:
Helge Delleree1ac3a2017-02-18 23:31:30 +01002198 case IPV6_UNICAST_HOPS:
Laurent Vivier21749c42018-06-27 23:21:52 +02002199 case IPV6_MULTICAST_HOPS:
2200 case IPV6_MULTICAST_LOOP:
Helge Delleree1ac3a2017-02-18 23:31:30 +01002201 case IPV6_RECVERR:
2202 case IPV6_RECVHOPLIMIT:
2203 case IPV6_2292HOPLIMIT:
2204 case IPV6_CHECKSUM:
Helge Dellerb9cce6d2019-03-10 12:12:16 +01002205 case IPV6_ADDRFORM:
2206 case IPV6_2292PKTINFO:
2207 case IPV6_RECVTCLASS:
2208 case IPV6_RECVRTHDR:
2209 case IPV6_2292RTHDR:
2210 case IPV6_RECVHOPOPTS:
2211 case IPV6_2292HOPOPTS:
2212 case IPV6_RECVDSTOPTS:
2213 case IPV6_2292DSTOPTS:
2214 case IPV6_TCLASS:
Shu-Chun Weng22db1212020-12-18 11:32:12 -08002215 case IPV6_ADDR_PREFERENCES:
Helge Dellerb9cce6d2019-03-10 12:12:16 +01002216#ifdef IPV6_RECVPATHMTU
2217 case IPV6_RECVPATHMTU:
2218#endif
2219#ifdef IPV6_TRANSPARENT
2220 case IPV6_TRANSPARENT:
2221#endif
2222#ifdef IPV6_FREEBIND
2223 case IPV6_FREEBIND:
2224#endif
2225#ifdef IPV6_RECVORIGDSTADDR
2226 case IPV6_RECVORIGDSTADDR:
2227#endif
Laurent Vivier0d78b3b2013-08-30 01:46:43 +02002228 val = 0;
2229 if (optlen < sizeof(uint32_t)) {
2230 return -TARGET_EINVAL;
2231 }
2232 if (get_user_u32(val, optval_addr)) {
2233 return -TARGET_EFAULT;
2234 }
2235 ret = get_errno(setsockopt(sockfd, level, optname,
2236 &val, sizeof(val)));
2237 break;
Helge Delleree1ac3a2017-02-18 23:31:30 +01002238 case IPV6_PKTINFO:
2239 {
2240 struct in6_pktinfo pki;
2241
2242 if (optlen < sizeof(pki)) {
2243 return -TARGET_EINVAL;
2244 }
2245
2246 if (copy_from_user(&pki, optval_addr, sizeof(pki))) {
2247 return -TARGET_EFAULT;
2248 }
2249
2250 pki.ipi6_ifindex = tswap32(pki.ipi6_ifindex);
2251
2252 ret = get_errno(setsockopt(sockfd, level, optname,
2253 &pki, sizeof(pki)));
2254 break;
2255 }
Neng Chen22bf4ee2019-06-19 16:17:10 +02002256 case IPV6_ADD_MEMBERSHIP:
2257 case IPV6_DROP_MEMBERSHIP:
2258 {
2259 struct ipv6_mreq ipv6mreq;
2260
2261 if (optlen < sizeof(ipv6mreq)) {
2262 return -TARGET_EINVAL;
2263 }
2264
2265 if (copy_from_user(&ipv6mreq, optval_addr, sizeof(ipv6mreq))) {
2266 return -TARGET_EFAULT;
2267 }
2268
2269 ipv6mreq.ipv6mr_interface = tswap32(ipv6mreq.ipv6mr_interface);
2270
2271 ret = get_errno(setsockopt(sockfd, level, optname,
2272 &ipv6mreq, sizeof(ipv6mreq)));
2273 break;
2274 }
Helge Delleree1ac3a2017-02-18 23:31:30 +01002275 default:
2276 goto unimplemented;
2277 }
2278 break;
2279 case SOL_ICMPV6:
2280 switch (optname) {
2281 case ICMPV6_FILTER:
2282 {
2283 struct icmp6_filter icmp6f;
2284
2285 if (optlen > sizeof(icmp6f)) {
2286 optlen = sizeof(icmp6f);
2287 }
2288
2289 if (copy_from_user(&icmp6f, optval_addr, optlen)) {
2290 return -TARGET_EFAULT;
2291 }
2292
2293 for (val = 0; val < 8; val++) {
2294 icmp6f.data[val] = tswap32(icmp6f.data[val]);
2295 }
2296
2297 ret = get_errno(setsockopt(sockfd, level, optname,
2298 &icmp6f, optlen));
2299 break;
2300 }
Laurent Vivier0d78b3b2013-08-30 01:46:43 +02002301 default:
2302 goto unimplemented;
2303 }
2304 break;
Jing Huang920394d2012-07-24 13:59:23 +00002305 case SOL_RAW:
2306 switch (optname) {
2307 case ICMP_FILTER:
Helge Delleree1ac3a2017-02-18 23:31:30 +01002308 case IPV6_CHECKSUM:
2309 /* those take an u32 value */
Jing Huang920394d2012-07-24 13:59:23 +00002310 if (optlen < sizeof(uint32_t)) {
2311 return -TARGET_EINVAL;
2312 }
2313
2314 if (get_user_u32(val, optval_addr)) {
2315 return -TARGET_EFAULT;
2316 }
2317 ret = get_errno(setsockopt(sockfd, level, optname,
2318 &val, sizeof(val)));
2319 break;
2320
2321 default:
2322 goto unimplemented;
2323 }
2324 break;
Yunqiang Suf31dddd2019-06-19 16:17:11 +02002325#if defined(SOL_ALG) && defined(ALG_SET_KEY) && defined(ALG_SET_AEAD_AUTHSIZE)
2326 case SOL_ALG:
2327 switch (optname) {
2328 case ALG_SET_KEY:
2329 {
2330 char *alg_key = g_malloc(optlen);
2331
2332 if (!alg_key) {
2333 return -TARGET_ENOMEM;
2334 }
2335 if (copy_from_user(alg_key, optval_addr, optlen)) {
2336 g_free(alg_key);
2337 return -TARGET_EFAULT;
2338 }
2339 ret = get_errno(setsockopt(sockfd, level, optname,
2340 alg_key, optlen));
2341 g_free(alg_key);
2342 break;
2343 }
2344 case ALG_SET_AEAD_AUTHSIZE:
2345 {
2346 ret = get_errno(setsockopt(sockfd, level, optname,
2347 NULL, optlen));
2348 break;
2349 }
2350 default:
2351 goto unimplemented;
2352 }
2353 break;
2354#endif
bellard3532fa72006-06-24 15:06:03 +00002355 case TARGET_SOL_SOCKET:
bellard8853f862004-02-22 14:57:26 +00002356 switch (optname) {
Laurent Vivier1b09aeb2013-01-01 08:24:11 +00002357 case TARGET_SO_RCVTIMEO:
2358 {
2359 struct timeval tv;
2360
2361 optname = SO_RCVTIMEO;
2362
2363set_timeout:
2364 if (optlen != sizeof(struct target_timeval)) {
2365 return -TARGET_EINVAL;
2366 }
2367
2368 if (copy_from_user_timeval(&tv, optval_addr)) {
2369 return -TARGET_EFAULT;
2370 }
2371
2372 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
2373 &tv, sizeof(tv)));
2374 return ret;
2375 }
2376 case TARGET_SO_SNDTIMEO:
2377 optname = SO_SNDTIMEO;
2378 goto set_timeout;
Laurent Vivierf57d4192013-08-30 01:46:41 +02002379 case TARGET_SO_ATTACH_FILTER:
2380 {
2381 struct target_sock_fprog *tfprog;
2382 struct target_sock_filter *tfilter;
2383 struct sock_fprog fprog;
2384 struct sock_filter *filter;
2385 int i;
2386
2387 if (optlen != sizeof(*tfprog)) {
2388 return -TARGET_EINVAL;
2389 }
2390 if (!lock_user_struct(VERIFY_READ, tfprog, optval_addr, 0)) {
2391 return -TARGET_EFAULT;
2392 }
2393 if (!lock_user_struct(VERIFY_READ, tfilter,
2394 tswapal(tfprog->filter), 0)) {
2395 unlock_user_struct(tfprog, optval_addr, 1);
2396 return -TARGET_EFAULT;
2397 }
2398
2399 fprog.len = tswap16(tfprog->len);
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05302400 filter = g_try_new(struct sock_filter, fprog.len);
Laurent Vivierf57d4192013-08-30 01:46:41 +02002401 if (filter == NULL) {
2402 unlock_user_struct(tfilter, tfprog->filter, 1);
2403 unlock_user_struct(tfprog, optval_addr, 1);
2404 return -TARGET_ENOMEM;
2405 }
2406 for (i = 0; i < fprog.len; i++) {
2407 filter[i].code = tswap16(tfilter[i].code);
2408 filter[i].jt = tfilter[i].jt;
2409 filter[i].jf = tfilter[i].jf;
2410 filter[i].k = tswap32(tfilter[i].k);
2411 }
2412 fprog.filter = filter;
2413
2414 ret = get_errno(setsockopt(sockfd, SOL_SOCKET,
2415 SO_ATTACH_FILTER, &fprog, sizeof(fprog)));
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05302416 g_free(filter);
Laurent Vivierf57d4192013-08-30 01:46:41 +02002417
2418 unlock_user_struct(tfilter, tfprog->filter, 1);
2419 unlock_user_struct(tfprog, optval_addr, 1);
2420 return ret;
2421 }
Joakim Tjernlund451aaf62014-07-12 15:47:06 +02002422 case TARGET_SO_BINDTODEVICE:
2423 {
2424 char *dev_ifname, *addr_ifname;
2425
2426 if (optlen > IFNAMSIZ - 1) {
2427 optlen = IFNAMSIZ - 1;
2428 }
2429 dev_ifname = lock_user(VERIFY_READ, optval_addr, optlen, 1);
2430 if (!dev_ifname) {
2431 return -TARGET_EFAULT;
2432 }
2433 optname = SO_BINDTODEVICE;
2434 addr_ifname = alloca(IFNAMSIZ);
2435 memcpy(addr_ifname, dev_ifname, optlen);
2436 addr_ifname[optlen] = 0;
Chen Gangfad6c582016-01-11 13:58:50 +08002437 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
2438 addr_ifname, optlen));
Joakim Tjernlund451aaf62014-07-12 15:47:06 +02002439 unlock_user (dev_ifname, optval_addr, 0);
2440 return ret;
2441 }
Carlo Marcelo Arenas Belón83eb6e52018-08-24 01:56:01 -07002442 case TARGET_SO_LINGER:
2443 {
2444 struct linger lg;
2445 struct target_linger *tlg;
2446
2447 if (optlen != sizeof(struct target_linger)) {
2448 return -TARGET_EINVAL;
2449 }
2450 if (!lock_user_struct(VERIFY_READ, tlg, optval_addr, 1)) {
2451 return -TARGET_EFAULT;
2452 }
2453 __get_user(lg.l_onoff, &tlg->l_onoff);
2454 __get_user(lg.l_linger, &tlg->l_linger);
2455 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, SO_LINGER,
2456 &lg, sizeof(lg)));
2457 unlock_user_struct(tlg, optval_addr, 0);
2458 return ret;
2459 }
bellard8853f862004-02-22 14:57:26 +00002460 /* Options with 'int' argument. */
bellard3532fa72006-06-24 15:06:03 +00002461 case TARGET_SO_DEBUG:
2462 optname = SO_DEBUG;
2463 break;
2464 case TARGET_SO_REUSEADDR:
2465 optname = SO_REUSEADDR;
2466 break;
Yunqiang Su113a9dd2018-10-30 13:55:08 +01002467#ifdef SO_REUSEPORT
2468 case TARGET_SO_REUSEPORT:
2469 optname = SO_REUSEPORT;
2470 break;
2471#endif
bellard3532fa72006-06-24 15:06:03 +00002472 case TARGET_SO_TYPE:
2473 optname = SO_TYPE;
2474 break;
2475 case TARGET_SO_ERROR:
2476 optname = SO_ERROR;
2477 break;
2478 case TARGET_SO_DONTROUTE:
2479 optname = SO_DONTROUTE;
2480 break;
2481 case TARGET_SO_BROADCAST:
2482 optname = SO_BROADCAST;
2483 break;
2484 case TARGET_SO_SNDBUF:
2485 optname = SO_SNDBUF;
2486 break;
Paul Burtond79b6cc2014-06-22 11:25:35 +01002487 case TARGET_SO_SNDBUFFORCE:
2488 optname = SO_SNDBUFFORCE;
2489 break;
bellard3532fa72006-06-24 15:06:03 +00002490 case TARGET_SO_RCVBUF:
2491 optname = SO_RCVBUF;
2492 break;
Paul Burtond79b6cc2014-06-22 11:25:35 +01002493 case TARGET_SO_RCVBUFFORCE:
2494 optname = SO_RCVBUFFORCE;
2495 break;
bellard3532fa72006-06-24 15:06:03 +00002496 case TARGET_SO_KEEPALIVE:
2497 optname = SO_KEEPALIVE;
2498 break;
2499 case TARGET_SO_OOBINLINE:
2500 optname = SO_OOBINLINE;
2501 break;
2502 case TARGET_SO_NO_CHECK:
2503 optname = SO_NO_CHECK;
2504 break;
2505 case TARGET_SO_PRIORITY:
2506 optname = SO_PRIORITY;
2507 break;
bellard5e83e8e2005-03-01 22:32:06 +00002508#ifdef SO_BSDCOMPAT
bellard3532fa72006-06-24 15:06:03 +00002509 case TARGET_SO_BSDCOMPAT:
2510 optname = SO_BSDCOMPAT;
2511 break;
bellard5e83e8e2005-03-01 22:32:06 +00002512#endif
bellard3532fa72006-06-24 15:06:03 +00002513 case TARGET_SO_PASSCRED:
2514 optname = SO_PASSCRED;
2515 break;
Paul Burton82d0fe62014-06-22 11:25:36 +01002516 case TARGET_SO_PASSSEC:
2517 optname = SO_PASSSEC;
2518 break;
bellard3532fa72006-06-24 15:06:03 +00002519 case TARGET_SO_TIMESTAMP:
2520 optname = SO_TIMESTAMP;
2521 break;
2522 case TARGET_SO_RCVLOWAT:
2523 optname = SO_RCVLOWAT;
2524 break;
bellard8853f862004-02-22 14:57:26 +00002525 default:
2526 goto unimplemented;
2527 }
bellard3532fa72006-06-24 15:06:03 +00002528 if (optlen < sizeof(uint32_t))
bellard2f619692007-11-16 10:46:05 +00002529 return -TARGET_EINVAL;
bellard3532fa72006-06-24 15:06:03 +00002530
bellard2f619692007-11-16 10:46:05 +00002531 if (get_user_u32(val, optval_addr))
2532 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00002533 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
bellard8853f862004-02-22 14:57:26 +00002534 break;
Josh Kunza2d86682019-10-29 15:43:10 -07002535#ifdef SOL_NETLINK
2536 case SOL_NETLINK:
2537 switch (optname) {
2538 case NETLINK_PKTINFO:
2539 case NETLINK_ADD_MEMBERSHIP:
2540 case NETLINK_DROP_MEMBERSHIP:
2541 case NETLINK_BROADCAST_ERROR:
2542 case NETLINK_NO_ENOBUFS:
2543#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2544 case NETLINK_LISTEN_ALL_NSID:
2545 case NETLINK_CAP_ACK:
2546#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2547#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
2548 case NETLINK_EXT_ACK:
2549#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2550#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
2551 case NETLINK_GET_STRICT_CHK:
2552#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2553 break;
2554 default:
2555 goto unimplemented;
2556 }
2557 val = 0;
2558 if (optlen < sizeof(uint32_t)) {
2559 return -TARGET_EINVAL;
2560 }
2561 if (get_user_u32(val, optval_addr)) {
2562 return -TARGET_EFAULT;
2563 }
2564 ret = get_errno(setsockopt(sockfd, SOL_NETLINK, optname, &val,
2565 sizeof(val)));
2566 break;
2567#endif /* SOL_NETLINK */
bellard7854b052003-03-29 17:22:23 +00002568 default:
bellard8853f862004-02-22 14:57:26 +00002569 unimplemented:
Josh Kunz39be5352020-02-03 18:54:13 -08002570 qemu_log_mask(LOG_UNIMP, "Unsupported setsockopt level=%d optname=%d\n",
2571 level, optname);
ths6fa13c12007-12-18 02:41:04 +00002572 ret = -TARGET_ENOPROTOOPT;
bellard7854b052003-03-29 17:22:23 +00002573 }
bellard8853f862004-02-22 14:57:26 +00002574 return ret;
bellard7854b052003-03-29 17:22:23 +00002575}
2576
ths0da46a62007-10-20 20:23:07 +00002577/* do_getsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002578static abi_long do_getsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00002579 abi_ulong optval_addr, abi_ulong optlen)
bellard7854b052003-03-29 17:22:23 +00002580{
blueswir1992f48a2007-10-14 16:27:31 +00002581 abi_long ret;
blueswir1b55266b2008-09-20 08:07:15 +00002582 int len, val;
2583 socklen_t lv;
bellard8853f862004-02-22 14:57:26 +00002584
2585 switch(level) {
bellard3532fa72006-06-24 15:06:03 +00002586 case TARGET_SOL_SOCKET:
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002587 level = SOL_SOCKET;
2588 switch (optname) {
2589 /* These don't just return a single integer */
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002590 case TARGET_SO_PEERNAME:
2591 goto unimplemented;
Andreas Schwab405dc4c2019-05-13 11:06:26 +02002592 case TARGET_SO_RCVTIMEO: {
2593 struct timeval tv;
2594 socklen_t tvlen;
2595
2596 optname = SO_RCVTIMEO;
2597
2598get_timeout:
2599 if (get_user_u32(len, optlen)) {
2600 return -TARGET_EFAULT;
2601 }
2602 if (len < 0) {
2603 return -TARGET_EINVAL;
2604 }
2605
2606 tvlen = sizeof(tv);
2607 ret = get_errno(getsockopt(sockfd, level, optname,
2608 &tv, &tvlen));
2609 if (ret < 0) {
2610 return ret;
2611 }
2612 if (len > sizeof(struct target_timeval)) {
2613 len = sizeof(struct target_timeval);
2614 }
2615 if (copy_to_user_timeval(optval_addr, &tv)) {
2616 return -TARGET_EFAULT;
2617 }
2618 if (put_user_u32(len, optlen)) {
2619 return -TARGET_EFAULT;
2620 }
2621 break;
2622 }
2623 case TARGET_SO_SNDTIMEO:
2624 optname = SO_SNDTIMEO;
2625 goto get_timeout;
Akos PASZTORY583359a2011-11-14 15:09:49 +02002626 case TARGET_SO_PEERCRED: {
2627 struct ucred cr;
2628 socklen_t crlen;
2629 struct target_ucred *tcr;
2630
2631 if (get_user_u32(len, optlen)) {
2632 return -TARGET_EFAULT;
2633 }
2634 if (len < 0) {
2635 return -TARGET_EINVAL;
2636 }
2637
2638 crlen = sizeof(cr);
2639 ret = get_errno(getsockopt(sockfd, level, SO_PEERCRED,
2640 &cr, &crlen));
2641 if (ret < 0) {
2642 return ret;
2643 }
2644 if (len > crlen) {
2645 len = crlen;
2646 }
2647 if (!lock_user_struct(VERIFY_WRITE, tcr, optval_addr, 0)) {
2648 return -TARGET_EFAULT;
2649 }
2650 __put_user(cr.pid, &tcr->pid);
2651 __put_user(cr.uid, &tcr->uid);
2652 __put_user(cr.gid, &tcr->gid);
2653 unlock_user_struct(tcr, optval_addr, 1);
2654 if (put_user_u32(len, optlen)) {
2655 return -TARGET_EFAULT;
2656 }
2657 break;
2658 }
Laurent Vivier6d485a52020-02-04 22:19:01 +01002659 case TARGET_SO_PEERSEC: {
2660 char *name;
2661
2662 if (get_user_u32(len, optlen)) {
2663 return -TARGET_EFAULT;
2664 }
2665 if (len < 0) {
2666 return -TARGET_EINVAL;
2667 }
2668 name = lock_user(VERIFY_WRITE, optval_addr, len, 0);
2669 if (!name) {
2670 return -TARGET_EFAULT;
2671 }
2672 lv = len;
2673 ret = get_errno(getsockopt(sockfd, level, SO_PEERSEC,
2674 name, &lv));
2675 if (put_user_u32(lv, optlen)) {
2676 ret = -TARGET_EFAULT;
2677 }
2678 unlock_user(name, optval_addr, lv);
2679 break;
2680 }
Carlo Marcelo Arenas Belón83eb6e52018-08-24 01:56:01 -07002681 case TARGET_SO_LINGER:
2682 {
2683 struct linger lg;
2684 socklen_t lglen;
2685 struct target_linger *tlg;
2686
2687 if (get_user_u32(len, optlen)) {
2688 return -TARGET_EFAULT;
2689 }
2690 if (len < 0) {
2691 return -TARGET_EINVAL;
2692 }
2693
2694 lglen = sizeof(lg);
2695 ret = get_errno(getsockopt(sockfd, level, SO_LINGER,
2696 &lg, &lglen));
2697 if (ret < 0) {
2698 return ret;
2699 }
2700 if (len > lglen) {
2701 len = lglen;
2702 }
2703 if (!lock_user_struct(VERIFY_WRITE, tlg, optval_addr, 0)) {
2704 return -TARGET_EFAULT;
2705 }
2706 __put_user(lg.l_onoff, &tlg->l_onoff);
2707 __put_user(lg.l_linger, &tlg->l_linger);
2708 unlock_user_struct(tlg, optval_addr, 1);
2709 if (put_user_u32(len, optlen)) {
2710 return -TARGET_EFAULT;
2711 }
2712 break;
2713 }
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002714 /* Options with 'int' argument. */
2715 case TARGET_SO_DEBUG:
2716 optname = SO_DEBUG;
2717 goto int_case;
2718 case TARGET_SO_REUSEADDR:
2719 optname = SO_REUSEADDR;
2720 goto int_case;
Yunqiang Su113a9dd2018-10-30 13:55:08 +01002721#ifdef SO_REUSEPORT
2722 case TARGET_SO_REUSEPORT:
2723 optname = SO_REUSEPORT;
2724 goto int_case;
2725#endif
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002726 case TARGET_SO_TYPE:
2727 optname = SO_TYPE;
2728 goto int_case;
2729 case TARGET_SO_ERROR:
2730 optname = SO_ERROR;
2731 goto int_case;
2732 case TARGET_SO_DONTROUTE:
2733 optname = SO_DONTROUTE;
2734 goto int_case;
2735 case TARGET_SO_BROADCAST:
2736 optname = SO_BROADCAST;
2737 goto int_case;
2738 case TARGET_SO_SNDBUF:
2739 optname = SO_SNDBUF;
2740 goto int_case;
2741 case TARGET_SO_RCVBUF:
2742 optname = SO_RCVBUF;
2743 goto int_case;
2744 case TARGET_SO_KEEPALIVE:
2745 optname = SO_KEEPALIVE;
2746 goto int_case;
2747 case TARGET_SO_OOBINLINE:
2748 optname = SO_OOBINLINE;
2749 goto int_case;
2750 case TARGET_SO_NO_CHECK:
2751 optname = SO_NO_CHECK;
2752 goto int_case;
2753 case TARGET_SO_PRIORITY:
2754 optname = SO_PRIORITY;
2755 goto int_case;
2756#ifdef SO_BSDCOMPAT
2757 case TARGET_SO_BSDCOMPAT:
2758 optname = SO_BSDCOMPAT;
2759 goto int_case;
2760#endif
2761 case TARGET_SO_PASSCRED:
2762 optname = SO_PASSCRED;
2763 goto int_case;
2764 case TARGET_SO_TIMESTAMP:
2765 optname = SO_TIMESTAMP;
2766 goto int_case;
2767 case TARGET_SO_RCVLOWAT:
2768 optname = SO_RCVLOWAT;
2769 goto int_case;
Paul Burtonaec1ca42014-06-22 11:25:34 +01002770 case TARGET_SO_ACCEPTCONN:
2771 optname = SO_ACCEPTCONN;
2772 goto int_case;
Jason A. Donenfeldec63e062021-02-04 16:39:25 +01002773 case TARGET_SO_PROTOCOL:
2774 optname = SO_PROTOCOL;
2775 goto int_case;
2776 case TARGET_SO_DOMAIN:
2777 optname = SO_DOMAIN;
2778 goto int_case;
bellard8853f862004-02-22 14:57:26 +00002779 default:
bellard2efbe912005-07-23 15:10:20 +00002780 goto int_case;
2781 }
2782 break;
2783 case SOL_TCP:
Shu-Chun Wengfe51b0a2020-12-18 11:32:11 -08002784 case SOL_UDP:
2785 /* TCP and UDP options all take an 'int' value. */
bellard2efbe912005-07-23 15:10:20 +00002786 int_case:
bellard2f619692007-11-16 10:46:05 +00002787 if (get_user_u32(len, optlen))
2788 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002789 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00002790 return -TARGET_EINVAL;
Mike Frysinger73160d92011-02-07 01:05:49 -05002791 lv = sizeof(lv);
bellard2efbe912005-07-23 15:10:20 +00002792 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2793 if (ret < 0)
2794 return ret;
Paul Burton8289d112014-06-22 11:25:33 +01002795 if (optname == SO_TYPE) {
2796 val = host_to_target_sock_type(val);
2797 }
bellard2efbe912005-07-23 15:10:20 +00002798 if (len > lv)
2799 len = lv;
bellard2f619692007-11-16 10:46:05 +00002800 if (len == 4) {
2801 if (put_user_u32(val, optval_addr))
2802 return -TARGET_EFAULT;
2803 } else {
2804 if (put_user_u8(val, optval_addr))
2805 return -TARGET_EFAULT;
Jamie Lentinf3b974c2010-11-26 15:04:08 +02002806 }
bellard2f619692007-11-16 10:46:05 +00002807 if (put_user_u32(len, optlen))
2808 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002809 break;
2810 case SOL_IP:
2811 switch(optname) {
2812 case IP_TOS:
2813 case IP_TTL:
2814 case IP_HDRINCL:
2815 case IP_ROUTER_ALERT:
2816 case IP_RECVOPTS:
2817 case IP_RETOPTS:
2818 case IP_PKTINFO:
2819 case IP_MTU_DISCOVER:
2820 case IP_RECVERR:
2821 case IP_RECVTOS:
2822#ifdef IP_FREEBIND
2823 case IP_FREEBIND:
2824#endif
2825 case IP_MULTICAST_TTL:
2826 case IP_MULTICAST_LOOP:
bellard2f619692007-11-16 10:46:05 +00002827 if (get_user_u32(len, optlen))
2828 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00002829 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00002830 return -TARGET_EINVAL;
Mike Frysinger73160d92011-02-07 01:05:49 -05002831 lv = sizeof(lv);
bellard8853f862004-02-22 14:57:26 +00002832 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2833 if (ret < 0)
2834 return ret;
bellard2efbe912005-07-23 15:10:20 +00002835 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
bellard2efbe912005-07-23 15:10:20 +00002836 len = 1;
bellard2f619692007-11-16 10:46:05 +00002837 if (put_user_u32(len, optlen)
2838 || put_user_u8(val, optval_addr))
2839 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002840 } else {
bellard2efbe912005-07-23 15:10:20 +00002841 if (len > sizeof(int))
2842 len = sizeof(int);
bellard2f619692007-11-16 10:46:05 +00002843 if (put_user_u32(len, optlen)
2844 || put_user_u32(val, optval_addr))
2845 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00002846 }
bellard8853f862004-02-22 14:57:26 +00002847 break;
bellard2efbe912005-07-23 15:10:20 +00002848 default:
thsc02f4992007-12-18 02:39:59 +00002849 ret = -TARGET_ENOPROTOOPT;
2850 break;
bellard8853f862004-02-22 14:57:26 +00002851 }
2852 break;
Tom Deseynbd8ed482018-12-13 14:06:11 +01002853 case SOL_IPV6:
2854 switch (optname) {
2855 case IPV6_MTU_DISCOVER:
2856 case IPV6_MTU:
2857 case IPV6_V6ONLY:
2858 case IPV6_RECVPKTINFO:
2859 case IPV6_UNICAST_HOPS:
2860 case IPV6_MULTICAST_HOPS:
2861 case IPV6_MULTICAST_LOOP:
2862 case IPV6_RECVERR:
2863 case IPV6_RECVHOPLIMIT:
2864 case IPV6_2292HOPLIMIT:
2865 case IPV6_CHECKSUM:
Helge Dellerb9cce6d2019-03-10 12:12:16 +01002866 case IPV6_ADDRFORM:
2867 case IPV6_2292PKTINFO:
2868 case IPV6_RECVTCLASS:
2869 case IPV6_RECVRTHDR:
2870 case IPV6_2292RTHDR:
2871 case IPV6_RECVHOPOPTS:
2872 case IPV6_2292HOPOPTS:
2873 case IPV6_RECVDSTOPTS:
2874 case IPV6_2292DSTOPTS:
2875 case IPV6_TCLASS:
Shu-Chun Weng22db1212020-12-18 11:32:12 -08002876 case IPV6_ADDR_PREFERENCES:
Helge Dellerb9cce6d2019-03-10 12:12:16 +01002877#ifdef IPV6_RECVPATHMTU
2878 case IPV6_RECVPATHMTU:
2879#endif
2880#ifdef IPV6_TRANSPARENT
2881 case IPV6_TRANSPARENT:
2882#endif
2883#ifdef IPV6_FREEBIND
2884 case IPV6_FREEBIND:
2885#endif
2886#ifdef IPV6_RECVORIGDSTADDR
2887 case IPV6_RECVORIGDSTADDR:
2888#endif
Tom Deseynbd8ed482018-12-13 14:06:11 +01002889 if (get_user_u32(len, optlen))
2890 return -TARGET_EFAULT;
2891 if (len < 0)
2892 return -TARGET_EINVAL;
2893 lv = sizeof(lv);
2894 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2895 if (ret < 0)
2896 return ret;
2897 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
2898 len = 1;
2899 if (put_user_u32(len, optlen)
2900 || put_user_u8(val, optval_addr))
2901 return -TARGET_EFAULT;
2902 } else {
2903 if (len > sizeof(int))
2904 len = sizeof(int);
2905 if (put_user_u32(len, optlen)
2906 || put_user_u32(val, optval_addr))
2907 return -TARGET_EFAULT;
2908 }
2909 break;
2910 default:
2911 ret = -TARGET_ENOPROTOOPT;
2912 break;
2913 }
2914 break;
Josh Kunza2d86682019-10-29 15:43:10 -07002915#ifdef SOL_NETLINK
2916 case SOL_NETLINK:
2917 switch (optname) {
2918 case NETLINK_PKTINFO:
2919 case NETLINK_BROADCAST_ERROR:
2920 case NETLINK_NO_ENOBUFS:
2921#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2922 case NETLINK_LISTEN_ALL_NSID:
2923 case NETLINK_CAP_ACK:
2924#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2925#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
2926 case NETLINK_EXT_ACK:
2927#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2928#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
2929 case NETLINK_GET_STRICT_CHK:
2930#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2931 if (get_user_u32(len, optlen)) {
2932 return -TARGET_EFAULT;
2933 }
2934 if (len != sizeof(val)) {
2935 return -TARGET_EINVAL;
2936 }
2937 lv = len;
2938 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2939 if (ret < 0) {
2940 return ret;
2941 }
2942 if (put_user_u32(lv, optlen)
2943 || put_user_u32(val, optval_addr)) {
2944 return -TARGET_EFAULT;
2945 }
2946 break;
2947#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2948 case NETLINK_LIST_MEMBERSHIPS:
2949 {
2950 uint32_t *results;
2951 int i;
2952 if (get_user_u32(len, optlen)) {
2953 return -TARGET_EFAULT;
2954 }
2955 if (len < 0) {
2956 return -TARGET_EINVAL;
2957 }
2958 results = lock_user(VERIFY_WRITE, optval_addr, len, 1);
Frédéric Fortier13e340c2021-03-28 14:01:35 -04002959 if (!results && len > 0) {
Josh Kunza2d86682019-10-29 15:43:10 -07002960 return -TARGET_EFAULT;
2961 }
2962 lv = len;
2963 ret = get_errno(getsockopt(sockfd, level, optname, results, &lv));
2964 if (ret < 0) {
2965 unlock_user(results, optval_addr, 0);
2966 return ret;
2967 }
2968 /* swap host endianess to target endianess. */
2969 for (i = 0; i < (len / sizeof(uint32_t)); i++) {
2970 results[i] = tswap32(results[i]);
2971 }
2972 if (put_user_u32(lv, optlen)) {
2973 return -TARGET_EFAULT;
2974 }
2975 unlock_user(results, optval_addr, 0);
2976 break;
2977 }
2978#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2979 default:
2980 goto unimplemented;
2981 }
Laurent Vivierc0cb8802019-11-12 11:50:55 +01002982 break;
Josh Kunza2d86682019-10-29 15:43:10 -07002983#endif /* SOL_NETLINK */
bellard8853f862004-02-22 14:57:26 +00002984 default:
2985 unimplemented:
Josh Kunz39be5352020-02-03 18:54:13 -08002986 qemu_log_mask(LOG_UNIMP,
2987 "getsockopt level=%d optname=%d not yet supported\n",
2988 level, optname);
thsc02f4992007-12-18 02:39:59 +00002989 ret = -TARGET_EOPNOTSUPP;
bellard8853f862004-02-22 14:57:26 +00002990 break;
2991 }
2992 return ret;
bellard7854b052003-03-29 17:22:23 +00002993}
2994
Max Filippov9ac22512018-04-04 17:30:41 -07002995/* Convert target low/high pair representing file offset into the host
2996 * low/high pair. This function doesn't handle offsets bigger than 64 bits
2997 * as the kernel doesn't handle them either.
2998 */
2999static void target_to_host_low_high(abi_ulong tlow,
3000 abi_ulong thigh,
3001 unsigned long *hlow,
3002 unsigned long *hhigh)
3003{
3004 uint64_t off = tlow |
3005 ((unsigned long long)thigh << TARGET_LONG_BITS / 2) <<
3006 TARGET_LONG_BITS / 2;
3007
3008 *hlow = off;
3009 *hhigh = (off >> HOST_LONG_BITS / 2) >> HOST_LONG_BITS / 2;
3010}
3011
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003012static struct iovec *lock_iovec(int type, abi_ulong target_addr,
Peter Maydelldab32b32016-07-15 14:57:26 +01003013 abi_ulong count, int copy)
pbrook53a59602006-03-25 19:31:22 +00003014{
3015 struct target_iovec *target_vec;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003016 struct iovec *vec;
3017 abi_ulong total_len, max_len;
balrogd732dcb2008-10-28 10:21:03 +00003018 int i;
Peter Maydell501bb4b2014-02-17 18:55:33 +00003019 int err = 0;
Tom Musta29560a62014-08-12 13:53:43 -05003020 bool bad_address = false;
pbrook53a59602006-03-25 19:31:22 +00003021
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003022 if (count == 0) {
3023 errno = 0;
3024 return NULL;
pbrook53a59602006-03-25 19:31:22 +00003025 }
Peter Maydelldab32b32016-07-15 14:57:26 +01003026 if (count > IOV_MAX) {
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003027 errno = EINVAL;
3028 return NULL;
3029 }
3030
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303031 vec = g_try_new0(struct iovec, count);
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003032 if (vec == NULL) {
3033 errno = ENOMEM;
3034 return NULL;
3035 }
3036
3037 target_vec = lock_user(VERIFY_READ, target_addr,
3038 count * sizeof(struct target_iovec), 1);
3039 if (target_vec == NULL) {
Peter Maydell501bb4b2014-02-17 18:55:33 +00003040 err = EFAULT;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003041 goto fail2;
3042 }
3043
3044 /* ??? If host page size > target page size, this will result in a
3045 value larger than what we can actually support. */
3046 max_len = 0x7fffffff & TARGET_PAGE_MASK;
3047 total_len = 0;
3048
3049 for (i = 0; i < count; i++) {
3050 abi_ulong base = tswapal(target_vec[i].iov_base);
3051 abi_long len = tswapal(target_vec[i].iov_len);
3052
3053 if (len < 0) {
Peter Maydell501bb4b2014-02-17 18:55:33 +00003054 err = EINVAL;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003055 goto fail;
3056 } else if (len == 0) {
3057 /* Zero length pointer is ignored. */
3058 vec[i].iov_base = 0;
3059 } else {
3060 vec[i].iov_base = lock_user(type, base, len, copy);
Tom Musta29560a62014-08-12 13:53:43 -05003061 /* If the first buffer pointer is bad, this is a fault. But
3062 * subsequent bad buffers will result in a partial write; this
3063 * is realized by filling the vector with null pointers and
3064 * zero lengths. */
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003065 if (!vec[i].iov_base) {
Tom Musta29560a62014-08-12 13:53:43 -05003066 if (i == 0) {
3067 err = EFAULT;
3068 goto fail;
3069 } else {
3070 bad_address = true;
3071 }
3072 }
3073 if (bad_address) {
3074 len = 0;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003075 }
3076 if (len > max_len - total_len) {
3077 len = max_len - total_len;
3078 }
3079 }
3080 vec[i].iov_len = len;
3081 total_len += len;
3082 }
3083
3084 unlock_user(target_vec, target_addr, 0);
3085 return vec;
3086
3087 fail:
Chen Gang S7eff5182015-01-23 18:01:09 +08003088 while (--i >= 0) {
3089 if (tswapal(target_vec[i].iov_len) > 0) {
3090 unlock_user(vec[i].iov_base, tswapal(target_vec[i].iov_base), 0);
3091 }
3092 }
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003093 unlock_user(target_vec, target_addr, 0);
Peter Maydell501bb4b2014-02-17 18:55:33 +00003094 fail2:
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303095 g_free(vec);
Peter Maydell501bb4b2014-02-17 18:55:33 +00003096 errno = err;
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003097 return NULL;
pbrook53a59602006-03-25 19:31:22 +00003098}
3099
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003100static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
Peter Maydelldab32b32016-07-15 14:57:26 +01003101 abi_ulong count, int copy)
pbrook53a59602006-03-25 19:31:22 +00003102{
3103 struct target_iovec *target_vec;
pbrook53a59602006-03-25 19:31:22 +00003104 int i;
3105
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003106 target_vec = lock_user(VERIFY_READ, target_addr,
3107 count * sizeof(struct target_iovec), 1);
3108 if (target_vec) {
3109 for (i = 0; i < count; i++) {
3110 abi_ulong base = tswapal(target_vec[i].iov_base);
Chen Gang S71ec7ce2015-01-23 18:07:50 +08003111 abi_long len = tswapal(target_vec[i].iov_len);
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003112 if (len < 0) {
3113 break;
3114 }
balrogd732dcb2008-10-28 10:21:03 +00003115 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
3116 }
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003117 unlock_user(target_vec, target_addr, 0);
pbrook53a59602006-03-25 19:31:22 +00003118 }
bellard579a97f2007-11-11 14:26:47 +00003119
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303120 g_free(vec);
pbrook53a59602006-03-25 19:31:22 +00003121}
3122
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003123static inline int target_to_host_sock_type(int *type)
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003124{
3125 int host_type = 0;
3126 int target_type = *type;
3127
3128 switch (target_type & TARGET_SOCK_TYPE_MASK) {
3129 case TARGET_SOCK_DGRAM:
3130 host_type = SOCK_DGRAM;
3131 break;
3132 case TARGET_SOCK_STREAM:
3133 host_type = SOCK_STREAM;
3134 break;
3135 default:
3136 host_type = target_type & TARGET_SOCK_TYPE_MASK;
3137 break;
3138 }
3139 if (target_type & TARGET_SOCK_CLOEXEC) {
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003140#if defined(SOCK_CLOEXEC)
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003141 host_type |= SOCK_CLOEXEC;
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003142#else
3143 return -TARGET_EINVAL;
3144#endif
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003145 }
3146 if (target_type & TARGET_SOCK_NONBLOCK) {
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003147#if defined(SOCK_NONBLOCK)
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003148 host_type |= SOCK_NONBLOCK;
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003149#elif !defined(O_NONBLOCK)
3150 return -TARGET_EINVAL;
3151#endif
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003152 }
3153 *type = host_type;
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003154 return 0;
3155}
3156
3157/* Try to emulate socket type flags after socket creation. */
3158static int sock_flags_fixup(int fd, int target_type)
3159{
3160#if !defined(SOCK_NONBLOCK) && defined(O_NONBLOCK)
3161 if (target_type & TARGET_SOCK_NONBLOCK) {
3162 int flags = fcntl(fd, F_GETFL);
3163 if (fcntl(fd, F_SETFL, O_NONBLOCK | flags) == -1) {
3164 close(fd);
3165 return -TARGET_EINVAL;
3166 }
3167 }
3168#endif
3169 return fd;
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003170}
3171
ths0da46a62007-10-20 20:23:07 +00003172/* do_socket() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003173static abi_long do_socket(int domain, int type, int protocol)
bellard3532fa72006-06-24 15:06:03 +00003174{
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003175 int target_type = type;
3176 int ret;
3177
3178 ret = target_to_host_sock_type(&type);
3179 if (ret) {
3180 return ret;
3181 }
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003182
Laurent Vivier575b22b2016-06-02 22:14:15 +02003183 if (domain == PF_NETLINK && !(
3184#ifdef CONFIG_RTNETLINK
3185 protocol == NETLINK_ROUTE ||
3186#endif
3187 protocol == NETLINK_KOBJECT_UEVENT ||
3188 protocol == NETLINK_AUDIT)) {
Josh Kunz71e24432020-07-06 17:10:36 -07003189 return -TARGET_EPROTONOSUPPORT;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003190 }
Laurent Vivierff626f22015-10-28 21:40:42 +01003191
3192 if (domain == AF_PACKET ||
3193 (domain == AF_INET && type == SOCK_PACKET)) {
3194 protocol = tswap16(protocol);
3195 }
3196
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003197 ret = get_errno(socket(domain, type, protocol));
3198 if (ret >= 0) {
3199 ret = sock_flags_fixup(ret, target_type);
Laurent Vivier0cf22722015-10-28 21:40:45 +01003200 if (type == SOCK_PACKET) {
3201 /* Manage an obsolete case :
3202 * if socket type is SOCK_PACKET, bind by name
3203 */
3204 fd_trans_register(ret, &target_packet_trans);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003205 } else if (domain == PF_NETLINK) {
3206 switch (protocol) {
Laurent Vivier575b22b2016-06-02 22:14:15 +02003207#ifdef CONFIG_RTNETLINK
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003208 case NETLINK_ROUTE:
3209 fd_trans_register(ret, &target_netlink_route_trans);
3210 break;
Laurent Vivier575b22b2016-06-02 22:14:15 +02003211#endif
Laurent Vivierb2656202016-05-22 18:56:20 +02003212 case NETLINK_KOBJECT_UEVENT:
3213 /* nothing to do: messages are strings */
3214 break;
Laurent Vivier5ce9bb52016-05-22 18:56:21 +02003215 case NETLINK_AUDIT:
3216 fd_trans_register(ret, &target_netlink_audit_trans);
3217 break;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003218 default:
3219 g_assert_not_reached();
3220 }
Laurent Vivier0cf22722015-10-28 21:40:45 +01003221 }
Edgar E. Iglesias53d09b72013-09-23 14:11:53 +02003222 }
3223 return ret;
bellard3532fa72006-06-24 15:06:03 +00003224}
3225
ths0da46a62007-10-20 20:23:07 +00003226/* do_bind() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003227static abi_long do_bind(int sockfd, abi_ulong target_addr,
3228 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00003229{
aurel328f7aeaf2009-01-30 19:47:57 +00003230 void *addr;
Arnaud Patard917507b2009-06-19 10:44:45 +03003231 abi_long ret;
aurel328f7aeaf2009-01-30 19:47:57 +00003232
Blue Swirl38724252010-09-18 05:53:14 +00003233 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003234 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003235 }
aurel328f7aeaf2009-01-30 19:47:57 +00003236
aurel32607175e2009-04-15 16:11:59 +00003237 addr = alloca(addrlen+1);
ths3b46e622007-09-17 08:09:54 +00003238
Laurent Vivier7b36f782015-10-28 21:40:44 +01003239 ret = target_to_host_sockaddr(sockfd, addr, target_addr, addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03003240 if (ret)
3241 return ret;
3242
bellard3532fa72006-06-24 15:06:03 +00003243 return get_errno(bind(sockfd, addr, addrlen));
3244}
3245
ths0da46a62007-10-20 20:23:07 +00003246/* do_connect() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003247static abi_long do_connect(int sockfd, abi_ulong target_addr,
3248 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00003249{
aurel328f7aeaf2009-01-30 19:47:57 +00003250 void *addr;
Arnaud Patard917507b2009-06-19 10:44:45 +03003251 abi_long ret;
aurel328f7aeaf2009-01-30 19:47:57 +00003252
Blue Swirl38724252010-09-18 05:53:14 +00003253 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003254 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003255 }
aurel328f7aeaf2009-01-30 19:47:57 +00003256
Joakim Tjernlund2dd08df2014-07-11 17:18:03 +02003257 addr = alloca(addrlen+1);
ths3b46e622007-09-17 08:09:54 +00003258
Laurent Vivier7b36f782015-10-28 21:40:44 +01003259 ret = target_to_host_sockaddr(sockfd, addr, target_addr, addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03003260 if (ret)
3261 return ret;
3262
Peter Maydell2a3c7612016-06-06 19:58:03 +01003263 return get_errno(safe_connect(sockfd, addr, addrlen));
bellard3532fa72006-06-24 15:06:03 +00003264}
3265
Alexander Graff19e00d2014-03-02 19:36:42 +00003266/* do_sendrecvmsg_locked() Must return target values and target errnos. */
3267static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
3268 int flags, int send)
bellard3532fa72006-06-24 15:06:03 +00003269{
balrog6de645c2008-10-28 10:26:29 +00003270 abi_long ret, len;
bellard3532fa72006-06-24 15:06:03 +00003271 struct msghdr msg;
Peter Maydelldab32b32016-07-15 14:57:26 +01003272 abi_ulong count;
bellard3532fa72006-06-24 15:06:03 +00003273 struct iovec *vec;
blueswir1992f48a2007-10-14 16:27:31 +00003274 abi_ulong target_vec;
bellard3532fa72006-06-24 15:06:03 +00003275
bellard3532fa72006-06-24 15:06:03 +00003276 if (msgp->msg_name) {
3277 msg.msg_namelen = tswap32(msgp->msg_namelen);
Joakim Tjernlund2dd08df2014-07-11 17:18:03 +02003278 msg.msg_name = alloca(msg.msg_namelen+1);
Laurent Vivier7b36f782015-10-28 21:40:44 +01003279 ret = target_to_host_sockaddr(fd, msg.msg_name,
3280 tswapal(msgp->msg_name),
3281 msg.msg_namelen);
Peter Maydell26a6fc92016-07-15 14:57:28 +01003282 if (ret == -TARGET_EFAULT) {
3283 /* For connected sockets msg_name and msg_namelen must
3284 * be ignored, so returning EFAULT immediately is wrong.
3285 * Instead, pass a bad msg_name to the host kernel, and
3286 * let it decide whether to return EFAULT or not.
3287 */
3288 msg.msg_name = (void *)-1;
3289 } else if (ret) {
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003290 goto out2;
Arnaud Patard917507b2009-06-19 10:44:45 +03003291 }
bellard3532fa72006-06-24 15:06:03 +00003292 } else {
3293 msg.msg_name = NULL;
3294 msg.msg_namelen = 0;
3295 }
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003296 msg.msg_controllen = 2 * tswapal(msgp->msg_controllen);
bellard3532fa72006-06-24 15:06:03 +00003297 msg.msg_control = alloca(msg.msg_controllen);
Jonas Schievink1d3d1b22018-07-12 00:12:44 +02003298 memset(msg.msg_control, 0, msg.msg_controllen);
3299
bellard3532fa72006-06-24 15:06:03 +00003300 msg.msg_flags = tswap32(msgp->msg_flags);
ths3b46e622007-09-17 08:09:54 +00003301
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003302 count = tswapal(msgp->msg_iovlen);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003303 target_vec = tswapal(msgp->msg_iov);
Peter Maydell97b07972016-07-15 14:57:27 +01003304
3305 if (count > IOV_MAX) {
3306 /* sendrcvmsg returns a different errno for this condition than
3307 * readv/writev, so we must catch it here before lock_iovec() does.
3308 */
3309 ret = -TARGET_EMSGSIZE;
3310 goto out2;
3311 }
3312
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003313 vec = lock_iovec(send ? VERIFY_READ : VERIFY_WRITE,
3314 target_vec, count, send);
3315 if (vec == NULL) {
3316 ret = -host_to_target_errno(errno);
3317 goto out2;
3318 }
bellard3532fa72006-06-24 15:06:03 +00003319 msg.msg_iovlen = count;
3320 msg.msg_iov = vec;
ths3b46e622007-09-17 08:09:54 +00003321
bellard3532fa72006-06-24 15:06:03 +00003322 if (send) {
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003323 if (fd_trans_target_to_host_data(fd)) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003324 void *host_msg;
3325
3326 host_msg = g_malloc(msg.msg_iov->iov_len);
3327 memcpy(host_msg, msg.msg_iov->iov_base, msg.msg_iov->iov_len);
3328 ret = fd_trans_target_to_host_data(fd)(host_msg,
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003329 msg.msg_iov->iov_len);
Laurent Vivier7d61d892016-06-21 19:51:14 +02003330 if (ret >= 0) {
3331 msg.msg_iov->iov_base = host_msg;
3332 ret = get_errno(safe_sendmsg(fd, &msg, flags));
3333 }
3334 g_free(host_msg);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003335 } else {
3336 ret = target_to_host_cmsg(&msg, msgp);
Laurent Vivier7d61d892016-06-21 19:51:14 +02003337 if (ret == 0) {
3338 ret = get_errno(safe_sendmsg(fd, &msg, flags));
3339 }
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003340 }
bellard3532fa72006-06-24 15:06:03 +00003341 } else {
Peter Maydell66687532016-06-06 19:58:04 +01003342 ret = get_errno(safe_recvmsg(fd, &msg, flags));
balrog6de645c2008-10-28 10:26:29 +00003343 if (!is_error(ret)) {
3344 len = ret;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003345 if (fd_trans_host_to_target_data(fd)) {
3346 ret = fd_trans_host_to_target_data(fd)(msg.msg_iov->iov_base,
Laurent Vivier2a03d3e2018-08-20 19:15:54 +02003347 MIN(msg.msg_iov->iov_len, len));
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003348 } else {
3349 ret = host_to_target_cmsg(msgp, &msg);
3350 }
Jing Huangca619062012-07-24 13:58:02 +00003351 if (!is_error(ret)) {
3352 msgp->msg_namelen = tswap32(msg.msg_namelen);
Andreas Schwab24894f32019-02-12 17:34:35 +01003353 msgp->msg_flags = tswap32(msg.msg_flags);
Peter Maydell26a6fc92016-07-15 14:57:28 +01003354 if (msg.msg_name != NULL && msg.msg_name != (void *)-1) {
Jing Huangca619062012-07-24 13:58:02 +00003355 ret = host_to_target_sockaddr(tswapal(msgp->msg_name),
3356 msg.msg_name, msg.msg_namelen);
3357 if (ret) {
3358 goto out;
3359 }
3360 }
3361
balrog6de645c2008-10-28 10:26:29 +00003362 ret = len;
Jing Huangca619062012-07-24 13:58:02 +00003363 }
balrog6de645c2008-10-28 10:26:29 +00003364 }
bellard3532fa72006-06-24 15:06:03 +00003365 }
Jing Huangca619062012-07-24 13:58:02 +00003366
3367out:
bellard3532fa72006-06-24 15:06:03 +00003368 unlock_iovec(vec, target_vec, count, !send);
Richard Hendersonf287b2c2012-09-15 13:20:25 -07003369out2:
Alexander Graff19e00d2014-03-02 19:36:42 +00003370 return ret;
3371}
3372
3373static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
3374 int flags, int send)
3375{
3376 abi_long ret;
3377 struct target_msghdr *msgp;
3378
3379 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
3380 msgp,
3381 target_msg,
3382 send ? 1 : 0)) {
3383 return -TARGET_EFAULT;
3384 }
3385 ret = do_sendrecvmsg_locked(fd, msgp, flags, send);
bellard579a97f2007-11-11 14:26:47 +00003386 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
bellard3532fa72006-06-24 15:06:03 +00003387 return ret;
3388}
3389
Alexander Graff19e00d2014-03-02 19:36:42 +00003390/* We don't rely on the C library to have sendmmsg/recvmmsg support,
3391 * so it might not have this *mmsg-specific flag either.
3392 */
3393#ifndef MSG_WAITFORONE
3394#define MSG_WAITFORONE 0x10000
3395#endif
3396
3397static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec,
3398 unsigned int vlen, unsigned int flags,
3399 int send)
3400{
3401 struct target_mmsghdr *mmsgp;
3402 abi_long ret = 0;
3403 int i;
3404
3405 if (vlen > UIO_MAXIOV) {
3406 vlen = UIO_MAXIOV;
3407 }
3408
3409 mmsgp = lock_user(VERIFY_WRITE, target_msgvec, sizeof(*mmsgp) * vlen, 1);
3410 if (!mmsgp) {
3411 return -TARGET_EFAULT;
3412 }
3413
3414 for (i = 0; i < vlen; i++) {
3415 ret = do_sendrecvmsg_locked(fd, &mmsgp[i].msg_hdr, flags, send);
3416 if (is_error(ret)) {
3417 break;
3418 }
3419 mmsgp[i].msg_len = tswap32(ret);
3420 /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
3421 if (flags & MSG_WAITFORONE) {
3422 flags |= MSG_DONTWAIT;
3423 }
3424 }
3425
3426 unlock_user(mmsgp, target_msgvec, sizeof(*mmsgp) * i);
3427
3428 /* Return number of datagrams sent if we sent any at all;
3429 * otherwise return the error.
3430 */
3431 if (i) {
3432 return i;
3433 }
3434 return ret;
3435}
Alexander Graff19e00d2014-03-02 19:36:42 +00003436
Peter Maydella94b4982013-02-08 04:35:04 +00003437/* do_accept4() Must return target values and target errnos. */
3438static abi_long do_accept4(int fd, abi_ulong target_addr,
3439 abi_ulong target_addrlen_addr, int flags)
pbrook1be9e1d2006-11-19 15:26:04 +00003440{
Andreas Schwabcd813362019-02-14 12:43:40 +01003441 socklen_t addrlen, ret_addrlen;
bellard2f619692007-11-16 10:46:05 +00003442 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00003443 abi_long ret;
Petar Jovanovicd25295d2014-03-31 17:41:23 +02003444 int host_flags;
3445
3446 host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
pbrook1be9e1d2006-11-19 15:26:04 +00003447
Peter Maydella94b4982013-02-08 04:35:04 +00003448 if (target_addr == 0) {
Peter Maydellff6dc132016-06-06 19:58:13 +01003449 return get_errno(safe_accept4(fd, NULL, NULL, host_flags));
Peter Maydella94b4982013-02-08 04:35:04 +00003450 }
Arnaud Patard917507b2009-06-19 10:44:45 +03003451
Matus Kysele554eb42020-09-30 17:16:16 +02003452 /* linux returns EFAULT if addrlen pointer is invalid */
bellard2f619692007-11-16 10:46:05 +00003453 if (get_user_u32(addrlen, target_addrlen_addr))
Matus Kysele554eb42020-09-30 17:16:16 +02003454 return -TARGET_EFAULT;
bellard2f619692007-11-16 10:46:05 +00003455
Blue Swirl38724252010-09-18 05:53:14 +00003456 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003457 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003458 }
aurel328f7aeaf2009-01-30 19:47:57 +00003459
Richard Hendersonc7169b02021-02-12 10:48:47 -08003460 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
Matus Kysele554eb42020-09-30 17:16:16 +02003461 return -TARGET_EFAULT;
Richard Hendersonc7169b02021-02-12 10:48:47 -08003462 }
Arnaud Patard917507b2009-06-19 10:44:45 +03003463
bellard2f619692007-11-16 10:46:05 +00003464 addr = alloca(addrlen);
3465
Andreas Schwabcd813362019-02-14 12:43:40 +01003466 ret_addrlen = addrlen;
3467 ret = get_errno(safe_accept4(fd, addr, &ret_addrlen, host_flags));
pbrook1be9e1d2006-11-19 15:26:04 +00003468 if (!is_error(ret)) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003469 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3470 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
bellard2f619692007-11-16 10:46:05 +00003471 ret = -TARGET_EFAULT;
Andreas Schwabcd813362019-02-14 12:43:40 +01003472 }
pbrook1be9e1d2006-11-19 15:26:04 +00003473 }
3474 return ret;
3475}
3476
ths0da46a62007-10-20 20:23:07 +00003477/* do_getpeername() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003478static abi_long do_getpeername(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00003479 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00003480{
Andreas Schwabcd813362019-02-14 12:43:40 +01003481 socklen_t addrlen, ret_addrlen;
bellard2f619692007-11-16 10:46:05 +00003482 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00003483 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003484
bellard2f619692007-11-16 10:46:05 +00003485 if (get_user_u32(addrlen, target_addrlen_addr))
3486 return -TARGET_EFAULT;
3487
Blue Swirl38724252010-09-18 05:53:14 +00003488 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003489 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003490 }
aurel328f7aeaf2009-01-30 19:47:57 +00003491
Richard Hendersonc7169b02021-02-12 10:48:47 -08003492 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
Arnaud Patard917507b2009-06-19 10:44:45 +03003493 return -TARGET_EFAULT;
Richard Hendersonc7169b02021-02-12 10:48:47 -08003494 }
Arnaud Patard917507b2009-06-19 10:44:45 +03003495
bellard2f619692007-11-16 10:46:05 +00003496 addr = alloca(addrlen);
3497
Andreas Schwabcd813362019-02-14 12:43:40 +01003498 ret_addrlen = addrlen;
3499 ret = get_errno(getpeername(fd, addr, &ret_addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003500 if (!is_error(ret)) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003501 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3502 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
bellard2f619692007-11-16 10:46:05 +00003503 ret = -TARGET_EFAULT;
Andreas Schwabcd813362019-02-14 12:43:40 +01003504 }
pbrook1be9e1d2006-11-19 15:26:04 +00003505 }
3506 return ret;
3507}
3508
ths0da46a62007-10-20 20:23:07 +00003509/* do_getsockname() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003510static abi_long do_getsockname(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00003511 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00003512{
Andreas Schwabcd813362019-02-14 12:43:40 +01003513 socklen_t addrlen, ret_addrlen;
bellard2f619692007-11-16 10:46:05 +00003514 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00003515 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003516
bellard2f619692007-11-16 10:46:05 +00003517 if (get_user_u32(addrlen, target_addrlen_addr))
3518 return -TARGET_EFAULT;
3519
Blue Swirl38724252010-09-18 05:53:14 +00003520 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003521 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003522 }
aurel328f7aeaf2009-01-30 19:47:57 +00003523
Richard Hendersonc7169b02021-02-12 10:48:47 -08003524 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
Arnaud Patard917507b2009-06-19 10:44:45 +03003525 return -TARGET_EFAULT;
Richard Hendersonc7169b02021-02-12 10:48:47 -08003526 }
Arnaud Patard917507b2009-06-19 10:44:45 +03003527
bellard2f619692007-11-16 10:46:05 +00003528 addr = alloca(addrlen);
3529
Andreas Schwabcd813362019-02-14 12:43:40 +01003530 ret_addrlen = addrlen;
3531 ret = get_errno(getsockname(fd, addr, &ret_addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003532 if (!is_error(ret)) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003533 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3534 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
bellard2f619692007-11-16 10:46:05 +00003535 ret = -TARGET_EFAULT;
Andreas Schwabcd813362019-02-14 12:43:40 +01003536 }
pbrook1be9e1d2006-11-19 15:26:04 +00003537 }
3538 return ret;
3539}
3540
ths0da46a62007-10-20 20:23:07 +00003541/* do_socketpair() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003542static abi_long do_socketpair(int domain, int type, int protocol,
bellard2f619692007-11-16 10:46:05 +00003543 abi_ulong target_tab_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00003544{
3545 int tab[2];
blueswir1992f48a2007-10-14 16:27:31 +00003546 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003547
Petar Jovanovicf651e6a2013-07-01 02:44:14 +02003548 target_to_host_sock_type(&type);
3549
pbrook1be9e1d2006-11-19 15:26:04 +00003550 ret = get_errno(socketpair(domain, type, protocol, tab));
3551 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00003552 if (put_user_s32(tab[0], target_tab_addr)
3553 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
3554 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00003555 }
3556 return ret;
3557}
3558
ths0da46a62007-10-20 20:23:07 +00003559/* do_sendto() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003560static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
3561 abi_ulong target_addr, socklen_t addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00003562{
3563 void *addr;
3564 void *host_msg;
Laurent Vivier7d61d892016-06-21 19:51:14 +02003565 void *copy_msg = NULL;
blueswir1992f48a2007-10-14 16:27:31 +00003566 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003567
Blue Swirl38724252010-09-18 05:53:14 +00003568 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003569 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00003570 }
aurel328f7aeaf2009-01-30 19:47:57 +00003571
bellard579a97f2007-11-11 14:26:47 +00003572 host_msg = lock_user(VERIFY_READ, msg, len, 1);
3573 if (!host_msg)
3574 return -TARGET_EFAULT;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003575 if (fd_trans_target_to_host_data(fd)) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003576 copy_msg = host_msg;
3577 host_msg = g_malloc(len);
3578 memcpy(host_msg, copy_msg, len);
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003579 ret = fd_trans_target_to_host_data(fd)(host_msg, len);
3580 if (ret < 0) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003581 goto fail;
Laurent Vivier6c5b5642016-05-22 18:56:19 +02003582 }
3583 }
pbrook1be9e1d2006-11-19 15:26:04 +00003584 if (target_addr) {
Joakim Tjernlund2dd08df2014-07-11 17:18:03 +02003585 addr = alloca(addrlen+1);
Laurent Vivier7b36f782015-10-28 21:40:44 +01003586 ret = target_to_host_sockaddr(fd, addr, target_addr, addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03003587 if (ret) {
Laurent Vivier7d61d892016-06-21 19:51:14 +02003588 goto fail;
Arnaud Patard917507b2009-06-19 10:44:45 +03003589 }
Peter Maydell66687532016-06-06 19:58:04 +01003590 ret = get_errno(safe_sendto(fd, host_msg, len, flags, addr, addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003591 } else {
Peter Maydell66687532016-06-06 19:58:04 +01003592 ret = get_errno(safe_sendto(fd, host_msg, len, flags, NULL, 0));
pbrook1be9e1d2006-11-19 15:26:04 +00003593 }
Laurent Vivier7d61d892016-06-21 19:51:14 +02003594fail:
3595 if (copy_msg) {
3596 g_free(host_msg);
3597 host_msg = copy_msg;
3598 }
pbrook1be9e1d2006-11-19 15:26:04 +00003599 unlock_user(host_msg, msg, 0);
3600 return ret;
3601}
3602
ths0da46a62007-10-20 20:23:07 +00003603/* do_recvfrom() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003604static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
3605 abi_ulong target_addr,
3606 abi_ulong target_addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00003607{
Andreas Schwabcd813362019-02-14 12:43:40 +01003608 socklen_t addrlen, ret_addrlen;
pbrook1be9e1d2006-11-19 15:26:04 +00003609 void *addr;
3610 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00003611 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00003612
Zach Reizner4a1e6bc2021-03-26 22:11:16 -04003613 if (!msg) {
3614 host_msg = NULL;
3615 } else {
3616 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
3617 if (!host_msg) {
3618 return -TARGET_EFAULT;
3619 }
3620 }
pbrook1be9e1d2006-11-19 15:26:04 +00003621 if (target_addr) {
bellard2f619692007-11-16 10:46:05 +00003622 if (get_user_u32(addrlen, target_addrlen)) {
3623 ret = -TARGET_EFAULT;
3624 goto fail;
3625 }
Blue Swirl38724252010-09-18 05:53:14 +00003626 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00003627 ret = -TARGET_EINVAL;
3628 goto fail;
3629 }
pbrook1be9e1d2006-11-19 15:26:04 +00003630 addr = alloca(addrlen);
Andreas Schwabcd813362019-02-14 12:43:40 +01003631 ret_addrlen = addrlen;
Peter Maydell66687532016-06-06 19:58:04 +01003632 ret = get_errno(safe_recvfrom(fd, host_msg, len, flags,
Andreas Schwabcd813362019-02-14 12:43:40 +01003633 addr, &ret_addrlen));
pbrook1be9e1d2006-11-19 15:26:04 +00003634 } else {
3635 addr = NULL; /* To keep compiler quiet. */
Andreas Schwabcd813362019-02-14 12:43:40 +01003636 addrlen = 0; /* To keep compiler quiet. */
Peter Maydell66687532016-06-06 19:58:04 +01003637 ret = get_errno(safe_recvfrom(fd, host_msg, len, flags, NULL, 0));
pbrook1be9e1d2006-11-19 15:26:04 +00003638 }
3639 if (!is_error(ret)) {
Laurent Vivierc35e1f92016-06-21 19:51:15 +02003640 if (fd_trans_host_to_target_data(fd)) {
Laurent Vivier2a03d3e2018-08-20 19:15:54 +02003641 abi_long trans;
3642 trans = fd_trans_host_to_target_data(fd)(host_msg, MIN(ret, len));
3643 if (is_error(trans)) {
3644 ret = trans;
3645 goto fail;
3646 }
Laurent Vivierc35e1f92016-06-21 19:51:15 +02003647 }
pbrook1be9e1d2006-11-19 15:26:04 +00003648 if (target_addr) {
Andreas Schwabcd813362019-02-14 12:43:40 +01003649 host_to_target_sockaddr(target_addr, addr,
3650 MIN(addrlen, ret_addrlen));
3651 if (put_user_u32(ret_addrlen, target_addrlen)) {
bellard2f619692007-11-16 10:46:05 +00003652 ret = -TARGET_EFAULT;
3653 goto fail;
3654 }
pbrook1be9e1d2006-11-19 15:26:04 +00003655 }
3656 unlock_user(host_msg, msg, len);
3657 } else {
bellard2f619692007-11-16 10:46:05 +00003658fail:
pbrook1be9e1d2006-11-19 15:26:04 +00003659 unlock_user(host_msg, msg, 0);
3660 }
3661 return ret;
3662}
3663
j_mayer32407102007-09-26 23:01:49 +00003664#ifdef TARGET_NR_socketcall
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003665/* do_socketcall() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003666static abi_long do_socketcall(int num, abi_ulong vptr)
bellard31e31b82003-02-18 22:55:36 +00003667{
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003668 static const unsigned nargs[] = { /* number of arguments per operation */
3669 [TARGET_SYS_SOCKET] = 3, /* domain, type, protocol */
3670 [TARGET_SYS_BIND] = 3, /* fd, addr, addrlen */
3671 [TARGET_SYS_CONNECT] = 3, /* fd, addr, addrlen */
3672 [TARGET_SYS_LISTEN] = 2, /* fd, backlog */
3673 [TARGET_SYS_ACCEPT] = 3, /* fd, addr, addrlen */
3674 [TARGET_SYS_GETSOCKNAME] = 3, /* fd, addr, addrlen */
3675 [TARGET_SYS_GETPEERNAME] = 3, /* fd, addr, addrlen */
3676 [TARGET_SYS_SOCKETPAIR] = 4, /* domain, type, protocol, tab */
3677 [TARGET_SYS_SEND] = 4, /* fd, msg, len, flags */
3678 [TARGET_SYS_RECV] = 4, /* fd, msg, len, flags */
3679 [TARGET_SYS_SENDTO] = 6, /* fd, msg, len, flags, addr, addrlen */
3680 [TARGET_SYS_RECVFROM] = 6, /* fd, msg, len, flags, addr, addrlen */
3681 [TARGET_SYS_SHUTDOWN] = 2, /* fd, how */
3682 [TARGET_SYS_SETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
3683 [TARGET_SYS_GETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
3684 [TARGET_SYS_SENDMSG] = 3, /* fd, msg, flags */
3685 [TARGET_SYS_RECVMSG] = 3, /* fd, msg, flags */
3686 [TARGET_SYS_ACCEPT4] = 4, /* fd, addr, addrlen, flags */
3687 [TARGET_SYS_RECVMMSG] = 4, /* fd, msgvec, vlen, flags */
3688 [TARGET_SYS_SENDMMSG] = 4, /* fd, msgvec, vlen, flags */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003689 };
3690 abi_long a[6]; /* max 6 args */
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003691 unsigned i;
bellard31e31b82003-02-18 22:55:36 +00003692
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003693 /* check the range of the first argument num */
3694 /* (TARGET_SYS_SENDMMSG is the highest among TARGET_SYS_xxx) */
3695 if (num < 1 || num > TARGET_SYS_SENDMMSG) {
3696 return -TARGET_EINVAL;
3697 }
3698 /* ensure we have space for args */
3699 if (nargs[num] > ARRAY_SIZE(a)) {
3700 return -TARGET_EINVAL;
3701 }
3702 /* collect the arguments in a[] according to nargs[] */
3703 for (i = 0; i < nargs[num]; ++i) {
3704 if (get_user_ual(a[i], vptr + i * sizeof(abi_long)) != 0) {
3705 return -TARGET_EFAULT;
André Hentschelb9d36eb2014-01-06 20:18:52 +01003706 }
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003707 }
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003708 /* now when we have the args, invoke the appropriate underlying function */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003709 switch (num) {
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003710 case TARGET_SYS_SOCKET: /* domain, type, protocol */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003711 return do_socket(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003712 case TARGET_SYS_BIND: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003713 return do_bind(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003714 case TARGET_SYS_CONNECT: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003715 return do_connect(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003716 case TARGET_SYS_LISTEN: /* sockfd, backlog */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003717 return get_errno(listen(a[0], a[1]));
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003718 case TARGET_SYS_ACCEPT: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003719 return do_accept4(a[0], a[1], a[2], 0);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003720 case TARGET_SYS_GETSOCKNAME: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003721 return do_getsockname(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003722 case TARGET_SYS_GETPEERNAME: /* sockfd, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003723 return do_getpeername(a[0], a[1], a[2]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003724 case TARGET_SYS_SOCKETPAIR: /* domain, type, protocol, tab */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003725 return do_socketpair(a[0], a[1], a[2], a[3]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003726 case TARGET_SYS_SEND: /* sockfd, msg, len, flags */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003727 return do_sendto(a[0], a[1], a[2], a[3], 0, 0);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003728 case TARGET_SYS_RECV: /* sockfd, msg, len, flags */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003729 return do_recvfrom(a[0], a[1], a[2], a[3], 0, 0);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003730 case TARGET_SYS_SENDTO: /* sockfd, msg, len, flags, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003731 return do_sendto(a[0], a[1], a[2], a[3], a[4], a[5]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003732 case TARGET_SYS_RECVFROM: /* sockfd, msg, len, flags, addr, addrlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003733 return do_recvfrom(a[0], a[1], a[2], a[3], a[4], a[5]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003734 case TARGET_SYS_SHUTDOWN: /* sockfd, how */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003735 return get_errno(shutdown(a[0], a[1]));
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003736 case TARGET_SYS_SETSOCKOPT: /* sockfd, level, optname, optval, optlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003737 return do_setsockopt(a[0], a[1], a[2], a[3], a[4]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003738 case TARGET_SYS_GETSOCKOPT: /* sockfd, level, optname, optval, optlen */
Michael Tokarev62dc90c2014-01-17 14:23:51 +04003739 return do_getsockopt(a[0], a[1], a[2], a[3], a[4]);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003740 case TARGET_SYS_SENDMSG: /* sockfd, msg, flags */
3741 return do_sendrecvmsg(a[0], a[1], a[2], 1);
3742 case TARGET_SYS_RECVMSG: /* sockfd, msg, flags */
3743 return do_sendrecvmsg(a[0], a[1], a[2], 0);
3744 case TARGET_SYS_ACCEPT4: /* sockfd, addr, addrlen, flags */
3745 return do_accept4(a[0], a[1], a[2], a[3]);
3746 case TARGET_SYS_RECVMMSG: /* sockfd, msgvec, vlen, flags */
3747 return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0);
3748 case TARGET_SYS_SENDMMSG: /* sockfd, msgvec, vlen, flags */
3749 return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 1);
bellard31e31b82003-02-18 22:55:36 +00003750 default:
Josh Kunz39be5352020-02-03 18:54:13 -08003751 qemu_log_mask(LOG_UNIMP, "Unsupported socketcall: %d\n", num);
Aleksandar Markovicff71a452016-09-22 18:56:57 +02003752 return -TARGET_EINVAL;
bellard31e31b82003-02-18 22:55:36 +00003753 }
bellard31e31b82003-02-18 22:55:36 +00003754}
j_mayer32407102007-09-26 23:01:49 +00003755#endif
bellard31e31b82003-02-18 22:55:36 +00003756
bellard8853f862004-02-22 14:57:26 +00003757#define N_SHM_REGIONS 32
3758
3759static struct shm_region {
Peter Maydellb6e17872016-02-09 15:57:11 +00003760 abi_ulong start;
3761 abi_ulong size;
3762 bool in_use;
bellard8853f862004-02-22 14:57:26 +00003763} shm_regions[N_SHM_REGIONS];
3764
Peter Maydell005eb2a2016-07-15 16:50:47 +01003765#ifndef TARGET_SEMID64_DS
3766/* asm-generic version of this struct */
3767struct target_semid64_ds
ths3eb6b042007-06-03 14:26:27 +00003768{
3769 struct target_ipc_perm sem_perm;
blueswir1992f48a2007-10-14 16:27:31 +00003770 abi_ulong sem_otime;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003771#if TARGET_ABI_BITS == 32
blueswir1992f48a2007-10-14 16:27:31 +00003772 abi_ulong __unused1;
Tom Musta03527342014-08-12 13:53:32 -05003773#endif
blueswir1992f48a2007-10-14 16:27:31 +00003774 abi_ulong sem_ctime;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003775#if TARGET_ABI_BITS == 32
blueswir1992f48a2007-10-14 16:27:31 +00003776 abi_ulong __unused2;
Tom Musta03527342014-08-12 13:53:32 -05003777#endif
blueswir1992f48a2007-10-14 16:27:31 +00003778 abi_ulong sem_nsems;
3779 abi_ulong __unused3;
3780 abi_ulong __unused4;
ths3eb6b042007-06-03 14:26:27 +00003781};
Peter Maydell005eb2a2016-07-15 16:50:47 +01003782#endif
ths3eb6b042007-06-03 14:26:27 +00003783
bellard579a97f2007-11-11 14:26:47 +00003784static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
3785 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00003786{
3787 struct target_ipc_perm *target_ip;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003788 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003789
bellard579a97f2007-11-11 14:26:47 +00003790 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
3791 return -TARGET_EFAULT;
Michael S. Tsirkine8bbe362009-09-30 18:56:44 +00003792 target_ip = &(target_sd->sem_perm);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003793 host_ip->__key = tswap32(target_ip->__key);
3794 host_ip->uid = tswap32(target_ip->uid);
3795 host_ip->gid = tswap32(target_ip->gid);
3796 host_ip->cuid = tswap32(target_ip->cuid);
3797 host_ip->cgid = tswap32(target_ip->cgid);
3798#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
3799 host_ip->mode = tswap32(target_ip->mode);
3800#else
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003801 host_ip->mode = tswap16(target_ip->mode);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003802#endif
3803#if defined(TARGET_PPC)
3804 host_ip->__seq = tswap32(target_ip->__seq);
3805#else
3806 host_ip->__seq = tswap16(target_ip->__seq);
3807#endif
ths3eb6b042007-06-03 14:26:27 +00003808 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00003809 return 0;
ths3eb6b042007-06-03 14:26:27 +00003810}
3811
bellard579a97f2007-11-11 14:26:47 +00003812static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
3813 struct ipc_perm *host_ip)
ths3eb6b042007-06-03 14:26:27 +00003814{
3815 struct target_ipc_perm *target_ip;
Peter Maydell005eb2a2016-07-15 16:50:47 +01003816 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003817
bellard579a97f2007-11-11 14:26:47 +00003818 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3819 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00003820 target_ip = &(target_sd->sem_perm);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003821 target_ip->__key = tswap32(host_ip->__key);
3822 target_ip->uid = tswap32(host_ip->uid);
3823 target_ip->gid = tswap32(host_ip->gid);
3824 target_ip->cuid = tswap32(host_ip->cuid);
3825 target_ip->cgid = tswap32(host_ip->cgid);
3826#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
3827 target_ip->mode = tswap32(host_ip->mode);
3828#else
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003829 target_ip->mode = tswap16(host_ip->mode);
Petar Jovanovic55a2b162013-10-30 14:46:31 +01003830#endif
3831#if defined(TARGET_PPC)
3832 target_ip->__seq = tswap32(host_ip->__seq);
3833#else
3834 target_ip->__seq = tswap16(host_ip->__seq);
3835#endif
ths3eb6b042007-06-03 14:26:27 +00003836 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00003837 return 0;
ths3eb6b042007-06-03 14:26:27 +00003838}
3839
bellard579a97f2007-11-11 14:26:47 +00003840static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
3841 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00003842{
Peter Maydell005eb2a2016-07-15 16:50:47 +01003843 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003844
bellard579a97f2007-11-11 14:26:47 +00003845 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
3846 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00003847 if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
3848 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003849 host_sd->sem_nsems = tswapal(target_sd->sem_nsems);
3850 host_sd->sem_otime = tswapal(target_sd->sem_otime);
3851 host_sd->sem_ctime = tswapal(target_sd->sem_ctime);
ths3eb6b042007-06-03 14:26:27 +00003852 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00003853 return 0;
ths3eb6b042007-06-03 14:26:27 +00003854}
3855
bellard579a97f2007-11-11 14:26:47 +00003856static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
3857 struct semid_ds *host_sd)
ths3eb6b042007-06-03 14:26:27 +00003858{
Peter Maydell005eb2a2016-07-15 16:50:47 +01003859 struct target_semid64_ds *target_sd;
ths3eb6b042007-06-03 14:26:27 +00003860
bellard579a97f2007-11-11 14:26:47 +00003861 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3862 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00003863 if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
Dong Xu Wang3a931132011-11-29 16:52:38 +08003864 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02003865 target_sd->sem_nsems = tswapal(host_sd->sem_nsems);
3866 target_sd->sem_otime = tswapal(host_sd->sem_otime);
3867 target_sd->sem_ctime = tswapal(host_sd->sem_ctime);
ths3eb6b042007-06-03 14:26:27 +00003868 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00003869 return 0;
ths3eb6b042007-06-03 14:26:27 +00003870}
3871
aurel32e5289082009-04-18 16:16:12 +00003872struct target_seminfo {
3873 int semmap;
3874 int semmni;
3875 int semmns;
3876 int semmnu;
3877 int semmsl;
3878 int semopm;
3879 int semume;
3880 int semusz;
3881 int semvmx;
3882 int semaem;
3883};
3884
3885static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
3886 struct seminfo *host_seminfo)
3887{
3888 struct target_seminfo *target_seminfo;
3889 if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
3890 return -TARGET_EFAULT;
3891 __put_user(host_seminfo->semmap, &target_seminfo->semmap);
3892 __put_user(host_seminfo->semmni, &target_seminfo->semmni);
3893 __put_user(host_seminfo->semmns, &target_seminfo->semmns);
3894 __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
3895 __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
3896 __put_user(host_seminfo->semopm, &target_seminfo->semopm);
3897 __put_user(host_seminfo->semume, &target_seminfo->semume);
3898 __put_user(host_seminfo->semusz, &target_seminfo->semusz);
3899 __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
3900 __put_user(host_seminfo->semaem, &target_seminfo->semaem);
3901 unlock_user_struct(target_seminfo, target_addr, 1);
3902 return 0;
3903}
3904
thsfa294812007-02-02 22:05:00 +00003905union semun {
3906 int val;
ths3eb6b042007-06-03 14:26:27 +00003907 struct semid_ds *buf;
thsfa294812007-02-02 22:05:00 +00003908 unsigned short *array;
aurel32e5289082009-04-18 16:16:12 +00003909 struct seminfo *__buf;
thsfa294812007-02-02 22:05:00 +00003910};
3911
ths3eb6b042007-06-03 14:26:27 +00003912union target_semun {
3913 int val;
aurel32e5289082009-04-18 16:16:12 +00003914 abi_ulong buf;
3915 abi_ulong array;
3916 abi_ulong __buf;
ths3eb6b042007-06-03 14:26:27 +00003917};
3918
aurel32e5289082009-04-18 16:16:12 +00003919static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
3920 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00003921{
aurel32e5289082009-04-18 16:16:12 +00003922 int nsems;
3923 unsigned short *array;
3924 union semun semun;
3925 struct semid_ds semid_ds;
3926 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00003927
aurel32e5289082009-04-18 16:16:12 +00003928 semun.buf = &semid_ds;
3929
3930 ret = semctl(semid, 0, IPC_STAT, semun);
3931 if (ret == -1)
3932 return get_errno(ret);
3933
3934 nsems = semid_ds.sem_nsems;
3935
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303936 *host_array = g_try_new(unsigned short, nsems);
Peter Maydell69d4c702014-02-17 18:55:34 +00003937 if (!*host_array) {
3938 return -TARGET_ENOMEM;
3939 }
aurel32e5289082009-04-18 16:16:12 +00003940 array = lock_user(VERIFY_READ, target_addr,
3941 nsems*sizeof(unsigned short), 1);
Peter Maydell69d4c702014-02-17 18:55:34 +00003942 if (!array) {
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303943 g_free(*host_array);
aurel32e5289082009-04-18 16:16:12 +00003944 return -TARGET_EFAULT;
Peter Maydell69d4c702014-02-17 18:55:34 +00003945 }
aurel32e5289082009-04-18 16:16:12 +00003946
3947 for(i=0; i<nsems; i++) {
3948 __get_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00003949 }
aurel32e5289082009-04-18 16:16:12 +00003950 unlock_user(array, target_addr, 0);
3951
bellard579a97f2007-11-11 14:26:47 +00003952 return 0;
ths3eb6b042007-06-03 14:26:27 +00003953}
3954
aurel32e5289082009-04-18 16:16:12 +00003955static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
3956 unsigned short **host_array)
ths3eb6b042007-06-03 14:26:27 +00003957{
aurel32e5289082009-04-18 16:16:12 +00003958 int nsems;
3959 unsigned short *array;
3960 union semun semun;
3961 struct semid_ds semid_ds;
3962 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00003963
aurel32e5289082009-04-18 16:16:12 +00003964 semun.buf = &semid_ds;
3965
3966 ret = semctl(semid, 0, IPC_STAT, semun);
3967 if (ret == -1)
3968 return get_errno(ret);
3969
3970 nsems = semid_ds.sem_nsems;
3971
3972 array = lock_user(VERIFY_WRITE, target_addr,
3973 nsems*sizeof(unsigned short), 0);
3974 if (!array)
3975 return -TARGET_EFAULT;
3976
3977 for(i=0; i<nsems; i++) {
3978 __put_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00003979 }
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05303980 g_free(*host_array);
aurel32e5289082009-04-18 16:16:12 +00003981 unlock_user(array, target_addr, 1);
3982
bellard579a97f2007-11-11 14:26:47 +00003983 return 0;
ths3eb6b042007-06-03 14:26:27 +00003984}
3985
aurel32e5289082009-04-18 16:16:12 +00003986static inline abi_long do_semctl(int semid, int semnum, int cmd,
Stefan Weild1c002b2015-02-08 15:40:58 +01003987 abi_ulong target_arg)
ths3eb6b042007-06-03 14:26:27 +00003988{
Stefan Weild1c002b2015-02-08 15:40:58 +01003989 union target_semun target_su = { .buf = target_arg };
ths3eb6b042007-06-03 14:26:27 +00003990 union semun arg;
3991 struct semid_ds dsarg;
vibi sreenivasan7b8118e2009-06-19 13:34:39 +05303992 unsigned short *array = NULL;
aurel32e5289082009-04-18 16:16:12 +00003993 struct seminfo seminfo;
3994 abi_long ret = -TARGET_EINVAL;
3995 abi_long err;
3996 cmd &= 0xff;
ths3eb6b042007-06-03 14:26:27 +00003997
3998 switch( cmd ) {
3999 case GETVAL:
ths3eb6b042007-06-03 14:26:27 +00004000 case SETVAL:
Tom Musta5464bae2014-08-12 13:53:34 -05004001 /* In 64 bit cross-endian situations, we will erroneously pick up
4002 * the wrong half of the union for the "val" element. To rectify
4003 * this, the entire 8-byte structure is byteswapped, followed by
4004 * a swap of the 4 byte val field. In other cases, the data is
4005 * already in proper host byte order. */
4006 if (sizeof(target_su.val) != (sizeof(target_su.buf))) {
4007 target_su.buf = tswapal(target_su.buf);
4008 arg.val = tswap32(target_su.val);
4009 } else {
4010 arg.val = target_su.val;
4011 }
aurel32e5289082009-04-18 16:16:12 +00004012 ret = get_errno(semctl(semid, semnum, cmd, arg));
ths3eb6b042007-06-03 14:26:27 +00004013 break;
4014 case GETALL:
ths3eb6b042007-06-03 14:26:27 +00004015 case SETALL:
aurel32e5289082009-04-18 16:16:12 +00004016 err = target_to_host_semarray(semid, &array, target_su.array);
4017 if (err)
4018 return err;
4019 arg.array = array;
4020 ret = get_errno(semctl(semid, semnum, cmd, arg));
4021 err = host_to_target_semarray(semid, target_su.array, &array);
4022 if (err)
4023 return err;
ths3eb6b042007-06-03 14:26:27 +00004024 break;
4025 case IPC_STAT:
ths3eb6b042007-06-03 14:26:27 +00004026 case IPC_SET:
aurel32e5289082009-04-18 16:16:12 +00004027 case SEM_STAT:
4028 err = target_to_host_semid_ds(&dsarg, target_su.buf);
4029 if (err)
4030 return err;
4031 arg.buf = &dsarg;
4032 ret = get_errno(semctl(semid, semnum, cmd, arg));
4033 err = host_to_target_semid_ds(target_su.buf, &dsarg);
4034 if (err)
4035 return err;
ths3eb6b042007-06-03 14:26:27 +00004036 break;
aurel32e5289082009-04-18 16:16:12 +00004037 case IPC_INFO:
4038 case SEM_INFO:
4039 arg.__buf = &seminfo;
4040 ret = get_errno(semctl(semid, semnum, cmd, arg));
4041 err = host_to_target_seminfo(target_su.__buf, &seminfo);
4042 if (err)
4043 return err;
4044 break;
4045 case IPC_RMID:
4046 case GETPID:
4047 case GETNCNT:
4048 case GETZCNT:
4049 ret = get_errno(semctl(semid, semnum, cmd, NULL));
4050 break;
ths3eb6b042007-06-03 14:26:27 +00004051 }
4052
4053 return ret;
4054}
4055
aurel32e5289082009-04-18 16:16:12 +00004056struct target_sembuf {
4057 unsigned short sem_num;
4058 short sem_op;
4059 short sem_flg;
4060};
4061
4062static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
4063 abi_ulong target_addr,
4064 unsigned nsops)
4065{
4066 struct target_sembuf *target_sembuf;
4067 int i;
4068
4069 target_sembuf = lock_user(VERIFY_READ, target_addr,
4070 nsops*sizeof(struct target_sembuf), 1);
4071 if (!target_sembuf)
4072 return -TARGET_EFAULT;
4073
4074 for(i=0; i<nsops; i++) {
4075 __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
4076 __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
4077 __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
4078 }
4079
4080 unlock_user(target_sembuf, target_addr, 0);
4081
4082 return 0;
4083}
4084
Matus Kyseld8c08b12020-06-26 14:46:11 +02004085#if defined(TARGET_NR_ipc) || defined(TARGET_NR_semop) || \
Filip Bozutacac46eb2020-08-25 00:30:50 +02004086 defined(TARGET_NR_semtimedop) || defined(TARGET_NR_semtimedop_time64)
Matus Kyseld8c08b12020-06-26 14:46:11 +02004087
4088/*
4089 * This macro is required to handle the s390 variants, which passes the
4090 * arguments in a different order than default.
4091 */
4092#ifdef __s390x__
4093#define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
4094 (__nsops), (__timeout), (__sops)
4095#else
4096#define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
4097 (__nsops), 0, (__sops), (__timeout)
4098#endif
4099
4100static inline abi_long do_semtimedop(int semid,
4101 abi_long ptr,
4102 unsigned nsops,
Filip Bozutacac46eb2020-08-25 00:30:50 +02004103 abi_long timeout, bool time64)
aurel32e5289082009-04-18 16:16:12 +00004104{
Filip Bozuta0a7ec842020-08-18 20:07:22 +02004105 struct sembuf *sops;
Matus Kyseld8c08b12020-06-26 14:46:11 +02004106 struct timespec ts, *pts = NULL;
Laurent Vivier524fa342019-05-29 10:48:04 +02004107 abi_long ret;
aurel32e5289082009-04-18 16:16:12 +00004108
Matus Kyseld8c08b12020-06-26 14:46:11 +02004109 if (timeout) {
4110 pts = &ts;
Filip Bozutacac46eb2020-08-25 00:30:50 +02004111 if (time64) {
4112 if (target_to_host_timespec64(pts, timeout)) {
4113 return -TARGET_EFAULT;
4114 }
4115 } else {
4116 if (target_to_host_timespec(pts, timeout)) {
4117 return -TARGET_EFAULT;
4118 }
Matus Kyseld8c08b12020-06-26 14:46:11 +02004119 }
4120 }
4121
Filip Bozuta0a7ec842020-08-18 20:07:22 +02004122 if (nsops > TARGET_SEMOPM) {
4123 return -TARGET_E2BIG;
4124 }
4125
4126 sops = g_new(struct sembuf, nsops);
4127
4128 if (target_to_host_sembuf(sops, ptr, nsops)) {
4129 g_free(sops);
aurel32e5289082009-04-18 16:16:12 +00004130 return -TARGET_EFAULT;
Filip Bozuta0a7ec842020-08-18 20:07:22 +02004131 }
aurel32e5289082009-04-18 16:16:12 +00004132
Laurent Vivier524fa342019-05-29 10:48:04 +02004133 ret = -TARGET_ENOSYS;
4134#ifdef __NR_semtimedop
Matus Kyseld8c08b12020-06-26 14:46:11 +02004135 ret = get_errno(safe_semtimedop(semid, sops, nsops, pts));
Laurent Vivier524fa342019-05-29 10:48:04 +02004136#endif
4137#ifdef __NR_ipc
4138 if (ret == -TARGET_ENOSYS) {
Matus Kyseld8c08b12020-06-26 14:46:11 +02004139 ret = get_errno(safe_ipc(IPCOP_semtimedop, semid,
4140 SEMTIMEDOP_IPC_ARGS(nsops, sops, (long)pts)));
Laurent Vivier524fa342019-05-29 10:48:04 +02004141 }
4142#endif
Filip Bozuta0a7ec842020-08-18 20:07:22 +02004143 g_free(sops);
Laurent Vivier524fa342019-05-29 10:48:04 +02004144 return ret;
aurel32e5289082009-04-18 16:16:12 +00004145}
Matus Kyseld8c08b12020-06-26 14:46:11 +02004146#endif
aurel32e5289082009-04-18 16:16:12 +00004147
ths1bc012f2007-06-03 14:27:49 +00004148struct target_msqid_ds
4149{
aurel321c54ff92008-10-13 21:08:44 +00004150 struct target_ipc_perm msg_perm;
4151 abi_ulong msg_stime;
4152#if TARGET_ABI_BITS == 32
4153 abi_ulong __unused1;
4154#endif
4155 abi_ulong msg_rtime;
4156#if TARGET_ABI_BITS == 32
4157 abi_ulong __unused2;
4158#endif
4159 abi_ulong msg_ctime;
4160#if TARGET_ABI_BITS == 32
4161 abi_ulong __unused3;
4162#endif
4163 abi_ulong __msg_cbytes;
4164 abi_ulong msg_qnum;
4165 abi_ulong msg_qbytes;
4166 abi_ulong msg_lspid;
4167 abi_ulong msg_lrpid;
4168 abi_ulong __unused4;
4169 abi_ulong __unused5;
ths1bc012f2007-06-03 14:27:49 +00004170};
4171
bellard579a97f2007-11-11 14:26:47 +00004172static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
4173 abi_ulong target_addr)
ths1bc012f2007-06-03 14:27:49 +00004174{
4175 struct target_msqid_ds *target_md;
4176
bellard579a97f2007-11-11 14:26:47 +00004177 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
4178 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00004179 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
4180 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02004181 host_md->msg_stime = tswapal(target_md->msg_stime);
4182 host_md->msg_rtime = tswapal(target_md->msg_rtime);
4183 host_md->msg_ctime = tswapal(target_md->msg_ctime);
4184 host_md->__msg_cbytes = tswapal(target_md->__msg_cbytes);
4185 host_md->msg_qnum = tswapal(target_md->msg_qnum);
4186 host_md->msg_qbytes = tswapal(target_md->msg_qbytes);
4187 host_md->msg_lspid = tswapal(target_md->msg_lspid);
4188 host_md->msg_lrpid = tswapal(target_md->msg_lrpid);
ths1bc012f2007-06-03 14:27:49 +00004189 unlock_user_struct(target_md, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00004190 return 0;
ths1bc012f2007-06-03 14:27:49 +00004191}
4192
bellard579a97f2007-11-11 14:26:47 +00004193static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
4194 struct msqid_ds *host_md)
ths1bc012f2007-06-03 14:27:49 +00004195{
4196 struct target_msqid_ds *target_md;
4197
bellard579a97f2007-11-11 14:26:47 +00004198 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
4199 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00004200 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
4201 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02004202 target_md->msg_stime = tswapal(host_md->msg_stime);
4203 target_md->msg_rtime = tswapal(host_md->msg_rtime);
4204 target_md->msg_ctime = tswapal(host_md->msg_ctime);
4205 target_md->__msg_cbytes = tswapal(host_md->__msg_cbytes);
4206 target_md->msg_qnum = tswapal(host_md->msg_qnum);
4207 target_md->msg_qbytes = tswapal(host_md->msg_qbytes);
4208 target_md->msg_lspid = tswapal(host_md->msg_lspid);
4209 target_md->msg_lrpid = tswapal(host_md->msg_lrpid);
ths1bc012f2007-06-03 14:27:49 +00004210 unlock_user_struct(target_md, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00004211 return 0;
ths1bc012f2007-06-03 14:27:49 +00004212}
4213
aurel321c54ff92008-10-13 21:08:44 +00004214struct target_msginfo {
4215 int msgpool;
4216 int msgmap;
4217 int msgmax;
4218 int msgmnb;
4219 int msgmni;
4220 int msgssz;
4221 int msgtql;
4222 unsigned short int msgseg;
4223};
4224
4225static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
4226 struct msginfo *host_msginfo)
4227{
4228 struct target_msginfo *target_msginfo;
4229 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
4230 return -TARGET_EFAULT;
4231 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
4232 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
4233 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
4234 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
4235 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
4236 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
4237 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
4238 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
4239 unlock_user_struct(target_msginfo, target_addr, 1);
aurel3200b229a2008-10-24 13:12:52 +00004240 return 0;
aurel321c54ff92008-10-13 21:08:44 +00004241}
4242
4243static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
ths1bc012f2007-06-03 14:27:49 +00004244{
4245 struct msqid_ds dsarg;
aurel321c54ff92008-10-13 21:08:44 +00004246 struct msginfo msginfo;
4247 abi_long ret = -TARGET_EINVAL;
4248
4249 cmd &= 0xff;
4250
4251 switch (cmd) {
ths1bc012f2007-06-03 14:27:49 +00004252 case IPC_STAT:
4253 case IPC_SET:
aurel321c54ff92008-10-13 21:08:44 +00004254 case MSG_STAT:
4255 if (target_to_host_msqid_ds(&dsarg,ptr))
4256 return -TARGET_EFAULT;
4257 ret = get_errno(msgctl(msgid, cmd, &dsarg));
4258 if (host_to_target_msqid_ds(ptr,&dsarg))
4259 return -TARGET_EFAULT;
4260 break;
4261 case IPC_RMID:
4262 ret = get_errno(msgctl(msgid, cmd, NULL));
4263 break;
4264 case IPC_INFO:
4265 case MSG_INFO:
4266 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
4267 if (host_to_target_msginfo(ptr, &msginfo))
4268 return -TARGET_EFAULT;
4269 break;
ths1bc012f2007-06-03 14:27:49 +00004270 }
aurel321c54ff92008-10-13 21:08:44 +00004271
ths1bc012f2007-06-03 14:27:49 +00004272 return ret;
4273}
4274
4275struct target_msgbuf {
aurel321c54ff92008-10-13 21:08:44 +00004276 abi_long mtype;
4277 char mtext[1];
ths1bc012f2007-06-03 14:27:49 +00004278};
4279
blueswir1992f48a2007-10-14 16:27:31 +00004280static inline abi_long do_msgsnd(int msqid, abi_long msgp,
Tom Mustaedcc5f92014-08-12 13:53:37 -05004281 ssize_t msgsz, int msgflg)
ths1bc012f2007-06-03 14:27:49 +00004282{
4283 struct target_msgbuf *target_mb;
4284 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00004285 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00004286
Tom Mustaedcc5f92014-08-12 13:53:37 -05004287 if (msgsz < 0) {
4288 return -TARGET_EINVAL;
4289 }
4290
bellard579a97f2007-11-11 14:26:47 +00004291 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
4292 return -TARGET_EFAULT;
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304293 host_mb = g_try_malloc(msgsz + sizeof(long));
zhanghailiang29e03fc2014-08-14 15:29:18 +08004294 if (!host_mb) {
4295 unlock_user_struct(target_mb, msgp, 0);
4296 return -TARGET_ENOMEM;
4297 }
Matthias Brauncbb21ee2011-08-12 19:57:41 +02004298 host_mb->mtype = (abi_long) tswapal(target_mb->mtype);
aurel321c54ff92008-10-13 21:08:44 +00004299 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
Laurent Vivier524fa342019-05-29 10:48:04 +02004300 ret = -TARGET_ENOSYS;
4301#ifdef __NR_msgsnd
Peter Maydell89f9fe42016-06-06 19:58:05 +01004302 ret = get_errno(safe_msgsnd(msqid, host_mb, msgsz, msgflg));
Laurent Vivier524fa342019-05-29 10:48:04 +02004303#endif
4304#ifdef __NR_ipc
4305 if (ret == -TARGET_ENOSYS) {
Matus Kyseld8c08b12020-06-26 14:46:11 +02004306#ifdef __s390x__
4307 ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg,
4308 host_mb));
4309#else
Laurent Vivier524fa342019-05-29 10:48:04 +02004310 ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg,
4311 host_mb, 0));
Matus Kyseld8c08b12020-06-26 14:46:11 +02004312#endif
Laurent Vivier524fa342019-05-29 10:48:04 +02004313 }
4314#endif
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304315 g_free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00004316 unlock_user_struct(target_mb, msgp, 0);
4317
4318 return ret;
4319}
4320
Matus Kyseld8c08b12020-06-26 14:46:11 +02004321#ifdef __NR_ipc
4322#if defined(__sparc__)
4323/* SPARC for msgrcv it does not use the kludge on final 2 arguments. */
4324#define MSGRCV_ARGS(__msgp, __msgtyp) __msgp, __msgtyp
4325#elif defined(__s390x__)
4326/* The s390 sys_ipc variant has only five parameters. */
4327#define MSGRCV_ARGS(__msgp, __msgtyp) \
4328 ((long int[]){(long int)__msgp, __msgtyp})
4329#else
4330#define MSGRCV_ARGS(__msgp, __msgtyp) \
4331 ((long int[]){(long int)__msgp, __msgtyp}), 0
4332#endif
4333#endif
4334
blueswir1992f48a2007-10-14 16:27:31 +00004335static inline abi_long do_msgrcv(int msqid, abi_long msgp,
Peter Maydell99874f62016-05-20 19:00:56 +01004336 ssize_t msgsz, abi_long msgtyp,
blueswir1992f48a2007-10-14 16:27:31 +00004337 int msgflg)
ths1bc012f2007-06-03 14:27:49 +00004338{
4339 struct target_msgbuf *target_mb;
bellard579a97f2007-11-11 14:26:47 +00004340 char *target_mtext;
ths1bc012f2007-06-03 14:27:49 +00004341 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00004342 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00004343
Peter Maydell99874f62016-05-20 19:00:56 +01004344 if (msgsz < 0) {
4345 return -TARGET_EINVAL;
4346 }
4347
bellard579a97f2007-11-11 14:26:47 +00004348 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
4349 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00004350
Peter Maydell415d8472016-05-20 19:00:57 +01004351 host_mb = g_try_malloc(msgsz + sizeof(long));
4352 if (!host_mb) {
4353 ret = -TARGET_ENOMEM;
4354 goto end;
4355 }
Laurent Vivier524fa342019-05-29 10:48:04 +02004356 ret = -TARGET_ENOSYS;
4357#ifdef __NR_msgrcv
Peter Maydell89f9fe42016-06-06 19:58:05 +01004358 ret = get_errno(safe_msgrcv(msqid, host_mb, msgsz, msgtyp, msgflg));
Laurent Vivier524fa342019-05-29 10:48:04 +02004359#endif
4360#ifdef __NR_ipc
4361 if (ret == -TARGET_ENOSYS) {
4362 ret = get_errno(safe_ipc(IPCOP_CALL(1, IPCOP_msgrcv), msqid, msgsz,
Matus Kyseld8c08b12020-06-26 14:46:11 +02004363 msgflg, MSGRCV_ARGS(host_mb, msgtyp)));
Laurent Vivier524fa342019-05-29 10:48:04 +02004364 }
4365#endif
aurel321c54ff92008-10-13 21:08:44 +00004366
bellard579a97f2007-11-11 14:26:47 +00004367 if (ret > 0) {
4368 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
4369 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
4370 if (!target_mtext) {
4371 ret = -TARGET_EFAULT;
4372 goto end;
4373 }
aurel321c54ff92008-10-13 21:08:44 +00004374 memcpy(target_mb->mtext, host_mb->mtext, ret);
bellard579a97f2007-11-11 14:26:47 +00004375 unlock_user(target_mtext, target_mtext_addr, ret);
4376 }
aurel321c54ff92008-10-13 21:08:44 +00004377
Matthias Brauncbb21ee2011-08-12 19:57:41 +02004378 target_mb->mtype = tswapal(host_mb->mtype);
ths1bc012f2007-06-03 14:27:49 +00004379
bellard579a97f2007-11-11 14:26:47 +00004380end:
4381 if (target_mb)
4382 unlock_user_struct(target_mb, msgp, 1);
Jim Meyering0d07fe42012-08-22 13:55:53 +02004383 g_free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00004384 return ret;
4385}
4386
Riku Voipio88a8c982009-04-03 10:42:00 +03004387static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
4388 abi_ulong target_addr)
4389{
4390 struct target_shmid_ds *target_sd;
4391
4392 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
4393 return -TARGET_EFAULT;
4394 if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
4395 return -TARGET_EFAULT;
4396 __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
4397 __get_user(host_sd->shm_atime, &target_sd->shm_atime);
4398 __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
4399 __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
4400 __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
4401 __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
4402 __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
4403 unlock_user_struct(target_sd, target_addr, 0);
4404 return 0;
4405}
4406
4407static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
4408 struct shmid_ds *host_sd)
4409{
4410 struct target_shmid_ds *target_sd;
4411
4412 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
4413 return -TARGET_EFAULT;
4414 if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
4415 return -TARGET_EFAULT;
4416 __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
4417 __put_user(host_sd->shm_atime, &target_sd->shm_atime);
4418 __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
4419 __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
4420 __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
4421 __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
4422 __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
4423 unlock_user_struct(target_sd, target_addr, 1);
4424 return 0;
4425}
4426
4427struct target_shminfo {
4428 abi_ulong shmmax;
4429 abi_ulong shmmin;
4430 abi_ulong shmmni;
4431 abi_ulong shmseg;
4432 abi_ulong shmall;
4433};
4434
4435static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
4436 struct shminfo *host_shminfo)
4437{
4438 struct target_shminfo *target_shminfo;
4439 if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
4440 return -TARGET_EFAULT;
4441 __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
4442 __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
4443 __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
4444 __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
4445 __put_user(host_shminfo->shmall, &target_shminfo->shmall);
4446 unlock_user_struct(target_shminfo, target_addr, 1);
4447 return 0;
4448}
4449
4450struct target_shm_info {
4451 int used_ids;
4452 abi_ulong shm_tot;
4453 abi_ulong shm_rss;
4454 abi_ulong shm_swp;
4455 abi_ulong swap_attempts;
4456 abi_ulong swap_successes;
4457};
4458
4459static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
4460 struct shm_info *host_shm_info)
4461{
4462 struct target_shm_info *target_shm_info;
4463 if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
4464 return -TARGET_EFAULT;
4465 __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
4466 __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
4467 __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
4468 __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
4469 __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
4470 __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
4471 unlock_user_struct(target_shm_info, target_addr, 1);
4472 return 0;
4473}
4474
4475static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
4476{
4477 struct shmid_ds dsarg;
4478 struct shminfo shminfo;
4479 struct shm_info shm_info;
4480 abi_long ret = -TARGET_EINVAL;
4481
4482 cmd &= 0xff;
4483
4484 switch(cmd) {
4485 case IPC_STAT:
4486 case IPC_SET:
4487 case SHM_STAT:
4488 if (target_to_host_shmid_ds(&dsarg, buf))
4489 return -TARGET_EFAULT;
4490 ret = get_errno(shmctl(shmid, cmd, &dsarg));
4491 if (host_to_target_shmid_ds(buf, &dsarg))
4492 return -TARGET_EFAULT;
4493 break;
4494 case IPC_INFO:
4495 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
4496 if (host_to_target_shminfo(buf, &shminfo))
4497 return -TARGET_EFAULT;
4498 break;
4499 case SHM_INFO:
4500 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
4501 if (host_to_target_shm_info(buf, &shm_info))
4502 return -TARGET_EFAULT;
4503 break;
4504 case IPC_RMID:
4505 case SHM_LOCK:
4506 case SHM_UNLOCK:
4507 ret = get_errno(shmctl(shmid, cmd, NULL));
4508 break;
4509 }
4510
4511 return ret;
4512}
4513
Peter Maydellee8e7612016-07-11 16:48:11 +01004514#ifndef TARGET_FORCE_SHMLBA
4515/* For most architectures, SHMLBA is the same as the page size;
4516 * some architectures have larger values, in which case they should
4517 * define TARGET_FORCE_SHMLBA and provide a target_shmlba() function.
4518 * This corresponds to the kernel arch code defining __ARCH_FORCE_SHMLBA
4519 * and defining its own value for SHMLBA.
4520 *
4521 * The kernel also permits SHMLBA to be set by the architecture to a
4522 * value larger than the page size without setting __ARCH_FORCE_SHMLBA;
4523 * this means that addresses are rounded to the large size if
4524 * SHM_RND is set but addresses not aligned to that size are not rejected
4525 * as long as they are at least page-aligned. Since the only architecture
4526 * which uses this is ia64 this code doesn't provide for that oddity.
4527 */
4528static inline abi_ulong target_shmlba(CPUArchState *cpu_env)
4529{
4530 return TARGET_PAGE_SIZE;
4531}
4532#endif
4533
4534static inline abi_ulong do_shmat(CPUArchState *cpu_env,
4535 int shmid, abi_ulong shmaddr, int shmflg)
Riku Voipio88a8c982009-04-03 10:42:00 +03004536{
Richard Henderson228168c2021-06-11 23:08:28 -07004537 CPUState *cpu = env_cpu(cpu_env);
Riku Voipio88a8c982009-04-03 10:42:00 +03004538 abi_long raddr;
4539 void *host_raddr;
4540 struct shmid_ds shm_info;
4541 int i,ret;
Peter Maydellee8e7612016-07-11 16:48:11 +01004542 abi_ulong shmlba;
Riku Voipio88a8c982009-04-03 10:42:00 +03004543
Richard Hendersonee1bf832021-02-12 10:48:44 -08004544 /* shmat pointers are always untagged */
4545
Riku Voipio88a8c982009-04-03 10:42:00 +03004546 /* find out the length of the shared memory segment */
4547 ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
4548 if (is_error(ret)) {
4549 /* can't get length, bail out */
4550 return ret;
4551 }
4552
Peter Maydellee8e7612016-07-11 16:48:11 +01004553 shmlba = target_shmlba(cpu_env);
4554
4555 if (shmaddr & (shmlba - 1)) {
4556 if (shmflg & SHM_RND) {
4557 shmaddr &= ~(shmlba - 1);
4558 } else {
4559 return -TARGET_EINVAL;
4560 }
4561 }
Richard Henderson46b12f42021-02-12 10:48:46 -08004562 if (!guest_range_valid_untagged(shmaddr, shm_info.shm_segsz)) {
Max Filippovebf9a362018-03-07 13:50:10 -08004563 return -TARGET_EINVAL;
4564 }
Peter Maydellee8e7612016-07-11 16:48:11 +01004565
Riku Voipio88a8c982009-04-03 10:42:00 +03004566 mmap_lock();
4567
Richard Henderson228168c2021-06-11 23:08:28 -07004568 /*
4569 * We're mapping shared memory, so ensure we generate code for parallel
4570 * execution and flush old translations. This will work up to the level
4571 * supported by the host -- anything that requires EXCP_ATOMIC will not
4572 * be atomic with respect to an external process.
4573 */
4574 if (!(cpu->tcg_cflags & CF_PARALLEL)) {
4575 cpu->tcg_cflags |= CF_PARALLEL;
4576 tb_flush(cpu);
4577 }
4578
Riku Voipio88a8c982009-04-03 10:42:00 +03004579 if (shmaddr)
Richard Henderson3e8f1622021-02-12 10:48:43 -08004580 host_raddr = shmat(shmid, (void *)g2h_untagged(shmaddr), shmflg);
Riku Voipio88a8c982009-04-03 10:42:00 +03004581 else {
4582 abi_ulong mmap_start;
4583
Richard Henderson30ab9ef2019-05-19 13:19:52 -07004584 /* In order to use the host shmat, we need to honor host SHMLBA. */
4585 mmap_start = mmap_find_vma(0, shm_info.shm_segsz, MAX(SHMLBA, shmlba));
Riku Voipio88a8c982009-04-03 10:42:00 +03004586
4587 if (mmap_start == -1) {
4588 errno = ENOMEM;
4589 host_raddr = (void *)-1;
4590 } else
Richard Henderson3e8f1622021-02-12 10:48:43 -08004591 host_raddr = shmat(shmid, g2h_untagged(mmap_start),
4592 shmflg | SHM_REMAP);
Riku Voipio88a8c982009-04-03 10:42:00 +03004593 }
4594
4595 if (host_raddr == (void *)-1) {
4596 mmap_unlock();
4597 return get_errno((long)host_raddr);
4598 }
4599 raddr=h2g((unsigned long)host_raddr);
4600
4601 page_set_flags(raddr, raddr + shm_info.shm_segsz,
Richard Hendersond9c58582021-02-12 10:48:32 -08004602 PAGE_VALID | PAGE_RESET | PAGE_READ |
4603 (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
Riku Voipio88a8c982009-04-03 10:42:00 +03004604
4605 for (i = 0; i < N_SHM_REGIONS; i++) {
Peter Maydellb6e17872016-02-09 15:57:11 +00004606 if (!shm_regions[i].in_use) {
4607 shm_regions[i].in_use = true;
Riku Voipio88a8c982009-04-03 10:42:00 +03004608 shm_regions[i].start = raddr;
4609 shm_regions[i].size = shm_info.shm_segsz;
4610 break;
4611 }
4612 }
4613
4614 mmap_unlock();
4615 return raddr;
4616
4617}
4618
4619static inline abi_long do_shmdt(abi_ulong shmaddr)
4620{
4621 int i;
Max Filippov3c5f6a52018-02-28 14:16:04 -08004622 abi_long rv;
4623
Richard Hendersonee1bf832021-02-12 10:48:44 -08004624 /* shmdt pointers are always untagged */
4625
Max Filippov3c5f6a52018-02-28 14:16:04 -08004626 mmap_lock();
Riku Voipio88a8c982009-04-03 10:42:00 +03004627
4628 for (i = 0; i < N_SHM_REGIONS; ++i) {
Peter Maydellb6e17872016-02-09 15:57:11 +00004629 if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
4630 shm_regions[i].in_use = false;
takasi-y@ops.dti.ne.jpe00ac242010-04-11 02:09:57 +09004631 page_set_flags(shmaddr, shmaddr + shm_regions[i].size, 0);
Riku Voipio88a8c982009-04-03 10:42:00 +03004632 break;
4633 }
4634 }
Richard Henderson3e8f1622021-02-12 10:48:43 -08004635 rv = get_errno(shmdt(g2h_untagged(shmaddr)));
Riku Voipio88a8c982009-04-03 10:42:00 +03004636
Max Filippov3c5f6a52018-02-28 14:16:04 -08004637 mmap_unlock();
4638
4639 return rv;
Riku Voipio88a8c982009-04-03 10:42:00 +03004640}
4641
aurel321c54ff92008-10-13 21:08:44 +00004642#ifdef TARGET_NR_ipc
pbrook53a59602006-03-25 19:31:22 +00004643/* ??? This only works with linear mappings. */
ths0da46a62007-10-20 20:23:07 +00004644/* do_ipc() must return target values and target errnos. */
Peter Maydellee8e7612016-07-11 16:48:11 +01004645static abi_long do_ipc(CPUArchState *cpu_env,
4646 unsigned int call, abi_long first,
Tom Musta37ed0952014-08-12 13:53:35 -05004647 abi_long second, abi_long third,
blueswir1992f48a2007-10-14 16:27:31 +00004648 abi_long ptr, abi_long fifth)
bellard8853f862004-02-22 14:57:26 +00004649{
4650 int version;
blueswir1992f48a2007-10-14 16:27:31 +00004651 abi_long ret = 0;
bellard8853f862004-02-22 14:57:26 +00004652
4653 version = call >> 16;
4654 call &= 0xffff;
4655
4656 switch (call) {
thsfa294812007-02-02 22:05:00 +00004657 case IPCOP_semop:
Filip Bozutacac46eb2020-08-25 00:30:50 +02004658 ret = do_semtimedop(first, ptr, second, 0, false);
Matus Kyseld8c08b12020-06-26 14:46:11 +02004659 break;
4660 case IPCOP_semtimedop:
4661 /*
4662 * The s390 sys_ipc variant has only five parameters instead of six
4663 * (as for default variant) and the only difference is the handling of
4664 * SEMTIMEDOP where on s390 the third parameter is used as a pointer
4665 * to a struct timespec where the generic variant uses fifth parameter.
4666 */
4667#if defined(TARGET_S390X)
Filip Bozutacac46eb2020-08-25 00:30:50 +02004668 ret = do_semtimedop(first, ptr, second, third, TARGET_ABI_BITS == 64);
Matus Kyseld8c08b12020-06-26 14:46:11 +02004669#else
Filip Bozutacac46eb2020-08-25 00:30:50 +02004670 ret = do_semtimedop(first, ptr, second, fifth, TARGET_ABI_BITS == 64);
Matus Kyseld8c08b12020-06-26 14:46:11 +02004671#endif
thsfa294812007-02-02 22:05:00 +00004672 break;
4673
4674 case IPCOP_semget:
4675 ret = get_errno(semget(first, second, third));
4676 break;
4677
Tom Musta5d2fa8e2014-08-12 13:53:33 -05004678 case IPCOP_semctl: {
4679 /* The semun argument to semctl is passed by value, so dereference the
4680 * ptr argument. */
4681 abi_ulong atptr;
Tom Musta37ed0952014-08-12 13:53:35 -05004682 get_user_ual(atptr, ptr);
Stefan Weild1c002b2015-02-08 15:40:58 +01004683 ret = do_semctl(first, second, third, atptr);
thsfa294812007-02-02 22:05:00 +00004684 break;
Tom Musta5d2fa8e2014-08-12 13:53:33 -05004685 }
thsd96372e2007-02-02 22:05:44 +00004686
aurel321c54ff92008-10-13 21:08:44 +00004687 case IPCOP_msgget:
4688 ret = get_errno(msgget(first, second));
4689 break;
thsd96372e2007-02-02 22:05:44 +00004690
aurel321c54ff92008-10-13 21:08:44 +00004691 case IPCOP_msgsnd:
4692 ret = do_msgsnd(first, ptr, second, third);
4693 break;
thsd96372e2007-02-02 22:05:44 +00004694
aurel321c54ff92008-10-13 21:08:44 +00004695 case IPCOP_msgctl:
4696 ret = do_msgctl(first, second, ptr);
4697 break;
thsd96372e2007-02-02 22:05:44 +00004698
aurel321c54ff92008-10-13 21:08:44 +00004699 case IPCOP_msgrcv:
4700 switch (version) {
4701 case 0:
4702 {
4703 struct target_ipc_kludge {
4704 abi_long msgp;
4705 abi_long msgtyp;
4706 } *tmp;
thsd96372e2007-02-02 22:05:44 +00004707
aurel321c54ff92008-10-13 21:08:44 +00004708 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
4709 ret = -TARGET_EFAULT;
4710 break;
ths1bc012f2007-06-03 14:27:49 +00004711 }
aurel321c54ff92008-10-13 21:08:44 +00004712
Laurent Vivier79dd77d2012-12-20 11:00:11 +00004713 ret = do_msgrcv(first, tswapal(tmp->msgp), second, tswapal(tmp->msgtyp), third);
aurel321c54ff92008-10-13 21:08:44 +00004714
4715 unlock_user_struct(tmp, ptr, 0);
4716 break;
4717 }
4718 default:
4719 ret = do_msgrcv(first, ptr, second, fifth, third);
4720 }
4721 break;
thsd96372e2007-02-02 22:05:44 +00004722
bellard8853f862004-02-22 14:57:26 +00004723 case IPCOP_shmat:
Riku Voipio88a8c982009-04-03 10:42:00 +03004724 switch (version) {
4725 default:
bellard5a4a8982007-11-11 17:39:18 +00004726 {
4727 abi_ulong raddr;
Peter Maydellee8e7612016-07-11 16:48:11 +01004728 raddr = do_shmat(cpu_env, first, ptr, second);
Riku Voipio88a8c982009-04-03 10:42:00 +03004729 if (is_error(raddr))
4730 return get_errno(raddr);
bellard2f619692007-11-16 10:46:05 +00004731 if (put_user_ual(raddr, third))
bellard5a4a8982007-11-11 17:39:18 +00004732 return -TARGET_EFAULT;
Riku Voipio88a8c982009-04-03 10:42:00 +03004733 break;
4734 }
4735 case 1:
4736 ret = -TARGET_EINVAL;
4737 break;
bellard5a4a8982007-11-11 17:39:18 +00004738 }
bellard8853f862004-02-22 14:57:26 +00004739 break;
4740 case IPCOP_shmdt:
Riku Voipio88a8c982009-04-03 10:42:00 +03004741 ret = do_shmdt(ptr);
bellard8853f862004-02-22 14:57:26 +00004742 break;
4743
4744 case IPCOP_shmget:
4745 /* IPC_* flag values are the same on all linux platforms */
4746 ret = get_errno(shmget(first, second, third));
4747 break;
4748
4749 /* IPC_* and SHM_* command values are the same on all linux platforms */
4750 case IPCOP_shmctl:
Petar Jovanovica2926782013-10-30 14:46:32 +01004751 ret = do_shmctl(first, second, ptr);
bellard8853f862004-02-22 14:57:26 +00004752 break;
4753 default:
Josh Kunz39be5352020-02-03 18:54:13 -08004754 qemu_log_mask(LOG_UNIMP, "Unsupported ipc call: %d (version %d)\n",
4755 call, version);
ths0da46a62007-10-20 20:23:07 +00004756 ret = -TARGET_ENOSYS;
bellard8853f862004-02-22 14:57:26 +00004757 break;
4758 }
4759 return ret;
4760}
j_mayer32407102007-09-26 23:01:49 +00004761#endif
bellard8853f862004-02-22 14:57:26 +00004762
bellard31e31b82003-02-18 22:55:36 +00004763/* kernel structure types definitions */
bellard31e31b82003-02-18 22:55:36 +00004764
Blue Swirl001faf32009-05-13 17:53:17 +00004765#define STRUCT(name, ...) STRUCT_ ## name,
bellard31e31b82003-02-18 22:55:36 +00004766#define STRUCT_SPECIAL(name) STRUCT_ ## name,
4767enum {
4768#include "syscall_types.h"
Alexander Graf8be656b2015-05-06 23:47:32 +02004769STRUCT_MAX
bellard31e31b82003-02-18 22:55:36 +00004770};
4771#undef STRUCT
4772#undef STRUCT_SPECIAL
4773
Blue Swirl001faf32009-05-13 17:53:17 +00004774#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
bellard31e31b82003-02-18 22:55:36 +00004775#define STRUCT_SPECIAL(name)
4776#include "syscall_types.h"
4777#undef STRUCT
4778#undef STRUCT_SPECIAL
4779
bellard31e31b82003-02-18 22:55:36 +00004780#define MAX_STRUCT_SIZE 4096
4781
Peter Maydelldace20d2011-01-10 13:11:24 +00004782#ifdef CONFIG_FIEMAP
Peter Maydell285da2b2011-01-06 15:04:18 +00004783/* So fiemap access checks don't overflow on 32 bit systems.
4784 * This is very slightly smaller than the limit imposed by
4785 * the underlying kernel.
4786 */
4787#define FIEMAP_MAX_EXTENTS ((UINT_MAX - sizeof(struct fiemap)) \
4788 / sizeof(struct fiemap_extent))
4789
4790static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004791 int fd, int cmd, abi_long arg)
Peter Maydell285da2b2011-01-06 15:04:18 +00004792{
4793 /* The parameter for this ioctl is a struct fiemap followed
4794 * by an array of struct fiemap_extent whose size is set
4795 * in fiemap->fm_extent_count. The array is filled in by the
4796 * ioctl.
4797 */
4798 int target_size_in, target_size_out;
4799 struct fiemap *fm;
4800 const argtype *arg_type = ie->arg_type;
4801 const argtype extent_arg_type[] = { MK_STRUCT(STRUCT_fiemap_extent) };
4802 void *argptr, *p;
4803 abi_long ret;
4804 int i, extent_size = thunk_type_size(extent_arg_type, 0);
4805 uint32_t outbufsz;
4806 int free_fm = 0;
4807
4808 assert(arg_type[0] == TYPE_PTR);
4809 assert(ie->access == IOC_RW);
4810 arg_type++;
4811 target_size_in = thunk_type_size(arg_type, 0);
4812 argptr = lock_user(VERIFY_READ, arg, target_size_in, 1);
4813 if (!argptr) {
4814 return -TARGET_EFAULT;
4815 }
4816 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4817 unlock_user(argptr, arg, 0);
4818 fm = (struct fiemap *)buf_temp;
4819 if (fm->fm_extent_count > FIEMAP_MAX_EXTENTS) {
4820 return -TARGET_EINVAL;
4821 }
4822
4823 outbufsz = sizeof (*fm) +
4824 (sizeof(struct fiemap_extent) * fm->fm_extent_count);
4825
4826 if (outbufsz > MAX_STRUCT_SIZE) {
4827 /* We can't fit all the extents into the fixed size buffer.
4828 * Allocate one that is large enough and use it instead.
4829 */
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304830 fm = g_try_malloc(outbufsz);
Peter Maydell285da2b2011-01-06 15:04:18 +00004831 if (!fm) {
4832 return -TARGET_ENOMEM;
4833 }
4834 memcpy(fm, buf_temp, sizeof(struct fiemap));
4835 free_fm = 1;
4836 }
Peter Maydell49ca6f32016-06-06 19:58:14 +01004837 ret = get_errno(safe_ioctl(fd, ie->host_cmd, fm));
Peter Maydell285da2b2011-01-06 15:04:18 +00004838 if (!is_error(ret)) {
4839 target_size_out = target_size_in;
4840 /* An extent_count of 0 means we were only counting the extents
4841 * so there are no structs to copy
4842 */
4843 if (fm->fm_extent_count != 0) {
4844 target_size_out += fm->fm_mapped_extents * extent_size;
4845 }
4846 argptr = lock_user(VERIFY_WRITE, arg, target_size_out, 0);
4847 if (!argptr) {
4848 ret = -TARGET_EFAULT;
4849 } else {
4850 /* Convert the struct fiemap */
4851 thunk_convert(argptr, fm, arg_type, THUNK_TARGET);
4852 if (fm->fm_extent_count != 0) {
4853 p = argptr + target_size_in;
4854 /* ...and then all the struct fiemap_extents */
4855 for (i = 0; i < fm->fm_mapped_extents; i++) {
4856 thunk_convert(p, &fm->fm_extents[i], extent_arg_type,
4857 THUNK_TARGET);
4858 p += extent_size;
4859 }
4860 }
4861 unlock_user(argptr, arg, target_size_out);
4862 }
4863 }
4864 if (free_fm) {
Harmandeep Kaur0e173b22015-10-06 21:47:12 +05304865 g_free(fm);
Peter Maydell285da2b2011-01-06 15:04:18 +00004866 }
4867 return ret;
4868}
Peter Maydelldace20d2011-01-10 13:11:24 +00004869#endif
Peter Maydell285da2b2011-01-06 15:04:18 +00004870
Laurent Vivier059c2f22011-03-30 00:12:12 +02004871static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02004872 int fd, int cmd, abi_long arg)
Laurent Vivier059c2f22011-03-30 00:12:12 +02004873{
4874 const argtype *arg_type = ie->arg_type;
4875 int target_size;
4876 void *argptr;
4877 int ret;
4878 struct ifconf *host_ifconf;
4879 uint32_t outbufsz;
4880 const argtype ifreq_arg_type[] = { MK_STRUCT(STRUCT_sockaddr_ifreq) };
Stefan4df7b7f2021-01-09 19:59:42 +01004881 const argtype ifreq_max_type[] = { MK_STRUCT(STRUCT_ifmap_ifreq) };
Laurent Vivier059c2f22011-03-30 00:12:12 +02004882 int target_ifreq_size;
4883 int nb_ifreq;
4884 int free_buf = 0;
4885 int i;
4886 int target_ifc_len;
4887 abi_long target_ifc_buf;
4888 int host_ifc_len;
4889 char *host_ifc_buf;
4890
4891 assert(arg_type[0] == TYPE_PTR);
4892 assert(ie->access == IOC_RW);
4893
4894 arg_type++;
4895 target_size = thunk_type_size(arg_type, 0);
4896
4897 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4898 if (!argptr)
4899 return -TARGET_EFAULT;
4900 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4901 unlock_user(argptr, arg, 0);
4902
4903 host_ifconf = (struct ifconf *)(unsigned long)buf_temp;
Laurent Vivier059c2f22011-03-30 00:12:12 +02004904 target_ifc_buf = (abi_long)(unsigned long)host_ifconf->ifc_buf;
Stefan4df7b7f2021-01-09 19:59:42 +01004905 target_ifreq_size = thunk_type_size(ifreq_max_type, 0);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004906
Kan Li22e4a2672018-10-24 20:13:03 +00004907 if (target_ifc_buf != 0) {
4908 target_ifc_len = host_ifconf->ifc_len;
4909 nb_ifreq = target_ifc_len / target_ifreq_size;
4910 host_ifc_len = nb_ifreq * sizeof(struct ifreq);
4911
4912 outbufsz = sizeof(*host_ifconf) + host_ifc_len;
4913 if (outbufsz > MAX_STRUCT_SIZE) {
4914 /*
4915 * We can't fit all the extents into the fixed size buffer.
4916 * Allocate one that is large enough and use it instead.
4917 */
Ahmed Abouzied7a5626a2022-01-04 16:38:41 +02004918 host_ifconf = g_try_malloc(outbufsz);
Kan Li22e4a2672018-10-24 20:13:03 +00004919 if (!host_ifconf) {
4920 return -TARGET_ENOMEM;
4921 }
4922 memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf));
4923 free_buf = 1;
Laurent Vivier059c2f22011-03-30 00:12:12 +02004924 }
Kan Li22e4a2672018-10-24 20:13:03 +00004925 host_ifc_buf = (char *)host_ifconf + sizeof(*host_ifconf);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004926
Kan Li22e4a2672018-10-24 20:13:03 +00004927 host_ifconf->ifc_len = host_ifc_len;
4928 } else {
4929 host_ifc_buf = NULL;
4930 }
Laurent Vivier059c2f22011-03-30 00:12:12 +02004931 host_ifconf->ifc_buf = host_ifc_buf;
4932
Peter Maydell49ca6f32016-06-06 19:58:14 +01004933 ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_ifconf));
Laurent Vivier059c2f22011-03-30 00:12:12 +02004934 if (!is_error(ret)) {
4935 /* convert host ifc_len to target ifc_len */
4936
4937 nb_ifreq = host_ifconf->ifc_len / sizeof(struct ifreq);
4938 target_ifc_len = nb_ifreq * target_ifreq_size;
4939 host_ifconf->ifc_len = target_ifc_len;
4940
4941 /* restore target ifc_buf */
4942
4943 host_ifconf->ifc_buf = (char *)(unsigned long)target_ifc_buf;
4944
4945 /* copy struct ifconf to target user */
4946
4947 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
4948 if (!argptr)
4949 return -TARGET_EFAULT;
4950 thunk_convert(argptr, host_ifconf, arg_type, THUNK_TARGET);
4951 unlock_user(argptr, arg, target_size);
4952
Kan Li22e4a2672018-10-24 20:13:03 +00004953 if (target_ifc_buf != 0) {
4954 /* copy ifreq[] to target user */
4955 argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0);
4956 for (i = 0; i < nb_ifreq ; i++) {
4957 thunk_convert(argptr + i * target_ifreq_size,
4958 host_ifc_buf + i * sizeof(struct ifreq),
4959 ifreq_arg_type, THUNK_TARGET);
4960 }
4961 unlock_user(argptr, target_ifc_buf, target_ifc_len);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004962 }
Laurent Vivier059c2f22011-03-30 00:12:12 +02004963 }
4964
4965 if (free_buf) {
Ahmed Abouzied7a5626a2022-01-04 16:38:41 +02004966 g_free(host_ifconf);
Laurent Vivier059c2f22011-03-30 00:12:12 +02004967 }
4968
4969 return ret;
4970}
4971
Cortland Tölvaa1333672018-10-08 09:35:21 -07004972#if defined(CONFIG_USBFS)
4973#if HOST_LONG_BITS > 64
4974#error USBDEVFS thunks do not support >64 bit hosts yet.
4975#endif
4976struct live_urb {
4977 uint64_t target_urb_adr;
4978 uint64_t target_buf_adr;
4979 char *target_buf_ptr;
4980 struct usbdevfs_urb host_urb;
4981};
4982
4983static GHashTable *usbdevfs_urb_hashtable(void)
4984{
4985 static GHashTable *urb_hashtable;
4986
4987 if (!urb_hashtable) {
4988 urb_hashtable = g_hash_table_new(g_int64_hash, g_int64_equal);
4989 }
4990 return urb_hashtable;
4991}
4992
4993static void urb_hashtable_insert(struct live_urb *urb)
4994{
4995 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
4996 g_hash_table_insert(urb_hashtable, urb, urb);
4997}
4998
4999static struct live_urb *urb_hashtable_lookup(uint64_t target_urb_adr)
5000{
5001 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
5002 return g_hash_table_lookup(urb_hashtable, &target_urb_adr);
5003}
5004
5005static void urb_hashtable_remove(struct live_urb *urb)
5006{
5007 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
5008 g_hash_table_remove(urb_hashtable, urb);
5009}
5010
5011static abi_long
5012do_ioctl_usbdevfs_reapurb(const IOCTLEntry *ie, uint8_t *buf_temp,
5013 int fd, int cmd, abi_long arg)
5014{
5015 const argtype usbfsurb_arg_type[] = { MK_STRUCT(STRUCT_usbdevfs_urb) };
5016 const argtype ptrvoid_arg_type[] = { TYPE_PTRVOID, 0, 0 };
5017 struct live_urb *lurb;
5018 void *argptr;
5019 uint64_t hurb;
5020 int target_size;
5021 uintptr_t target_urb_adr;
5022 abi_long ret;
5023
5024 target_size = thunk_type_size(usbfsurb_arg_type, THUNK_TARGET);
5025
5026 memset(buf_temp, 0, sizeof(uint64_t));
5027 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
5028 if (is_error(ret)) {
5029 return ret;
5030 }
5031
5032 memcpy(&hurb, buf_temp, sizeof(uint64_t));
5033 lurb = (void *)((uintptr_t)hurb - offsetof(struct live_urb, host_urb));
5034 if (!lurb->target_urb_adr) {
5035 return -TARGET_EFAULT;
5036 }
5037 urb_hashtable_remove(lurb);
5038 unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr,
5039 lurb->host_urb.buffer_length);
5040 lurb->target_buf_ptr = NULL;
5041
5042 /* restore the guest buffer pointer */
5043 lurb->host_urb.buffer = (void *)(uintptr_t)lurb->target_buf_adr;
5044
5045 /* update the guest urb struct */
5046 argptr = lock_user(VERIFY_WRITE, lurb->target_urb_adr, target_size, 0);
5047 if (!argptr) {
5048 g_free(lurb);
5049 return -TARGET_EFAULT;
5050 }
5051 thunk_convert(argptr, &lurb->host_urb, usbfsurb_arg_type, THUNK_TARGET);
5052 unlock_user(argptr, lurb->target_urb_adr, target_size);
5053
5054 target_size = thunk_type_size(ptrvoid_arg_type, THUNK_TARGET);
5055 /* write back the urb handle */
5056 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5057 if (!argptr) {
5058 g_free(lurb);
5059 return -TARGET_EFAULT;
5060 }
5061
5062 /* GHashTable uses 64-bit keys but thunk_convert expects uintptr_t */
5063 target_urb_adr = lurb->target_urb_adr;
5064 thunk_convert(argptr, &target_urb_adr, ptrvoid_arg_type, THUNK_TARGET);
5065 unlock_user(argptr, arg, target_size);
5066
5067 g_free(lurb);
5068 return ret;
5069}
5070
5071static abi_long
5072do_ioctl_usbdevfs_discardurb(const IOCTLEntry *ie,
5073 uint8_t *buf_temp __attribute__((unused)),
5074 int fd, int cmd, abi_long arg)
5075{
5076 struct live_urb *lurb;
5077
5078 /* map target address back to host URB with metadata. */
5079 lurb = urb_hashtable_lookup(arg);
5080 if (!lurb) {
5081 return -TARGET_EFAULT;
5082 }
5083 return get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
5084}
5085
5086static abi_long
5087do_ioctl_usbdevfs_submiturb(const IOCTLEntry *ie, uint8_t *buf_temp,
5088 int fd, int cmd, abi_long arg)
5089{
5090 const argtype *arg_type = ie->arg_type;
5091 int target_size;
5092 abi_long ret;
5093 void *argptr;
5094 int rw_dir;
5095 struct live_urb *lurb;
5096
5097 /*
5098 * each submitted URB needs to map to a unique ID for the
5099 * kernel, and that unique ID needs to be a pointer to
5100 * host memory. hence, we need to malloc for each URB.
5101 * isochronous transfers have a variable length struct.
5102 */
5103 arg_type++;
5104 target_size = thunk_type_size(arg_type, THUNK_TARGET);
5105
5106 /* construct host copy of urb and metadata */
Markus Armbrusterb21e2382022-03-15 15:41:56 +01005107 lurb = g_try_new0(struct live_urb, 1);
Cortland Tölvaa1333672018-10-08 09:35:21 -07005108 if (!lurb) {
5109 return -TARGET_ENOMEM;
5110 }
5111
5112 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5113 if (!argptr) {
5114 g_free(lurb);
5115 return -TARGET_EFAULT;
5116 }
5117 thunk_convert(&lurb->host_urb, argptr, arg_type, THUNK_HOST);
5118 unlock_user(argptr, arg, 0);
5119
5120 lurb->target_urb_adr = arg;
5121 lurb->target_buf_adr = (uintptr_t)lurb->host_urb.buffer;
5122
5123 /* buffer space used depends on endpoint type so lock the entire buffer */
5124 /* control type urbs should check the buffer contents for true direction */
5125 rw_dir = lurb->host_urb.endpoint & USB_DIR_IN ? VERIFY_WRITE : VERIFY_READ;
5126 lurb->target_buf_ptr = lock_user(rw_dir, lurb->target_buf_adr,
5127 lurb->host_urb.buffer_length, 1);
5128 if (lurb->target_buf_ptr == NULL) {
5129 g_free(lurb);
5130 return -TARGET_EFAULT;
5131 }
5132
5133 /* update buffer pointer in host copy */
5134 lurb->host_urb.buffer = lurb->target_buf_ptr;
5135
5136 ret = get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
5137 if (is_error(ret)) {
5138 unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr, 0);
5139 g_free(lurb);
5140 } else {
5141 urb_hashtable_insert(lurb);
5142 }
5143
5144 return ret;
5145}
5146#endif /* CONFIG_USBFS */
5147
Alexander Graf56e904e2012-01-31 18:42:06 +01005148static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
Laurent Vivier45c874e2015-06-16 00:35:28 +02005149 int cmd, abi_long arg)
Alexander Graf56e904e2012-01-31 18:42:06 +01005150{
5151 void *argptr;
5152 struct dm_ioctl *host_dm;
5153 abi_long guest_data;
5154 uint32_t guest_data_size;
5155 int target_size;
5156 const argtype *arg_type = ie->arg_type;
5157 abi_long ret;
5158 void *big_buf = NULL;
5159 char *host_data;
5160
5161 arg_type++;
5162 target_size = thunk_type_size(arg_type, 0);
5163 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5164 if (!argptr) {
5165 ret = -TARGET_EFAULT;
5166 goto out;
5167 }
5168 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5169 unlock_user(argptr, arg, 0);
5170
5171 /* buf_temp is too small, so fetch things into a bigger buffer */
5172 big_buf = g_malloc0(((struct dm_ioctl*)buf_temp)->data_size * 2);
5173 memcpy(big_buf, buf_temp, target_size);
5174 buf_temp = big_buf;
5175 host_dm = big_buf;
5176
5177 guest_data = arg + host_dm->data_start;
5178 if ((guest_data - arg) < 0) {
Peter Maydellf9757b12016-07-12 13:02:14 +01005179 ret = -TARGET_EINVAL;
Alexander Graf56e904e2012-01-31 18:42:06 +01005180 goto out;
5181 }
5182 guest_data_size = host_dm->data_size - host_dm->data_start;
5183 host_data = (char*)host_dm + host_dm->data_start;
5184
5185 argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1);
Peter Maydell32112152016-07-12 13:02:13 +01005186 if (!argptr) {
5187 ret = -TARGET_EFAULT;
5188 goto out;
5189 }
5190
Alexander Graf56e904e2012-01-31 18:42:06 +01005191 switch (ie->host_cmd) {
5192 case DM_REMOVE_ALL:
5193 case DM_LIST_DEVICES:
5194 case DM_DEV_CREATE:
5195 case DM_DEV_REMOVE:
5196 case DM_DEV_SUSPEND:
5197 case DM_DEV_STATUS:
5198 case DM_DEV_WAIT:
5199 case DM_TABLE_STATUS:
5200 case DM_TABLE_CLEAR:
5201 case DM_TABLE_DEPS:
5202 case DM_LIST_VERSIONS:
5203 /* no input data */
5204 break;
5205 case DM_DEV_RENAME:
5206 case DM_DEV_SET_GEOMETRY:
5207 /* data contains only strings */
5208 memcpy(host_data, argptr, guest_data_size);
5209 break;
5210 case DM_TARGET_MSG:
5211 memcpy(host_data, argptr, guest_data_size);
5212 *(uint64_t*)host_data = tswap64(*(uint64_t*)argptr);
5213 break;
5214 case DM_TABLE_LOAD:
5215 {
5216 void *gspec = argptr;
5217 void *cur_data = host_data;
5218 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
5219 int spec_size = thunk_type_size(arg_type, 0);
5220 int i;
5221
5222 for (i = 0; i < host_dm->target_count; i++) {
5223 struct dm_target_spec *spec = cur_data;
5224 uint32_t next;
5225 int slen;
5226
5227 thunk_convert(spec, gspec, arg_type, THUNK_HOST);
5228 slen = strlen((char*)gspec + spec_size) + 1;
5229 next = spec->next;
5230 spec->next = sizeof(*spec) + slen;
5231 strcpy((char*)&spec[1], gspec + spec_size);
5232 gspec += next;
5233 cur_data += spec->next;
5234 }
5235 break;
5236 }
5237 default:
5238 ret = -TARGET_EINVAL;
Chen Gang Sdec04732015-01-25 08:00:42 +08005239 unlock_user(argptr, guest_data, 0);
Alexander Graf56e904e2012-01-31 18:42:06 +01005240 goto out;
5241 }
5242 unlock_user(argptr, guest_data, 0);
5243
Peter Maydell49ca6f32016-06-06 19:58:14 +01005244 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
Alexander Graf56e904e2012-01-31 18:42:06 +01005245 if (!is_error(ret)) {
5246 guest_data = arg + host_dm->data_start;
5247 guest_data_size = host_dm->data_size - host_dm->data_start;
5248 argptr = lock_user(VERIFY_WRITE, guest_data, guest_data_size, 0);
5249 switch (ie->host_cmd) {
5250 case DM_REMOVE_ALL:
5251 case DM_DEV_CREATE:
5252 case DM_DEV_REMOVE:
5253 case DM_DEV_RENAME:
5254 case DM_DEV_SUSPEND:
5255 case DM_DEV_STATUS:
5256 case DM_TABLE_LOAD:
5257 case DM_TABLE_CLEAR:
5258 case DM_TARGET_MSG:
5259 case DM_DEV_SET_GEOMETRY:
5260 /* no return data */
5261 break;
5262 case DM_LIST_DEVICES:
5263 {
5264 struct dm_name_list *nl = (void*)host_dm + host_dm->data_start;
5265 uint32_t remaining_data = guest_data_size;
5266 void *cur_data = argptr;
5267 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
5268 int nl_size = 12; /* can't use thunk_size due to alignment */
5269
5270 while (1) {
5271 uint32_t next = nl->next;
5272 if (next) {
5273 nl->next = nl_size + (strlen(nl->name) + 1);
5274 }
5275 if (remaining_data < nl->next) {
5276 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5277 break;
5278 }
5279 thunk_convert(cur_data, nl, arg_type, THUNK_TARGET);
5280 strcpy(cur_data + nl_size, nl->name);
5281 cur_data += nl->next;
5282 remaining_data -= nl->next;
5283 if (!next) {
5284 break;
5285 }
5286 nl = (void*)nl + next;
5287 }
5288 break;
5289 }
5290 case DM_DEV_WAIT:
5291 case DM_TABLE_STATUS:
5292 {
5293 struct dm_target_spec *spec = (void*)host_dm + host_dm->data_start;
5294 void *cur_data = argptr;
5295 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
5296 int spec_size = thunk_type_size(arg_type, 0);
5297 int i;
5298
5299 for (i = 0; i < host_dm->target_count; i++) {
5300 uint32_t next = spec->next;
5301 int slen = strlen((char*)&spec[1]) + 1;
5302 spec->next = (cur_data - argptr) + spec_size + slen;
5303 if (guest_data_size < spec->next) {
5304 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5305 break;
5306 }
5307 thunk_convert(cur_data, spec, arg_type, THUNK_TARGET);
5308 strcpy(cur_data + spec_size, (char*)&spec[1]);
5309 cur_data = argptr + spec->next;
5310 spec = (void*)host_dm + host_dm->data_start + next;
5311 }
5312 break;
5313 }
5314 case DM_TABLE_DEPS:
5315 {
5316 void *hdata = (void*)host_dm + host_dm->data_start;
5317 int count = *(uint32_t*)hdata;
5318 uint64_t *hdev = hdata + 8;
5319 uint64_t *gdev = argptr + 8;
5320 int i;
5321
5322 *(uint32_t*)argptr = tswap32(count);
5323 for (i = 0; i < count; i++) {
5324 *gdev = tswap64(*hdev);
5325 gdev++;
5326 hdev++;
5327 }
5328 break;
5329 }
5330 case DM_LIST_VERSIONS:
5331 {
5332 struct dm_target_versions *vers = (void*)host_dm + host_dm->data_start;
5333 uint32_t remaining_data = guest_data_size;
5334 void *cur_data = argptr;
5335 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_versions) };
5336 int vers_size = thunk_type_size(arg_type, 0);
5337
5338 while (1) {
5339 uint32_t next = vers->next;
5340 if (next) {
5341 vers->next = vers_size + (strlen(vers->name) + 1);
5342 }
5343 if (remaining_data < vers->next) {
5344 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5345 break;
5346 }
5347 thunk_convert(cur_data, vers, arg_type, THUNK_TARGET);
5348 strcpy(cur_data + vers_size, vers->name);
5349 cur_data += vers->next;
5350 remaining_data -= vers->next;
5351 if (!next) {
5352 break;
5353 }
5354 vers = (void*)vers + next;
5355 }
5356 break;
5357 }
5358 default:
Chen Gang Sdec04732015-01-25 08:00:42 +08005359 unlock_user(argptr, guest_data, 0);
Alexander Graf56e904e2012-01-31 18:42:06 +01005360 ret = -TARGET_EINVAL;
5361 goto out;
5362 }
5363 unlock_user(argptr, guest_data, guest_data_size);
5364
5365 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5366 if (!argptr) {
5367 ret = -TARGET_EFAULT;
5368 goto out;
5369 }
5370 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5371 unlock_user(argptr, arg, target_size);
5372 }
5373out:
Stefan Weilad11ad72012-09-04 22:14:19 +02005374 g_free(big_buf);
Alexander Graf56e904e2012-01-31 18:42:06 +01005375 return ret;
5376}
5377
Alexander Grafa59b5e32014-08-22 13:15:50 +02005378static abi_long do_ioctl_blkpg(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
Laurent Vivier45c874e2015-06-16 00:35:28 +02005379 int cmd, abi_long arg)
Alexander Grafa59b5e32014-08-22 13:15:50 +02005380{
5381 void *argptr;
5382 int target_size;
5383 const argtype *arg_type = ie->arg_type;
5384 const argtype part_arg_type[] = { MK_STRUCT(STRUCT_blkpg_partition) };
5385 abi_long ret;
5386
5387 struct blkpg_ioctl_arg *host_blkpg = (void*)buf_temp;
5388 struct blkpg_partition host_part;
5389
5390 /* Read and convert blkpg */
5391 arg_type++;
5392 target_size = thunk_type_size(arg_type, 0);
5393 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5394 if (!argptr) {
5395 ret = -TARGET_EFAULT;
5396 goto out;
5397 }
5398 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5399 unlock_user(argptr, arg, 0);
5400
5401 switch (host_blkpg->op) {
5402 case BLKPG_ADD_PARTITION:
5403 case BLKPG_DEL_PARTITION:
5404 /* payload is struct blkpg_partition */
5405 break;
5406 default:
5407 /* Unknown opcode */
5408 ret = -TARGET_EINVAL;
5409 goto out;
5410 }
5411
5412 /* Read and convert blkpg->data */
5413 arg = (abi_long)(uintptr_t)host_blkpg->data;
5414 target_size = thunk_type_size(part_arg_type, 0);
5415 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5416 if (!argptr) {
5417 ret = -TARGET_EFAULT;
5418 goto out;
5419 }
5420 thunk_convert(&host_part, argptr, part_arg_type, THUNK_HOST);
5421 unlock_user(argptr, arg, 0);
5422
5423 /* Swizzle the data pointer to our local copy and call! */
5424 host_blkpg->data = &host_part;
Peter Maydell49ca6f32016-06-06 19:58:14 +01005425 ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_blkpg));
Alexander Grafa59b5e32014-08-22 13:15:50 +02005426
5427out:
5428 return ret;
5429}
5430
Laurent Vivier7ff7b662013-07-02 14:04:12 +01005431static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02005432 int fd, int cmd, abi_long arg)
Laurent Vivier7ff7b662013-07-02 14:04:12 +01005433{
5434 const argtype *arg_type = ie->arg_type;
5435 const StructEntry *se;
5436 const argtype *field_types;
5437 const int *dst_offsets, *src_offsets;
5438 int target_size;
5439 void *argptr;
Marc-André Lureaub78c5222019-03-05 16:15:00 +01005440 abi_ulong *target_rt_dev_ptr = NULL;
5441 unsigned long *host_rt_dev_ptr = NULL;
Laurent Vivier7ff7b662013-07-02 14:04:12 +01005442 abi_long ret;
5443 int i;
5444
5445 assert(ie->access == IOC_W);
5446 assert(*arg_type == TYPE_PTR);
5447 arg_type++;
5448 assert(*arg_type == TYPE_STRUCT);
5449 target_size = thunk_type_size(arg_type, 0);
5450 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5451 if (!argptr) {
5452 return -TARGET_EFAULT;
5453 }
5454 arg_type++;
5455 assert(*arg_type == (int)STRUCT_rtentry);
5456 se = struct_entries + *arg_type++;
5457 assert(se->convert[0] == NULL);
5458 /* convert struct here to be able to catch rt_dev string */
5459 field_types = se->field_types;
5460 dst_offsets = se->field_offsets[THUNK_HOST];
5461 src_offsets = se->field_offsets[THUNK_TARGET];
5462 for (i = 0; i < se->nb_fields; i++) {
5463 if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) {
5464 assert(*field_types == TYPE_PTRVOID);
5465 target_rt_dev_ptr = (abi_ulong *)(argptr + src_offsets[i]);
5466 host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]);
5467 if (*target_rt_dev_ptr != 0) {
5468 *host_rt_dev_ptr = (unsigned long)lock_user_string(
5469 tswapal(*target_rt_dev_ptr));
5470 if (!*host_rt_dev_ptr) {
5471 unlock_user(argptr, arg, 0);
5472 return -TARGET_EFAULT;
5473 }
5474 } else {
5475 *host_rt_dev_ptr = 0;
5476 }
5477 field_types++;
5478 continue;
5479 }
5480 field_types = thunk_convert(buf_temp + dst_offsets[i],
5481 argptr + src_offsets[i],
5482 field_types, THUNK_HOST);
5483 }
5484 unlock_user(argptr, arg, 0);
5485
Peter Maydell49ca6f32016-06-06 19:58:14 +01005486 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
Marc-André Lureaub78c5222019-03-05 16:15:00 +01005487
5488 assert(host_rt_dev_ptr != NULL);
5489 assert(target_rt_dev_ptr != NULL);
Laurent Vivier7ff7b662013-07-02 14:04:12 +01005490 if (*host_rt_dev_ptr != 0) {
5491 unlock_user((void *)*host_rt_dev_ptr,
5492 *target_rt_dev_ptr, 0);
5493 }
5494 return ret;
5495}
5496
Paul Burtonca56f5b2014-06-22 11:25:47 +01005497static abi_long do_ioctl_kdsigaccept(const IOCTLEntry *ie, uint8_t *buf_temp,
Laurent Vivier45c874e2015-06-16 00:35:28 +02005498 int fd, int cmd, abi_long arg)
Paul Burtonca56f5b2014-06-22 11:25:47 +01005499{
5500 int sig = target_to_host_signal(arg);
Peter Maydell49ca6f32016-06-06 19:58:14 +01005501 return get_errno(safe_ioctl(fd, ie->host_cmd, sig));
Paul Burtonca56f5b2014-06-22 11:25:47 +01005502}
5503
Daniel P. Berrangé6d5d5dd2019-07-18 15:06:41 +02005504static abi_long do_ioctl_SIOCGSTAMP(const IOCTLEntry *ie, uint8_t *buf_temp,
5505 int fd, int cmd, abi_long arg)
5506{
5507 struct timeval tv;
5508 abi_long ret;
5509
5510 ret = get_errno(safe_ioctl(fd, SIOCGSTAMP, &tv));
5511 if (is_error(ret)) {
5512 return ret;
5513 }
5514
5515 if (cmd == (int)TARGET_SIOCGSTAMP_OLD) {
5516 if (copy_to_user_timeval(arg, &tv)) {
5517 return -TARGET_EFAULT;
5518 }
5519 } else {
5520 if (copy_to_user_timeval64(arg, &tv)) {
5521 return -TARGET_EFAULT;
5522 }
5523 }
5524
5525 return ret;
5526}
5527
5528static abi_long do_ioctl_SIOCGSTAMPNS(const IOCTLEntry *ie, uint8_t *buf_temp,
5529 int fd, int cmd, abi_long arg)
5530{
5531 struct timespec ts;
5532 abi_long ret;
5533
5534 ret = get_errno(safe_ioctl(fd, SIOCGSTAMPNS, &ts));
5535 if (is_error(ret)) {
5536 return ret;
5537 }
5538
5539 if (cmd == (int)TARGET_SIOCGSTAMPNS_OLD) {
5540 if (host_to_target_timespec(arg, &ts)) {
5541 return -TARGET_EFAULT;
5542 }
5543 } else{
5544 if (host_to_target_timespec64(arg, &ts)) {
5545 return -TARGET_EFAULT;
5546 }
5547 }
5548
5549 return ret;
5550}
5551
Andreas Schwab2b74f622018-01-29 11:47:06 +01005552#ifdef TIOCGPTPEER
5553static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry *ie, uint8_t *buf_temp,
5554 int fd, int cmd, abi_long arg)
5555{
5556 int flags = target_to_host_bitmask(arg, fcntl_flags_tbl);
5557 return get_errno(safe_ioctl(fd, ie->host_cmd, flags));
5558}
5559#endif
5560
Chen Gange865b972020-06-05 09:32:21 +08005561#ifdef HAVE_DRM_H
5562
5563static void unlock_drm_version(struct drm_version *host_ver,
5564 struct target_drm_version *target_ver,
5565 bool copy)
5566{
5567 unlock_user(host_ver->name, target_ver->name,
5568 copy ? host_ver->name_len : 0);
5569 unlock_user(host_ver->date, target_ver->date,
5570 copy ? host_ver->date_len : 0);
5571 unlock_user(host_ver->desc, target_ver->desc,
5572 copy ? host_ver->desc_len : 0);
5573}
5574
5575static inline abi_long target_to_host_drmversion(struct drm_version *host_ver,
5576 struct target_drm_version *target_ver)
5577{
5578 memset(host_ver, 0, sizeof(*host_ver));
5579
5580 __get_user(host_ver->name_len, &target_ver->name_len);
5581 if (host_ver->name_len) {
5582 host_ver->name = lock_user(VERIFY_WRITE, target_ver->name,
5583 target_ver->name_len, 0);
5584 if (!host_ver->name) {
5585 return -EFAULT;
5586 }
5587 }
5588
5589 __get_user(host_ver->date_len, &target_ver->date_len);
5590 if (host_ver->date_len) {
5591 host_ver->date = lock_user(VERIFY_WRITE, target_ver->date,
5592 target_ver->date_len, 0);
5593 if (!host_ver->date) {
5594 goto err;
5595 }
5596 }
5597
5598 __get_user(host_ver->desc_len, &target_ver->desc_len);
5599 if (host_ver->desc_len) {
5600 host_ver->desc = lock_user(VERIFY_WRITE, target_ver->desc,
5601 target_ver->desc_len, 0);
5602 if (!host_ver->desc) {
5603 goto err;
5604 }
5605 }
5606
5607 return 0;
5608err:
5609 unlock_drm_version(host_ver, target_ver, false);
5610 return -EFAULT;
5611}
5612
5613static inline void host_to_target_drmversion(
5614 struct target_drm_version *target_ver,
5615 struct drm_version *host_ver)
5616{
5617 __put_user(host_ver->version_major, &target_ver->version_major);
5618 __put_user(host_ver->version_minor, &target_ver->version_minor);
5619 __put_user(host_ver->version_patchlevel, &target_ver->version_patchlevel);
5620 __put_user(host_ver->name_len, &target_ver->name_len);
5621 __put_user(host_ver->date_len, &target_ver->date_len);
5622 __put_user(host_ver->desc_len, &target_ver->desc_len);
5623 unlock_drm_version(host_ver, target_ver, true);
5624}
5625
5626static abi_long do_ioctl_drm(const IOCTLEntry *ie, uint8_t *buf_temp,
5627 int fd, int cmd, abi_long arg)
5628{
5629 struct drm_version *ver;
5630 struct target_drm_version *target_ver;
5631 abi_long ret;
5632
5633 switch (ie->host_cmd) {
5634 case DRM_IOCTL_VERSION:
5635 if (!lock_user_struct(VERIFY_WRITE, target_ver, arg, 0)) {
5636 return -TARGET_EFAULT;
5637 }
5638 ver = (struct drm_version *)buf_temp;
5639 ret = target_to_host_drmversion(ver, target_ver);
5640 if (!is_error(ret)) {
5641 ret = get_errno(safe_ioctl(fd, ie->host_cmd, ver));
5642 if (is_error(ret)) {
5643 unlock_drm_version(ver, target_ver, false);
5644 } else {
5645 host_to_target_drmversion(target_ver, ver);
5646 }
5647 }
5648 unlock_user_struct(target_ver, arg, 0);
5649 return ret;
5650 }
5651 return -TARGET_ENOSYS;
5652}
5653
Chen Gang913b03c2020-08-02 21:39:38 +08005654static abi_long do_ioctl_drm_i915_getparam(const IOCTLEntry *ie,
5655 struct drm_i915_getparam *gparam,
5656 int fd, abi_long arg)
5657{
5658 abi_long ret;
5659 int value;
5660 struct target_drm_i915_getparam *target_gparam;
5661
5662 if (!lock_user_struct(VERIFY_READ, target_gparam, arg, 0)) {
5663 return -TARGET_EFAULT;
5664 }
5665
5666 __get_user(gparam->param, &target_gparam->param);
5667 gparam->value = &value;
5668 ret = get_errno(safe_ioctl(fd, ie->host_cmd, gparam));
5669 put_user_s32(value, target_gparam->value);
5670
5671 unlock_user_struct(target_gparam, arg, 0);
5672 return ret;
5673}
5674
5675static abi_long do_ioctl_drm_i915(const IOCTLEntry *ie, uint8_t *buf_temp,
5676 int fd, int cmd, abi_long arg)
5677{
5678 switch (ie->host_cmd) {
5679 case DRM_IOCTL_I915_GETPARAM:
5680 return do_ioctl_drm_i915_getparam(ie,
5681 (struct drm_i915_getparam *)buf_temp,
5682 fd, arg);
5683 default:
5684 return -TARGET_ENOSYS;
5685 }
5686}
5687
Chen Gange865b972020-06-05 09:32:21 +08005688#endif
5689
Shu-Chun Weng6addf062020-09-28 18:48:01 -07005690static abi_long do_ioctl_TUNSETTXFILTER(const IOCTLEntry *ie, uint8_t *buf_temp,
5691 int fd, int cmd, abi_long arg)
5692{
5693 struct tun_filter *filter = (struct tun_filter *)buf_temp;
5694 struct tun_filter *target_filter;
5695 char *target_addr;
5696
5697 assert(ie->access == IOC_W);
5698
5699 target_filter = lock_user(VERIFY_READ, arg, sizeof(*target_filter), 1);
5700 if (!target_filter) {
5701 return -TARGET_EFAULT;
5702 }
5703 filter->flags = tswap16(target_filter->flags);
5704 filter->count = tswap16(target_filter->count);
5705 unlock_user(target_filter, arg, 0);
5706
5707 if (filter->count) {
5708 if (offsetof(struct tun_filter, addr) + filter->count * ETH_ALEN >
5709 MAX_STRUCT_SIZE) {
5710 return -TARGET_EFAULT;
5711 }
5712
5713 target_addr = lock_user(VERIFY_READ,
5714 arg + offsetof(struct tun_filter, addr),
5715 filter->count * ETH_ALEN, 1);
5716 if (!target_addr) {
5717 return -TARGET_EFAULT;
5718 }
5719 memcpy(filter->addr, target_addr, filter->count * ETH_ALEN);
5720 unlock_user(target_addr, arg + offsetof(struct tun_filter, addr), 0);
5721 }
5722
5723 return get_errno(safe_ioctl(fd, ie->host_cmd, filter));
5724}
5725
Filip Bozuta79482e592020-06-19 14:47:27 +02005726IOCTLEntry ioctl_entries[] = {
Blue Swirl001faf32009-05-13 17:53:17 +00005727#define IOCTL(cmd, access, ...) \
Peter Maydelld2ef05b2011-01-06 15:04:17 +00005728 { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
5729#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
5730 { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
Helge Deller8cb762f2016-12-06 16:24:03 +01005731#define IOCTL_IGNORE(cmd) \
5732 { TARGET_ ## cmd, 0, #cmd },
bellard31e31b82003-02-18 22:55:36 +00005733#include "ioctls.h"
5734 { 0, 0, },
5735};
5736
pbrook53a59602006-03-25 19:31:22 +00005737/* ??? Implement proper locking for ioctls. */
ths0da46a62007-10-20 20:23:07 +00005738/* do_ioctl() Must return target values and target errnos. */
Laurent Vivier45c874e2015-06-16 00:35:28 +02005739static abi_long do_ioctl(int fd, int cmd, abi_long arg)
bellard31e31b82003-02-18 22:55:36 +00005740{
5741 const IOCTLEntry *ie;
5742 const argtype *arg_type;
blueswir1992f48a2007-10-14 16:27:31 +00005743 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00005744 uint8_t buf_temp[MAX_STRUCT_SIZE];
pbrook53a59602006-03-25 19:31:22 +00005745 int target_size;
5746 void *argptr;
bellard31e31b82003-02-18 22:55:36 +00005747
5748 ie = ioctl_entries;
5749 for(;;) {
5750 if (ie->target_cmd == 0) {
Josh Kunz39be5352020-02-03 18:54:13 -08005751 qemu_log_mask(
5752 LOG_UNIMP, "Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
ths0da46a62007-10-20 20:23:07 +00005753 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00005754 }
5755 if (ie->target_cmd == cmd)
5756 break;
5757 ie++;
5758 }
5759 arg_type = ie->arg_type;
Peter Maydelld2ef05b2011-01-06 15:04:17 +00005760 if (ie->do_ioctl) {
5761 return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
Helge Deller8cb762f2016-12-06 16:24:03 +01005762 } else if (!ie->host_cmd) {
5763 /* Some architectures define BSD ioctls in their headers
5764 that are not implemented in Linux. */
5765 return -TARGET_ENOSYS;
Peter Maydelld2ef05b2011-01-06 15:04:17 +00005766 }
5767
bellard31e31b82003-02-18 22:55:36 +00005768 switch(arg_type[0]) {
5769 case TYPE_NULL:
5770 /* no argument */
Peter Maydell49ca6f32016-06-06 19:58:14 +01005771 ret = get_errno(safe_ioctl(fd, ie->host_cmd));
bellard31e31b82003-02-18 22:55:36 +00005772 break;
5773 case TYPE_PTRVOID:
5774 case TYPE_INT:
Filip Bozutac858e532020-01-15 20:36:47 +01005775 case TYPE_LONG:
5776 case TYPE_ULONG:
Peter Maydell49ca6f32016-06-06 19:58:14 +01005777 ret = get_errno(safe_ioctl(fd, ie->host_cmd, arg));
bellard31e31b82003-02-18 22:55:36 +00005778 break;
5779 case TYPE_PTR:
5780 arg_type++;
pbrook53a59602006-03-25 19:31:22 +00005781 target_size = thunk_type_size(arg_type, 0);
bellard31e31b82003-02-18 22:55:36 +00005782 switch(ie->access) {
5783 case IOC_R:
Peter Maydell49ca6f32016-06-06 19:58:14 +01005784 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
bellard31e31b82003-02-18 22:55:36 +00005785 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005786 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5787 if (!argptr)
5788 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005789 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5790 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00005791 }
5792 break;
5793 case IOC_W:
bellard579a97f2007-11-11 14:26:47 +00005794 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5795 if (!argptr)
5796 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005797 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5798 unlock_user(argptr, arg, 0);
Peter Maydell49ca6f32016-06-06 19:58:14 +01005799 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
bellard31e31b82003-02-18 22:55:36 +00005800 break;
5801 default:
5802 case IOC_RW:
bellard579a97f2007-11-11 14:26:47 +00005803 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5804 if (!argptr)
5805 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005806 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5807 unlock_user(argptr, arg, 0);
Peter Maydell49ca6f32016-06-06 19:58:14 +01005808 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
bellard31e31b82003-02-18 22:55:36 +00005809 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005810 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5811 if (!argptr)
5812 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00005813 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5814 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00005815 }
5816 break;
5817 }
5818 break;
5819 default:
Josh Kunz39be5352020-02-03 18:54:13 -08005820 qemu_log_mask(LOG_UNIMP,
5821 "Unsupported ioctl type: cmd=0x%04lx type=%d\n",
5822 (long)cmd, arg_type[0]);
ths0da46a62007-10-20 20:23:07 +00005823 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00005824 break;
5825 }
5826 return ret;
5827}
5828
blueswir1b39bc502008-10-05 10:51:10 +00005829static const bitmask_transtbl iflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00005830 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
5831 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
5832 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
5833 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
5834 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
5835 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
5836 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
5837 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
5838 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
5839 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
5840 { TARGET_IXON, TARGET_IXON, IXON, IXON },
5841 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
5842 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
5843 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
Filip Bozutac218b4e2020-07-23 23:02:32 +02005844 { TARGET_IUTF8, TARGET_IUTF8, IUTF8, IUTF8},
bellard31e31b82003-02-18 22:55:36 +00005845 { 0, 0, 0, 0 }
5846};
5847
blueswir1b39bc502008-10-05 10:51:10 +00005848static const bitmask_transtbl oflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00005849 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
5850 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
5851 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
5852 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
5853 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
5854 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
5855 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
5856 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
5857 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
5858 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
5859 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
5860 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
5861 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
5862 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
5863 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
5864 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
5865 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
5866 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
5867 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
5868 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
5869 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
5870 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
5871 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
5872 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
5873 { 0, 0, 0, 0 }
5874};
5875
blueswir1b39bc502008-10-05 10:51:10 +00005876static const bitmask_transtbl cflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00005877 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
5878 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
5879 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
5880 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
5881 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
5882 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
5883 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
5884 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
5885 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
5886 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
5887 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
5888 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
5889 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
5890 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
5891 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
5892 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
5893 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
5894 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
5895 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
5896 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
5897 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
5898 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
5899 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
5900 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
5901 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
5902 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
5903 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
5904 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
5905 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
5906 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
5907 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
5908 { 0, 0, 0, 0 }
5909};
5910
blueswir1b39bc502008-10-05 10:51:10 +00005911static const bitmask_transtbl lflag_tbl[] = {
Filip Bozutac218b4e2020-07-23 23:02:32 +02005912 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
5913 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
5914 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
5915 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
5916 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
5917 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
5918 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
5919 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
5920 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
5921 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
5922 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
5923 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
5924 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
5925 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
5926 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
5927 { TARGET_EXTPROC, TARGET_EXTPROC, EXTPROC, EXTPROC},
5928 { 0, 0, 0, 0 }
bellard31e31b82003-02-18 22:55:36 +00005929};
5930
5931static void target_to_host_termios (void *dst, const void *src)
5932{
5933 struct host_termios *host = dst;
5934 const struct target_termios *target = src;
ths3b46e622007-09-17 08:09:54 +00005935
ths5fafdf22007-09-16 21:08:06 +00005936 host->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00005937 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00005938 host->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00005939 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00005940 host->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00005941 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00005942 host->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00005943 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
5944 host->c_line = target->c_line;
ths3b46e622007-09-17 08:09:54 +00005945
Arnaud Patard44607122009-04-21 17:39:08 +03005946 memset(host->c_cc, 0, sizeof(host->c_cc));
ths5fafdf22007-09-16 21:08:06 +00005947 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
5948 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
ths3b46e622007-09-17 08:09:54 +00005949 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
ths5fafdf22007-09-16 21:08:06 +00005950 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
ths3b46e622007-09-17 08:09:54 +00005951 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
ths5fafdf22007-09-16 21:08:06 +00005952 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
ths3b46e622007-09-17 08:09:54 +00005953 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
ths5fafdf22007-09-16 21:08:06 +00005954 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
ths3b46e622007-09-17 08:09:54 +00005955 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
ths5fafdf22007-09-16 21:08:06 +00005956 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
5957 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
ths3b46e622007-09-17 08:09:54 +00005958 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
5959 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
5960 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
5961 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
5962 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
ths5fafdf22007-09-16 21:08:06 +00005963 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
bellard31e31b82003-02-18 22:55:36 +00005964}
ths3b46e622007-09-17 08:09:54 +00005965
bellard31e31b82003-02-18 22:55:36 +00005966static void host_to_target_termios (void *dst, const void *src)
5967{
5968 struct target_termios *target = dst;
5969 const struct host_termios *host = src;
5970
ths5fafdf22007-09-16 21:08:06 +00005971 target->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00005972 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00005973 target->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00005974 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00005975 target->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00005976 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00005977 target->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00005978 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
5979 target->c_line = host->c_line;
ths3b46e622007-09-17 08:09:54 +00005980
Arnaud Patard44607122009-04-21 17:39:08 +03005981 memset(target->c_cc, 0, sizeof(target->c_cc));
bellard31e31b82003-02-18 22:55:36 +00005982 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
5983 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
5984 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
5985 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
5986 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
5987 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
5988 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
5989 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
5990 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
5991 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
5992 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
5993 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
5994 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
5995 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
5996 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
5997 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
5998 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
5999}
6000
blueswir18e853dc2008-10-05 10:49:32 +00006001static const StructEntry struct_termios_def = {
bellard31e31b82003-02-18 22:55:36 +00006002 .convert = { host_to_target_termios, target_to_host_termios },
6003 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
6004 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
Filip Bozuta888468d2020-07-23 23:02:33 +02006005 .print = print_termios,
bellard31e31b82003-02-18 22:55:36 +00006006};
6007
Philippe Mathieu-Daudé180d4ef2021-05-17 07:52:43 +02006008static const bitmask_transtbl mmap_flags_tbl[] = {
Helge Deller541e1692017-10-31 13:53:58 +01006009 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
6010 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
6011 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
6012 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS,
6013 MAP_ANONYMOUS, MAP_ANONYMOUS },
6014 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN,
6015 MAP_GROWSDOWN, MAP_GROWSDOWN },
6016 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE,
6017 MAP_DENYWRITE, MAP_DENYWRITE },
6018 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE,
6019 MAP_EXECUTABLE, MAP_EXECUTABLE },
6020 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
6021 { TARGET_MAP_NORESERVE, TARGET_MAP_NORESERVE,
6022 MAP_NORESERVE, MAP_NORESERVE },
6023 { TARGET_MAP_HUGETLB, TARGET_MAP_HUGETLB, MAP_HUGETLB, MAP_HUGETLB },
6024 /* MAP_STACK had been ignored by the kernel for quite some time.
6025 Recognize it for the target insofar as we do not want to pass
6026 it through to the host. */
6027 { TARGET_MAP_STACK, TARGET_MAP_STACK, 0, 0 },
6028 { 0, 0, 0, 0 }
bellard5286db72003-06-05 00:57:30 +00006029};
6030
Laurent Vivier9d12f792020-03-10 11:33:55 +01006031/*
6032 * NOTE: TARGET_ABI32 is defined for TARGET_I386 (but not for TARGET_X86_64)
6033 * TARGET_I386 is defined if TARGET_X86_64 is defined
6034 */
bellard2ab83ea2003-06-15 19:56:46 +00006035#if defined(TARGET_I386)
bellard6dbad632003-03-16 18:05:05 +00006036
6037/* NOTE: there is really one LDT for all the threads */
blueswir1b1d8e522008-10-26 13:43:07 +00006038static uint8_t *ldt_table;
bellard6dbad632003-03-16 18:05:05 +00006039
bellard03acab62007-11-11 14:57:14 +00006040static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00006041{
6042 int size;
pbrook53a59602006-03-25 19:31:22 +00006043 void *p;
bellard6dbad632003-03-16 18:05:05 +00006044
6045 if (!ldt_table)
6046 return 0;
6047 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
6048 if (size > bytecount)
6049 size = bytecount;
bellard579a97f2007-11-11 14:26:47 +00006050 p = lock_user(VERIFY_WRITE, ptr, size, 0);
6051 if (!p)
bellard03acab62007-11-11 14:57:14 +00006052 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00006053 /* ??? Should this by byteswapped? */
pbrook53a59602006-03-25 19:31:22 +00006054 memcpy(p, ldt_table, size);
6055 unlock_user(p, ptr, size);
bellard6dbad632003-03-16 18:05:05 +00006056 return size;
6057}
6058
6059/* XXX: add locking support */
bellard03acab62007-11-11 14:57:14 +00006060static abi_long write_ldt(CPUX86State *env,
6061 abi_ulong ptr, unsigned long bytecount, int oldmode)
bellard6dbad632003-03-16 18:05:05 +00006062{
6063 struct target_modify_ldt_ldt_s ldt_info;
pbrook53a59602006-03-25 19:31:22 +00006064 struct target_modify_ldt_ldt_s *target_ldt_info;
bellard6dbad632003-03-16 18:05:05 +00006065 int seg_32bit, contents, read_exec_only, limit_in_pages;
bellard8d18e892007-11-14 15:18:40 +00006066 int seg_not_present, useable, lm;
bellard6dbad632003-03-16 18:05:05 +00006067 uint32_t *lp, entry_1, entry_2;
6068
6069 if (bytecount != sizeof(ldt_info))
bellard03acab62007-11-11 14:57:14 +00006070 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +00006071 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
bellard03acab62007-11-11 14:57:14 +00006072 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00006073 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02006074 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
pbrook53a59602006-03-25 19:31:22 +00006075 ldt_info.limit = tswap32(target_ldt_info->limit);
6076 ldt_info.flags = tswap32(target_ldt_info->flags);
6077 unlock_user_struct(target_ldt_info, ptr, 0);
ths3b46e622007-09-17 08:09:54 +00006078
bellard6dbad632003-03-16 18:05:05 +00006079 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
bellard03acab62007-11-11 14:57:14 +00006080 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00006081 seg_32bit = ldt_info.flags & 1;
6082 contents = (ldt_info.flags >> 1) & 3;
6083 read_exec_only = (ldt_info.flags >> 3) & 1;
6084 limit_in_pages = (ldt_info.flags >> 4) & 1;
6085 seg_not_present = (ldt_info.flags >> 5) & 1;
6086 useable = (ldt_info.flags >> 6) & 1;
bellard8d18e892007-11-14 15:18:40 +00006087#ifdef TARGET_ABI32
6088 lm = 0;
6089#else
6090 lm = (ldt_info.flags >> 7) & 1;
6091#endif
bellard6dbad632003-03-16 18:05:05 +00006092 if (contents == 3) {
6093 if (oldmode)
bellard03acab62007-11-11 14:57:14 +00006094 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00006095 if (seg_not_present == 0)
bellard03acab62007-11-11 14:57:14 +00006096 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00006097 }
6098 /* allocate the LDT */
6099 if (!ldt_table) {
balroge4415702008-11-10 02:55:33 +00006100 env->ldt.base = target_mmap(0,
6101 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
6102 PROT_READ|PROT_WRITE,
6103 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
6104 if (env->ldt.base == -1)
bellard03acab62007-11-11 14:57:14 +00006105 return -TARGET_ENOMEM;
Richard Henderson3e8f1622021-02-12 10:48:43 -08006106 memset(g2h_untagged(env->ldt.base), 0,
balroge4415702008-11-10 02:55:33 +00006107 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
bellard6dbad632003-03-16 18:05:05 +00006108 env->ldt.limit = 0xffff;
Richard Henderson3e8f1622021-02-12 10:48:43 -08006109 ldt_table = g2h_untagged(env->ldt.base);
bellard6dbad632003-03-16 18:05:05 +00006110 }
6111
6112 /* NOTE: same code as Linux kernel */
6113 /* Allow LDTs to be cleared by the user. */
6114 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
6115 if (oldmode ||
6116 (contents == 0 &&
6117 read_exec_only == 1 &&
6118 seg_32bit == 0 &&
6119 limit_in_pages == 0 &&
6120 seg_not_present == 1 &&
6121 useable == 0 )) {
6122 entry_1 = 0;
6123 entry_2 = 0;
6124 goto install;
6125 }
6126 }
ths3b46e622007-09-17 08:09:54 +00006127
bellard6dbad632003-03-16 18:05:05 +00006128 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
6129 (ldt_info.limit & 0x0ffff);
6130 entry_2 = (ldt_info.base_addr & 0xff000000) |
6131 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
6132 (ldt_info.limit & 0xf0000) |
6133 ((read_exec_only ^ 1) << 9) |
6134 (contents << 10) |
6135 ((seg_not_present ^ 1) << 15) |
6136 (seg_32bit << 22) |
6137 (limit_in_pages << 23) |
bellard8d18e892007-11-14 15:18:40 +00006138 (lm << 21) |
bellard6dbad632003-03-16 18:05:05 +00006139 0x7000;
6140 if (!oldmode)
6141 entry_2 |= (useable << 20);
bellard14ae3ba2003-05-27 23:25:06 +00006142
bellard6dbad632003-03-16 18:05:05 +00006143 /* Install the new entry ... */
6144install:
6145 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
6146 lp[0] = tswap32(entry_1);
6147 lp[1] = tswap32(entry_2);
6148 return 0;
6149}
6150
6151/* specific and weird i386 syscalls */
blueswir18fcd3692008-08-17 20:26:25 +00006152static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
6153 unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00006154{
bellard03acab62007-11-11 14:57:14 +00006155 abi_long ret;
ths3b46e622007-09-17 08:09:54 +00006156
bellard6dbad632003-03-16 18:05:05 +00006157 switch (func) {
6158 case 0:
6159 ret = read_ldt(ptr, bytecount);
6160 break;
6161 case 1:
6162 ret = write_ldt(env, ptr, bytecount, 1);
6163 break;
6164 case 0x11:
6165 ret = write_ldt(env, ptr, bytecount, 0);
6166 break;
bellard03acab62007-11-11 14:57:14 +00006167 default:
6168 ret = -TARGET_ENOSYS;
6169 break;
bellard6dbad632003-03-16 18:05:05 +00006170 }
6171 return ret;
6172}
bellard1b6b0292003-03-22 17:31:38 +00006173
Laurent Vivier9d12f792020-03-10 11:33:55 +01006174#if defined(TARGET_ABI32)
Alexander Grafbc22eb42013-07-16 18:44:58 +01006175abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00006176{
Richard Henderson3e8f1622021-02-12 10:48:43 -08006177 uint64_t *gdt_table = g2h_untagged(env->gdt.base);
bellard8d18e892007-11-14 15:18:40 +00006178 struct target_modify_ldt_ldt_s ldt_info;
6179 struct target_modify_ldt_ldt_s *target_ldt_info;
6180 int seg_32bit, contents, read_exec_only, limit_in_pages;
6181 int seg_not_present, useable, lm;
6182 uint32_t *lp, entry_1, entry_2;
6183 int i;
6184
6185 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
6186 if (!target_ldt_info)
6187 return -TARGET_EFAULT;
6188 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02006189 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
bellard8d18e892007-11-14 15:18:40 +00006190 ldt_info.limit = tswap32(target_ldt_info->limit);
6191 ldt_info.flags = tswap32(target_ldt_info->flags);
6192 if (ldt_info.entry_number == -1) {
6193 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
6194 if (gdt_table[i] == 0) {
6195 ldt_info.entry_number = i;
6196 target_ldt_info->entry_number = tswap32(i);
6197 break;
6198 }
6199 }
6200 }
6201 unlock_user_struct(target_ldt_info, ptr, 1);
6202
6203 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
6204 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
6205 return -TARGET_EINVAL;
6206 seg_32bit = ldt_info.flags & 1;
6207 contents = (ldt_info.flags >> 1) & 3;
6208 read_exec_only = (ldt_info.flags >> 3) & 1;
6209 limit_in_pages = (ldt_info.flags >> 4) & 1;
6210 seg_not_present = (ldt_info.flags >> 5) & 1;
6211 useable = (ldt_info.flags >> 6) & 1;
6212#ifdef TARGET_ABI32
6213 lm = 0;
6214#else
6215 lm = (ldt_info.flags >> 7) & 1;
6216#endif
6217
6218 if (contents == 3) {
6219 if (seg_not_present == 0)
6220 return -TARGET_EINVAL;
6221 }
6222
6223 /* NOTE: same code as Linux kernel */
6224 /* Allow LDTs to be cleared by the user. */
6225 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
6226 if ((contents == 0 &&
6227 read_exec_only == 1 &&
6228 seg_32bit == 0 &&
6229 limit_in_pages == 0 &&
6230 seg_not_present == 1 &&
6231 useable == 0 )) {
6232 entry_1 = 0;
6233 entry_2 = 0;
6234 goto install;
6235 }
6236 }
6237
6238 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
6239 (ldt_info.limit & 0x0ffff);
6240 entry_2 = (ldt_info.base_addr & 0xff000000) |
6241 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
6242 (ldt_info.limit & 0xf0000) |
6243 ((read_exec_only ^ 1) << 9) |
6244 (contents << 10) |
6245 ((seg_not_present ^ 1) << 15) |
6246 (seg_32bit << 22) |
6247 (limit_in_pages << 23) |
6248 (useable << 20) |
6249 (lm << 21) |
6250 0x7000;
6251
6252 /* Install the new entry ... */
6253install:
6254 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
6255 lp[0] = tswap32(entry_1);
6256 lp[1] = tswap32(entry_2);
6257 return 0;
6258}
6259
blueswir18fcd3692008-08-17 20:26:25 +00006260static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00006261{
6262 struct target_modify_ldt_ldt_s *target_ldt_info;
Richard Henderson3e8f1622021-02-12 10:48:43 -08006263 uint64_t *gdt_table = g2h_untagged(env->gdt.base);
bellard8d18e892007-11-14 15:18:40 +00006264 uint32_t base_addr, limit, flags;
6265 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
6266 int seg_not_present, useable, lm;
6267 uint32_t *lp, entry_1, entry_2;
6268
6269 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
6270 if (!target_ldt_info)
6271 return -TARGET_EFAULT;
6272 idx = tswap32(target_ldt_info->entry_number);
6273 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
6274 idx > TARGET_GDT_ENTRY_TLS_MAX) {
6275 unlock_user_struct(target_ldt_info, ptr, 1);
6276 return -TARGET_EINVAL;
6277 }
6278 lp = (uint32_t *)(gdt_table + idx);
6279 entry_1 = tswap32(lp[0]);
6280 entry_2 = tswap32(lp[1]);
6281
6282 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
6283 contents = (entry_2 >> 10) & 3;
6284 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
6285 seg_32bit = (entry_2 >> 22) & 1;
6286 limit_in_pages = (entry_2 >> 23) & 1;
6287 useable = (entry_2 >> 20) & 1;
6288#ifdef TARGET_ABI32
6289 lm = 0;
6290#else
6291 lm = (entry_2 >> 21) & 1;
6292#endif
6293 flags = (seg_32bit << 0) | (contents << 1) |
6294 (read_exec_only << 3) | (limit_in_pages << 4) |
6295 (seg_not_present << 5) | (useable << 6) | (lm << 7);
6296 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
6297 base_addr = (entry_1 >> 16) |
6298 (entry_2 & 0xff000000) |
6299 ((entry_2 & 0xff) << 16);
Matthias Brauncbb21ee2011-08-12 19:57:41 +02006300 target_ldt_info->base_addr = tswapal(base_addr);
bellard8d18e892007-11-14 15:18:40 +00006301 target_ldt_info->limit = tswap32(limit);
6302 target_ldt_info->flags = tswap32(flags);
6303 unlock_user_struct(target_ldt_info, ptr, 1);
6304 return 0;
6305}
6306
Laurent Vivier9d12f792020-03-10 11:33:55 +01006307abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
6308{
Helge Deller538fabc2020-04-25 00:00:33 +02006309 return -TARGET_ENOSYS;
Laurent Vivier9d12f792020-03-10 11:33:55 +01006310}
6311#else
Peter Maydell2667e712013-07-16 18:44:59 +01006312abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
bellardd2fd1af2007-11-14 18:08:56 +00006313{
Juan Quintela1add8692011-06-16 17:37:09 +01006314 abi_long ret = 0;
bellardd2fd1af2007-11-14 18:08:56 +00006315 abi_ulong val;
6316 int idx;
Juan Quintela1add8692011-06-16 17:37:09 +01006317
bellardd2fd1af2007-11-14 18:08:56 +00006318 switch(code) {
6319 case TARGET_ARCH_SET_GS:
6320 case TARGET_ARCH_SET_FS:
6321 if (code == TARGET_ARCH_SET_GS)
6322 idx = R_GS;
6323 else
6324 idx = R_FS;
6325 cpu_x86_load_seg(env, idx, 0);
6326 env->segs[idx].base = addr;
6327 break;
6328 case TARGET_ARCH_GET_GS:
6329 case TARGET_ARCH_GET_FS:
6330 if (code == TARGET_ARCH_GET_GS)
6331 idx = R_GS;
6332 else
6333 idx = R_FS;
6334 val = env->segs[idx].base;
6335 if (put_user(val, addr, abi_ulong))
Juan Quintela1add8692011-06-16 17:37:09 +01006336 ret = -TARGET_EFAULT;
bellardd2fd1af2007-11-14 18:08:56 +00006337 break;
6338 default:
6339 ret = -TARGET_EINVAL;
6340 break;
6341 }
Juan Quintela1add8692011-06-16 17:37:09 +01006342 return ret;
bellardd2fd1af2007-11-14 18:08:56 +00006343}
Laurent Vivier9d12f792020-03-10 11:33:55 +01006344#endif /* defined(TARGET_ABI32 */
bellard2ab83ea2003-06-15 19:56:46 +00006345#endif /* defined(TARGET_I386) */
6346
Richard Henderson87e9bf22021-12-27 07:01:22 -08006347/*
6348 * These constants are generic. Supply any that are missing from the host.
6349 */
6350#ifndef PR_SET_NAME
6351# define PR_SET_NAME 15
6352# define PR_GET_NAME 16
6353#endif
6354#ifndef PR_SET_FP_MODE
6355# define PR_SET_FP_MODE 45
6356# define PR_GET_FP_MODE 46
6357# define PR_FP_MODE_FR (1 << 0)
6358# define PR_FP_MODE_FRE (1 << 1)
6359#endif
6360#ifndef PR_SVE_SET_VL
6361# define PR_SVE_SET_VL 50
6362# define PR_SVE_GET_VL 51
6363# define PR_SVE_VL_LEN_MASK 0xffff
6364# define PR_SVE_VL_INHERIT (1 << 17)
6365#endif
6366#ifndef PR_PAC_RESET_KEYS
6367# define PR_PAC_RESET_KEYS 54
6368# define PR_PAC_APIAKEY (1 << 0)
6369# define PR_PAC_APIBKEY (1 << 1)
6370# define PR_PAC_APDAKEY (1 << 2)
6371# define PR_PAC_APDBKEY (1 << 3)
6372# define PR_PAC_APGAKEY (1 << 4)
6373#endif
6374#ifndef PR_SET_TAGGED_ADDR_CTRL
6375# define PR_SET_TAGGED_ADDR_CTRL 55
6376# define PR_GET_TAGGED_ADDR_CTRL 56
6377# define PR_TAGGED_ADDR_ENABLE (1UL << 0)
6378#endif
6379#ifndef PR_MTE_TCF_SHIFT
6380# define PR_MTE_TCF_SHIFT 1
6381# define PR_MTE_TCF_NONE (0UL << PR_MTE_TCF_SHIFT)
6382# define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT)
6383# define PR_MTE_TCF_ASYNC (2UL << PR_MTE_TCF_SHIFT)
6384# define PR_MTE_TCF_MASK (3UL << PR_MTE_TCF_SHIFT)
6385# define PR_MTE_TAG_SHIFT 3
6386# define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT)
6387#endif
Richard Henderson220717a2021-12-27 07:01:23 -08006388#ifndef PR_SET_IO_FLUSHER
6389# define PR_SET_IO_FLUSHER 57
6390# define PR_GET_IO_FLUSHER 58
6391#endif
6392#ifndef PR_SET_SYSCALL_USER_DISPATCH
6393# define PR_SET_SYSCALL_USER_DISPATCH 59
6394#endif
Richard Henderson24d87c12022-07-08 20:45:37 +05306395#ifndef PR_SME_SET_VL
6396# define PR_SME_SET_VL 63
6397# define PR_SME_GET_VL 64
6398# define PR_SME_VL_LEN_MASK 0xffff
6399# define PR_SME_VL_INHERIT (1 << 17)
6400#endif
Richard Henderson87e9bf22021-12-27 07:01:22 -08006401
6402#include "target_prctl.h"
6403
6404static abi_long do_prctl_inval0(CPUArchState *env)
6405{
6406 return -TARGET_EINVAL;
6407}
6408
6409static abi_long do_prctl_inval1(CPUArchState *env, abi_long arg2)
6410{
6411 return -TARGET_EINVAL;
6412}
6413
6414#ifndef do_prctl_get_fp_mode
6415#define do_prctl_get_fp_mode do_prctl_inval0
6416#endif
6417#ifndef do_prctl_set_fp_mode
6418#define do_prctl_set_fp_mode do_prctl_inval1
6419#endif
Richard Hendersonfd72f5d2022-07-08 20:45:36 +05306420#ifndef do_prctl_sve_get_vl
6421#define do_prctl_sve_get_vl do_prctl_inval0
Richard Henderson87e9bf22021-12-27 07:01:22 -08006422#endif
Richard Hendersonfd72f5d2022-07-08 20:45:36 +05306423#ifndef do_prctl_sve_set_vl
6424#define do_prctl_sve_set_vl do_prctl_inval1
Richard Henderson87e9bf22021-12-27 07:01:22 -08006425#endif
6426#ifndef do_prctl_reset_keys
6427#define do_prctl_reset_keys do_prctl_inval1
6428#endif
6429#ifndef do_prctl_set_tagged_addr_ctrl
6430#define do_prctl_set_tagged_addr_ctrl do_prctl_inval1
6431#endif
6432#ifndef do_prctl_get_tagged_addr_ctrl
6433#define do_prctl_get_tagged_addr_ctrl do_prctl_inval0
6434#endif
Richard Henderson6e8dcac2021-12-27 07:01:24 -08006435#ifndef do_prctl_get_unalign
6436#define do_prctl_get_unalign do_prctl_inval1
6437#endif
6438#ifndef do_prctl_set_unalign
6439#define do_prctl_set_unalign do_prctl_inval1
6440#endif
Richard Henderson24d87c12022-07-08 20:45:37 +05306441#ifndef do_prctl_sme_get_vl
6442#define do_prctl_sme_get_vl do_prctl_inval0
6443#endif
6444#ifndef do_prctl_sme_set_vl
6445#define do_prctl_sme_set_vl do_prctl_inval1
6446#endif
Richard Henderson87e9bf22021-12-27 07:01:22 -08006447
6448static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
6449 abi_long arg3, abi_long arg4, abi_long arg5)
6450{
6451 abi_long ret;
6452
6453 switch (option) {
6454 case PR_GET_PDEATHSIG:
6455 {
6456 int deathsig;
6457 ret = get_errno(prctl(PR_GET_PDEATHSIG, &deathsig,
6458 arg3, arg4, arg5));
Richard Henderson1edebb32022-01-06 14:57:36 -08006459 if (!is_error(ret) &&
6460 put_user_s32(host_to_target_signal(deathsig), arg2)) {
Richard Henderson87e9bf22021-12-27 07:01:22 -08006461 return -TARGET_EFAULT;
6462 }
6463 return ret;
6464 }
Richard Hendersonf746c652022-01-06 14:57:37 -08006465 case PR_SET_PDEATHSIG:
6466 return get_errno(prctl(PR_SET_PDEATHSIG, target_to_host_signal(arg2),
6467 arg3, arg4, arg5));
Richard Henderson87e9bf22021-12-27 07:01:22 -08006468 case PR_GET_NAME:
6469 {
6470 void *name = lock_user(VERIFY_WRITE, arg2, 16, 1);
6471 if (!name) {
6472 return -TARGET_EFAULT;
6473 }
6474 ret = get_errno(prctl(PR_GET_NAME, (uintptr_t)name,
6475 arg3, arg4, arg5));
6476 unlock_user(name, arg2, 16);
6477 return ret;
6478 }
6479 case PR_SET_NAME:
6480 {
6481 void *name = lock_user(VERIFY_READ, arg2, 16, 1);
6482 if (!name) {
6483 return -TARGET_EFAULT;
6484 }
6485 ret = get_errno(prctl(PR_SET_NAME, (uintptr_t)name,
6486 arg3, arg4, arg5));
6487 unlock_user(name, arg2, 0);
6488 return ret;
6489 }
6490 case PR_GET_FP_MODE:
6491 return do_prctl_get_fp_mode(env);
6492 case PR_SET_FP_MODE:
6493 return do_prctl_set_fp_mode(env, arg2);
6494 case PR_SVE_GET_VL:
Richard Hendersonfd72f5d2022-07-08 20:45:36 +05306495 return do_prctl_sve_get_vl(env);
Richard Henderson87e9bf22021-12-27 07:01:22 -08006496 case PR_SVE_SET_VL:
Richard Hendersonfd72f5d2022-07-08 20:45:36 +05306497 return do_prctl_sve_set_vl(env, arg2);
Richard Henderson24d87c12022-07-08 20:45:37 +05306498 case PR_SME_GET_VL:
6499 return do_prctl_sme_get_vl(env);
6500 case PR_SME_SET_VL:
6501 return do_prctl_sme_set_vl(env, arg2);
Richard Henderson87e9bf22021-12-27 07:01:22 -08006502 case PR_PAC_RESET_KEYS:
6503 if (arg3 || arg4 || arg5) {
6504 return -TARGET_EINVAL;
6505 }
6506 return do_prctl_reset_keys(env, arg2);
6507 case PR_SET_TAGGED_ADDR_CTRL:
6508 if (arg3 || arg4 || arg5) {
6509 return -TARGET_EINVAL;
6510 }
6511 return do_prctl_set_tagged_addr_ctrl(env, arg2);
6512 case PR_GET_TAGGED_ADDR_CTRL:
6513 if (arg2 || arg3 || arg4 || arg5) {
6514 return -TARGET_EINVAL;
6515 }
6516 return do_prctl_get_tagged_addr_ctrl(env);
Richard Henderson220717a2021-12-27 07:01:23 -08006517
Richard Henderson6e8dcac2021-12-27 07:01:24 -08006518 case PR_GET_UNALIGN:
6519 return do_prctl_get_unalign(env, arg2);
6520 case PR_SET_UNALIGN:
6521 return do_prctl_set_unalign(env, arg2);
6522
Richard Henderson4f4e5562022-01-06 14:57:38 -08006523 case PR_CAP_AMBIENT:
6524 case PR_CAPBSET_READ:
6525 case PR_CAPBSET_DROP:
Richard Henderson220717a2021-12-27 07:01:23 -08006526 case PR_GET_DUMPABLE:
6527 case PR_SET_DUMPABLE:
6528 case PR_GET_KEEPCAPS:
6529 case PR_SET_KEEPCAPS:
Richard Henderson4f4e5562022-01-06 14:57:38 -08006530 case PR_GET_SECUREBITS:
6531 case PR_SET_SECUREBITS:
Richard Henderson220717a2021-12-27 07:01:23 -08006532 case PR_GET_TIMING:
6533 case PR_SET_TIMING:
6534 case PR_GET_TIMERSLACK:
6535 case PR_SET_TIMERSLACK:
6536 case PR_MCE_KILL:
6537 case PR_MCE_KILL_GET:
6538 case PR_GET_NO_NEW_PRIVS:
6539 case PR_SET_NO_NEW_PRIVS:
6540 case PR_GET_IO_FLUSHER:
6541 case PR_SET_IO_FLUSHER:
6542 /* Some prctl options have no pointer arguments and we can pass on. */
6543 return get_errno(prctl(option, arg2, arg3, arg4, arg5));
6544
6545 case PR_GET_CHILD_SUBREAPER:
6546 case PR_SET_CHILD_SUBREAPER:
6547 case PR_GET_SPECULATION_CTRL:
6548 case PR_SET_SPECULATION_CTRL:
6549 case PR_GET_TID_ADDRESS:
6550 /* TODO */
6551 return -TARGET_EINVAL;
6552
6553 case PR_GET_FPEXC:
6554 case PR_SET_FPEXC:
6555 /* Was used for SPE on PowerPC. */
6556 return -TARGET_EINVAL;
6557
6558 case PR_GET_ENDIAN:
6559 case PR_SET_ENDIAN:
6560 case PR_GET_FPEMU:
6561 case PR_SET_FPEMU:
6562 case PR_SET_MM:
Richard Henderson87e9bf22021-12-27 07:01:22 -08006563 case PR_GET_SECCOMP:
6564 case PR_SET_SECCOMP:
Richard Henderson220717a2021-12-27 07:01:23 -08006565 case PR_SET_SYSCALL_USER_DISPATCH:
6566 case PR_GET_THP_DISABLE:
6567 case PR_SET_THP_DISABLE:
6568 case PR_GET_TSC:
6569 case PR_SET_TSC:
Richard Henderson220717a2021-12-27 07:01:23 -08006570 /* Disable to prevent the target disabling stuff we need. */
Richard Henderson87e9bf22021-12-27 07:01:22 -08006571 return -TARGET_EINVAL;
Richard Henderson220717a2021-12-27 07:01:23 -08006572
Richard Henderson87e9bf22021-12-27 07:01:22 -08006573 default:
Richard Henderson220717a2021-12-27 07:01:23 -08006574 qemu_log_mask(LOG_UNIMP, "Unsupported prctl: " TARGET_ABI_FMT_ld "\n",
6575 option);
6576 return -TARGET_EINVAL;
Richard Henderson87e9bf22021-12-27 07:01:22 -08006577 }
6578}
6579
Riku Voipio05098a92011-03-04 15:27:29 +02006580#define NEW_STACK_SIZE 0x40000
pbrookd865bab2008-06-07 22:12:17 +00006581
pbrookd865bab2008-06-07 22:12:17 +00006582
6583static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
6584typedef struct {
Andreas Färber9349b4f2012-03-14 01:38:32 +01006585 CPUArchState *env;
pbrookd865bab2008-06-07 22:12:17 +00006586 pthread_mutex_t mutex;
6587 pthread_cond_t cond;
6588 pthread_t thread;
6589 uint32_t tid;
6590 abi_ulong child_tidptr;
6591 abi_ulong parent_tidptr;
6592 sigset_t sigmask;
6593} new_thread_info;
6594
6595static void *clone_func(void *arg)
6596{
6597 new_thread_info *info = arg;
Andreas Färber9349b4f2012-03-14 01:38:32 +01006598 CPUArchState *env;
Andreas Färber0d342822012-12-17 07:12:13 +01006599 CPUState *cpu;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03006600 TaskState *ts;
pbrookd865bab2008-06-07 22:12:17 +00006601
Emilio G. Cota70903762015-08-23 20:23:41 -04006602 rcu_register_thread();
Emilio G. Cota3468b592017-07-19 18:57:58 -04006603 tcg_register_thread();
pbrookd865bab2008-06-07 22:12:17 +00006604 env = info->env;
Richard Henderson29a0af62019-03-22 16:07:18 -07006605 cpu = env_cpu(env);
Andreas Färbera2247f82013-06-09 19:47:04 +02006606 thread_cpu = cpu;
Andreas Färber0429a972013-08-26 18:14:44 +02006607 ts = (TaskState *)cpu->opaque;
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +00006608 info->tid = sys_gettid();
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03006609 task_settid(ts);
pbrookd865bab2008-06-07 22:12:17 +00006610 if (info->child_tidptr)
6611 put_user_u32(info->tid, info->child_tidptr);
6612 if (info->parent_tidptr)
6613 put_user_u32(info->tid, info->parent_tidptr);
Richard Henderson5ebdd772019-03-14 13:10:53 -07006614 qemu_guest_random_seed_thread_part2(cpu->random_seed);
pbrookd865bab2008-06-07 22:12:17 +00006615 /* Enable signals. */
6616 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
6617 /* Signal to the parent that we're ready. */
6618 pthread_mutex_lock(&info->mutex);
6619 pthread_cond_broadcast(&info->cond);
6620 pthread_mutex_unlock(&info->mutex);
Emilio G. Cotaa4dd3d52017-10-18 18:01:41 -04006621 /* Wait until the parent has finished initializing the tls state. */
pbrookd865bab2008-06-07 22:12:17 +00006622 pthread_mutex_lock(&clone_lock);
6623 pthread_mutex_unlock(&clone_lock);
6624 cpu_loop(env);
6625 /* never exits */
6626 return NULL;
6627}
bellard1b6b0292003-03-22 17:31:38 +00006628
ths0da46a62007-10-20 20:23:07 +00006629/* do_fork() Must return host values and target errnos (unlike most
6630 do_*() functions). */
Andreas Färber9349b4f2012-03-14 01:38:32 +01006631static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
pbrookd865bab2008-06-07 22:12:17 +00006632 abi_ulong parent_tidptr, target_ulong newtls,
6633 abi_ulong child_tidptr)
bellard1b6b0292003-03-22 17:31:38 +00006634{
Richard Henderson29a0af62019-03-22 16:07:18 -07006635 CPUState *cpu = env_cpu(env);
bellard1b6b0292003-03-22 17:31:38 +00006636 int ret;
bellard5cd43932003-03-29 16:54:36 +00006637 TaskState *ts;
Andreas Färber0429a972013-08-26 18:14:44 +02006638 CPUState *new_cpu;
Andreas Färber9349b4f2012-03-14 01:38:32 +01006639 CPUArchState *new_env;
pbrookd865bab2008-06-07 22:12:17 +00006640 sigset_t sigmask;
ths3b46e622007-09-17 08:09:54 +00006641
Peter Maydell5ea2fc82016-08-02 18:41:27 +01006642 flags &= ~CLONE_IGNORED_FLAGS;
6643
balrog436d1242008-09-21 02:39:45 +00006644 /* Emulate vfork() with fork() */
6645 if (flags & CLONE_VFORK)
6646 flags &= ~(CLONE_VFORK | CLONE_VM);
6647
bellard1b6b0292003-03-22 17:31:38 +00006648 if (flags & CLONE_VM) {
Andreas Färber0429a972013-08-26 18:14:44 +02006649 TaskState *parent_ts = (TaskState *)cpu->opaque;
pbrookd865bab2008-06-07 22:12:17 +00006650 new_thread_info info;
6651 pthread_attr_t attr;
Peter Maydell24cb36a2013-07-16 18:45:00 +01006652
Peter Maydell5ea2fc82016-08-02 18:41:27 +01006653 if (((flags & CLONE_THREAD_FLAGS) != CLONE_THREAD_FLAGS) ||
6654 (flags & CLONE_INVALID_THREAD_FLAGS)) {
6655 return -TARGET_EINVAL;
6656 }
6657
Markus Armbrusterc78d65e2015-09-14 13:53:03 +02006658 ts = g_new0(TaskState, 1);
pbrook624f7972008-05-31 16:11:38 +00006659 init_task_state(ts);
Max Filippov73a988d2018-03-30 06:19:58 -07006660
6661 /* Grab a mutex so that thread setup appears atomic. */
6662 pthread_mutex_lock(&clone_lock);
6663
Richard Henderson6cc9d672021-03-01 19:21:08 -08006664 /*
6665 * If this is our first additional thread, we need to ensure we
6666 * generate code for parallel execution and flush old translations.
6667 * Do this now so that the copy gets CF_PARALLEL too.
6668 */
6669 if (!(cpu->tcg_cflags & CF_PARALLEL)) {
6670 cpu->tcg_cflags |= CF_PARALLEL;
6671 tb_flush(cpu);
6672 }
6673
bellard1b6b0292003-03-22 17:31:38 +00006674 /* we create a new CPU instance. */
thsc5be9f02007-02-28 20:20:53 +00006675 new_env = cpu_copy(env);
pbrook6e68e072008-05-30 17:22:15 +00006676 /* Init regs that differ from the parent. */
Richard Henderson608999d2019-11-06 12:33:15 +01006677 cpu_clone_regs_child(new_env, newsp, flags);
Richard Henderson07a6ecf2019-11-06 12:33:16 +01006678 cpu_clone_regs_parent(env, flags);
Richard Henderson29a0af62019-03-22 16:07:18 -07006679 new_cpu = env_cpu(new_env);
Andreas Färber0429a972013-08-26 18:14:44 +02006680 new_cpu->opaque = ts;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03006681 ts->bprm = parent_ts->bprm;
6682 ts->info = parent_ts->info;
Peter Maydell3d3efba2016-05-27 15:51:49 +01006683 ts->signal_mask = parent_ts->signal_mask;
pbrookd865bab2008-06-07 22:12:17 +00006684
Peter Maydell7cfbd382016-08-02 18:41:26 +01006685 if (flags & CLONE_CHILD_CLEARTID) {
pbrookc2764712009-03-07 15:24:59 +00006686 ts->child_tidptr = child_tidptr;
6687 }
6688
Peter Maydell7cfbd382016-08-02 18:41:26 +01006689 if (flags & CLONE_SETTLS) {
pbrookd865bab2008-06-07 22:12:17 +00006690 cpu_set_tls (new_env, newtls);
Peter Maydell7cfbd382016-08-02 18:41:26 +01006691 }
pbrookd865bab2008-06-07 22:12:17 +00006692
pbrookd865bab2008-06-07 22:12:17 +00006693 memset(&info, 0, sizeof(info));
6694 pthread_mutex_init(&info.mutex, NULL);
6695 pthread_mutex_lock(&info.mutex);
6696 pthread_cond_init(&info.cond, NULL);
6697 info.env = new_env;
Peter Maydell7cfbd382016-08-02 18:41:26 +01006698 if (flags & CLONE_CHILD_SETTID) {
pbrookd865bab2008-06-07 22:12:17 +00006699 info.child_tidptr = child_tidptr;
Peter Maydell7cfbd382016-08-02 18:41:26 +01006700 }
6701 if (flags & CLONE_PARENT_SETTID) {
pbrookd865bab2008-06-07 22:12:17 +00006702 info.parent_tidptr = parent_tidptr;
Peter Maydell7cfbd382016-08-02 18:41:26 +01006703 }
pbrookd865bab2008-06-07 22:12:17 +00006704
6705 ret = pthread_attr_init(&attr);
Nathan Froyd48e15fc2010-10-29 07:48:57 -07006706 ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE);
6707 ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pbrookd865bab2008-06-07 22:12:17 +00006708 /* It is not safe to deliver signals until the child has finished
6709 initializing, so temporarily block all signals. */
6710 sigfillset(&sigmask);
6711 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
Richard Henderson5ebdd772019-03-14 13:10:53 -07006712 cpu->random_seed = qemu_guest_random_seed_thread_part1();
pbrookd865bab2008-06-07 22:12:17 +00006713
6714 ret = pthread_create(&info.thread, &attr, clone_func, &info);
pbrookc2764712009-03-07 15:24:59 +00006715 /* TODO: Free new CPU state if thread creation failed. */
pbrookd865bab2008-06-07 22:12:17 +00006716
6717 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
6718 pthread_attr_destroy(&attr);
6719 if (ret == 0) {
6720 /* Wait for the child to initialize. */
6721 pthread_cond_wait(&info.cond, &info.mutex);
6722 ret = info.tid;
pbrookd865bab2008-06-07 22:12:17 +00006723 } else {
6724 ret = -1;
6725 }
6726 pthread_mutex_unlock(&info.mutex);
6727 pthread_cond_destroy(&info.cond);
6728 pthread_mutex_destroy(&info.mutex);
6729 pthread_mutex_unlock(&clone_lock);
bellard1b6b0292003-03-22 17:31:38 +00006730 } else {
6731 /* if no CLONE_VM, we consider it is a fork */
Peter Maydell5ea2fc82016-08-02 18:41:27 +01006732 if (flags & CLONE_INVALID_FORK_FLAGS) {
6733 return -TARGET_EINVAL;
6734 }
6735
6736 /* We can't support custom termination signals */
6737 if ((flags & CSIGNAL) != TARGET_SIGCHLD) {
Timothy E Baldwin93b4eff2015-08-31 00:26:21 +01006738 return -TARGET_EINVAL;
6739 }
Timothy E Baldwin7d92d342016-05-27 15:51:58 +01006740
6741 if (block_signals()) {
Richard Hendersonaf254a22021-11-22 19:47:33 +01006742 return -QEMU_ERESTARTSYS;
Timothy E Baldwin7d92d342016-05-27 15:51:58 +01006743 }
6744
pbrookd865bab2008-06-07 22:12:17 +00006745 fork_start();
bellard1b6b0292003-03-22 17:31:38 +00006746 ret = fork();
pbrookd865bab2008-06-07 22:12:17 +00006747 if (ret == 0) {
aurel322b1319c2008-12-18 22:44:04 +00006748 /* Child Process. */
Richard Henderson608999d2019-11-06 12:33:15 +01006749 cpu_clone_regs_child(env, newsp, flags);
pbrookd865bab2008-06-07 22:12:17 +00006750 fork_end(1);
aurel322b1319c2008-12-18 22:44:04 +00006751 /* There is a race condition here. The parent process could
6752 theoretically read the TID in the child process before the child
6753 tid is set. This would require using either ptrace
6754 (not implemented) or having *_tidptr to point at a shared memory
6755 mapping. We can't repeat the spinlock hack used above because
6756 the child process gets its own copy of the lock. */
pbrookd865bab2008-06-07 22:12:17 +00006757 if (flags & CLONE_CHILD_SETTID)
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +00006758 put_user_u32(sys_gettid(), child_tidptr);
pbrookd865bab2008-06-07 22:12:17 +00006759 if (flags & CLONE_PARENT_SETTID)
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +00006760 put_user_u32(sys_gettid(), parent_tidptr);
Andreas Färber0429a972013-08-26 18:14:44 +02006761 ts = (TaskState *)cpu->opaque;
pbrookd865bab2008-06-07 22:12:17 +00006762 if (flags & CLONE_SETTLS)
6763 cpu_set_tls (env, newtls);
pbrookc2764712009-03-07 15:24:59 +00006764 if (flags & CLONE_CHILD_CLEARTID)
6765 ts->child_tidptr = child_tidptr;
pbrookd865bab2008-06-07 22:12:17 +00006766 } else {
Richard Henderson07a6ecf2019-11-06 12:33:16 +01006767 cpu_clone_regs_parent(env, flags);
pbrookd865bab2008-06-07 22:12:17 +00006768 fork_end(0);
6769 }
bellard1b6b0292003-03-22 17:31:38 +00006770 }
6771 return ret;
6772}
6773
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006774/* warning : doesn't handle linux specific flags... */
6775static int target_to_host_fcntl_cmd(int cmd)
6776{
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006777 int ret;
6778
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006779 switch(cmd) {
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006780 case TARGET_F_DUPFD:
6781 case TARGET_F_GETFD:
6782 case TARGET_F_SETFD:
6783 case TARGET_F_GETFL:
6784 case TARGET_F_SETFL:
Andreas Schwab2d92c682020-05-25 09:59:28 +02006785 case TARGET_F_OFD_GETLK:
6786 case TARGET_F_OFD_SETLK:
6787 case TARGET_F_OFD_SETLKW:
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006788 ret = cmd;
6789 break;
6790 case TARGET_F_GETLK:
6791 ret = F_GETLK64;
6792 break;
6793 case TARGET_F_SETLK:
6794 ret = F_SETLK64;
6795 break;
6796 case TARGET_F_SETLKW:
6797 ret = F_SETLKW64;
6798 break;
6799 case TARGET_F_GETOWN:
6800 ret = F_GETOWN;
6801 break;
6802 case TARGET_F_SETOWN:
6803 ret = F_SETOWN;
6804 break;
6805 case TARGET_F_GETSIG:
6806 ret = F_GETSIG;
6807 break;
6808 case TARGET_F_SETSIG:
6809 ret = F_SETSIG;
6810 break;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006811#if TARGET_ABI_BITS == 32
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006812 case TARGET_F_GETLK64:
6813 ret = F_GETLK64;
6814 break;
6815 case TARGET_F_SETLK64:
6816 ret = F_SETLK64;
6817 break;
6818 case TARGET_F_SETLKW64:
6819 ret = F_SETLKW64;
6820 break;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006821#endif
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006822 case TARGET_F_SETLEASE:
6823 ret = F_SETLEASE;
6824 break;
6825 case TARGET_F_GETLEASE:
6826 ret = F_GETLEASE;
6827 break;
malcfbd5de92009-09-06 06:31:59 +04006828#ifdef F_DUPFD_CLOEXEC
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006829 case TARGET_F_DUPFD_CLOEXEC:
6830 ret = F_DUPFD_CLOEXEC;
6831 break;
malcfbd5de92009-09-06 06:31:59 +04006832#endif
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006833 case TARGET_F_NOTIFY:
6834 ret = F_NOTIFY;
6835 break;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006836#ifdef F_GETOWN_EX
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006837 case TARGET_F_GETOWN_EX:
6838 ret = F_GETOWN_EX;
6839 break;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006840#endif
6841#ifdef F_SETOWN_EX
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006842 case TARGET_F_SETOWN_EX:
6843 ret = F_SETOWN_EX;
6844 break;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01006845#endif
Peter Maydellddf31aa2016-06-30 17:33:49 +01006846#ifdef F_SETPIPE_SZ
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006847 case TARGET_F_SETPIPE_SZ:
6848 ret = F_SETPIPE_SZ;
6849 break;
6850 case TARGET_F_GETPIPE_SZ:
6851 ret = F_GETPIPE_SZ;
6852 break;
Peter Maydellddf31aa2016-06-30 17:33:49 +01006853#endif
Shu-Chun Weng2bb963f2020-12-18 11:32:10 -08006854#ifdef F_ADD_SEALS
6855 case TARGET_F_ADD_SEALS:
6856 ret = F_ADD_SEALS;
6857 break;
6858 case TARGET_F_GET_SEALS:
6859 ret = F_GET_SEALS;
6860 break;
6861#endif
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006862 default:
6863 ret = -TARGET_EINVAL;
6864 break;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006865 }
Shivaprasad G Bhat4a545762018-07-13 07:34:46 -05006866
6867#if defined(__powerpc64__)
6868 /* On PPC64, glibc headers has the F_*LK* defined to 12, 13 and 14 and
6869 * is not supported by kernel. The glibc fcntl call actually adjusts
6870 * them to 5, 6 and 7 before making the syscall(). Since we make the
6871 * syscall directly, adjust to what is supported by the kernel.
6872 */
6873 if (ret >= F_GETLK64 && ret <= F_SETLKW64) {
6874 ret -= F_GETLK64 - 5;
6875 }
6876#endif
6877
6878 return ret;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02006879}
6880
Laurent Vivierae68ad92018-05-10 01:11:21 +02006881#define FLOCK_TRANSTBL \
6882 switch (type) { \
6883 TRANSTBL_CONVERT(F_RDLCK); \
6884 TRANSTBL_CONVERT(F_WRLCK); \
6885 TRANSTBL_CONVERT(F_UNLCK); \
Laurent Vivierae68ad92018-05-10 01:11:21 +02006886 }
6887
6888static int target_to_host_flock(int type)
6889{
6890#define TRANSTBL_CONVERT(a) case TARGET_##a: return a
6891 FLOCK_TRANSTBL
6892#undef TRANSTBL_CONVERT
6893 return -TARGET_EINVAL;
6894}
6895
6896static int host_to_target_flock(int type)
6897{
6898#define TRANSTBL_CONVERT(a) case a: return TARGET_##a
6899 FLOCK_TRANSTBL
6900#undef TRANSTBL_CONVERT
6901 /* if we don't know how to convert the value coming
6902 * from the host we copy to the target field as-is
6903 */
6904 return type;
6905}
Laurent Vivier2ba7f732013-01-10 21:42:48 +01006906
Peter Maydell213d3e92016-06-13 11:22:05 +01006907static inline abi_long copy_from_user_flock(struct flock64 *fl,
6908 abi_ulong target_flock_addr)
6909{
6910 struct target_flock *target_fl;
Laurent Vivierae68ad92018-05-10 01:11:21 +02006911 int l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006912
6913 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
6914 return -TARGET_EFAULT;
6915 }
6916
6917 __get_user(l_type, &target_fl->l_type);
Laurent Vivierae68ad92018-05-10 01:11:21 +02006918 l_type = target_to_host_flock(l_type);
6919 if (l_type < 0) {
6920 return l_type;
6921 }
6922 fl->l_type = l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006923 __get_user(fl->l_whence, &target_fl->l_whence);
6924 __get_user(fl->l_start, &target_fl->l_start);
6925 __get_user(fl->l_len, &target_fl->l_len);
6926 __get_user(fl->l_pid, &target_fl->l_pid);
6927 unlock_user_struct(target_fl, target_flock_addr, 0);
6928 return 0;
6929}
6930
6931static inline abi_long copy_to_user_flock(abi_ulong target_flock_addr,
6932 const struct flock64 *fl)
6933{
6934 struct target_flock *target_fl;
6935 short l_type;
6936
6937 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
6938 return -TARGET_EFAULT;
6939 }
6940
Laurent Vivierae68ad92018-05-10 01:11:21 +02006941 l_type = host_to_target_flock(fl->l_type);
Peter Maydell213d3e92016-06-13 11:22:05 +01006942 __put_user(l_type, &target_fl->l_type);
6943 __put_user(fl->l_whence, &target_fl->l_whence);
6944 __put_user(fl->l_start, &target_fl->l_start);
6945 __put_user(fl->l_len, &target_fl->l_len);
6946 __put_user(fl->l_pid, &target_fl->l_pid);
6947 unlock_user_struct(target_fl, target_flock_addr, 1);
6948 return 0;
6949}
6950
6951typedef abi_long from_flock64_fn(struct flock64 *fl, abi_ulong target_addr);
6952typedef abi_long to_flock64_fn(abi_ulong target_addr, const struct flock64 *fl);
6953
6954#if defined(TARGET_ARM) && TARGET_ABI_BITS == 32
Richard Hendersonffe81d42022-01-06 20:25:59 -08006955struct target_oabi_flock64 {
6956 abi_short l_type;
6957 abi_short l_whence;
6958 abi_llong l_start;
6959 abi_llong l_len;
6960 abi_int l_pid;
6961} QEMU_PACKED;
6962
Laurent Vivier7f254c52018-05-02 23:57:30 +02006963static inline abi_long copy_from_user_oabi_flock64(struct flock64 *fl,
Peter Maydell213d3e92016-06-13 11:22:05 +01006964 abi_ulong target_flock_addr)
6965{
Laurent Vivier7f254c52018-05-02 23:57:30 +02006966 struct target_oabi_flock64 *target_fl;
Laurent Vivierae68ad92018-05-10 01:11:21 +02006967 int l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006968
6969 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
6970 return -TARGET_EFAULT;
6971 }
6972
6973 __get_user(l_type, &target_fl->l_type);
Laurent Vivierae68ad92018-05-10 01:11:21 +02006974 l_type = target_to_host_flock(l_type);
6975 if (l_type < 0) {
6976 return l_type;
6977 }
6978 fl->l_type = l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01006979 __get_user(fl->l_whence, &target_fl->l_whence);
6980 __get_user(fl->l_start, &target_fl->l_start);
6981 __get_user(fl->l_len, &target_fl->l_len);
6982 __get_user(fl->l_pid, &target_fl->l_pid);
6983 unlock_user_struct(target_fl, target_flock_addr, 0);
6984 return 0;
6985}
6986
Laurent Vivier7f254c52018-05-02 23:57:30 +02006987static inline abi_long copy_to_user_oabi_flock64(abi_ulong target_flock_addr,
Peter Maydell213d3e92016-06-13 11:22:05 +01006988 const struct flock64 *fl)
6989{
Laurent Vivier7f254c52018-05-02 23:57:30 +02006990 struct target_oabi_flock64 *target_fl;
Peter Maydell213d3e92016-06-13 11:22:05 +01006991 short l_type;
6992
6993 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
6994 return -TARGET_EFAULT;
6995 }
6996
Laurent Vivierae68ad92018-05-10 01:11:21 +02006997 l_type = host_to_target_flock(fl->l_type);
Peter Maydell213d3e92016-06-13 11:22:05 +01006998 __put_user(l_type, &target_fl->l_type);
6999 __put_user(fl->l_whence, &target_fl->l_whence);
7000 __put_user(fl->l_start, &target_fl->l_start);
7001 __put_user(fl->l_len, &target_fl->l_len);
7002 __put_user(fl->l_pid, &target_fl->l_pid);
7003 unlock_user_struct(target_fl, target_flock_addr, 1);
7004 return 0;
7005}
7006#endif
7007
7008static inline abi_long copy_from_user_flock64(struct flock64 *fl,
7009 abi_ulong target_flock_addr)
7010{
7011 struct target_flock64 *target_fl;
Laurent Vivierae68ad92018-05-10 01:11:21 +02007012 int l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01007013
7014 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
7015 return -TARGET_EFAULT;
7016 }
7017
7018 __get_user(l_type, &target_fl->l_type);
Laurent Vivierae68ad92018-05-10 01:11:21 +02007019 l_type = target_to_host_flock(l_type);
7020 if (l_type < 0) {
7021 return l_type;
7022 }
7023 fl->l_type = l_type;
Peter Maydell213d3e92016-06-13 11:22:05 +01007024 __get_user(fl->l_whence, &target_fl->l_whence);
7025 __get_user(fl->l_start, &target_fl->l_start);
7026 __get_user(fl->l_len, &target_fl->l_len);
7027 __get_user(fl->l_pid, &target_fl->l_pid);
7028 unlock_user_struct(target_fl, target_flock_addr, 0);
7029 return 0;
7030}
7031
7032static inline abi_long copy_to_user_flock64(abi_ulong target_flock_addr,
7033 const struct flock64 *fl)
7034{
7035 struct target_flock64 *target_fl;
7036 short l_type;
7037
7038 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
7039 return -TARGET_EFAULT;
7040 }
7041
Laurent Vivierae68ad92018-05-10 01:11:21 +02007042 l_type = host_to_target_flock(fl->l_type);
Peter Maydell213d3e92016-06-13 11:22:05 +01007043 __put_user(l_type, &target_fl->l_type);
7044 __put_user(fl->l_whence, &target_fl->l_whence);
7045 __put_user(fl->l_start, &target_fl->l_start);
7046 __put_user(fl->l_len, &target_fl->l_len);
7047 __put_user(fl->l_pid, &target_fl->l_pid);
7048 unlock_user_struct(target_fl, target_flock_addr, 1);
7049 return 0;
7050}
7051
blueswir1992f48a2007-10-14 16:27:31 +00007052static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
bellard7775e9e2003-05-14 22:46:48 +00007053{
ths43f238d2007-01-05 20:55:49 +00007054 struct flock64 fl64;
Andreas Schwab8d5d3002014-03-07 15:24:08 +01007055#ifdef F_GETOWN_EX
7056 struct f_owner_ex fox;
7057 struct target_f_owner_ex *target_fox;
7058#endif
blueswir1992f48a2007-10-14 16:27:31 +00007059 abi_long ret;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007060 int host_cmd = target_to_host_fcntl_cmd(cmd);
7061
7062 if (host_cmd == -TARGET_EINVAL)
7063 return host_cmd;
pbrook53a59602006-03-25 19:31:22 +00007064
bellard7775e9e2003-05-14 22:46:48 +00007065 switch(cmd) {
7066 case TARGET_F_GETLK:
Peter Maydell213d3e92016-06-13 11:22:05 +01007067 ret = copy_from_user_flock(&fl64, arg);
7068 if (ret) {
7069 return ret;
7070 }
Peter Maydell435da5e2016-06-13 11:22:05 +01007071 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00007072 if (ret == 0) {
Peter Maydell213d3e92016-06-13 11:22:05 +01007073 ret = copy_to_user_flock(arg, &fl64);
bellard7775e9e2003-05-14 22:46:48 +00007074 }
7075 break;
ths3b46e622007-09-17 08:09:54 +00007076
bellard7775e9e2003-05-14 22:46:48 +00007077 case TARGET_F_SETLK:
7078 case TARGET_F_SETLKW:
Peter Maydell213d3e92016-06-13 11:22:05 +01007079 ret = copy_from_user_flock(&fl64, arg);
7080 if (ret) {
7081 return ret;
7082 }
Peter Maydell435da5e2016-06-13 11:22:05 +01007083 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00007084 break;
ths3b46e622007-09-17 08:09:54 +00007085
bellard7775e9e2003-05-14 22:46:48 +00007086 case TARGET_F_GETLK64:
Andreas Schwab2d92c682020-05-25 09:59:28 +02007087 case TARGET_F_OFD_GETLK:
Peter Maydell213d3e92016-06-13 11:22:05 +01007088 ret = copy_from_user_flock64(&fl64, arg);
7089 if (ret) {
7090 return ret;
7091 }
Peter Maydell435da5e2016-06-13 11:22:05 +01007092 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
ths43f238d2007-01-05 20:55:49 +00007093 if (ret == 0) {
Peter Maydell213d3e92016-06-13 11:22:05 +01007094 ret = copy_to_user_flock64(arg, &fl64);
ths43f238d2007-01-05 20:55:49 +00007095 }
bellard9ee1fa22007-11-11 15:11:19 +00007096 break;
bellard7775e9e2003-05-14 22:46:48 +00007097 case TARGET_F_SETLK64:
7098 case TARGET_F_SETLKW64:
Andreas Schwab2d92c682020-05-25 09:59:28 +02007099 case TARGET_F_OFD_SETLK:
7100 case TARGET_F_OFD_SETLKW:
Peter Maydell213d3e92016-06-13 11:22:05 +01007101 ret = copy_from_user_flock64(&fl64, arg);
7102 if (ret) {
7103 return ret;
7104 }
Peter Maydell435da5e2016-06-13 11:22:05 +01007105 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00007106 break;
7107
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007108 case TARGET_F_GETFL:
Peter Maydell435da5e2016-06-13 11:22:05 +01007109 ret = get_errno(safe_fcntl(fd, host_cmd, arg));
bellard9ee1fa22007-11-11 15:11:19 +00007110 if (ret >= 0) {
7111 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
7112 }
bellardffa65c32004-01-04 23:57:22 +00007113 break;
7114
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007115 case TARGET_F_SETFL:
Peter Maydell435da5e2016-06-13 11:22:05 +01007116 ret = get_errno(safe_fcntl(fd, host_cmd,
7117 target_to_host_bitmask(arg,
7118 fcntl_flags_tbl)));
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007119 break;
7120
Andreas Schwab8d5d3002014-03-07 15:24:08 +01007121#ifdef F_GETOWN_EX
7122 case TARGET_F_GETOWN_EX:
Peter Maydell435da5e2016-06-13 11:22:05 +01007123 ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
Andreas Schwab8d5d3002014-03-07 15:24:08 +01007124 if (ret >= 0) {
7125 if (!lock_user_struct(VERIFY_WRITE, target_fox, arg, 0))
7126 return -TARGET_EFAULT;
7127 target_fox->type = tswap32(fox.type);
7128 target_fox->pid = tswap32(fox.pid);
7129 unlock_user_struct(target_fox, arg, 1);
7130 }
7131 break;
7132#endif
7133
7134#ifdef F_SETOWN_EX
7135 case TARGET_F_SETOWN_EX:
7136 if (!lock_user_struct(VERIFY_READ, target_fox, arg, 1))
7137 return -TARGET_EFAULT;
7138 fox.type = tswap32(target_fox->type);
7139 fox.pid = tswap32(target_fox->pid);
7140 unlock_user_struct(target_fox, arg, 0);
Peter Maydell435da5e2016-06-13 11:22:05 +01007141 ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
Andreas Schwab8d5d3002014-03-07 15:24:08 +01007142 break;
7143#endif
7144
Timothy Baldwina7b4c9b2020-07-29 21:06:44 +01007145 case TARGET_F_SETSIG:
7146 ret = get_errno(safe_fcntl(fd, host_cmd, target_to_host_signal(arg)));
7147 break;
7148
7149 case TARGET_F_GETSIG:
7150 ret = host_to_target_signal(get_errno(safe_fcntl(fd, host_cmd, arg)));
7151 break;
7152
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007153 case TARGET_F_SETOWN:
7154 case TARGET_F_GETOWN:
Ulrich Hecht7e22e542009-07-24 19:10:27 +02007155 case TARGET_F_SETLEASE:
7156 case TARGET_F_GETLEASE:
Peter Maydell7e3b92e2016-06-20 15:50:37 +01007157 case TARGET_F_SETPIPE_SZ:
7158 case TARGET_F_GETPIPE_SZ:
Shu-Chun Weng2bb963f2020-12-18 11:32:10 -08007159 case TARGET_F_ADD_SEALS:
7160 case TARGET_F_GET_SEALS:
Peter Maydell435da5e2016-06-13 11:22:05 +01007161 ret = get_errno(safe_fcntl(fd, host_cmd, arg));
bellardffa65c32004-01-04 23:57:22 +00007162 break;
7163
bellard7775e9e2003-05-14 22:46:48 +00007164 default:
Peter Maydell435da5e2016-06-13 11:22:05 +01007165 ret = get_errno(safe_fcntl(fd, cmd, arg));
bellard7775e9e2003-05-14 22:46:48 +00007166 break;
7167 }
7168 return ret;
7169}
7170
bellard67867302003-11-23 17:05:30 +00007171#ifdef USE_UID16
bellard7775e9e2003-05-14 22:46:48 +00007172
bellard67867302003-11-23 17:05:30 +00007173static inline int high2lowuid(int uid)
7174{
7175 if (uid > 65535)
7176 return 65534;
7177 else
7178 return uid;
7179}
7180
7181static inline int high2lowgid(int gid)
7182{
7183 if (gid > 65535)
7184 return 65534;
7185 else
7186 return gid;
7187}
7188
7189static inline int low2highuid(int uid)
7190{
7191 if ((int16_t)uid == -1)
7192 return -1;
7193 else
7194 return uid;
7195}
7196
7197static inline int low2highgid(int gid)
7198{
7199 if ((int16_t)gid == -1)
7200 return -1;
7201 else
7202 return gid;
7203}
Riku Voipio0c866a72011-04-18 15:23:06 +03007204static inline int tswapid(int id)
7205{
7206 return tswap16(id);
7207}
Peter Maydell76ca3102014-03-02 19:36:41 +00007208
7209#define put_user_id(x, gaddr) put_user_u16(x, gaddr)
7210
Riku Voipio0c866a72011-04-18 15:23:06 +03007211#else /* !USE_UID16 */
7212static inline int high2lowuid(int uid)
7213{
7214 return uid;
7215}
7216static inline int high2lowgid(int gid)
7217{
7218 return gid;
7219}
7220static inline int low2highuid(int uid)
7221{
7222 return uid;
7223}
7224static inline int low2highgid(int gid)
7225{
7226 return gid;
7227}
7228static inline int tswapid(int id)
7229{
7230 return tswap32(id);
7231}
Peter Maydell76ca3102014-03-02 19:36:41 +00007232
7233#define put_user_id(x, gaddr) put_user_u32(x, gaddr)
7234
bellard67867302003-11-23 17:05:30 +00007235#endif /* USE_UID16 */
bellard1b6b0292003-03-22 17:31:38 +00007236
Peter Maydellfd6f7792016-03-01 16:33:02 +00007237/* We must do direct syscalls for setting UID/GID, because we want to
7238 * implement the Linux system call semantics of "change only for this thread",
7239 * not the libc/POSIX semantics of "change for all threads in process".
7240 * (See http://ewontfix.com/17/ for more details.)
7241 * We use the 32-bit version of the syscalls if present; if it is not
7242 * then either the host architecture supports 32-bit UIDs natively with
7243 * the standard syscall, or the 16-bit UID is the best we can do.
7244 */
7245#ifdef __NR_setuid32
7246#define __NR_sys_setuid __NR_setuid32
7247#else
7248#define __NR_sys_setuid __NR_setuid
7249#endif
7250#ifdef __NR_setgid32
7251#define __NR_sys_setgid __NR_setgid32
7252#else
7253#define __NR_sys_setgid __NR_setgid
7254#endif
7255#ifdef __NR_setresuid32
7256#define __NR_sys_setresuid __NR_setresuid32
7257#else
7258#define __NR_sys_setresuid __NR_setresuid
7259#endif
7260#ifdef __NR_setresgid32
7261#define __NR_sys_setresgid __NR_setresgid32
7262#else
7263#define __NR_sys_setresgid __NR_setresgid
7264#endif
7265
7266_syscall1(int, sys_setuid, uid_t, uid)
7267_syscall1(int, sys_setgid, gid_t, gid)
7268_syscall3(int, sys_setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
7269_syscall3(int, sys_setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
7270
bellard31e31b82003-02-18 22:55:36 +00007271void syscall_init(void)
7272{
bellard2ab83ea2003-06-15 19:56:46 +00007273 IOCTLEntry *ie;
7274 const argtype *arg_type;
7275 int size;
7276
Alexander Graf8be656b2015-05-06 23:47:32 +02007277 thunk_init(STRUCT_MAX);
7278
Blue Swirl001faf32009-05-13 17:53:17 +00007279#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
ths5fafdf22007-09-16 21:08:06 +00007280#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
bellard31e31b82003-02-18 22:55:36 +00007281#include "syscall_types.h"
7282#undef STRUCT
7283#undef STRUCT_SPECIAL
bellard2ab83ea2003-06-15 19:56:46 +00007284
7285 /* we patch the ioctl size if necessary. We rely on the fact that
7286 no ioctl has all the bits at '1' in the size field */
7287 ie = ioctl_entries;
7288 while (ie->target_cmd != 0) {
7289 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
7290 TARGET_IOC_SIZEMASK) {
7291 arg_type = ie->arg_type;
7292 if (arg_type[0] != TYPE_PTR) {
ths5fafdf22007-09-16 21:08:06 +00007293 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00007294 ie->target_cmd);
7295 exit(1);
7296 }
7297 arg_type++;
7298 size = thunk_type_size(arg_type, 0);
ths5fafdf22007-09-16 21:08:06 +00007299 ie->target_cmd = (ie->target_cmd &
bellard2ab83ea2003-06-15 19:56:46 +00007300 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
7301 (size << TARGET_IOC_SIZESHIFT);
7302 }
thsb92c47c2007-11-01 00:07:38 +00007303
bellard2ab83ea2003-06-15 19:56:46 +00007304 /* automatic consistency check if same arch */
balrog872ea0c2008-09-21 02:31:19 +00007305#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
7306 (defined(__x86_64__) && defined(TARGET_X86_64))
7307 if (unlikely(ie->target_cmd != ie->host_cmd)) {
7308 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
7309 ie->name, ie->target_cmd, ie->host_cmd);
bellard2ab83ea2003-06-15 19:56:46 +00007310 }
7311#endif
7312 ie++;
7313 }
bellard31e31b82003-02-18 22:55:36 +00007314}
bellardc573ff62004-01-04 15:51:36 +00007315
pbrookce4defa2006-02-09 16:49:55 +00007316#ifdef TARGET_NR_truncate64
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02007317static inline abi_long target_truncate64(CPUArchState *cpu_env, const char *arg1,
blueswir1992f48a2007-10-14 16:27:31 +00007318 abi_long arg2,
7319 abi_long arg3,
7320 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00007321{
James Clarke8bf8e9d2017-09-15 20:33:13 +01007322 if (regpairs_aligned(cpu_env, TARGET_NR_truncate64)) {
pbrookce4defa2006-02-09 16:49:55 +00007323 arg2 = arg3;
7324 arg3 = arg4;
Riku Voipio48e515d2011-07-12 15:40:51 +03007325 }
pbrookce4defa2006-02-09 16:49:55 +00007326 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
7327}
7328#endif
7329
7330#ifdef TARGET_NR_ftruncate64
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02007331static inline abi_long target_ftruncate64(CPUArchState *cpu_env, abi_long arg1,
blueswir1992f48a2007-10-14 16:27:31 +00007332 abi_long arg2,
7333 abi_long arg3,
7334 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00007335{
James Clarke8bf8e9d2017-09-15 20:33:13 +01007336 if (regpairs_aligned(cpu_env, TARGET_NR_ftruncate64)) {
pbrookce4defa2006-02-09 16:49:55 +00007337 arg2 = arg3;
7338 arg3 = arg4;
Riku Voipio48e515d2011-07-12 15:40:51 +03007339 }
pbrookce4defa2006-02-09 16:49:55 +00007340 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
7341}
7342#endif
7343
Alistair Francis859e8a82020-03-12 15:13:49 -07007344#if defined(TARGET_NR_timer_settime) || \
7345 (defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD))
Filip Bozuta2c86c902020-07-22 17:34:20 +02007346static inline abi_long target_to_host_itimerspec(struct itimerspec *host_its,
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007347 abi_ulong target_addr)
7348{
Filip Bozuta2c86c902020-07-22 17:34:20 +02007349 if (target_to_host_timespec(&host_its->it_interval, target_addr +
7350 offsetof(struct target_itimerspec,
7351 it_interval)) ||
7352 target_to_host_timespec(&host_its->it_value, target_addr +
7353 offsetof(struct target_itimerspec,
7354 it_value))) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007355 return -TARGET_EFAULT;
7356 }
7357
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007358 return 0;
7359}
Alistair Francis859e8a82020-03-12 15:13:49 -07007360#endif
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007361
Filip Bozuta828cb3a2020-07-22 17:34:21 +02007362#if defined(TARGET_NR_timer_settime64) || \
7363 (defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD))
7364static inline abi_long target_to_host_itimerspec64(struct itimerspec *host_its,
7365 abi_ulong target_addr)
7366{
7367 if (target_to_host_timespec64(&host_its->it_interval, target_addr +
7368 offsetof(struct target__kernel_itimerspec,
7369 it_interval)) ||
7370 target_to_host_timespec64(&host_its->it_value, target_addr +
7371 offsetof(struct target__kernel_itimerspec,
7372 it_value))) {
7373 return -TARGET_EFAULT;
7374 }
7375
7376 return 0;
7377}
7378#endif
7379
Alistair Francis859e8a82020-03-12 15:13:49 -07007380#if ((defined(TARGET_NR_timerfd_gettime) || \
7381 defined(TARGET_NR_timerfd_settime)) && defined(CONFIG_TIMERFD)) || \
Filip Bozuta2c86c902020-07-22 17:34:20 +02007382 defined(TARGET_NR_timer_gettime) || defined(TARGET_NR_timer_settime)
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007383static inline abi_long host_to_target_itimerspec(abi_ulong target_addr,
Filip Bozuta2c86c902020-07-22 17:34:20 +02007384 struct itimerspec *host_its)
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007385{
Filip Bozuta2c86c902020-07-22 17:34:20 +02007386 if (host_to_target_timespec(target_addr + offsetof(struct target_itimerspec,
7387 it_interval),
7388 &host_its->it_interval) ||
7389 host_to_target_timespec(target_addr + offsetof(struct target_itimerspec,
7390 it_value),
7391 &host_its->it_value)) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007392 return -TARGET_EFAULT;
7393 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007394 return 0;
7395}
Alistair Francis859e8a82020-03-12 15:13:49 -07007396#endif
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +11007397
Filip Bozuta828cb3a2020-07-22 17:34:21 +02007398#if ((defined(TARGET_NR_timerfd_gettime64) || \
7399 defined(TARGET_NR_timerfd_settime64)) && defined(CONFIG_TIMERFD)) || \
7400 defined(TARGET_NR_timer_gettime64) || defined(TARGET_NR_timer_settime64)
7401static inline abi_long host_to_target_itimerspec64(abi_ulong target_addr,
7402 struct itimerspec *host_its)
7403{
7404 if (host_to_target_timespec64(target_addr +
7405 offsetof(struct target__kernel_itimerspec,
7406 it_interval),
7407 &host_its->it_interval) ||
7408 host_to_target_timespec64(target_addr +
7409 offsetof(struct target__kernel_itimerspec,
7410 it_value),
7411 &host_its->it_value)) {
7412 return -TARGET_EFAULT;
7413 }
7414 return 0;
7415}
7416#endif
7417
Alistair Francis859e8a82020-03-12 15:13:49 -07007418#if defined(TARGET_NR_adjtimex) || \
7419 (defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME))
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +02007420static inline abi_long target_to_host_timex(struct timex *host_tx,
7421 abi_long target_addr)
7422{
7423 struct target_timex *target_tx;
7424
7425 if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) {
7426 return -TARGET_EFAULT;
7427 }
7428
7429 __get_user(host_tx->modes, &target_tx->modes);
7430 __get_user(host_tx->offset, &target_tx->offset);
7431 __get_user(host_tx->freq, &target_tx->freq);
7432 __get_user(host_tx->maxerror, &target_tx->maxerror);
7433 __get_user(host_tx->esterror, &target_tx->esterror);
7434 __get_user(host_tx->status, &target_tx->status);
7435 __get_user(host_tx->constant, &target_tx->constant);
7436 __get_user(host_tx->precision, &target_tx->precision);
7437 __get_user(host_tx->tolerance, &target_tx->tolerance);
7438 __get_user(host_tx->time.tv_sec, &target_tx->time.tv_sec);
7439 __get_user(host_tx->time.tv_usec, &target_tx->time.tv_usec);
7440 __get_user(host_tx->tick, &target_tx->tick);
7441 __get_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7442 __get_user(host_tx->jitter, &target_tx->jitter);
7443 __get_user(host_tx->shift, &target_tx->shift);
7444 __get_user(host_tx->stabil, &target_tx->stabil);
7445 __get_user(host_tx->jitcnt, &target_tx->jitcnt);
7446 __get_user(host_tx->calcnt, &target_tx->calcnt);
7447 __get_user(host_tx->errcnt, &target_tx->errcnt);
7448 __get_user(host_tx->stbcnt, &target_tx->stbcnt);
7449 __get_user(host_tx->tai, &target_tx->tai);
7450
7451 unlock_user_struct(target_tx, target_addr, 0);
7452 return 0;
7453}
7454
7455static inline abi_long host_to_target_timex(abi_long target_addr,
7456 struct timex *host_tx)
7457{
7458 struct target_timex *target_tx;
7459
7460 if (!lock_user_struct(VERIFY_WRITE, target_tx, target_addr, 0)) {
7461 return -TARGET_EFAULT;
7462 }
7463
7464 __put_user(host_tx->modes, &target_tx->modes);
7465 __put_user(host_tx->offset, &target_tx->offset);
7466 __put_user(host_tx->freq, &target_tx->freq);
7467 __put_user(host_tx->maxerror, &target_tx->maxerror);
7468 __put_user(host_tx->esterror, &target_tx->esterror);
7469 __put_user(host_tx->status, &target_tx->status);
7470 __put_user(host_tx->constant, &target_tx->constant);
7471 __put_user(host_tx->precision, &target_tx->precision);
7472 __put_user(host_tx->tolerance, &target_tx->tolerance);
7473 __put_user(host_tx->time.tv_sec, &target_tx->time.tv_sec);
7474 __put_user(host_tx->time.tv_usec, &target_tx->time.tv_usec);
7475 __put_user(host_tx->tick, &target_tx->tick);
7476 __put_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7477 __put_user(host_tx->jitter, &target_tx->jitter);
7478 __put_user(host_tx->shift, &target_tx->shift);
7479 __put_user(host_tx->stabil, &target_tx->stabil);
7480 __put_user(host_tx->jitcnt, &target_tx->jitcnt);
7481 __put_user(host_tx->calcnt, &target_tx->calcnt);
7482 __put_user(host_tx->errcnt, &target_tx->errcnt);
7483 __put_user(host_tx->stbcnt, &target_tx->stbcnt);
7484 __put_user(host_tx->tai, &target_tx->tai);
7485
7486 unlock_user_struct(target_tx, target_addr, 1);
7487 return 0;
7488}
Alistair Francis859e8a82020-03-12 15:13:49 -07007489#endif
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +02007490
Filip Bozuta6ac03b22020-08-24 21:21:15 +02007491
7492#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
7493static inline abi_long target_to_host_timex64(struct timex *host_tx,
7494 abi_long target_addr)
7495{
7496 struct target__kernel_timex *target_tx;
7497
7498 if (copy_from_user_timeval64(&host_tx->time, target_addr +
7499 offsetof(struct target__kernel_timex,
7500 time))) {
7501 return -TARGET_EFAULT;
7502 }
7503
7504 if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) {
7505 return -TARGET_EFAULT;
7506 }
7507
7508 __get_user(host_tx->modes, &target_tx->modes);
7509 __get_user(host_tx->offset, &target_tx->offset);
7510 __get_user(host_tx->freq, &target_tx->freq);
7511 __get_user(host_tx->maxerror, &target_tx->maxerror);
7512 __get_user(host_tx->esterror, &target_tx->esterror);
7513 __get_user(host_tx->status, &target_tx->status);
7514 __get_user(host_tx->constant, &target_tx->constant);
7515 __get_user(host_tx->precision, &target_tx->precision);
7516 __get_user(host_tx->tolerance, &target_tx->tolerance);
7517 __get_user(host_tx->tick, &target_tx->tick);
7518 __get_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7519 __get_user(host_tx->jitter, &target_tx->jitter);
7520 __get_user(host_tx->shift, &target_tx->shift);
7521 __get_user(host_tx->stabil, &target_tx->stabil);
7522 __get_user(host_tx->jitcnt, &target_tx->jitcnt);
7523 __get_user(host_tx->calcnt, &target_tx->calcnt);
7524 __get_user(host_tx->errcnt, &target_tx->errcnt);
7525 __get_user(host_tx->stbcnt, &target_tx->stbcnt);
7526 __get_user(host_tx->tai, &target_tx->tai);
7527
7528 unlock_user_struct(target_tx, target_addr, 0);
7529 return 0;
7530}
7531
7532static inline abi_long host_to_target_timex64(abi_long target_addr,
7533 struct timex *host_tx)
7534{
7535 struct target__kernel_timex *target_tx;
7536
7537 if (copy_to_user_timeval64(target_addr +
7538 offsetof(struct target__kernel_timex, time),
7539 &host_tx->time)) {
7540 return -TARGET_EFAULT;
7541 }
7542
7543 if (!lock_user_struct(VERIFY_WRITE, target_tx, target_addr, 0)) {
7544 return -TARGET_EFAULT;
7545 }
7546
7547 __put_user(host_tx->modes, &target_tx->modes);
7548 __put_user(host_tx->offset, &target_tx->offset);
7549 __put_user(host_tx->freq, &target_tx->freq);
7550 __put_user(host_tx->maxerror, &target_tx->maxerror);
7551 __put_user(host_tx->esterror, &target_tx->esterror);
7552 __put_user(host_tx->status, &target_tx->status);
7553 __put_user(host_tx->constant, &target_tx->constant);
7554 __put_user(host_tx->precision, &target_tx->precision);
7555 __put_user(host_tx->tolerance, &target_tx->tolerance);
7556 __put_user(host_tx->tick, &target_tx->tick);
7557 __put_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7558 __put_user(host_tx->jitter, &target_tx->jitter);
7559 __put_user(host_tx->shift, &target_tx->shift);
7560 __put_user(host_tx->stabil, &target_tx->stabil);
7561 __put_user(host_tx->jitcnt, &target_tx->jitcnt);
7562 __put_user(host_tx->calcnt, &target_tx->calcnt);
7563 __put_user(host_tx->errcnt, &target_tx->errcnt);
7564 __put_user(host_tx->stbcnt, &target_tx->stbcnt);
7565 __put_user(host_tx->tai, &target_tx->tai);
7566
7567 unlock_user_struct(target_tx, target_addr, 1);
7568 return 0;
7569}
7570#endif
7571
Michael Forney96ff7582021-05-25 20:55:56 -07007572#ifndef HAVE_SIGEV_NOTIFY_THREAD_ID
7573#define sigev_notify_thread_id _sigev_un._tid
7574#endif
7575
Peter Maydellc0659762014-08-09 15:42:32 +01007576static inline abi_long target_to_host_sigevent(struct sigevent *host_sevp,
7577 abi_ulong target_addr)
7578{
7579 struct target_sigevent *target_sevp;
7580
7581 if (!lock_user_struct(VERIFY_READ, target_sevp, target_addr, 1)) {
7582 return -TARGET_EFAULT;
7583 }
7584
7585 /* This union is awkward on 64 bit systems because it has a 32 bit
7586 * integer and a pointer in it; we follow the conversion approach
7587 * used for handling sigval types in signal.c so the guest should get
7588 * the correct value back even if we did a 64 bit byteswap and it's
7589 * using the 32 bit integer.
7590 */
7591 host_sevp->sigev_value.sival_ptr =
7592 (void *)(uintptr_t)tswapal(target_sevp->sigev_value.sival_ptr);
7593 host_sevp->sigev_signo =
7594 target_to_host_signal(tswap32(target_sevp->sigev_signo));
7595 host_sevp->sigev_notify = tswap32(target_sevp->sigev_notify);
Michael Forney96ff7582021-05-25 20:55:56 -07007596 host_sevp->sigev_notify_thread_id = tswap32(target_sevp->_sigev_un._tid);
Peter Maydellc0659762014-08-09 15:42:32 +01007597
7598 unlock_user_struct(target_sevp, target_addr, 1);
7599 return 0;
7600}
7601
Tom Musta6f6a4032014-08-12 13:53:42 -05007602#if defined(TARGET_NR_mlockall)
7603static inline int target_to_host_mlockall_arg(int arg)
7604{
7605 int result = 0;
7606
Filip Bozuta02e5d7d2020-08-11 18:45:51 +02007607 if (arg & TARGET_MCL_CURRENT) {
Tom Musta6f6a4032014-08-12 13:53:42 -05007608 result |= MCL_CURRENT;
7609 }
Filip Bozuta02e5d7d2020-08-11 18:45:51 +02007610 if (arg & TARGET_MCL_FUTURE) {
Tom Musta6f6a4032014-08-12 13:53:42 -05007611 result |= MCL_FUTURE;
7612 }
Filip Bozuta02e5d7d2020-08-11 18:45:51 +02007613#ifdef MCL_ONFAULT
7614 if (arg & TARGET_MCL_ONFAULT) {
7615 result |= MCL_ONFAULT;
7616 }
7617#endif
7618
Tom Musta6f6a4032014-08-12 13:53:42 -05007619 return result;
7620}
7621#endif
7622
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02007623#if (defined(TARGET_NR_stat64) || defined(TARGET_NR_lstat64) || \
7624 defined(TARGET_NR_fstat64) || defined(TARGET_NR_fstatat64) || \
7625 defined(TARGET_NR_newfstatat))
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02007626static inline abi_long host_to_target_stat64(CPUArchState *cpu_env,
balrog6a24a772008-09-20 02:23:36 +00007627 abi_ulong target_addr,
7628 struct stat *host_st)
7629{
Alexander Graf09701192013-09-03 20:12:15 +01007630#if defined(TARGET_ARM) && defined(TARGET_ABI32)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02007631 if (cpu_env->eabi) {
balrog6a24a772008-09-20 02:23:36 +00007632 struct target_eabi_stat64 *target_st;
7633
7634 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
7635 return -TARGET_EFAULT;
7636 memset(target_st, 0, sizeof(struct target_eabi_stat64));
7637 __put_user(host_st->st_dev, &target_st->st_dev);
7638 __put_user(host_st->st_ino, &target_st->st_ino);
7639#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
7640 __put_user(host_st->st_ino, &target_st->__st_ino);
7641#endif
7642 __put_user(host_st->st_mode, &target_st->st_mode);
7643 __put_user(host_st->st_nlink, &target_st->st_nlink);
7644 __put_user(host_st->st_uid, &target_st->st_uid);
7645 __put_user(host_st->st_gid, &target_st->st_gid);
7646 __put_user(host_st->st_rdev, &target_st->st_rdev);
7647 __put_user(host_st->st_size, &target_st->st_size);
7648 __put_user(host_st->st_blksize, &target_st->st_blksize);
7649 __put_user(host_st->st_blocks, &target_st->st_blocks);
7650 __put_user(host_st->st_atime, &target_st->target_st_atime);
7651 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
7652 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
Michael Forneyfebf6fa2021-05-25 20:55:31 -07007653#ifdef HAVE_STRUCT_STAT_ST_ATIM
Chen-Yu Tsai5f992db2019-05-23 00:21:47 +08007654 __put_user(host_st->st_atim.tv_nsec, &target_st->target_st_atime_nsec);
7655 __put_user(host_st->st_mtim.tv_nsec, &target_st->target_st_mtime_nsec);
7656 __put_user(host_st->st_ctim.tv_nsec, &target_st->target_st_ctime_nsec);
7657#endif
balrog6a24a772008-09-20 02:23:36 +00007658 unlock_user_struct(target_st, target_addr, 1);
7659 } else
7660#endif
7661 {
Stefan Weil20d155b2013-10-30 22:52:24 +01007662#if defined(TARGET_HAS_STRUCT_STAT64)
balrog6a24a772008-09-20 02:23:36 +00007663 struct target_stat64 *target_st;
Stefan Weil20d155b2013-10-30 22:52:24 +01007664#else
7665 struct target_stat *target_st;
aurel329d33b762009-04-08 23:07:05 +00007666#endif
balrog6a24a772008-09-20 02:23:36 +00007667
7668 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
7669 return -TARGET_EFAULT;
aurel329d33b762009-04-08 23:07:05 +00007670 memset(target_st, 0, sizeof(*target_st));
balrog6a24a772008-09-20 02:23:36 +00007671 __put_user(host_st->st_dev, &target_st->st_dev);
7672 __put_user(host_st->st_ino, &target_st->st_ino);
7673#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
7674 __put_user(host_st->st_ino, &target_st->__st_ino);
7675#endif
7676 __put_user(host_st->st_mode, &target_st->st_mode);
7677 __put_user(host_st->st_nlink, &target_st->st_nlink);
7678 __put_user(host_st->st_uid, &target_st->st_uid);
7679 __put_user(host_st->st_gid, &target_st->st_gid);
7680 __put_user(host_st->st_rdev, &target_st->st_rdev);
7681 /* XXX: better use of kernel struct */
7682 __put_user(host_st->st_size, &target_st->st_size);
7683 __put_user(host_st->st_blksize, &target_st->st_blksize);
7684 __put_user(host_st->st_blocks, &target_st->st_blocks);
7685 __put_user(host_st->st_atime, &target_st->target_st_atime);
7686 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
7687 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
Michael Forneyfebf6fa2021-05-25 20:55:31 -07007688#ifdef HAVE_STRUCT_STAT_ST_ATIM
Chen-Yu Tsai5f992db2019-05-23 00:21:47 +08007689 __put_user(host_st->st_atim.tv_nsec, &target_st->target_st_atime_nsec);
7690 __put_user(host_st->st_mtim.tv_nsec, &target_st->target_st_mtime_nsec);
7691 __put_user(host_st->st_ctim.tv_nsec, &target_st->target_st_ctime_nsec);
7692#endif
balrog6a24a772008-09-20 02:23:36 +00007693 unlock_user_struct(target_st, target_addr, 1);
7694 }
7695
7696 return 0;
7697}
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02007698#endif
balrog6a24a772008-09-20 02:23:36 +00007699
Aleksandar Rikaloefa92182019-06-28 12:43:34 +02007700#if defined(TARGET_NR_statx) && defined(__NR_statx)
7701static inline abi_long host_to_target_statx(struct target_statx *host_stx,
7702 abi_ulong target_addr)
7703{
7704 struct target_statx *target_stx;
7705
7706 if (!lock_user_struct(VERIFY_WRITE, target_stx, target_addr, 0)) {
7707 return -TARGET_EFAULT;
7708 }
7709 memset(target_stx, 0, sizeof(*target_stx));
7710
7711 __put_user(host_stx->stx_mask, &target_stx->stx_mask);
7712 __put_user(host_stx->stx_blksize, &target_stx->stx_blksize);
7713 __put_user(host_stx->stx_attributes, &target_stx->stx_attributes);
7714 __put_user(host_stx->stx_nlink, &target_stx->stx_nlink);
7715 __put_user(host_stx->stx_uid, &target_stx->stx_uid);
7716 __put_user(host_stx->stx_gid, &target_stx->stx_gid);
7717 __put_user(host_stx->stx_mode, &target_stx->stx_mode);
7718 __put_user(host_stx->stx_ino, &target_stx->stx_ino);
7719 __put_user(host_stx->stx_size, &target_stx->stx_size);
7720 __put_user(host_stx->stx_blocks, &target_stx->stx_blocks);
7721 __put_user(host_stx->stx_attributes_mask, &target_stx->stx_attributes_mask);
7722 __put_user(host_stx->stx_atime.tv_sec, &target_stx->stx_atime.tv_sec);
7723 __put_user(host_stx->stx_atime.tv_nsec, &target_stx->stx_atime.tv_nsec);
Ariadne Conilld1e26702019-11-22 11:40:40 -06007724 __put_user(host_stx->stx_btime.tv_sec, &target_stx->stx_btime.tv_sec);
7725 __put_user(host_stx->stx_btime.tv_nsec, &target_stx->stx_btime.tv_nsec);
7726 __put_user(host_stx->stx_ctime.tv_sec, &target_stx->stx_ctime.tv_sec);
7727 __put_user(host_stx->stx_ctime.tv_nsec, &target_stx->stx_ctime.tv_nsec);
7728 __put_user(host_stx->stx_mtime.tv_sec, &target_stx->stx_mtime.tv_sec);
7729 __put_user(host_stx->stx_mtime.tv_nsec, &target_stx->stx_mtime.tv_nsec);
Aleksandar Rikaloefa92182019-06-28 12:43:34 +02007730 __put_user(host_stx->stx_rdev_major, &target_stx->stx_rdev_major);
7731 __put_user(host_stx->stx_rdev_minor, &target_stx->stx_rdev_minor);
7732 __put_user(host_stx->stx_dev_major, &target_stx->stx_dev_major);
7733 __put_user(host_stx->stx_dev_minor, &target_stx->stx_dev_minor);
7734
7735 unlock_user_struct(target_stx, target_addr, 1);
7736
7737 return 0;
7738}
7739#endif
7740
Alistair Francis14690292020-03-18 15:47:01 -07007741static int do_sys_futex(int *uaddr, int op, int val,
7742 const struct timespec *timeout, int *uaddr2,
7743 int val3)
7744{
7745#if HOST_LONG_BITS == 64
7746#if defined(__NR_futex)
7747 /* always a 64-bit time_t, it doesn't define _time64 version */
7748 return sys_futex(uaddr, op, val, timeout, uaddr2, val3);
7749
7750#endif
7751#else /* HOST_LONG_BITS == 64 */
7752#if defined(__NR_futex_time64)
7753 if (sizeof(timeout->tv_sec) == 8) {
7754 /* _time64 function on 32bit arch */
7755 return sys_futex_time64(uaddr, op, val, timeout, uaddr2, val3);
7756 }
7757#endif
7758#if defined(__NR_futex)
7759 /* old function on 32bit arch */
7760 return sys_futex(uaddr, op, val, timeout, uaddr2, val3);
7761#endif
7762#endif /* HOST_LONG_BITS == 64 */
7763 g_assert_not_reached();
7764}
7765
7766static int do_safe_futex(int *uaddr, int op, int val,
7767 const struct timespec *timeout, int *uaddr2,
7768 int val3)
7769{
7770#if HOST_LONG_BITS == 64
7771#if defined(__NR_futex)
7772 /* always a 64-bit time_t, it doesn't define _time64 version */
7773 return get_errno(safe_futex(uaddr, op, val, timeout, uaddr2, val3));
7774#endif
7775#else /* HOST_LONG_BITS == 64 */
7776#if defined(__NR_futex_time64)
7777 if (sizeof(timeout->tv_sec) == 8) {
7778 /* _time64 function on 32bit arch */
7779 return get_errno(safe_futex_time64(uaddr, op, val, timeout, uaddr2,
7780 val3));
7781 }
7782#endif
7783#if defined(__NR_futex)
7784 /* old function on 32bit arch */
7785 return get_errno(safe_futex(uaddr, op, val, timeout, uaddr2, val3));
7786#endif
7787#endif /* HOST_LONG_BITS == 64 */
7788 return -TARGET_ENOSYS;
7789}
Aleksandar Rikaloefa92182019-06-28 12:43:34 +02007790
pbrookbd0c5662008-05-29 14:34:11 +00007791/* ??? Using host futex calls even when target atomic operations
7792 are not really atomic probably breaks things. However implementing
7793 futexes locally would make futexes shared between multiple processes
7794 tricky. However they're probably useless because guest atomic
7795 operations won't work either. */
Richard Henderson0fbc0f82022-08-28 19:09:59 -07007796#if defined(TARGET_NR_futex) || defined(TARGET_NR_futex_time64)
7797static int do_futex(CPUState *cpu, bool time64, target_ulong uaddr,
7798 int op, int val, target_ulong timeout,
7799 target_ulong uaddr2, int val3)
pbrookbd0c5662008-05-29 14:34:11 +00007800{
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007801 struct timespec ts, *pts = NULL;
7802 void *haddr2 = NULL;
Nathan Froyda16aae02009-08-03 08:43:29 -07007803 int base_op;
pbrookbd0c5662008-05-29 14:34:11 +00007804
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007805 /* We assume FUTEX_* constants are the same on both host and target. */
Martin Mohringa29ccd62009-05-04 21:34:56 +03007806#ifdef FUTEX_CMD_MASK
Nathan Froyda16aae02009-08-03 08:43:29 -07007807 base_op = op & FUTEX_CMD_MASK;
Martin Mohringa29ccd62009-05-04 21:34:56 +03007808#else
Nathan Froyda16aae02009-08-03 08:43:29 -07007809 base_op = op;
Martin Mohringa29ccd62009-05-04 21:34:56 +03007810#endif
Nathan Froyda16aae02009-08-03 08:43:29 -07007811 switch (base_op) {
pbrookbd0c5662008-05-29 14:34:11 +00007812 case FUTEX_WAIT:
John Rigbycce246e2013-02-23 16:14:07 -07007813 case FUTEX_WAIT_BITSET:
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007814 val = tswap32(val);
7815 break;
Richard Hendersonc72a90d2022-08-28 19:10:03 -07007816 case FUTEX_WAIT_REQUEUE_PI:
7817 val = tswap32(val);
7818 haddr2 = g2h(cpu, uaddr2);
7819 break;
7820 case FUTEX_LOCK_PI:
7821 case FUTEX_LOCK_PI2:
7822 break;
pbrookbd0c5662008-05-29 14:34:11 +00007823 case FUTEX_WAKE:
Richard Hendersona6180f82022-08-28 19:10:01 -07007824 case FUTEX_WAKE_BITSET:
Richard Hendersonc72a90d2022-08-28 19:10:03 -07007825 case FUTEX_TRYLOCK_PI:
7826 case FUTEX_UNLOCK_PI:
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007827 timeout = 0;
7828 break;
pbrookbd0c5662008-05-29 14:34:11 +00007829 case FUTEX_FD:
Richard Henderson0f946732022-08-28 19:10:02 -07007830 val = target_to_host_signal(val);
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007831 timeout = 0;
7832 break;
pbrookbd0c5662008-05-29 14:34:11 +00007833 case FUTEX_CMP_REQUEUE:
Richard Hendersonc72a90d2022-08-28 19:10:03 -07007834 case FUTEX_CMP_REQUEUE_PI:
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007835 val3 = tswap32(val3);
7836 /* fall through */
7837 case FUTEX_REQUEUE:
Nathan Froyda16aae02009-08-03 08:43:29 -07007838 case FUTEX_WAKE_OP:
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007839 /*
7840 * For these, the 4th argument is not TIMEOUT, but VAL2.
7841 * But the prototype of do_safe_futex takes a pointer, so
7842 * insert casts to satisfy the compiler. We do not need
7843 * to tswap VAL2 since it's not compared to guest memory.
7844 */
7845 pts = (struct timespec *)(uintptr_t)timeout;
7846 timeout = 0;
7847 haddr2 = g2h(cpu, uaddr2);
7848 break;
pbrookbd0c5662008-05-29 14:34:11 +00007849 default:
7850 return -TARGET_ENOSYS;
7851 }
Richard Henderson57b9ccd2022-08-28 19:10:00 -07007852 if (timeout) {
7853 pts = &ts;
7854 if (time64
7855 ? target_to_host_timespec64(pts, timeout)
7856 : target_to_host_timespec(pts, timeout)) {
7857 return -TARGET_EFAULT;
7858 }
7859 }
7860 return do_safe_futex(g2h(cpu, uaddr), op, val, pts, haddr2, val3);
pbrookbd0c5662008-05-29 14:34:11 +00007861}
Alistair Francis859e8a82020-03-12 15:13:49 -07007862#endif
Alistair Francis14690292020-03-18 15:47:01 -07007863
Laurent Vivier0f0426f2015-09-01 22:27:33 +02007864#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
7865static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname,
7866 abi_long handle, abi_long mount_id,
7867 abi_long flags)
7868{
7869 struct file_handle *target_fh;
7870 struct file_handle *fh;
7871 int mid = 0;
7872 abi_long ret;
7873 char *name;
7874 unsigned int size, total_size;
7875
7876 if (get_user_s32(size, handle)) {
7877 return -TARGET_EFAULT;
7878 }
7879
7880 name = lock_user_string(pathname);
7881 if (!name) {
7882 return -TARGET_EFAULT;
7883 }
7884
7885 total_size = sizeof(struct file_handle) + size;
7886 target_fh = lock_user(VERIFY_WRITE, handle, total_size, 0);
7887 if (!target_fh) {
7888 unlock_user(name, pathname, 0);
7889 return -TARGET_EFAULT;
7890 }
7891
7892 fh = g_malloc0(total_size);
7893 fh->handle_bytes = size;
7894
7895 ret = get_errno(name_to_handle_at(dirfd, path(name), fh, &mid, flags));
7896 unlock_user(name, pathname, 0);
7897
7898 /* man name_to_handle_at(2):
7899 * Other than the use of the handle_bytes field, the caller should treat
7900 * the file_handle structure as an opaque data type
7901 */
7902
7903 memcpy(target_fh, fh, total_size);
7904 target_fh->handle_bytes = tswap32(fh->handle_bytes);
7905 target_fh->handle_type = tswap32(fh->handle_type);
7906 g_free(fh);
7907 unlock_user(target_fh, handle, total_size);
7908
7909 if (put_user_s32(mid, mount_id)) {
7910 return -TARGET_EFAULT;
7911 }
7912
7913 return ret;
7914
7915}
7916#endif
7917
7918#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
7919static abi_long do_open_by_handle_at(abi_long mount_fd, abi_long handle,
7920 abi_long flags)
7921{
7922 struct file_handle *target_fh;
7923 struct file_handle *fh;
7924 unsigned int size, total_size;
7925 abi_long ret;
7926
7927 if (get_user_s32(size, handle)) {
7928 return -TARGET_EFAULT;
7929 }
7930
7931 total_size = sizeof(struct file_handle) + size;
7932 target_fh = lock_user(VERIFY_READ, handle, total_size, 1);
7933 if (!target_fh) {
7934 return -TARGET_EFAULT;
7935 }
7936
Thomas Huthe9d49d52015-10-09 17:56:38 +02007937 fh = g_memdup(target_fh, total_size);
Laurent Vivier0f0426f2015-09-01 22:27:33 +02007938 fh->handle_bytes = size;
7939 fh->handle_type = tswap32(target_fh->handle_type);
7940
7941 ret = get_errno(open_by_handle_at(mount_fd, fh,
7942 target_to_host_bitmask(flags, fcntl_flags_tbl)));
7943
7944 g_free(fh);
7945
7946 unlock_user(target_fh, handle, total_size);
7947
7948 return ret;
7949}
7950#endif
pbrookbd0c5662008-05-29 14:34:11 +00007951
Laurent Viviere36800c2015-10-02 14:48:09 +02007952#if defined(TARGET_NR_signalfd) || defined(TARGET_NR_signalfd4)
7953
Laurent Viviere36800c2015-10-02 14:48:09 +02007954static abi_long do_signalfd4(int fd, abi_long mask, int flags)
7955{
7956 int host_flags;
7957 target_sigset_t *target_mask;
7958 sigset_t host_mask;
7959 abi_long ret;
7960
Helge Deller78721302021-02-10 07:12:14 +01007961 if (flags & ~(TARGET_O_NONBLOCK_MASK | TARGET_O_CLOEXEC)) {
Laurent Viviere36800c2015-10-02 14:48:09 +02007962 return -TARGET_EINVAL;
7963 }
7964 if (!lock_user_struct(VERIFY_READ, target_mask, mask, 1)) {
7965 return -TARGET_EFAULT;
7966 }
7967
7968 target_to_host_sigset(&host_mask, target_mask);
7969
7970 host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
7971
7972 ret = get_errno(signalfd(fd, &host_mask, host_flags));
7973 if (ret >= 0) {
7974 fd_trans_register(ret, &target_signalfd_trans);
7975 }
7976
7977 unlock_user_struct(target_mask, mask, 0);
7978
7979 return ret;
7980}
7981#endif
7982
pbrook1d9d8b52009-04-16 15:17:02 +00007983/* Map host to target signal numbers for the wait family of syscalls.
7984 Assume all other status bits are the same. */
Richard Hendersona05c6402012-09-15 11:34:20 -07007985int host_to_target_waitstatus(int status)
pbrook1d9d8b52009-04-16 15:17:02 +00007986{
7987 if (WIFSIGNALED(status)) {
7988 return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
7989 }
7990 if (WIFSTOPPED(status)) {
7991 return (host_to_target_signal(WSTOPSIG(status)) << 8)
7992 | (status & 0xff);
7993 }
7994 return status;
7995}
7996
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02007997static int open_self_cmdline(CPUArchState *cpu_env, int fd)
Wim Vander Schelden76b94242014-06-18 11:02:39 +02007998{
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02007999 CPUState *cpu = env_cpu(cpu_env);
Andreas Schwab58de8b92017-03-20 12:31:55 +01008000 struct linux_binprm *bprm = ((TaskState *)cpu->opaque)->bprm;
8001 int i;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02008002
Andreas Schwab58de8b92017-03-20 12:31:55 +01008003 for (i = 0; i < bprm->argc; i++) {
8004 size_t len = strlen(bprm->argv[i]) + 1;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02008005
Andreas Schwab58de8b92017-03-20 12:31:55 +01008006 if (write(fd, bprm->argv[i], len) != len) {
Wim Vander Schelden76b94242014-06-18 11:02:39 +02008007 return -1;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02008008 }
8009 }
8010
Andreas Schwab58de8b92017-03-20 12:31:55 +01008011 return 0;
Wim Vander Schelden76b94242014-06-18 11:02:39 +02008012}
8013
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008014static int open_self_maps(CPUArchState *cpu_env, int fd)
Alexander Graf36c08d42011-11-02 20:23:24 +01008015{
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02008016 CPUState *cpu = env_cpu(cpu_env);
Andreas Färber0429a972013-08-26 18:14:44 +02008017 TaskState *ts = cpu->opaque;
Alex Bennée01ef6b92020-04-03 20:11:46 +01008018 GSList *map_info = read_self_maps();
8019 GSList *s;
Alex Bennéebb551732020-04-03 20:11:47 +01008020 int count;
Alexander Graf36c08d42011-11-02 20:23:24 +01008021
Alex Bennée01ef6b92020-04-03 20:11:46 +01008022 for (s = map_info; s; s = g_slist_next(s)) {
8023 MapInfo *e = (MapInfo *) s->data;
Alexander Graf1a49ef22012-05-01 16:30:28 +01008024
Alex Bennée01ef6b92020-04-03 20:11:46 +01008025 if (h2g_valid(e->start)) {
8026 unsigned long min = e->start;
8027 unsigned long max = e->end;
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04008028 int flags = page_get_flags(h2g(min));
Alex Bennée01ef6b92020-04-03 20:11:46 +01008029 const char *path;
8030
8031 max = h2g_valid(max - 1) ?
Richard Henderson3e8f1622021-02-12 10:48:43 -08008032 max : (uintptr_t) g2h_untagged(GUEST_ADDR_MAX) + 1;
Alex Bennée01ef6b92020-04-03 20:11:46 +01008033
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04008034 if (page_check_range(h2g(min), max - min, flags) == -1) {
8035 continue;
8036 }
Alex Bennée01ef6b92020-04-03 20:11:46 +01008037
Helge Deller0a3346b2022-09-24 13:44:59 +02008038#ifdef TARGET_HPPA
8039 if (h2g(max) == ts->info->stack_limit) {
8040#else
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04008041 if (h2g(min) == ts->info->stack_limit) {
Helge Deller0a3346b2022-09-24 13:44:59 +02008042#endif
Alex Bennéebb551732020-04-03 20:11:47 +01008043 path = "[stack]";
Alex Bennée01ef6b92020-04-03 20:11:46 +01008044 } else {
8045 path = e->path;
Mikhail Ilyind67f4aa2014-08-05 17:33:51 +04008046 }
Alex Bennée01ef6b92020-04-03 20:11:46 +01008047
Alex Bennéebb551732020-04-03 20:11:47 +01008048 count = dprintf(fd, TARGET_ABI_FMT_ptr "-" TARGET_ABI_FMT_ptr
8049 " %c%c%c%c %08" PRIx64 " %s %"PRId64,
8050 h2g(min), h2g(max - 1) + 1,
Nicolas Surbayrole08f3a962021-03-08 10:19:59 +01008051 (flags & PAGE_READ) ? 'r' : '-',
8052 (flags & PAGE_WRITE_ORG) ? 'w' : '-',
8053 (flags & PAGE_EXEC) ? 'x' : '-',
Andrey Kazmine13685a2021-12-27 15:50:48 +03008054 e->is_priv ? 'p' : 's',
Alex Bennéebb551732020-04-03 20:11:47 +01008055 (uint64_t) e->offset, e->dev, e->inode);
8056 if (path) {
8057 dprintf(fd, "%*s%s\n", 73 - count, "", path);
8058 } else {
8059 dprintf(fd, "\n");
8060 }
Alexander Graf1a49ef22012-05-01 16:30:28 +01008061 }
8062 }
8063
Alex Bennée01ef6b92020-04-03 20:11:46 +01008064 free_self_maps(map_info);
8065
Richard Hendersonbf02adc2020-02-12 19:22:22 -08008066#ifdef TARGET_VSYSCALL_PAGE
8067 /*
8068 * We only support execution from the vsyscall page.
8069 * This is as if CONFIG_LEGACY_VSYSCALL_XONLY=y from v5.3.
8070 */
Alex Bennéebb551732020-04-03 20:11:47 +01008071 count = dprintf(fd, TARGET_FMT_lx "-" TARGET_FMT_lx
8072 " --xp 00000000 00:00 0",
8073 TARGET_VSYSCALL_PAGE, TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE);
8074 dprintf(fd, "%*s%s\n", 73 - count, "", "[vsyscall]");
Richard Hendersonbf02adc2020-02-12 19:22:22 -08008075#endif
8076
Alexander Graf36c08d42011-11-02 20:23:24 +01008077 return 0;
8078}
8079
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008080static int open_self_stat(CPUArchState *cpu_env, int fd)
Alexander Graf480b8e72011-11-02 20:23:25 +01008081{
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02008082 CPUState *cpu = env_cpu(cpu_env);
Andreas Färber0429a972013-08-26 18:14:44 +02008083 TaskState *ts = cpu->opaque;
Alex Bennée7ad4d5a2020-04-14 21:06:23 +01008084 g_autoptr(GString) buf = g_string_new(NULL);
Alexander Graf480b8e72011-11-02 20:23:25 +01008085 int i;
8086
8087 for (i = 0; i < 44; i++) {
Alex Bennée7ad4d5a2020-04-14 21:06:23 +01008088 if (i == 0) {
8089 /* pid */
8090 g_string_printf(buf, FMT_pid " ", getpid());
8091 } else if (i == 1) {
8092 /* app name */
8093 gchar *bin = g_strrstr(ts->bprm->argv[0], "/");
8094 bin = bin ? bin + 1 : ts->bprm->argv[0];
8095 g_string_printf(buf, "(%.15s) ", bin);
Andreas Schwab7aa9fe32021-06-21 11:32:59 +02008096 } else if (i == 3) {
8097 /* ppid */
8098 g_string_printf(buf, FMT_pid " ", getppid());
Cameron Esfahanieb33cda2022-01-27 16:12:51 -08008099 } else if (i == 21) {
8100 /* starttime */
8101 g_string_printf(buf, "%" PRIu64 " ", ts->start_boottime);
Alex Bennée7ad4d5a2020-04-14 21:06:23 +01008102 } else if (i == 27) {
8103 /* stack bottom */
8104 g_string_printf(buf, TARGET_ABI_FMT_ld " ", ts->info->start_stack);
8105 } else {
8106 /* for the rest, there is MasterCard */
8107 g_string_printf(buf, "0%c", i == 43 ? '\n' : ' ');
8108 }
Alexander Graf480b8e72011-11-02 20:23:25 +01008109
Alex Bennée7ad4d5a2020-04-14 21:06:23 +01008110 if (write(fd, buf->str, buf->len) != buf->len) {
8111 return -1;
8112 }
Alexander Graf480b8e72011-11-02 20:23:25 +01008113 }
8114
8115 return 0;
8116}
8117
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008118static int open_self_auxv(CPUArchState *cpu_env, int fd)
Alexander Graf257450e2011-11-02 20:23:26 +01008119{
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02008120 CPUState *cpu = env_cpu(cpu_env);
Andreas Färber0429a972013-08-26 18:14:44 +02008121 TaskState *ts = cpu->opaque;
Alexander Graf257450e2011-11-02 20:23:26 +01008122 abi_ulong auxv = ts->info->saved_auxv;
8123 abi_ulong len = ts->info->auxv_len;
8124 char *ptr;
8125
8126 /*
8127 * Auxiliary vector is stored in target process stack.
8128 * read in whole auxv vector and copy it to file
8129 */
8130 ptr = lock_user(VERIFY_READ, auxv, len, 0);
8131 if (ptr != NULL) {
8132 while (len > 0) {
8133 ssize_t r;
8134 r = write(fd, ptr, len);
8135 if (r <= 0) {
8136 break;
8137 }
8138 len -= r;
8139 ptr += r;
8140 }
8141 lseek(fd, 0, SEEK_SET);
8142 unlock_user(ptr, auxv, len);
8143 }
8144
8145 return 0;
8146}
8147
Andreas Schwab463d8e72013-07-02 14:04:12 +01008148static int is_proc_myself(const char *filename, const char *entry)
8149{
8150 if (!strncmp(filename, "/proc/", strlen("/proc/"))) {
8151 filename += strlen("/proc/");
8152 if (!strncmp(filename, "self/", strlen("self/"))) {
8153 filename += strlen("self/");
8154 } else if (*filename >= '1' && *filename <= '9') {
8155 char myself[80];
8156 snprintf(myself, sizeof(myself), "%d/", getpid());
8157 if (!strncmp(filename, myself, strlen(myself))) {
8158 filename += strlen(myself);
8159 } else {
8160 return 0;
8161 }
8162 } else {
8163 return 0;
8164 }
8165 if (!strcmp(filename, entry)) {
8166 return 1;
8167 }
8168 }
8169 return 0;
8170}
8171
Marc-André Lureauee3eb3a2022-03-23 19:57:18 +04008172#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN || \
Helge Deller93a56612020-04-24 23:06:48 +02008173 defined(TARGET_SPARC) || defined(TARGET_M68K) || defined(TARGET_HPPA)
Laurent Vivierde6b9932013-08-30 01:46:40 +02008174static int is_proc(const char *filename, const char *entry)
8175{
8176 return strcmp(filename, entry) == 0;
8177}
Laurent Vivierfff69382019-05-17 15:31:48 +02008178#endif
Laurent Vivierde6b9932013-08-30 01:46:40 +02008179
Marc-André Lureauee3eb3a2022-03-23 19:57:18 +04008180#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008181static int open_net_route(CPUArchState *cpu_env, int fd)
Laurent Vivierde6b9932013-08-30 01:46:40 +02008182{
8183 FILE *fp;
8184 char *line = NULL;
8185 size_t len = 0;
8186 ssize_t read;
8187
8188 fp = fopen("/proc/net/route", "r");
8189 if (fp == NULL) {
Peter Maydella3ca7bb2016-05-12 18:47:26 +01008190 return -1;
Laurent Vivierde6b9932013-08-30 01:46:40 +02008191 }
8192
8193 /* read header */
8194
8195 read = getline(&line, &len, fp);
8196 dprintf(fd, "%s", line);
8197
8198 /* read routes */
8199
8200 while ((read = getline(&line, &len, fp)) != -1) {
8201 char iface[16];
8202 uint32_t dest, gw, mask;
8203 unsigned int flags, refcnt, use, metric, mtu, window, irtt;
Peter Maydell9d0bd0c2019-02-05 17:42:07 +00008204 int fields;
8205
8206 fields = sscanf(line,
8207 "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
8208 iface, &dest, &gw, &flags, &refcnt, &use, &metric,
8209 &mask, &mtu, &window, &irtt);
8210 if (fields != 11) {
8211 continue;
8212 }
Laurent Vivierde6b9932013-08-30 01:46:40 +02008213 dprintf(fd, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
8214 iface, tswap32(dest), tswap32(gw), flags, refcnt, use,
8215 metric, tswap32(mask), mtu, window, irtt);
8216 }
8217
8218 free(line);
8219 fclose(fp);
8220
8221 return 0;
8222}
8223#endif
8224
Laurent Vivierfff69382019-05-17 15:31:48 +02008225#if defined(TARGET_SPARC)
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008226static int open_cpuinfo(CPUArchState *cpu_env, int fd)
Laurent Vivierfff69382019-05-17 15:31:48 +02008227{
8228 dprintf(fd, "type\t\t: sun4u\n");
8229 return 0;
8230}
8231#endif
8232
Helge Deller93a56612020-04-24 23:06:48 +02008233#if defined(TARGET_HPPA)
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008234static int open_cpuinfo(CPUArchState *cpu_env, int fd)
Helge Deller93a56612020-04-24 23:06:48 +02008235{
8236 dprintf(fd, "cpu family\t: PA-RISC 1.1e\n");
8237 dprintf(fd, "cpu\t\t: PA7300LC (PCX-L2)\n");
8238 dprintf(fd, "capabilities\t: os32\n");
8239 dprintf(fd, "model\t\t: 9000/778/B160L\n");
8240 dprintf(fd, "model name\t: Merlin L2 160 QEMU (9000/778/B160L)\n");
8241 return 0;
8242}
8243#endif
8244
Laurent Vivier4ab67132019-05-17 15:31:49 +02008245#if defined(TARGET_M68K)
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008246static int open_hardware(CPUArchState *cpu_env, int fd)
Laurent Vivier4ab67132019-05-17 15:31:49 +02008247{
8248 dprintf(fd, "Model:\t\tqemu-m68k\n");
8249 return 0;
8250}
8251#endif
8252
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008253static int do_openat(CPUArchState *cpu_env, int dirfd, const char *pathname, int flags, mode_t mode)
Alexander Graf3be14d02011-11-02 20:23:23 +01008254{
8255 struct fake_open {
8256 const char *filename;
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008257 int (*fill)(CPUArchState *cpu_env, int fd);
Laurent Vivierde6b9932013-08-30 01:46:40 +02008258 int (*cmp)(const char *s1, const char *s2);
Alexander Graf3be14d02011-11-02 20:23:23 +01008259 };
8260 const struct fake_open *fake_open;
8261 static const struct fake_open fakes[] = {
Laurent Vivierde6b9932013-08-30 01:46:40 +02008262 { "maps", open_self_maps, is_proc_myself },
8263 { "stat", open_self_stat, is_proc_myself },
8264 { "auxv", open_self_auxv, is_proc_myself },
Wim Vander Schelden76b94242014-06-18 11:02:39 +02008265 { "cmdline", open_self_cmdline, is_proc_myself },
Marc-André Lureauee3eb3a2022-03-23 19:57:18 +04008266#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN
Laurent Vivierde6b9932013-08-30 01:46:40 +02008267 { "/proc/net/route", open_net_route, is_proc },
8268#endif
Helge Deller93a56612020-04-24 23:06:48 +02008269#if defined(TARGET_SPARC) || defined(TARGET_HPPA)
Laurent Vivierfff69382019-05-17 15:31:48 +02008270 { "/proc/cpuinfo", open_cpuinfo, is_proc },
8271#endif
Laurent Vivier4ab67132019-05-17 15:31:49 +02008272#if defined(TARGET_M68K)
8273 { "/proc/hardware", open_hardware, is_proc },
8274#endif
Laurent Vivierde6b9932013-08-30 01:46:40 +02008275 { NULL, NULL, NULL }
Alexander Graf3be14d02011-11-02 20:23:23 +01008276 };
8277
Maxim Ostapenkoaa07f5e2014-05-02 11:17:07 +03008278 if (is_proc_myself(pathname, "exe")) {
Laurent Vivier00ed8a32022-09-27 14:43:57 +02008279 return safe_openat(dirfd, exec_path, flags, mode);
Maxim Ostapenkoaa07f5e2014-05-02 11:17:07 +03008280 }
8281
Alexander Graf3be14d02011-11-02 20:23:23 +01008282 for (fake_open = fakes; fake_open->filename; fake_open++) {
Laurent Vivierde6b9932013-08-30 01:46:40 +02008283 if (fake_open->cmp(pathname, fake_open->filename)) {
Alexander Graf3be14d02011-11-02 20:23:23 +01008284 break;
8285 }
8286 }
8287
8288 if (fake_open->filename) {
8289 const char *tmpdir;
8290 char filename[PATH_MAX];
8291 int fd, r;
8292
Rainer Müller5b63de62022-07-29 17:49:51 +02008293 fd = memfd_create("qemu-open", 0);
Alexander Graf3be14d02011-11-02 20:23:23 +01008294 if (fd < 0) {
Rainer Müller5b63de62022-07-29 17:49:51 +02008295 if (errno != ENOSYS) {
8296 return fd;
8297 }
8298 /* create temporary file to map stat to */
8299 tmpdir = getenv("TMPDIR");
8300 if (!tmpdir)
8301 tmpdir = "/tmp";
8302 snprintf(filename, sizeof(filename), "%s/qemu-open.XXXXXX", tmpdir);
8303 fd = mkstemp(filename);
8304 if (fd < 0) {
8305 return fd;
8306 }
8307 unlink(filename);
Alexander Graf3be14d02011-11-02 20:23:23 +01008308 }
Alexander Graf3be14d02011-11-02 20:23:23 +01008309
8310 if ((r = fake_open->fill(cpu_env, fd))) {
Peter Maydella3ca7bb2016-05-12 18:47:26 +01008311 int e = errno;
Alexander Graf3be14d02011-11-02 20:23:23 +01008312 close(fd);
Peter Maydella3ca7bb2016-05-12 18:47:26 +01008313 errno = e;
Alexander Graf3be14d02011-11-02 20:23:23 +01008314 return r;
8315 }
8316 lseek(fd, 0, SEEK_SET);
8317
8318 return fd;
8319 }
8320
Timothy E Baldwinc10a0732016-05-12 18:47:48 +01008321 return safe_openat(dirfd, path(pathname), flags, mode);
Alexander Graf3be14d02011-11-02 20:23:23 +01008322}
8323
Alexander Grafaecc8862014-11-10 21:33:03 +01008324#define TIMER_MAGIC 0x0caf0000
8325#define TIMER_MAGIC_MASK 0xffff0000
8326
8327/* Convert QEMU provided timer ID back to internal 16bit index format */
8328static target_timer_t get_timer_id(abi_long arg)
8329{
8330 target_timer_t timerid = arg;
8331
8332 if ((timerid & TIMER_MAGIC_MASK) != TIMER_MAGIC) {
8333 return -TARGET_EINVAL;
8334 }
8335
8336 timerid &= 0xffff;
8337
8338 if (timerid >= ARRAY_SIZE(g_posix_timers)) {
8339 return -TARGET_EINVAL;
8340 }
8341
8342 return timerid;
8343}
8344
Samuel Thibault2e0a8712018-01-09 21:16:43 +01008345static int target_to_host_cpu_mask(unsigned long *host_mask,
8346 size_t host_size,
8347 abi_ulong target_addr,
8348 size_t target_size)
8349{
8350 unsigned target_bits = sizeof(abi_ulong) * 8;
8351 unsigned host_bits = sizeof(*host_mask) * 8;
8352 abi_ulong *target_mask;
8353 unsigned i, j;
8354
8355 assert(host_size >= target_size);
8356
8357 target_mask = lock_user(VERIFY_READ, target_addr, target_size, 1);
8358 if (!target_mask) {
8359 return -TARGET_EFAULT;
8360 }
8361 memset(host_mask, 0, host_size);
8362
8363 for (i = 0 ; i < target_size / sizeof(abi_ulong); i++) {
8364 unsigned bit = i * target_bits;
8365 abi_ulong val;
8366
8367 __get_user(val, &target_mask[i]);
8368 for (j = 0; j < target_bits; j++, bit++) {
8369 if (val & (1UL << j)) {
8370 host_mask[bit / host_bits] |= 1UL << (bit % host_bits);
8371 }
8372 }
8373 }
8374
8375 unlock_user(target_mask, target_addr, 0);
8376 return 0;
8377}
8378
8379static int host_to_target_cpu_mask(const unsigned long *host_mask,
8380 size_t host_size,
8381 abi_ulong target_addr,
8382 size_t target_size)
8383{
8384 unsigned target_bits = sizeof(abi_ulong) * 8;
8385 unsigned host_bits = sizeof(*host_mask) * 8;
8386 abi_ulong *target_mask;
8387 unsigned i, j;
8388
8389 assert(host_size >= target_size);
8390
8391 target_mask = lock_user(VERIFY_WRITE, target_addr, target_size, 0);
8392 if (!target_mask) {
8393 return -TARGET_EFAULT;
8394 }
8395
8396 for (i = 0 ; i < target_size / sizeof(abi_ulong); i++) {
8397 unsigned bit = i * target_bits;
8398 abi_ulong val = 0;
8399
8400 for (j = 0; j < target_bits; j++, bit++) {
8401 if (host_mask[bit / host_bits] & (1UL << (bit % host_bits))) {
8402 val |= 1UL << j;
8403 }
8404 }
8405 __put_user(val, &target_mask[i]);
8406 }
8407
8408 unlock_user(target_mask, target_addr, target_size);
8409 return 0;
8410}
8411
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008412#ifdef TARGET_NR_getdents
Richard Hendersonaee14c72021-11-14 11:35:39 +01008413static int do_getdents(abi_long dirfd, abi_long arg2, abi_long count)
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008414{
Richard Hendersonaee14c72021-11-14 11:35:39 +01008415 g_autofree void *hdirp = NULL;
8416 void *tdirp;
8417 int hlen, hoff, toff;
8418 int hreclen, treclen;
8419 off64_t prev_diroff = 0;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008420
Richard Hendersonaee14c72021-11-14 11:35:39 +01008421 hdirp = g_try_malloc(count);
8422 if (!hdirp) {
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008423 return -TARGET_ENOMEM;
8424 }
8425
Richard Hendersonaee14c72021-11-14 11:35:39 +01008426#ifdef EMULATE_GETDENTS_WITH_GETDENTS
8427 hlen = sys_getdents(dirfd, hdirp, count);
8428#else
8429 hlen = sys_getdents64(dirfd, hdirp, count);
8430#endif
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008431
Richard Hendersonaee14c72021-11-14 11:35:39 +01008432 hlen = get_errno(hlen);
8433 if (is_error(hlen)) {
8434 return hlen;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008435 }
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008436
Richard Hendersonaee14c72021-11-14 11:35:39 +01008437 tdirp = lock_user(VERIFY_WRITE, arg2, count, 0);
8438 if (!tdirp) {
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008439 return -TARGET_EFAULT;
8440 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008441
8442 for (hoff = toff = 0; hoff < hlen; hoff += hreclen, toff += treclen) {
8443#ifdef EMULATE_GETDENTS_WITH_GETDENTS
8444 struct linux_dirent *hde = hdirp + hoff;
8445#else
8446 struct linux_dirent64 *hde = hdirp + hoff;
8447#endif
8448 struct target_dirent *tde = tdirp + toff;
8449 int namelen;
8450 uint8_t type;
8451
8452 namelen = strlen(hde->d_name);
8453 hreclen = hde->d_reclen;
8454 treclen = offsetof(struct target_dirent, d_name) + namelen + 2;
8455 treclen = QEMU_ALIGN_UP(treclen, __alignof(struct target_dirent));
8456
8457 if (toff + treclen > count) {
8458 /*
8459 * If the host struct is smaller than the target struct, or
8460 * requires less alignment and thus packs into less space,
8461 * then the host can return more entries than we can pass
8462 * on to the guest.
8463 */
8464 if (toff == 0) {
8465 toff = -TARGET_EINVAL; /* result buffer is too small */
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008466 break;
8467 }
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008468 /*
Richard Hendersonaee14c72021-11-14 11:35:39 +01008469 * Return what we have, resetting the file pointer to the
8470 * location of the first record not returned.
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008471 */
Richard Hendersonaee14c72021-11-14 11:35:39 +01008472 lseek64(dirfd, prev_diroff, SEEK_SET);
8473 break;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008474 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008475
8476 prev_diroff = hde->d_off;
8477 tde->d_ino = tswapal(hde->d_ino);
8478 tde->d_off = tswapal(hde->d_off);
8479 tde->d_reclen = tswap16(treclen);
8480 memcpy(tde->d_name, hde->d_name, namelen + 1);
8481
8482 /*
8483 * The getdents type is in what was formerly a padding byte at the
8484 * end of the structure.
8485 */
8486#ifdef EMULATE_GETDENTS_WITH_GETDENTS
8487 type = *((uint8_t *)hde + hreclen - 1);
8488#else
8489 type = hde->d_type;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008490#endif
Richard Hendersonaee14c72021-11-14 11:35:39 +01008491 *((uint8_t *)tde + treclen - 1) = type;
8492 }
8493
8494 unlock_user(tdirp, arg2, toff);
8495 return toff;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008496}
8497#endif /* TARGET_NR_getdents */
8498
8499#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
Richard Hendersonaee14c72021-11-14 11:35:39 +01008500static int do_getdents64(abi_long dirfd, abi_long arg2, abi_long count)
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008501{
Richard Hendersonaee14c72021-11-14 11:35:39 +01008502 g_autofree void *hdirp = NULL;
8503 void *tdirp;
8504 int hlen, hoff, toff;
8505 int hreclen, treclen;
8506 off64_t prev_diroff = 0;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008507
Richard Hendersonaee14c72021-11-14 11:35:39 +01008508 hdirp = g_try_malloc(count);
8509 if (!hdirp) {
8510 return -TARGET_ENOMEM;
8511 }
8512
8513 hlen = get_errno(sys_getdents64(dirfd, hdirp, count));
8514 if (is_error(hlen)) {
8515 return hlen;
8516 }
8517
8518 tdirp = lock_user(VERIFY_WRITE, arg2, count, 0);
8519 if (!tdirp) {
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008520 return -TARGET_EFAULT;
8521 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008522
8523 for (hoff = toff = 0; hoff < hlen; hoff += hreclen, toff += treclen) {
8524 struct linux_dirent64 *hde = hdirp + hoff;
8525 struct target_dirent64 *tde = tdirp + toff;
8526 int namelen;
8527
8528 namelen = strlen(hde->d_name) + 1;
8529 hreclen = hde->d_reclen;
8530 treclen = offsetof(struct target_dirent64, d_name) + namelen;
8531 treclen = QEMU_ALIGN_UP(treclen, __alignof(struct target_dirent64));
8532
8533 if (toff + treclen > count) {
8534 /*
8535 * If the host struct is smaller than the target struct, or
8536 * requires less alignment and thus packs into less space,
8537 * then the host can return more entries than we can pass
8538 * on to the guest.
8539 */
8540 if (toff == 0) {
8541 toff = -TARGET_EINVAL; /* result buffer is too small */
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008542 break;
8543 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008544 /*
8545 * Return what we have, resetting the file pointer to the
8546 * location of the first record not returned.
8547 */
8548 lseek64(dirfd, prev_diroff, SEEK_SET);
8549 break;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008550 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008551
8552 prev_diroff = hde->d_off;
8553 tde->d_ino = tswap64(hde->d_ino);
8554 tde->d_off = tswap64(hde->d_off);
8555 tde->d_reclen = tswap16(treclen);
8556 tde->d_type = hde->d_type;
8557 memcpy(tde->d_name, hde->d_name, namelen);
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008558 }
Richard Hendersonaee14c72021-11-14 11:35:39 +01008559
8560 unlock_user(tdirp, arg2, toff);
8561 return toff;
Richard Hendersonfd08ddb2021-11-14 11:35:36 +01008562}
8563#endif /* TARGET_NR_getdents64 */
8564
YAMAMOTO Takashie10fbe82021-05-31 14:50:12 +09008565#if defined(TARGET_NR_pivot_root) && defined(__NR_pivot_root)
8566_syscall2(int, pivot_root, const char *, new_root, const char *, put_old)
8567#endif
8568
Richard Hendersondc1ce182018-08-18 12:01:04 -07008569/* This is an internal helper for do_syscall so that it is easier
8570 * to have a single return point, so that actions, such as logging
8571 * of syscall results, can be performed.
8572 * All errnos that do_syscall() returns must be -TARGET_<errcode>.
8573 */
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +02008574static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
Richard Hendersondc1ce182018-08-18 12:01:04 -07008575 abi_long arg2, abi_long arg3, abi_long arg4,
8576 abi_long arg5, abi_long arg6, abi_long arg7,
8577 abi_long arg8)
bellard31e31b82003-02-18 22:55:36 +00008578{
Richard Henderson29a0af62019-03-22 16:07:18 -07008579 CPUState *cpu = env_cpu(cpu_env);
blueswir1992f48a2007-10-14 16:27:31 +00008580 abi_long ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008581#if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) \
8582 || defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64) \
Aleksandar Rikaloefa92182019-06-28 12:43:34 +02008583 || defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64) \
8584 || defined(TARGET_NR_statx)
bellard31e31b82003-02-18 22:55:36 +00008585 struct stat st;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008586#endif
8587#if defined(TARGET_NR_statfs) || defined(TARGET_NR_statfs64) \
8588 || defined(TARGET_NR_fstatfs)
bellard56c8f682005-11-28 22:28:41 +00008589 struct statfs stfs;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008590#endif
pbrook53a59602006-03-25 19:31:22 +00008591 void *p;
ths3b46e622007-09-17 08:09:54 +00008592
bellard31e31b82003-02-18 22:55:36 +00008593 switch(num) {
8594 case TARGET_NR_exit:
Andreas Färber9b056fc2013-06-24 23:53:10 +02008595 /* In old applications this may be used to implement _exit(2).
zhaolichang6f9ff552020-09-17 15:50:25 +08008596 However in threaded applications it is used for thread termination,
Andreas Färber9b056fc2013-06-24 23:53:10 +02008597 and _exit_group is used for application termination.
8598 Do thread termination if we have more then one thread. */
Timothy E Baldwina0995882016-05-27 15:51:56 +01008599
8600 if (block_signals()) {
Richard Hendersonaf254a22021-11-22 19:47:33 +01008601 return -QEMU_ERESTARTSYS;
Timothy E Baldwina0995882016-05-27 15:51:56 +01008602 }
8603
Alex Bennée1f81ce92020-05-20 15:05:39 +01008604 pthread_mutex_lock(&clone_lock);
Alex Bennéedd1f6342016-09-30 22:31:01 +01008605
Andreas Färberbdc44642013-06-24 23:50:24 +02008606 if (CPU_NEXT(first_cpu)) {
Alex Bennée1f81ce92020-05-20 15:05:39 +01008607 TaskState *ts = cpu->opaque;
pbrookc2764712009-03-07 15:24:59 +00008608
Richard Henderson976a55c2022-08-18 18:03:52 -07008609 object_property_set_bool(OBJECT(cpu), "realized", false, NULL);
Alex Bennée1f81ce92020-05-20 15:05:39 +01008610 object_unref(OBJECT(cpu));
8611 /*
8612 * At this point the CPU should be unrealized and removed
8613 * from cpu lists. We can clean-up the rest of the thread
8614 * data without the lock held.
8615 */
Alex Bennéedd1f6342016-09-30 22:31:01 +01008616
Alex Bennée1f81ce92020-05-20 15:05:39 +01008617 pthread_mutex_unlock(&clone_lock);
Alex Bennéedd1f6342016-09-30 22:31:01 +01008618
Richard Henderson976a55c2022-08-18 18:03:52 -07008619 if (ts->child_tidptr) {
8620 put_user_u32(0, ts->child_tidptr);
8621 do_sys_futex(g2h(cpu, ts->child_tidptr),
8622 FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
8623 }
Andreas Färbera2247f82013-06-09 19:47:04 +02008624 thread_cpu = NULL;
Andreas Färber9b056fc2013-06-24 23:53:10 +02008625 g_free(ts);
Emilio G. Cota70903762015-08-23 20:23:41 -04008626 rcu_unregister_thread();
Andreas Färber9b056fc2013-06-24 23:53:10 +02008627 pthread_exit(NULL);
8628 }
Alex Bennéedd1f6342016-09-30 22:31:01 +01008629
Alex Bennée1f81ce92020-05-20 15:05:39 +01008630 pthread_mutex_unlock(&clone_lock);
Alex Bennée708b6a62018-06-22 17:09:10 +01008631 preexit_cleanup(cpu_env, arg1);
pbrookc2764712009-03-07 15:24:59 +00008632 _exit(arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008633 return 0; /* avoid warning */
bellard31e31b82003-02-18 22:55:36 +00008634 case TARGET_NR_read:
Andreas Schwabba584f12019-03-05 17:45:05 +01008635 if (arg2 == 0 && arg3 == 0) {
8636 return get_errno(safe_read(arg1, 0, 0));
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008637 } else {
aurel3238d840e2009-01-30 19:48:17 +00008638 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008639 return -TARGET_EFAULT;
Timothy E Baldwin50afd022016-05-12 18:47:47 +01008640 ret = get_errno(safe_read(arg1, p, arg3));
Laurent Viviere36800c2015-10-02 14:48:09 +02008641 if (ret >= 0 &&
Laurent Vivier5d4d3662015-10-28 21:40:43 +01008642 fd_trans_host_to_target_data(arg1)) {
8643 ret = fd_trans_host_to_target_data(arg1)(p, ret);
Laurent Viviere36800c2015-10-02 14:48:09 +02008644 }
aurel3238d840e2009-01-30 19:48:17 +00008645 unlock_user(p, arg2, ret);
8646 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008647 return ret;
bellard31e31b82003-02-18 22:55:36 +00008648 case TARGET_NR_write:
Tony Garnock-Jones58cfa6c2018-09-08 19:22:05 +01008649 if (arg2 == 0 && arg3 == 0) {
8650 return get_errno(safe_write(arg1, 0, 0));
8651 }
bellard579a97f2007-11-11 14:26:47 +00008652 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008653 return -TARGET_EFAULT;
Laurent Vivier04b9bcf2017-03-01 10:37:47 +01008654 if (fd_trans_target_to_host_data(arg1)) {
8655 void *copy = g_malloc(arg3);
8656 memcpy(copy, p, arg3);
8657 ret = fd_trans_target_to_host_data(arg1)(copy, arg3);
8658 if (ret >= 0) {
8659 ret = get_errno(safe_write(arg1, copy, ret));
8660 }
8661 g_free(copy);
8662 } else {
8663 ret = get_errno(safe_write(arg1, p, arg3));
8664 }
pbrook53a59602006-03-25 19:31:22 +00008665 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008666 return ret;
8667
Chen Gang704eff62015-08-21 05:37:33 +08008668#ifdef TARGET_NR_open
bellard31e31b82003-02-18 22:55:36 +00008669 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00008670 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008671 return -TARGET_EFAULT;
Riku Voipio0b2effd2014-08-06 10:36:37 +03008672 ret = get_errno(do_openat(cpu_env, AT_FDCWD, p,
8673 target_to_host_bitmask(arg2, fcntl_flags_tbl),
8674 arg3));
Laurent Viviere36800c2015-10-02 14:48:09 +02008675 fd_trans_unregister(ret);
pbrook53a59602006-03-25 19:31:22 +00008676 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008677 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008678#endif
ths82424832007-09-24 09:21:55 +00008679 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00008680 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008681 return -TARGET_EFAULT;
Riku Voipio0b2effd2014-08-06 10:36:37 +03008682 ret = get_errno(do_openat(cpu_env, arg1, p,
8683 target_to_host_bitmask(arg3, fcntl_flags_tbl),
8684 arg4));
Laurent Viviere36800c2015-10-02 14:48:09 +02008685 fd_trans_unregister(ret);
bellard579a97f2007-11-11 14:26:47 +00008686 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008687 return ret;
Laurent Vivier0f0426f2015-09-01 22:27:33 +02008688#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
8689 case TARGET_NR_name_to_handle_at:
8690 ret = do_name_to_handle_at(arg1, arg2, arg3, arg4, arg5);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008691 return ret;
Laurent Vivier0f0426f2015-09-01 22:27:33 +02008692#endif
8693#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
8694 case TARGET_NR_open_by_handle_at:
8695 ret = do_open_by_handle_at(arg1, arg2, arg3);
Laurent Viviere36800c2015-10-02 14:48:09 +02008696 fd_trans_unregister(ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008697 return ret;
Laurent Vivier0f0426f2015-09-01 22:27:33 +02008698#endif
Helge Dellercc054c62022-09-18 21:45:46 +02008699#if defined(__NR_pidfd_open) && defined(TARGET_NR_pidfd_open)
8700 case TARGET_NR_pidfd_open:
8701 return get_errno(pidfd_open(arg1, arg2));
8702#endif
8703#if defined(__NR_pidfd_send_signal) && defined(TARGET_NR_pidfd_send_signal)
8704 case TARGET_NR_pidfd_send_signal:
8705 {
Laurent Vivier46187d72022-10-05 18:38:26 +02008706 siginfo_t uinfo, *puinfo;
Helge Dellercc054c62022-09-18 21:45:46 +02008707
Laurent Vivier46187d72022-10-05 18:38:26 +02008708 if (arg3) {
8709 p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
8710 if (!p) {
8711 return -TARGET_EFAULT;
8712 }
8713 target_to_host_siginfo(&uinfo, p);
8714 unlock_user(p, arg3, 0);
8715 puinfo = &uinfo;
8716 } else {
8717 puinfo = NULL;
Helge Dellercc054c62022-09-18 21:45:46 +02008718 }
Helge Dellercc054c62022-09-18 21:45:46 +02008719 ret = get_errno(pidfd_send_signal(arg1, target_to_host_signal(arg2),
Laurent Vivier46187d72022-10-05 18:38:26 +02008720 puinfo, arg4));
Helge Dellercc054c62022-09-18 21:45:46 +02008721 }
8722 return ret;
8723#endif
8724#if defined(__NR_pidfd_getfd) && defined(TARGET_NR_pidfd_getfd)
8725 case TARGET_NR_pidfd_getfd:
8726 return get_errno(pidfd_getfd(arg1, arg2, arg3));
8727#endif
bellard31e31b82003-02-18 22:55:36 +00008728 case TARGET_NR_close:
Laurent Viviere36800c2015-10-02 14:48:09 +02008729 fd_trans_unregister(arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008730 return get_errno(close(arg1));
8731
bellard31e31b82003-02-18 22:55:36 +00008732 case TARGET_NR_brk:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008733 return do_brk(arg1);
Chen Gang704eff62015-08-21 05:37:33 +08008734#ifdef TARGET_NR_fork
bellard31e31b82003-02-18 22:55:36 +00008735 case TARGET_NR_fork:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008736 return get_errno(do_fork(cpu_env, TARGET_SIGCHLD, 0, 0, 0, 0));
Chen Gang704eff62015-08-21 05:37:33 +08008737#endif
thse5febef2007-04-01 18:31:35 +00008738#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00008739 case TARGET_NR_waitpid:
8740 {
pbrook53a59602006-03-25 19:31:22 +00008741 int status;
Timothy E Baldwin4af80a32016-05-12 18:47:49 +01008742 ret = get_errno(safe_wait4(arg1, &status, arg3, 0));
Alexander Graf53795572011-11-24 00:44:43 +01008743 if (!is_error(ret) && arg2 && ret
pbrook1d9d8b52009-04-16 15:17:02 +00008744 && put_user_s32(host_to_target_waitstatus(status), arg2))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008745 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00008746 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008747 return ret;
thse5febef2007-04-01 18:31:35 +00008748#endif
pbrookf0cbb612008-05-30 18:20:05 +00008749#ifdef TARGET_NR_waitid
8750 case TARGET_NR_waitid:
8751 {
8752 siginfo_t info;
8753 info.si_pid = 0;
Timothy E Baldwin4af80a32016-05-12 18:47:49 +01008754 ret = get_errno(safe_waitid(arg1, arg2, &info, arg4, NULL));
pbrookf0cbb612008-05-30 18:20:05 +00008755 if (!is_error(ret) && arg3 && info.si_pid != 0) {
Anthony Liguoric227f092009-10-01 16:12:16 -05008756 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008757 return -TARGET_EFAULT;
pbrookf0cbb612008-05-30 18:20:05 +00008758 host_to_target_siginfo(p, &info);
Anthony Liguoric227f092009-10-01 16:12:16 -05008759 unlock_user(p, arg3, sizeof(target_siginfo_t));
pbrookf0cbb612008-05-30 18:20:05 +00008760 }
8761 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008762 return ret;
pbrookf0cbb612008-05-30 18:20:05 +00008763#endif
j_mayer7a3148a2007-04-05 07:13:51 +00008764#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00008765 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00008766 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008767 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008768 ret = get_errno(creat(p, arg2));
Laurent Viviere36800c2015-10-02 14:48:09 +02008769 fd_trans_unregister(ret);
pbrook53a59602006-03-25 19:31:22 +00008770 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008771 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00008772#endif
Chen Gang704eff62015-08-21 05:37:33 +08008773#ifdef TARGET_NR_link
bellard31e31b82003-02-18 22:55:36 +00008774 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00008775 {
8776 void * p2;
8777 p = lock_user_string(arg1);
8778 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00008779 if (!p || !p2)
8780 ret = -TARGET_EFAULT;
8781 else
8782 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00008783 unlock_user(p2, arg2, 0);
8784 unlock_user(p, arg1, 0);
8785 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008786 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008787#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01008788#if defined(TARGET_NR_linkat)
ths64f0ce42007-09-24 09:25:06 +00008789 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00008790 {
8791 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00008792 if (!arg2 || !arg4)
Richard Henderson2852aaf2018-08-18 12:01:06 -07008793 return -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00008794 p = lock_user_string(arg2);
8795 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00008796 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00008797 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00008798 else
Peter Maydellc0d472b2013-06-12 16:20:21 +01008799 ret = get_errno(linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00008800 unlock_user(p, arg2, 0);
8801 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00008802 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008803 return ret;
ths64f0ce42007-09-24 09:25:06 +00008804#endif
Chen Gang704eff62015-08-21 05:37:33 +08008805#ifdef TARGET_NR_unlink
bellard31e31b82003-02-18 22:55:36 +00008806 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00008807 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008808 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008809 ret = get_errno(unlink(p));
8810 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008811 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008812#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01008813#if defined(TARGET_NR_unlinkat)
ths8170f562007-09-24 09:24:11 +00008814 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00008815 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008816 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01008817 ret = get_errno(unlinkat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00008818 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008819 return ret;
balrogb7d35e62007-12-12 00:40:24 +00008820#endif
bellard31e31b82003-02-18 22:55:36 +00008821 case TARGET_NR_execve:
bellard7854b052003-03-29 17:22:23 +00008822 {
8823 char **argp, **envp;
bellardf7341ff2003-03-30 21:00:25 +00008824 int argc, envc;
blueswir1992f48a2007-10-14 16:27:31 +00008825 abi_ulong gp;
8826 abi_ulong guest_argp;
8827 abi_ulong guest_envp;
8828 abi_ulong addr;
bellard7854b052003-03-29 17:22:23 +00008829 char **q;
8830
bellardf7341ff2003-03-30 21:00:25 +00008831 argc = 0;
pbrook53a59602006-03-25 19:31:22 +00008832 guest_argp = arg2;
pbrookda94d262008-05-30 18:24:00 +00008833 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00008834 if (get_user_ual(addr, gp))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008835 return -TARGET_EFAULT;
ths03aa1972007-12-02 06:28:08 +00008836 if (!addr)
bellard2f619692007-11-16 10:46:05 +00008837 break;
bellard7854b052003-03-29 17:22:23 +00008838 argc++;
bellard2f619692007-11-16 10:46:05 +00008839 }
bellardf7341ff2003-03-30 21:00:25 +00008840 envc = 0;
pbrook53a59602006-03-25 19:31:22 +00008841 guest_envp = arg3;
pbrookda94d262008-05-30 18:24:00 +00008842 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00008843 if (get_user_ual(addr, gp))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008844 return -TARGET_EFAULT;
ths03aa1972007-12-02 06:28:08 +00008845 if (!addr)
bellard2f619692007-11-16 10:46:05 +00008846 break;
bellard7854b052003-03-29 17:22:23 +00008847 envc++;
bellard2f619692007-11-16 10:46:05 +00008848 }
bellard7854b052003-03-29 17:22:23 +00008849
Prasad J Panditb936cb52017-03-07 12:51:47 +05308850 argp = g_new0(char *, argc + 1);
8851 envp = g_new0(char *, envc + 1);
bellard7854b052003-03-29 17:22:23 +00008852
pbrookda94d262008-05-30 18:24:00 +00008853 for (gp = guest_argp, q = argp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00008854 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00008855 if (get_user_ual(addr, gp))
8856 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00008857 if (!addr)
8858 break;
bellard2f619692007-11-16 10:46:05 +00008859 if (!(*q = lock_user_string(addr)))
8860 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00008861 }
bellardf7341ff2003-03-30 21:00:25 +00008862 *q = NULL;
8863
pbrookda94d262008-05-30 18:24:00 +00008864 for (gp = guest_envp, q = envp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00008865 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00008866 if (get_user_ual(addr, gp))
8867 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00008868 if (!addr)
8869 break;
bellard2f619692007-11-16 10:46:05 +00008870 if (!(*q = lock_user_string(addr)))
8871 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00008872 }
bellardf7341ff2003-03-30 21:00:25 +00008873 *q = NULL;
bellard7854b052003-03-29 17:22:23 +00008874
bellard2f619692007-11-16 10:46:05 +00008875 if (!(p = lock_user_string(arg1)))
8876 goto execve_efault;
Timothy E Baldwinffdcbe22016-05-12 18:47:50 +01008877 /* Although execve() is not an interruptible syscall it is
8878 * a special case where we must use the safe_syscall wrapper:
8879 * if we allow a signal to happen before we make the host
8880 * syscall then we will 'lose' it, because at the point of
8881 * execve the process leaves QEMU's control. So we use the
8882 * safe syscall wrapper to ensure that we either take the
8883 * signal as a guest signal, or else it does not happen
8884 * before the execve completes and makes it the other
8885 * program's problem.
8886 */
Laurent Vivierf07eb1c2022-09-27 14:43:56 +02008887 if (is_proc_myself(p, "exe")) {
8888 ret = get_errno(safe_execve(exec_path, argp, envp));
8889 } else {
8890 ret = get_errno(safe_execve(p, argp, envp));
8891 }
pbrook53a59602006-03-25 19:31:22 +00008892 unlock_user(p, arg1, 0);
8893
bellard2f619692007-11-16 10:46:05 +00008894 goto execve_end;
8895
8896 execve_efault:
8897 ret = -TARGET_EFAULT;
8898
8899 execve_end:
pbrook53a59602006-03-25 19:31:22 +00008900 for (gp = guest_argp, q = argp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00008901 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00008902 if (get_user_ual(addr, gp)
8903 || !addr)
8904 break;
pbrook53a59602006-03-25 19:31:22 +00008905 unlock_user(*q, addr, 0);
8906 }
8907 for (gp = guest_envp, q = envp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00008908 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00008909 if (get_user_ual(addr, gp)
8910 || !addr)
8911 break;
pbrook53a59602006-03-25 19:31:22 +00008912 unlock_user(*q, addr, 0);
8913 }
Prasad J Panditb936cb52017-03-07 12:51:47 +05308914
8915 g_free(argp);
8916 g_free(envp);
bellard7854b052003-03-29 17:22:23 +00008917 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008918 return ret;
bellard31e31b82003-02-18 22:55:36 +00008919 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00008920 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008921 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008922 ret = get_errno(chdir(p));
8923 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008924 return ret;
bellarda315a142005-01-30 22:59:18 +00008925#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00008926 case TARGET_NR_time:
8927 {
pbrook53a59602006-03-25 19:31:22 +00008928 time_t host_time;
8929 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00008930 if (!is_error(ret)
8931 && arg1
8932 && put_user_sal(host_time, arg1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008933 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00008934 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008935 return ret;
bellarda315a142005-01-30 22:59:18 +00008936#endif
Chen Gang704eff62015-08-21 05:37:33 +08008937#ifdef TARGET_NR_mknod
bellard31e31b82003-02-18 22:55:36 +00008938 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00008939 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008940 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008941 ret = get_errno(mknod(p, arg2, arg3));
8942 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008943 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008944#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01008945#if defined(TARGET_NR_mknodat)
ths75ac37a2007-09-24 09:23:05 +00008946 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00008947 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008948 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01008949 ret = get_errno(mknodat(arg1, p, arg3, arg4));
bellard579a97f2007-11-11 14:26:47 +00008950 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008951 return ret;
ths75ac37a2007-09-24 09:23:05 +00008952#endif
Chen Gang704eff62015-08-21 05:37:33 +08008953#ifdef TARGET_NR_chmod
bellard31e31b82003-02-18 22:55:36 +00008954 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00008955 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07008956 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00008957 ret = get_errno(chmod(p, arg2));
8958 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008959 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08008960#endif
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008961#ifdef TARGET_NR_lseek
bellard31e31b82003-02-18 22:55:36 +00008962 case TARGET_NR_lseek:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008963 return get_errno(lseek(arg1, arg2, arg3));
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02008964#endif
Richard Henderson92317332010-05-03 10:07:53 -07008965#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA)
8966 /* Alpha specific */
j_mayer7a3148a2007-04-05 07:13:51 +00008967 case TARGET_NR_getxpid:
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02008968 cpu_env->ir[IR_A4] = getppid();
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008969 return get_errno(getpid());
Richard Henderson92317332010-05-03 10:07:53 -07008970#endif
8971#ifdef TARGET_NR_getpid
8972 case TARGET_NR_getpid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07008973 return get_errno(getpid());
Richard Henderson92317332010-05-03 10:07:53 -07008974#endif
bellard31e31b82003-02-18 22:55:36 +00008975 case TARGET_NR_mount:
Paul Burton356d7712014-06-22 11:25:37 +01008976 {
8977 /* need to look at the data field */
8978 void *p2, *p3;
8979
8980 if (arg1) {
8981 p = lock_user_string(arg1);
8982 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07008983 return -TARGET_EFAULT;
Paul Burton356d7712014-06-22 11:25:37 +01008984 }
8985 } else {
8986 p = NULL;
8987 }
8988
8989 p2 = lock_user_string(arg2);
8990 if (!p2) {
8991 if (arg1) {
8992 unlock_user(p, arg1, 0);
8993 }
Richard Henderson2852aaf2018-08-18 12:01:06 -07008994 return -TARGET_EFAULT;
Paul Burton356d7712014-06-22 11:25:37 +01008995 }
8996
8997 if (arg3) {
8998 p3 = lock_user_string(arg3);
8999 if (!p3) {
9000 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00009001 unlock_user(p, arg1, 0);
Paul Burton356d7712014-06-22 11:25:37 +01009002 }
9003 unlock_user(p2, arg2, 0);
Richard Henderson2852aaf2018-08-18 12:01:06 -07009004 return -TARGET_EFAULT;
Paul Burton356d7712014-06-22 11:25:37 +01009005 }
9006 } else {
9007 p3 = NULL;
9008 }
9009
9010 /* FIXME - arg5 should be locked, but it isn't clear how to
9011 * do that since it's not guaranteed to be a NULL-terminated
9012 * string.
9013 */
9014 if (!arg5) {
9015 ret = mount(p, p2, p3, (unsigned long)arg4, NULL);
9016 } else {
Richard Henderson3e8f1622021-02-12 10:48:43 -08009017 ret = mount(p, p2, p3, (unsigned long)arg4, g2h(cpu, arg5));
Paul Burton356d7712014-06-22 11:25:37 +01009018 }
9019 ret = get_errno(ret);
9020
9021 if (arg1) {
9022 unlock_user(p, arg1, 0);
9023 }
9024 unlock_user(p2, arg2, 0);
9025 if (arg3) {
9026 unlock_user(p3, arg3, 0);
9027 }
9028 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009029 return ret;
Laurent Vivier6eb9dbf2020-05-02 21:46:42 +02009030#if defined(TARGET_NR_umount) || defined(TARGET_NR_oldumount)
9031#if defined(TARGET_NR_umount)
bellard31e31b82003-02-18 22:55:36 +00009032 case TARGET_NR_umount:
Laurent Vivier6eb9dbf2020-05-02 21:46:42 +02009033#endif
9034#if defined(TARGET_NR_oldumount)
9035 case TARGET_NR_oldumount:
9036#endif
bellard579a97f2007-11-11 14:26:47 +00009037 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009038 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009039 ret = get_errno(umount(p));
9040 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009041 return ret;
thse5febef2007-04-01 18:31:35 +00009042#endif
j_mayer7a3148a2007-04-05 07:13:51 +00009043#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009044 case TARGET_NR_stime:
9045 {
Laurent Vivier0f1f2d42019-11-12 15:25:56 +01009046 struct timespec ts;
9047 ts.tv_nsec = 0;
9048 if (get_user_sal(ts.tv_sec, arg1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009049 return -TARGET_EFAULT;
Laurent Vivier0f1f2d42019-11-12 15:25:56 +01009050 }
9051 return get_errno(clock_settime(CLOCK_REALTIME, &ts));
bellard31e31b82003-02-18 22:55:36 +00009052 }
j_mayer7a3148a2007-04-05 07:13:51 +00009053#endif
j_mayer7a3148a2007-04-05 07:13:51 +00009054#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009055 case TARGET_NR_alarm:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009056 return alarm(arg1);
j_mayer7a3148a2007-04-05 07:13:51 +00009057#endif
j_mayer7a3148a2007-04-05 07:13:51 +00009058#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009059 case TARGET_NR_pause:
Timothy E Baldwinf59ec602016-05-27 15:51:55 +01009060 if (!block_signals()) {
9061 sigsuspend(&((TaskState *)cpu->opaque)->signal_mask);
9062 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009063 return -TARGET_EINTR;
j_mayer7a3148a2007-04-05 07:13:51 +00009064#endif
thse5febef2007-04-01 18:31:35 +00009065#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00009066 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00009067 {
pbrook53a59602006-03-25 19:31:22 +00009068 struct utimbuf tbuf, *host_tbuf;
9069 struct target_utimbuf *target_tbuf;
9070 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00009071 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009072 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02009073 tbuf.actime = tswapal(target_tbuf->actime);
9074 tbuf.modtime = tswapal(target_tbuf->modtime);
pbrook53a59602006-03-25 19:31:22 +00009075 unlock_user_struct(target_tbuf, arg2, 0);
9076 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00009077 } else {
pbrook53a59602006-03-25 19:31:22 +00009078 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00009079 }
bellard579a97f2007-11-11 14:26:47 +00009080 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009081 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009082 ret = get_errno(utime(p, host_tbuf));
9083 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00009084 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009085 return ret;
thse5febef2007-04-01 18:31:35 +00009086#endif
Chen Gang704eff62015-08-21 05:37:33 +08009087#ifdef TARGET_NR_utimes
bellard978a66f2004-12-06 22:58:05 +00009088 case TARGET_NR_utimes:
9089 {
bellard978a66f2004-12-06 22:58:05 +00009090 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00009091 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00009092 if (copy_from_user_timeval(&tv[0], arg2)
9093 || copy_from_user_timeval(&tv[1],
9094 arg2 + sizeof(struct target_timeval)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009095 return -TARGET_EFAULT;
bellard978a66f2004-12-06 22:58:05 +00009096 tvp = tv;
9097 } else {
9098 tvp = NULL;
9099 }
bellard579a97f2007-11-11 14:26:47 +00009100 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009101 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009102 ret = get_errno(utimes(p, tvp));
9103 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00009104 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009105 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009106#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01009107#if defined(TARGET_NR_futimesat)
balrogac8a6552008-09-20 02:25:39 +00009108 case TARGET_NR_futimesat:
9109 {
9110 struct timeval *tvp, tv[2];
9111 if (arg3) {
9112 if (copy_from_user_timeval(&tv[0], arg3)
9113 || copy_from_user_timeval(&tv[1],
9114 arg3 + sizeof(struct target_timeval)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009115 return -TARGET_EFAULT;
balrogac8a6552008-09-20 02:25:39 +00009116 tvp = tv;
9117 } else {
9118 tvp = NULL;
9119 }
Richard Henderson2852aaf2018-08-18 12:01:06 -07009120 if (!(p = lock_user_string(arg2))) {
9121 return -TARGET_EFAULT;
9122 }
Peter Maydellc0d472b2013-06-12 16:20:21 +01009123 ret = get_errno(futimesat(arg1, path(p), tvp));
balrogac8a6552008-09-20 02:25:39 +00009124 unlock_user(p, arg2, 0);
9125 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009126 return ret;
balrogac8a6552008-09-20 02:25:39 +00009127#endif
Chen Gang704eff62015-08-21 05:37:33 +08009128#ifdef TARGET_NR_access
bellard31e31b82003-02-18 22:55:36 +00009129 case TARGET_NR_access:
Richard Henderson2852aaf2018-08-18 12:01:06 -07009130 if (!(p = lock_user_string(arg1))) {
9131 return -TARGET_EFAULT;
9132 }
Ulrich Hecht719f9082009-07-03 17:09:29 +02009133 ret = get_errno(access(path(p), arg2));
pbrook53a59602006-03-25 19:31:22 +00009134 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009135 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009136#endif
ths92a34c12007-09-24 09:27:49 +00009137#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
9138 case TARGET_NR_faccessat:
Richard Henderson2852aaf2018-08-18 12:01:06 -07009139 if (!(p = lock_user_string(arg2))) {
9140 return -TARGET_EFAULT;
9141 }
Peter Maydellc0d472b2013-06-12 16:20:21 +01009142 ret = get_errno(faccessat(arg1, p, arg3, 0));
bellard579a97f2007-11-11 14:26:47 +00009143 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009144 return ret;
ths92a34c12007-09-24 09:27:49 +00009145#endif
j_mayer7a3148a2007-04-05 07:13:51 +00009146#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009147 case TARGET_NR_nice:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009148 return get_errno(nice(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +00009149#endif
bellard31e31b82003-02-18 22:55:36 +00009150 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00009151 sync();
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009152 return 0;
Aleksandar Markovic5a03cd02016-10-10 13:23:30 +02009153#if defined(TARGET_NR_syncfs) && defined(CONFIG_SYNCFS)
9154 case TARGET_NR_syncfs:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009155 return get_errno(syncfs(arg1));
Aleksandar Markovic5a03cd02016-10-10 13:23:30 +02009156#endif
bellard31e31b82003-02-18 22:55:36 +00009157 case TARGET_NR_kill:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009158 return get_errno(safe_kill(arg1, target_to_host_signal(arg2)));
Chen Gang704eff62015-08-21 05:37:33 +08009159#ifdef TARGET_NR_rename
bellard31e31b82003-02-18 22:55:36 +00009160 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00009161 {
9162 void *p2;
9163 p = lock_user_string(arg1);
9164 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00009165 if (!p || !p2)
9166 ret = -TARGET_EFAULT;
9167 else
9168 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00009169 unlock_user(p2, arg2, 0);
9170 unlock_user(p, arg1, 0);
9171 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009172 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009173#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01009174#if defined(TARGET_NR_renameat)
ths722183f2007-09-24 09:24:37 +00009175 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00009176 {
bellard579a97f2007-11-11 14:26:47 +00009177 void *p2;
ths722183f2007-09-24 09:24:37 +00009178 p = lock_user_string(arg2);
9179 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00009180 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00009181 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00009182 else
Peter Maydellc0d472b2013-06-12 16:20:21 +01009183 ret = get_errno(renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00009184 unlock_user(p2, arg4, 0);
9185 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00009186 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009187 return ret;
ths722183f2007-09-24 09:24:37 +00009188#endif
Andreas Schwab95d03072018-01-23 11:53:31 +01009189#if defined(TARGET_NR_renameat2)
9190 case TARGET_NR_renameat2:
9191 {
9192 void *p2;
9193 p = lock_user_string(arg2);
9194 p2 = lock_user_string(arg4);
9195 if (!p || !p2) {
9196 ret = -TARGET_EFAULT;
9197 } else {
9198 ret = get_errno(sys_renameat2(arg1, p, arg3, p2, arg5));
9199 }
9200 unlock_user(p2, arg4, 0);
9201 unlock_user(p, arg2, 0);
9202 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009203 return ret;
Andreas Schwab95d03072018-01-23 11:53:31 +01009204#endif
Chen Gang704eff62015-08-21 05:37:33 +08009205#ifdef TARGET_NR_mkdir
bellard31e31b82003-02-18 22:55:36 +00009206 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00009207 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009208 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009209 ret = get_errno(mkdir(p, arg2));
9210 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009211 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009212#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01009213#if defined(TARGET_NR_mkdirat)
ths4472ad02007-09-24 09:22:32 +00009214 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00009215 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009216 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +01009217 ret = get_errno(mkdirat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00009218 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009219 return ret;
ths4472ad02007-09-24 09:22:32 +00009220#endif
Chen Gang704eff62015-08-21 05:37:33 +08009221#ifdef TARGET_NR_rmdir
bellard31e31b82003-02-18 22:55:36 +00009222 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00009223 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009224 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009225 ret = get_errno(rmdir(p));
9226 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009227 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009228#endif
bellard31e31b82003-02-18 22:55:36 +00009229 case TARGET_NR_dup:
9230 ret = get_errno(dup(arg1));
Laurent Viviere36800c2015-10-02 14:48:09 +02009231 if (ret >= 0) {
9232 fd_trans_dup(arg1, ret);
9233 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009234 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009235#ifdef TARGET_NR_pipe
bellard31e31b82003-02-18 22:55:36 +00009236 case TARGET_NR_pipe:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009237 return do_pipe(cpu_env, arg1, 0, 0);
Chen Gang704eff62015-08-21 05:37:33 +08009238#endif
Riku Voipio099d6b02009-05-05 12:10:04 +03009239#ifdef TARGET_NR_pipe2
9240 case TARGET_NR_pipe2:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009241 return do_pipe(cpu_env, arg1,
9242 target_to_host_bitmask(arg2, fcntl_flags_tbl), 1);
Riku Voipio099d6b02009-05-05 12:10:04 +03009243#endif
bellard31e31b82003-02-18 22:55:36 +00009244 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00009245 {
pbrook53a59602006-03-25 19:31:22 +00009246 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00009247 struct tms tms;
9248 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00009249 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00009250 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
9251 if (!tmsp)
Richard Henderson2852aaf2018-08-18 12:01:06 -07009252 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +02009253 tmsp->tms_utime = tswapal(host_to_target_clock_t(tms.tms_utime));
9254 tmsp->tms_stime = tswapal(host_to_target_clock_t(tms.tms_stime));
9255 tmsp->tms_cutime = tswapal(host_to_target_clock_t(tms.tms_cutime));
9256 tmsp->tms_cstime = tswapal(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00009257 }
bellardc596ed12003-07-13 17:32:31 +00009258 if (!is_error(ret))
9259 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00009260 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009261 return ret;
bellard31e31b82003-02-18 22:55:36 +00009262 case TARGET_NR_acct:
aurel3238d840e2009-01-30 19:48:17 +00009263 if (arg1 == 0) {
9264 ret = get_errno(acct(NULL));
9265 } else {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009266 if (!(p = lock_user_string(arg1))) {
9267 return -TARGET_EFAULT;
9268 }
aurel3238d840e2009-01-30 19:48:17 +00009269 ret = get_errno(acct(path(p)));
9270 unlock_user(p, arg1, 0);
9271 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009272 return ret;
Richard Henderson8070e7b2013-07-24 09:50:00 -10009273#ifdef TARGET_NR_umount2
bellard31e31b82003-02-18 22:55:36 +00009274 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00009275 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009276 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009277 ret = get_errno(umount2(p, arg2));
9278 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009279 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00009280#endif
bellard31e31b82003-02-18 22:55:36 +00009281 case TARGET_NR_ioctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009282 return do_ioctl(arg1, arg2, arg3);
Michael Clark47ae93c2018-03-03 01:31:11 +13009283#ifdef TARGET_NR_fcntl
bellard31e31b82003-02-18 22:55:36 +00009284 case TARGET_NR_fcntl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009285 return do_fcntl(arg1, arg2, arg3);
Michael Clark47ae93c2018-03-03 01:31:11 +13009286#endif
bellard31e31b82003-02-18 22:55:36 +00009287 case TARGET_NR_setpgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009288 return get_errno(setpgid(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00009289 case TARGET_NR_umask:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009290 return get_errno(umask(arg1));
bellard31e31b82003-02-18 22:55:36 +00009291 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00009292 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009293 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009294 ret = get_errno(chroot(p));
9295 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009296 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009297#ifdef TARGET_NR_dup2
bellard31e31b82003-02-18 22:55:36 +00009298 case TARGET_NR_dup2:
9299 ret = get_errno(dup2(arg1, arg2));
Laurent Viviere36800c2015-10-02 14:48:09 +02009300 if (ret >= 0) {
9301 fd_trans_dup(arg1, arg2);
9302 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009303 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009304#endif
Ulrich Hechtd0927932009-09-17 20:22:14 +03009305#if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3)
9306 case TARGET_NR_dup3:
Peter Maydell10fa9932017-12-15 15:18:00 +00009307 {
9308 int host_flags;
9309
9310 if ((arg3 & ~TARGET_O_CLOEXEC) != 0) {
9311 return -EINVAL;
9312 }
9313 host_flags = target_to_host_bitmask(arg3, fcntl_flags_tbl);
9314 ret = get_errno(dup3(arg1, arg2, host_flags));
Laurent Viviere36800c2015-10-02 14:48:09 +02009315 if (ret >= 0) {
9316 fd_trans_dup(arg1, arg2);
9317 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009318 return ret;
Peter Maydell10fa9932017-12-15 15:18:00 +00009319 }
Ulrich Hechtd0927932009-09-17 20:22:14 +03009320#endif
j_mayer7a3148a2007-04-05 07:13:51 +00009321#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009322 case TARGET_NR_getppid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009323 return get_errno(getppid());
j_mayer7a3148a2007-04-05 07:13:51 +00009324#endif
Chen Gang704eff62015-08-21 05:37:33 +08009325#ifdef TARGET_NR_getpgrp
bellard31e31b82003-02-18 22:55:36 +00009326 case TARGET_NR_getpgrp:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009327 return get_errno(getpgrp());
Chen Gang704eff62015-08-21 05:37:33 +08009328#endif
bellard31e31b82003-02-18 22:55:36 +00009329 case TARGET_NR_setsid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009330 return get_errno(setsid());
thse5febef2007-04-01 18:31:35 +00009331#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00009332 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00009333 {
Richard Henderson02d0de12021-04-22 16:02:26 -07009334#if defined(TARGET_MIPS)
bellard106ec872006-06-27 21:08:10 +00009335 struct target_sigaction act, oact, *pact, *old_act;
9336
9337 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00009338 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009339 return -TARGET_EFAULT;
bellard106ec872006-06-27 21:08:10 +00009340 act._sa_handler = old_act->_sa_handler;
9341 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
9342 act.sa_flags = old_act->sa_flags;
9343 unlock_user_struct(old_act, arg2, 0);
9344 pact = &act;
9345 } else {
9346 pact = NULL;
9347 }
9348
Richard Henderson02fb28e2021-04-22 16:02:23 -07009349 ret = get_errno(do_sigaction(arg1, pact, &oact, 0));
bellard106ec872006-06-27 21:08:10 +00009350
9351 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00009352 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009353 return -TARGET_EFAULT;
bellard106ec872006-06-27 21:08:10 +00009354 old_act->_sa_handler = oact._sa_handler;
9355 old_act->sa_flags = oact.sa_flags;
9356 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
9357 old_act->sa_mask.sig[1] = 0;
9358 old_act->sa_mask.sig[2] = 0;
9359 old_act->sa_mask.sig[3] = 0;
9360 unlock_user_struct(old_act, arg3, 1);
9361 }
Richard Henderson6049f4f2009-12-27 18:30:03 -08009362#else
9363 struct target_old_sigaction *old_act;
9364 struct target_sigaction act, oact, *pact;
9365 if (arg2) {
9366 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009367 return -TARGET_EFAULT;
Richard Henderson6049f4f2009-12-27 18:30:03 -08009368 act._sa_handler = old_act->_sa_handler;
9369 target_siginitset(&act.sa_mask, old_act->sa_mask);
9370 act.sa_flags = old_act->sa_flags;
Richard Hendersonca192272021-04-22 16:02:24 -07009371#ifdef TARGET_ARCH_HAS_SA_RESTORER
Richard Henderson6049f4f2009-12-27 18:30:03 -08009372 act.sa_restorer = old_act->sa_restorer;
Richard Hendersonca192272021-04-22 16:02:24 -07009373#endif
Richard Henderson6049f4f2009-12-27 18:30:03 -08009374 unlock_user_struct(old_act, arg2, 0);
9375 pact = &act;
9376 } else {
9377 pact = NULL;
9378 }
Richard Henderson02fb28e2021-04-22 16:02:23 -07009379 ret = get_errno(do_sigaction(arg1, pact, &oact, 0));
Richard Henderson6049f4f2009-12-27 18:30:03 -08009380 if (!is_error(ret) && arg3) {
9381 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009382 return -TARGET_EFAULT;
Richard Henderson6049f4f2009-12-27 18:30:03 -08009383 old_act->_sa_handler = oact._sa_handler;
9384 old_act->sa_mask = oact.sa_mask.sig[0];
9385 old_act->sa_flags = oact.sa_flags;
Richard Hendersonca192272021-04-22 16:02:24 -07009386#ifdef TARGET_ARCH_HAS_SA_RESTORER
Richard Henderson6049f4f2009-12-27 18:30:03 -08009387 old_act->sa_restorer = oact.sa_restorer;
Richard Hendersonca192272021-04-22 16:02:24 -07009388#endif
Richard Henderson6049f4f2009-12-27 18:30:03 -08009389 unlock_user_struct(old_act, arg3, 1);
9390 }
ths388bb212007-05-13 13:58:00 +00009391#endif
bellard31e31b82003-02-18 22:55:36 +00009392 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009393 return ret;
thse5febef2007-04-01 18:31:35 +00009394#endif
bellard66fb9762003-03-23 01:06:05 +00009395 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00009396 {
Richard Henderson0f6f9902021-04-22 16:02:25 -07009397 /*
9398 * For Alpha and SPARC this is a 5 argument syscall, with
Peter Maydell78bfef72017-11-06 18:33:26 +00009399 * a 'restorer' parameter which must be copied into the
9400 * sa_restorer field of the sigaction struct.
9401 * For Alpha that 'restorer' is arg5; for SPARC it is arg4,
9402 * and arg5 is the sigsetsize.
Peter Maydell78bfef72017-11-06 18:33:26 +00009403 */
Richard Henderson0f6f9902021-04-22 16:02:25 -07009404#if defined(TARGET_ALPHA)
9405 target_ulong sigsetsize = arg4;
9406 target_ulong restorer = arg5;
9407#elif defined(TARGET_SPARC)
Peter Maydell78bfef72017-11-06 18:33:26 +00009408 target_ulong restorer = arg4;
9409 target_ulong sigsetsize = arg5;
9410#else
9411 target_ulong sigsetsize = arg4;
Richard Henderson02fb28e2021-04-22 16:02:23 -07009412 target_ulong restorer = 0;
Peter Maydell78bfef72017-11-06 18:33:26 +00009413#endif
Richard Hendersonfb804392021-04-22 16:02:27 -07009414 struct target_sigaction *act = NULL;
9415 struct target_sigaction *oact = NULL;
pbrook53a59602006-03-25 19:31:22 +00009416
Peter Maydell78bfef72017-11-06 18:33:26 +00009417 if (sigsetsize != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009418 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01009419 }
Richard Hendersonfb804392021-04-22 16:02:27 -07009420 if (arg2 && !lock_user_struct(VERIFY_READ, act, arg2, 1)) {
9421 return -TARGET_EFAULT;
Peter Maydell78bfef72017-11-06 18:33:26 +00009422 }
Richard Hendersonfb804392021-04-22 16:02:27 -07009423 if (arg3 && !lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
9424 ret = -TARGET_EFAULT;
9425 } else {
9426 ret = get_errno(do_sigaction(arg1, act, oact, restorer));
9427 if (oact) {
9428 unlock_user_struct(oact, arg3, 1);
bellard579a97f2007-11-11 14:26:47 +00009429 }
Richard Hendersonfb804392021-04-22 16:02:27 -07009430 }
9431 if (act) {
pbrook53a59602006-03-25 19:31:22 +00009432 unlock_user_struct(act, arg2, 0);
Richard Hendersonfb804392021-04-22 16:02:27 -07009433 }
pbrook53a59602006-03-25 19:31:22 +00009434 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009435 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00009436#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009437 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00009438 {
9439 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00009440 abi_ulong target_set;
Peter Maydell3d3efba2016-05-27 15:51:49 +01009441 ret = do_sigprocmask(0, NULL, &cur_set);
9442 if (!ret) {
9443 host_to_target_old_sigset(&target_set, &cur_set);
9444 ret = target_set;
9445 }
bellard66fb9762003-03-23 01:06:05 +00009446 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009447 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00009448#endif
9449#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00009450 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00009451 {
Miloš Stojanovića8617d82017-05-15 16:59:43 +02009452 sigset_t set, oset;
blueswir1992f48a2007-10-14 16:27:31 +00009453 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00009454 target_to_host_old_sigset(&set, &target_set);
Peter Maydell3d3efba2016-05-27 15:51:49 +01009455 ret = do_sigprocmask(SIG_SETMASK, &set, &oset);
9456 if (!ret) {
9457 host_to_target_old_sigset(&target_set, &oset);
9458 ret = target_set;
9459 }
bellard66fb9762003-03-23 01:06:05 +00009460 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009461 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +00009462#endif
thse5febef2007-04-01 18:31:35 +00009463#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00009464 case TARGET_NR_sigprocmask:
9465 {
Richard Hendersona5b3b132010-05-03 10:07:55 -07009466#if defined(TARGET_ALPHA)
9467 sigset_t set, oldset;
9468 abi_ulong mask;
9469 int how;
9470
9471 switch (arg1) {
9472 case TARGET_SIG_BLOCK:
9473 how = SIG_BLOCK;
9474 break;
9475 case TARGET_SIG_UNBLOCK:
9476 how = SIG_UNBLOCK;
9477 break;
9478 case TARGET_SIG_SETMASK:
9479 how = SIG_SETMASK;
9480 break;
9481 default:
Richard Henderson259841c2018-08-18 12:01:09 -07009482 return -TARGET_EINVAL;
Richard Hendersona5b3b132010-05-03 10:07:55 -07009483 }
9484 mask = arg2;
9485 target_to_host_old_sigset(&set, &mask);
9486
Peter Maydell3d3efba2016-05-27 15:51:49 +01009487 ret = do_sigprocmask(how, &set, &oldset);
Richard Hendersona5b3b132010-05-03 10:07:55 -07009488 if (!is_error(ret)) {
9489 host_to_target_old_sigset(&mask, &oldset);
9490 ret = mask;
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +02009491 cpu_env->ir[IR_V0] = 0; /* force no error */
Richard Hendersona5b3b132010-05-03 10:07:55 -07009492 }
9493#else
bellard66fb9762003-03-23 01:06:05 +00009494 sigset_t set, oldset, *set_ptr;
Richard Hendersona5b3b132010-05-03 10:07:55 -07009495 int how;
ths3b46e622007-09-17 08:09:54 +00009496
pbrook53a59602006-03-25 19:31:22 +00009497 if (arg2) {
Patrick Ventureebce1712022-01-26 13:25:59 -08009498 p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1);
9499 if (!p) {
9500 return -TARGET_EFAULT;
9501 }
9502 target_to_host_old_sigset(&set, p);
9503 unlock_user(p, arg2, 0);
9504 set_ptr = &set;
Richard Hendersona5b3b132010-05-03 10:07:55 -07009505 switch (arg1) {
bellard66fb9762003-03-23 01:06:05 +00009506 case TARGET_SIG_BLOCK:
9507 how = SIG_BLOCK;
9508 break;
9509 case TARGET_SIG_UNBLOCK:
9510 how = SIG_UNBLOCK;
9511 break;
9512 case TARGET_SIG_SETMASK:
9513 how = SIG_SETMASK;
9514 break;
9515 default:
Richard Henderson259841c2018-08-18 12:01:09 -07009516 return -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00009517 }
bellard66fb9762003-03-23 01:06:05 +00009518 } else {
9519 how = 0;
9520 set_ptr = NULL;
9521 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01009522 ret = do_sigprocmask(how, set_ptr, &oldset);
pbrook53a59602006-03-25 19:31:22 +00009523 if (!is_error(ret) && arg3) {
Anthony Liguoric227f092009-10-01 16:12:16 -05009524 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009525 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009526 host_to_target_old_sigset(p, &oldset);
Anthony Liguoric227f092009-10-01 16:12:16 -05009527 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00009528 }
Richard Hendersona5b3b132010-05-03 10:07:55 -07009529#endif
bellard66fb9762003-03-23 01:06:05 +00009530 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009531 return ret;
thse5febef2007-04-01 18:31:35 +00009532#endif
bellard66fb9762003-03-23 01:06:05 +00009533 case TARGET_NR_rt_sigprocmask:
9534 {
9535 int how = arg1;
9536 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00009537
Peter Maydellc8157012016-06-30 14:23:24 +01009538 if (arg4 != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009539 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01009540 }
9541
pbrook53a59602006-03-25 19:31:22 +00009542 if (arg2) {
Shu-Chun Wengd3ced2a2022-01-26 13:25:58 -08009543 p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1);
9544 if (!p) {
9545 return -TARGET_EFAULT;
9546 }
9547 target_to_host_sigset(&set, p);
9548 unlock_user(p, arg2, 0);
9549 set_ptr = &set;
bellard66fb9762003-03-23 01:06:05 +00009550 switch(how) {
9551 case TARGET_SIG_BLOCK:
9552 how = SIG_BLOCK;
9553 break;
9554 case TARGET_SIG_UNBLOCK:
9555 how = SIG_UNBLOCK;
9556 break;
9557 case TARGET_SIG_SETMASK:
9558 how = SIG_SETMASK;
9559 break;
9560 default:
Richard Henderson259841c2018-08-18 12:01:09 -07009561 return -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00009562 }
bellard66fb9762003-03-23 01:06:05 +00009563 } else {
9564 how = 0;
9565 set_ptr = NULL;
9566 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01009567 ret = do_sigprocmask(how, set_ptr, &oldset);
pbrook53a59602006-03-25 19:31:22 +00009568 if (!is_error(ret) && arg3) {
Anthony Liguoric227f092009-10-01 16:12:16 -05009569 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009570 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009571 host_to_target_sigset(p, &oldset);
Anthony Liguoric227f092009-10-01 16:12:16 -05009572 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00009573 }
9574 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009575 return ret;
thse5febef2007-04-01 18:31:35 +00009576#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00009577 case TARGET_NR_sigpending:
9578 {
9579 sigset_t set;
9580 ret = get_errno(sigpending(&set));
9581 if (!is_error(ret)) {
Anthony Liguoric227f092009-10-01 16:12:16 -05009582 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009583 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009584 host_to_target_old_sigset(p, &set);
Anthony Liguoric227f092009-10-01 16:12:16 -05009585 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00009586 }
9587 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009588 return ret;
thse5febef2007-04-01 18:31:35 +00009589#endif
bellard66fb9762003-03-23 01:06:05 +00009590 case TARGET_NR_rt_sigpending:
9591 {
9592 sigset_t set;
Peter Maydellc8157012016-06-30 14:23:24 +01009593
9594 /* Yes, this check is >, not != like most. We follow the kernel's
9595 * logic and it does it like this because it implements
9596 * NR_sigpending through the same code path, and in that case
9597 * the old_sigset_t is smaller in size.
9598 */
9599 if (arg2 > sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009600 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01009601 }
9602
bellard66fb9762003-03-23 01:06:05 +00009603 ret = get_errno(sigpending(&set));
9604 if (!is_error(ret)) {
Anthony Liguoric227f092009-10-01 16:12:16 -05009605 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009606 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009607 host_to_target_sigset(p, &set);
Anthony Liguoric227f092009-10-01 16:12:16 -05009608 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00009609 }
9610 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009611 return ret;
thse5febef2007-04-01 18:31:35 +00009612#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00009613 case TARGET_NR_sigsuspend:
9614 {
Richard Henderson0a99f092022-03-15 01:43:05 -07009615 sigset_t *set;
9616
Richard Hendersonf43ce122010-05-03 10:07:54 -07009617#if defined(TARGET_ALPHA)
Richard Henderson0a99f092022-03-15 01:43:05 -07009618 TaskState *ts = cpu->opaque;
Richard Henderson7fb5ef32022-03-15 01:43:04 -07009619 /* target_to_host_old_sigset will bswap back */
9620 abi_ulong mask = tswapal(arg1);
Richard Henderson0a99f092022-03-15 01:43:05 -07009621 set = &ts->sigsuspend_mask;
9622 target_to_host_old_sigset(set, &mask);
Richard Hendersonf43ce122010-05-03 10:07:54 -07009623#else
Richard Henderson0a99f092022-03-15 01:43:05 -07009624 ret = process_sigsuspend_mask(&set, arg1, sizeof(target_sigset_t));
9625 if (ret != 0) {
9626 return ret;
Peter Maydell3d3efba2016-05-27 15:51:49 +01009627 }
Richard Henderson0a99f092022-03-15 01:43:05 -07009628#endif
9629 ret = get_errno(safe_rt_sigsuspend(set, SIGSET_T_SIZE));
9630 finish_sigsuspend_mask(ret);
bellard66fb9762003-03-23 01:06:05 +00009631 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009632 return ret;
thse5febef2007-04-01 18:31:35 +00009633#endif
bellard66fb9762003-03-23 01:06:05 +00009634 case TARGET_NR_rt_sigsuspend:
9635 {
Richard Henderson0a99f092022-03-15 01:43:05 -07009636 sigset_t *set;
Peter Maydellc8157012016-06-30 14:23:24 +01009637
Richard Henderson0a99f092022-03-15 01:43:05 -07009638 ret = process_sigsuspend_mask(&set, arg1, arg2);
9639 if (ret != 0) {
9640 return ret;
Peter Maydellc8157012016-06-30 14:23:24 +01009641 }
Richard Henderson0a99f092022-03-15 01:43:05 -07009642 ret = get_errno(safe_rt_sigsuspend(set, SIGSET_T_SIZE));
9643 finish_sigsuspend_mask(ret);
bellard66fb9762003-03-23 01:06:05 +00009644 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009645 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -07009646#ifdef TARGET_NR_rt_sigtimedwait
bellard66fb9762003-03-23 01:06:05 +00009647 case TARGET_NR_rt_sigtimedwait:
9648 {
bellard66fb9762003-03-23 01:06:05 +00009649 sigset_t set;
9650 struct timespec uts, *puts;
9651 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00009652
Peter Maydellc8157012016-06-30 14:23:24 +01009653 if (arg4 != sizeof(target_sigset_t)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009654 return -TARGET_EINVAL;
Peter Maydellc8157012016-06-30 14:23:24 +01009655 }
9656
Anthony Liguoric227f092009-10-01 16:12:16 -05009657 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009658 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009659 target_to_host_sigset(&set, p);
9660 unlock_user(p, arg1, 0);
9661 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00009662 puts = &uts;
Filip Bozuta4d213002020-07-24 20:16:51 +02009663 if (target_to_host_timespec(puts, arg3)) {
9664 return -TARGET_EFAULT;
9665 }
bellard66fb9762003-03-23 01:06:05 +00009666 } else {
9667 puts = NULL;
9668 }
Peter Maydellb3f82332016-06-06 19:58:08 +01009669 ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts,
9670 SIGSET_T_SIZE));
Petar Jovanovic974a1962014-03-03 15:07:41 +01009671 if (!is_error(ret)) {
9672 if (arg2) {
9673 p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t),
9674 0);
9675 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009676 return -TARGET_EFAULT;
Petar Jovanovic974a1962014-03-03 15:07:41 +01009677 }
9678 host_to_target_siginfo(p, &uinfo);
9679 unlock_user(p, arg2, sizeof(target_siginfo_t));
9680 }
9681 ret = host_to_target_signal(ret);
bellard66fb9762003-03-23 01:06:05 +00009682 }
9683 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009684 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -07009685#endif
Filip Bozutaddcbde12020-08-24 21:21:16 +02009686#ifdef TARGET_NR_rt_sigtimedwait_time64
9687 case TARGET_NR_rt_sigtimedwait_time64:
9688 {
9689 sigset_t set;
9690 struct timespec uts, *puts;
9691 siginfo_t uinfo;
9692
9693 if (arg4 != sizeof(target_sigset_t)) {
9694 return -TARGET_EINVAL;
9695 }
9696
9697 p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
9698 if (!p) {
9699 return -TARGET_EFAULT;
9700 }
9701 target_to_host_sigset(&set, p);
9702 unlock_user(p, arg1, 0);
9703 if (arg3) {
9704 puts = &uts;
9705 if (target_to_host_timespec64(puts, arg3)) {
9706 return -TARGET_EFAULT;
9707 }
9708 } else {
9709 puts = NULL;
9710 }
9711 ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts,
9712 SIGSET_T_SIZE));
9713 if (!is_error(ret)) {
9714 if (arg2) {
9715 p = lock_user(VERIFY_WRITE, arg2,
9716 sizeof(target_siginfo_t), 0);
9717 if (!p) {
9718 return -TARGET_EFAULT;
9719 }
9720 host_to_target_siginfo(p, &uinfo);
9721 unlock_user(p, arg2, sizeof(target_siginfo_t));
9722 }
9723 ret = host_to_target_signal(ret);
9724 }
9725 }
9726 return ret;
9727#endif
bellard66fb9762003-03-23 01:06:05 +00009728 case TARGET_NR_rt_sigqueueinfo:
9729 {
9730 siginfo_t uinfo;
Peter Maydell4debae62016-06-20 15:50:36 +01009731
9732 p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
9733 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009734 return -TARGET_EFAULT;
Peter Maydell4debae62016-06-20 15:50:36 +01009735 }
pbrook53a59602006-03-25 19:31:22 +00009736 target_to_host_siginfo(&uinfo, p);
Miloš Stojanovićd8b6d892017-05-15 16:59:44 +02009737 unlock_user(p, arg3, 0);
fanwenjie9b9145f2022-08-31 11:55:25 +08009738 ret = get_errno(sys_rt_sigqueueinfo(arg1, target_to_host_signal(arg2), &uinfo));
bellard66fb9762003-03-23 01:06:05 +00009739 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009740 return ret;
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +02009741 case TARGET_NR_rt_tgsigqueueinfo:
9742 {
9743 siginfo_t uinfo;
9744
9745 p = lock_user(VERIFY_READ, arg4, sizeof(target_siginfo_t), 1);
9746 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009747 return -TARGET_EFAULT;
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +02009748 }
9749 target_to_host_siginfo(&uinfo, p);
9750 unlock_user(p, arg4, 0);
fanwenjie9b9145f2022-08-31 11:55:25 +08009751 ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, target_to_host_signal(arg3), &uinfo));
Miloš Stojanovićcf8b8bf2017-05-15 16:59:46 +02009752 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009753 return ret;
thse5febef2007-04-01 18:31:35 +00009754#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00009755 case TARGET_NR_sigreturn:
Peter Maydell3d3efba2016-05-27 15:51:49 +01009756 if (block_signals()) {
Richard Hendersonaf254a22021-11-22 19:47:33 +01009757 return -QEMU_ERESTARTSYS;
Peter Maydell3d3efba2016-05-27 15:51:49 +01009758 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009759 return do_sigreturn(cpu_env);
thse5febef2007-04-01 18:31:35 +00009760#endif
bellard66fb9762003-03-23 01:06:05 +00009761 case TARGET_NR_rt_sigreturn:
Peter Maydell3d3efba2016-05-27 15:51:49 +01009762 if (block_signals()) {
Richard Hendersonaf254a22021-11-22 19:47:33 +01009763 return -QEMU_ERESTARTSYS;
Peter Maydell3d3efba2016-05-27 15:51:49 +01009764 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009765 return do_rt_sigreturn(cpu_env);
bellard31e31b82003-02-18 22:55:36 +00009766 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00009767 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009768 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009769 ret = get_errno(sethostname(p, arg2));
9770 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009771 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009772#ifdef TARGET_NR_setrlimit
bellard31e31b82003-02-18 22:55:36 +00009773 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +00009774 {
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03009775 int resource = target_to_host_resource(arg1);
pbrook53a59602006-03-25 19:31:22 +00009776 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00009777 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +00009778 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009779 return -TARGET_EFAULT;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09009780 rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
9781 rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00009782 unlock_user_struct(target_rlim, arg2, 0);
Max Filippov5dfa88f2018-09-17 11:13:14 -07009783 /*
9784 * If we just passed through resource limit settings for memory then
9785 * they would also apply to QEMU's own allocations, and QEMU will
9786 * crash or hang or die if its allocations fail. Ideally we would
9787 * track the guest allocations in QEMU and apply the limits ourselves.
9788 * For now, just tell the guest the call succeeded but don't actually
9789 * limit anything.
9790 */
9791 if (resource != RLIMIT_AS &&
9792 resource != RLIMIT_DATA &&
9793 resource != RLIMIT_STACK) {
9794 return get_errno(setrlimit(resource, &rlim));
9795 } else {
9796 return 0;
9797 }
bellard9de5e442003-03-23 16:49:39 +00009798 }
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009799#endif
9800#ifdef TARGET_NR_getrlimit
bellard31e31b82003-02-18 22:55:36 +00009801 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00009802 {
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +03009803 int resource = target_to_host_resource(arg1);
pbrook53a59602006-03-25 19:31:22 +00009804 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00009805 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00009806
bellard9de5e442003-03-23 16:49:39 +00009807 ret = get_errno(getrlimit(resource, &rlim));
9808 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00009809 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009810 return -TARGET_EFAULT;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09009811 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
9812 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00009813 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00009814 }
9815 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009816 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +02009817#endif
bellard31e31b82003-02-18 22:55:36 +00009818 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00009819 {
9820 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00009821 ret = get_errno(getrusage(arg1, &rusage));
9822 if (!is_error(ret)) {
Petar Jovanovica39fb272014-04-08 19:24:30 +02009823 ret = host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00009824 }
9825 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009826 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -07009827#if defined(TARGET_NR_gettimeofday)
bellard31e31b82003-02-18 22:55:36 +00009828 case TARGET_NR_gettimeofday:
9829 {
bellard31e31b82003-02-18 22:55:36 +00009830 struct timeval tv;
Richard Hendersona52f5f82020-02-12 19:22:23 -08009831 struct timezone tz;
9832
9833 ret = get_errno(gettimeofday(&tv, &tz));
bellard31e31b82003-02-18 22:55:36 +00009834 if (!is_error(ret)) {
Richard Hendersona52f5f82020-02-12 19:22:23 -08009835 if (arg1 && copy_to_user_timeval(arg1, &tv)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009836 return -TARGET_EFAULT;
Richard Hendersona52f5f82020-02-12 19:22:23 -08009837 }
9838 if (arg2 && copy_to_user_timezone(arg2, &tz)) {
9839 return -TARGET_EFAULT;
9840 }
bellard31e31b82003-02-18 22:55:36 +00009841 }
9842 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009843 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -07009844#endif
9845#if defined(TARGET_NR_settimeofday)
bellard31e31b82003-02-18 22:55:36 +00009846 case TARGET_NR_settimeofday:
9847 {
Paul Burtonb67d8032014-06-22 11:25:41 +01009848 struct timeval tv, *ptv = NULL;
Paul Burtonef4467e2014-06-22 11:25:40 +01009849 struct timezone tz, *ptz = NULL;
9850
Paul Burtonb67d8032014-06-22 11:25:41 +01009851 if (arg1) {
9852 if (copy_from_user_timeval(&tv, arg1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009853 return -TARGET_EFAULT;
Paul Burtonb67d8032014-06-22 11:25:41 +01009854 }
9855 ptv = &tv;
9856 }
Paul Burtonef4467e2014-06-22 11:25:40 +01009857
9858 if (arg2) {
9859 if (copy_from_user_timezone(&tz, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009860 return -TARGET_EFAULT;
Paul Burtonef4467e2014-06-22 11:25:40 +01009861 }
9862 ptz = &tz;
9863 }
9864
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009865 return get_errno(settimeofday(ptv, ptz));
bellard31e31b82003-02-18 22:55:36 +00009866 }
Alistair Francis859e8a82020-03-12 15:13:49 -07009867#endif
Laurent Vivier9468a5d2013-01-10 22:30:50 +01009868#if defined(TARGET_NR_select)
bellard31e31b82003-02-18 22:55:36 +00009869 case TARGET_NR_select:
Laurent Vivier5457dc92016-07-08 01:17:27 +02009870#if defined(TARGET_WANT_NI_OLD_SELECT)
9871 /* some architectures used to have old_select here
9872 * but now ENOSYS it.
9873 */
9874 ret = -TARGET_ENOSYS;
9875#elif defined(TARGET_WANT_OLD_SYS_SELECT)
9876 ret = do_old_select(arg1);
Laurent Vivier9468a5d2013-01-10 22:30:50 +01009877#else
Laurent Vivier5457dc92016-07-08 01:17:27 +02009878 ret = do_select(arg1, arg2, arg3, arg4, arg5);
Laurent Vivier9468a5d2013-01-10 22:30:50 +01009879#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009880 return ret;
bellard048f6b42005-11-26 18:47:20 +00009881#endif
Riku Voipio9e423822010-05-07 12:28:05 +00009882#ifdef TARGET_NR_pselect6
9883 case TARGET_NR_pselect6:
Filip Bozutae5ce9682020-08-25 00:30:49 +02009884 return do_pselect6(arg1, arg2, arg3, arg4, arg5, arg6, false);
9885#endif
9886#ifdef TARGET_NR_pselect6_time64
9887 case TARGET_NR_pselect6_time64:
9888 return do_pselect6(arg1, arg2, arg3, arg4, arg5, arg6, true);
Riku Voipio9e423822010-05-07 12:28:05 +00009889#endif
Chen Gang704eff62015-08-21 05:37:33 +08009890#ifdef TARGET_NR_symlink
bellard31e31b82003-02-18 22:55:36 +00009891 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00009892 {
9893 void *p2;
9894 p = lock_user_string(arg1);
9895 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00009896 if (!p || !p2)
9897 ret = -TARGET_EFAULT;
9898 else
9899 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00009900 unlock_user(p2, arg2, 0);
9901 unlock_user(p, arg1, 0);
9902 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009903 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009904#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01009905#if defined(TARGET_NR_symlinkat)
thsf0b62432007-09-24 09:25:40 +00009906 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00009907 {
bellard579a97f2007-11-11 14:26:47 +00009908 void *p2;
thsf0b62432007-09-24 09:25:40 +00009909 p = lock_user_string(arg1);
9910 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00009911 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00009912 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00009913 else
Peter Maydellc0d472b2013-06-12 16:20:21 +01009914 ret = get_errno(symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00009915 unlock_user(p2, arg3, 0);
9916 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00009917 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009918 return ret;
thsf0b62432007-09-24 09:25:40 +00009919#endif
Chen Gang704eff62015-08-21 05:37:33 +08009920#ifdef TARGET_NR_readlink
bellard31e31b82003-02-18 22:55:36 +00009921 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00009922 {
Andreas Schwab463d8e72013-07-02 14:04:12 +01009923 void *p2;
pbrook53a59602006-03-25 19:31:22 +00009924 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00009925 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
Andreas Schwab463d8e72013-07-02 14:04:12 +01009926 if (!p || !p2) {
bellard579a97f2007-11-11 14:26:47 +00009927 ret = -TARGET_EFAULT;
Mike Frysingerf17f4982014-08-08 09:40:25 +09009928 } else if (!arg3) {
9929 /* Short circuit this for the magic exe check. */
9930 ret = -TARGET_EINVAL;
Andreas Schwab463d8e72013-07-02 14:04:12 +01009931 } else if (is_proc_myself((const char *)p, "exe")) {
9932 char real[PATH_MAX], *temp;
9933 temp = realpath(exec_path, real);
Mike Frysingerf17f4982014-08-08 09:40:25 +09009934 /* Return value is # of bytes that we wrote to the buffer. */
9935 if (temp == NULL) {
9936 ret = get_errno(-1);
9937 } else {
9938 /* Don't worry about sign mismatch as earlier mapping
9939 * logic would have thrown a bad address error. */
9940 ret = MIN(strlen(real), arg3);
9941 /* We cannot NUL terminate the string. */
9942 memcpy(p2, real, ret);
9943 }
Andreas Schwab463d8e72013-07-02 14:04:12 +01009944 } else {
9945 ret = get_errno(readlink(path(p), p2, arg3));
aurel32d088d662009-01-30 20:09:01 +00009946 }
pbrook53a59602006-03-25 19:31:22 +00009947 unlock_user(p2, arg2, ret);
9948 unlock_user(p, arg1, 0);
9949 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009950 return ret;
Chen Gang704eff62015-08-21 05:37:33 +08009951#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +01009952#if defined(TARGET_NR_readlinkat)
ths5e0ccb12007-09-24 09:26:10 +00009953 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +00009954 {
bellard579a97f2007-11-11 14:26:47 +00009955 void *p2;
ths5e0ccb12007-09-24 09:26:10 +00009956 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00009957 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
Andreas Schwab463d8e72013-07-02 14:04:12 +01009958 if (!p || !p2) {
9959 ret = -TARGET_EFAULT;
Jameson Nash65d48302022-08-08 15:07:27 -04009960 } else if (!arg4) {
9961 /* Short circuit this for the magic exe check. */
9962 ret = -TARGET_EINVAL;
Andreas Schwab463d8e72013-07-02 14:04:12 +01009963 } else if (is_proc_myself((const char *)p, "exe")) {
9964 char real[PATH_MAX], *temp;
9965 temp = realpath(exec_path, real);
Jameson Nash65d48302022-08-08 15:07:27 -04009966 /* Return value is # of bytes that we wrote to the buffer. */
9967 if (temp == NULL) {
9968 ret = get_errno(-1);
9969 } else {
9970 /* Don't worry about sign mismatch as earlier mapping
9971 * logic would have thrown a bad address error. */
9972 ret = MIN(strlen(real), arg4);
9973 /* We cannot NUL terminate the string. */
9974 memcpy(p2, real, ret);
9975 }
Andreas Schwab463d8e72013-07-02 14:04:12 +01009976 } else {
Peter Maydellc0d472b2013-06-12 16:20:21 +01009977 ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
Andreas Schwab463d8e72013-07-02 14:04:12 +01009978 }
bellard579a97f2007-11-11 14:26:47 +00009979 unlock_user(p2, arg3, ret);
9980 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +00009981 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009982 return ret;
ths5e0ccb12007-09-24 09:26:10 +00009983#endif
thse5febef2007-04-01 18:31:35 +00009984#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +00009985 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +00009986 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -07009987 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00009988 ret = get_errno(swapon(p, arg2));
9989 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -07009990 return ret;
thse5febef2007-04-01 18:31:35 +00009991#endif
bellard31e31b82003-02-18 22:55:36 +00009992 case TARGET_NR_reboot:
Laurent Vivierc07ecc62013-01-07 11:40:06 +00009993 if (arg3 == LINUX_REBOOT_CMD_RESTART2) {
9994 /* arg4 must be ignored in all other cases */
9995 p = lock_user_string(arg4);
9996 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -07009997 return -TARGET_EFAULT;
Laurent Vivierc07ecc62013-01-07 11:40:06 +00009998 }
9999 ret = get_errno(reboot(arg1, arg2, arg3, p));
10000 unlock_user(p, arg4, 0);
10001 } else {
10002 ret = get_errno(reboot(arg1, arg2, arg3, NULL));
10003 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010004 return ret;
thse5febef2007-04-01 18:31:35 +000010005#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +000010006 case TARGET_NR_mmap:
Alexander Graf09701192013-09-03 20:12:15 +010010007#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
10008 (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
Ulrich Hechta4c075f2009-07-24 16:57:31 +020010009 defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \
10010 || defined(TARGET_S390X)
bellard31e31b82003-02-18 22:55:36 +000010011 {
blueswir1992f48a2007-10-14 16:27:31 +000010012 abi_ulong *v;
10013 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +000010014 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010015 return -TARGET_EFAULT;
Matthias Brauncbb21ee2011-08-12 19:57:41 +020010016 v1 = tswapal(v[0]);
10017 v2 = tswapal(v[1]);
10018 v3 = tswapal(v[2]);
10019 v4 = tswapal(v[3]);
10020 v5 = tswapal(v[4]);
10021 v6 = tswapal(v[5]);
pbrook53a59602006-03-25 19:31:22 +000010022 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +000010023 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +000010024 target_to_host_bitmask(v4, mmap_flags_tbl),
10025 v5, v6));
bellard31e31b82003-02-18 22:55:36 +000010026 }
bellard31e31b82003-02-18 22:55:36 +000010027#else
Richard Hendersonee1bf832021-02-12 10:48:44 -080010028 /* mmap pointers are always untagged */
ths5fafdf22007-09-16 21:08:06 +000010029 ret = get_errno(target_mmap(arg1, arg2, arg3,
10030 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +000010031 arg5,
10032 arg6));
bellard31e31b82003-02-18 22:55:36 +000010033#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010034 return ret;
thse5febef2007-04-01 18:31:35 +000010035#endif
bellarda315a142005-01-30 22:59:18 +000010036#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +000010037 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +000010038#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +000010039#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +000010040#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010041 ret = target_mmap(arg1, arg2, arg3,
10042 target_to_host_bitmask(arg4, mmap_flags_tbl),
10043 arg5, arg6 << MMAP_SHIFT);
10044 return get_errno(ret);
bellarda315a142005-01-30 22:59:18 +000010045#endif
bellard31e31b82003-02-18 22:55:36 +000010046 case TARGET_NR_munmap:
Richard Hendersonee1bf832021-02-12 10:48:44 -080010047 arg1 = cpu_untagged_addr(cpu, arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010048 return get_errno(target_munmap(arg1, arg2));
bellard9de5e442003-03-23 16:49:39 +000010049 case TARGET_NR_mprotect:
Richard Hendersonee1bf832021-02-12 10:48:44 -080010050 arg1 = cpu_untagged_addr(cpu, arg1);
Paul Brook97374d32010-06-16 13:03:51 +010010051 {
Andreas Färber0429a972013-08-26 18:14:44 +020010052 TaskState *ts = cpu->opaque;
Paul Brook97374d32010-06-16 13:03:51 +010010053 /* Special hack to detect libc making the stack executable. */
10054 if ((arg3 & PROT_GROWSDOWN)
10055 && arg1 >= ts->info->stack_limit
10056 && arg1 <= ts->info->start_stack) {
10057 arg3 &= ~PROT_GROWSDOWN;
10058 arg2 = arg2 + arg1 - ts->info->stack_limit;
10059 arg1 = ts->info->stack_limit;
10060 }
10061 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010062 return get_errno(target_mprotect(arg1, arg2, arg3));
thse5febef2007-04-01 18:31:35 +000010063#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +000010064 case TARGET_NR_mremap:
Richard Hendersonee1bf832021-02-12 10:48:44 -080010065 arg1 = cpu_untagged_addr(cpu, arg1);
10066 /* mremap new_addr (arg5) is always untagged */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010067 return get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
thse5febef2007-04-01 18:31:35 +000010068#endif
pbrook53a59602006-03-25 19:31:22 +000010069 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +000010070#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +000010071 case TARGET_NR_msync:
Richard Henderson3e8f1622021-02-12 10:48:43 -080010072 return get_errno(msync(g2h(cpu, arg1), arg2, arg3));
thse5febef2007-04-01 18:31:35 +000010073#endif
10074#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +000010075 case TARGET_NR_mlock:
Richard Henderson3e8f1622021-02-12 10:48:43 -080010076 return get_errno(mlock(g2h(cpu, arg1), arg2));
thse5febef2007-04-01 18:31:35 +000010077#endif
10078#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +000010079 case TARGET_NR_munlock:
Richard Henderson3e8f1622021-02-12 10:48:43 -080010080 return get_errno(munlock(g2h(cpu, arg1), arg2));
thse5febef2007-04-01 18:31:35 +000010081#endif
10082#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +000010083 case TARGET_NR_mlockall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010084 return get_errno(mlockall(target_to_host_mlockall_arg(arg1)));
thse5febef2007-04-01 18:31:35 +000010085#endif
10086#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +000010087 case TARGET_NR_munlockall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010088 return get_errno(munlockall());
thse5febef2007-04-01 18:31:35 +000010089#endif
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010090#ifdef TARGET_NR_truncate
bellard31e31b82003-02-18 22:55:36 +000010091 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +000010092 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010093 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010094 ret = get_errno(truncate(p, arg2));
10095 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010096 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010097#endif
10098#ifdef TARGET_NR_ftruncate
bellard31e31b82003-02-18 22:55:36 +000010099 case TARGET_NR_ftruncate:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010100 return get_errno(ftruncate(arg1, arg2));
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010101#endif
bellard31e31b82003-02-18 22:55:36 +000010102 case TARGET_NR_fchmod:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010103 return get_errno(fchmod(arg1, arg2));
Peter Maydellc0d472b2013-06-12 16:20:21 +010010104#if defined(TARGET_NR_fchmodat)
ths814d7972007-09-24 09:26:51 +000010105 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +000010106 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010107 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +010010108 ret = get_errno(fchmodat(arg1, p, arg3, 0));
bellard579a97f2007-11-11 14:26:47 +000010109 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010110 return ret;
ths814d7972007-09-24 09:26:51 +000010111#endif
bellard31e31b82003-02-18 22:55:36 +000010112 case TARGET_NR_getpriority:
Richard Henderson95c09822012-06-07 15:14:50 -070010113 /* Note that negative values are valid for getpriority, so we must
10114 differentiate based on errno settings. */
10115 errno = 0;
10116 ret = getpriority(arg1, arg2);
10117 if (ret == -1 && errno != 0) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010118 return -host_to_target_errno(errno);
Richard Henderson95c09822012-06-07 15:14:50 -070010119 }
10120#ifdef TARGET_ALPHA
10121 /* Return value is the unbiased priority. Signal no error. */
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020010122 cpu_env->ir[IR_V0] = 0;
Richard Henderson95c09822012-06-07 15:14:50 -070010123#else
10124 /* Return value is a biased priority to avoid negative numbers. */
10125 ret = 20 - ret;
10126#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010127 return ret;
bellard31e31b82003-02-18 22:55:36 +000010128 case TARGET_NR_setpriority:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010129 return get_errno(setpriority(arg1, arg2, arg3));
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010130#ifdef TARGET_NR_statfs
bellard31e31b82003-02-18 22:55:36 +000010131 case TARGET_NR_statfs:
Richard Henderson2852aaf2018-08-18 12:01:06 -070010132 if (!(p = lock_user_string(arg1))) {
10133 return -TARGET_EFAULT;
10134 }
pbrook53a59602006-03-25 19:31:22 +000010135 ret = get_errno(statfs(path(p), &stfs));
10136 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +000010137 convert_statfs:
10138 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +000010139 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +000010140
bellard579a97f2007-11-11 14:26:47 +000010141 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010142 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000010143 __put_user(stfs.f_type, &target_stfs->f_type);
10144 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
10145 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
10146 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
10147 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
10148 __put_user(stfs.f_files, &target_stfs->f_files);
10149 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
10150 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
10151 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
10152 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
Alexander Graf229d3372012-09-19 04:39:53 +020010153 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
Shea Levyd4247ec2018-03-01 06:15:00 -050010154#ifdef _STATFS_F_FLAGS
10155 __put_user(stfs.f_flags, &target_stfs->f_flags);
10156#else
10157 __put_user(0, &target_stfs->f_flags);
10158#endif
Alexander Graf229d3372012-09-19 04:39:53 +020010159 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
pbrook53a59602006-03-25 19:31:22 +000010160 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +000010161 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010162 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010163#endif
10164#ifdef TARGET_NR_fstatfs
bellard31e31b82003-02-18 22:55:36 +000010165 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +000010166 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +000010167 goto convert_statfs;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010168#endif
bellard56c8f682005-11-28 22:28:41 +000010169#ifdef TARGET_NR_statfs64
10170 case TARGET_NR_statfs64:
Richard Henderson2852aaf2018-08-18 12:01:06 -070010171 if (!(p = lock_user_string(arg1))) {
10172 return -TARGET_EFAULT;
10173 }
pbrook53a59602006-03-25 19:31:22 +000010174 ret = get_errno(statfs(path(p), &stfs));
10175 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +000010176 convert_statfs64:
10177 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +000010178 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +000010179
bellard579a97f2007-11-11 14:26:47 +000010180 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010181 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000010182 __put_user(stfs.f_type, &target_stfs->f_type);
10183 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
10184 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
10185 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
10186 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
10187 __put_user(stfs.f_files, &target_stfs->f_files);
10188 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
10189 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
10190 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
10191 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
Alexander Graf229d3372012-09-19 04:39:53 +020010192 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
Frajob94e2b42020-01-30 15:00:30 +020010193#ifdef _STATFS_F_FLAGS
10194 __put_user(stfs.f_flags, &target_stfs->f_flags);
10195#else
10196 __put_user(0, &target_stfs->f_flags);
10197#endif
Alexander Graf229d3372012-09-19 04:39:53 +020010198 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
bellard579a97f2007-11-11 14:26:47 +000010199 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +000010200 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010201 return ret;
bellard56c8f682005-11-28 22:28:41 +000010202 case TARGET_NR_fstatfs64:
10203 ret = get_errno(fstatfs(arg1, &stfs));
10204 goto convert_statfs64;
10205#endif
thse5febef2007-04-01 18:31:35 +000010206#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +000010207 case TARGET_NR_socketcall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010208 return do_socketcall(arg1, arg2);
thse5febef2007-04-01 18:31:35 +000010209#endif
bellard3532fa72006-06-24 15:06:03 +000010210#ifdef TARGET_NR_accept
10211 case TARGET_NR_accept:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010212 return do_accept4(arg1, arg2, arg3, 0);
Peter Maydella94b4982013-02-08 04:35:04 +000010213#endif
10214#ifdef TARGET_NR_accept4
10215 case TARGET_NR_accept4:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010216 return do_accept4(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +000010217#endif
10218#ifdef TARGET_NR_bind
10219 case TARGET_NR_bind:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010220 return do_bind(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +000010221#endif
10222#ifdef TARGET_NR_connect
10223 case TARGET_NR_connect:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010224 return do_connect(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +000010225#endif
10226#ifdef TARGET_NR_getpeername
10227 case TARGET_NR_getpeername:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010228 return do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +000010229#endif
10230#ifdef TARGET_NR_getsockname
10231 case TARGET_NR_getsockname:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010232 return do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +000010233#endif
10234#ifdef TARGET_NR_getsockopt
10235 case TARGET_NR_getsockopt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010236 return do_getsockopt(arg1, arg2, arg3, arg4, arg5);
bellard3532fa72006-06-24 15:06:03 +000010237#endif
10238#ifdef TARGET_NR_listen
10239 case TARGET_NR_listen:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010240 return get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +000010241#endif
10242#ifdef TARGET_NR_recv
10243 case TARGET_NR_recv:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010244 return do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +000010245#endif
10246#ifdef TARGET_NR_recvfrom
10247 case TARGET_NR_recvfrom:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010248 return do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +000010249#endif
10250#ifdef TARGET_NR_recvmsg
10251 case TARGET_NR_recvmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010252 return do_sendrecvmsg(arg1, arg2, arg3, 0);
bellard3532fa72006-06-24 15:06:03 +000010253#endif
10254#ifdef TARGET_NR_send
10255 case TARGET_NR_send:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010256 return do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +000010257#endif
10258#ifdef TARGET_NR_sendmsg
10259 case TARGET_NR_sendmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010260 return do_sendrecvmsg(arg1, arg2, arg3, 1);
bellard3532fa72006-06-24 15:06:03 +000010261#endif
Alexander Graff19e00d2014-03-02 19:36:42 +000010262#ifdef TARGET_NR_sendmmsg
10263 case TARGET_NR_sendmmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010264 return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1);
Alistair Francis859e8a82020-03-12 15:13:49 -070010265#endif
10266#ifdef TARGET_NR_recvmmsg
Alexander Graff19e00d2014-03-02 19:36:42 +000010267 case TARGET_NR_recvmmsg:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010268 return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0);
Alexander Graff19e00d2014-03-02 19:36:42 +000010269#endif
bellard3532fa72006-06-24 15:06:03 +000010270#ifdef TARGET_NR_sendto
10271 case TARGET_NR_sendto:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010272 return do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +000010273#endif
10274#ifdef TARGET_NR_shutdown
10275 case TARGET_NR_shutdown:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010276 return get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +000010277#endif
Laurent Vivierf894efd2016-02-21 10:56:23 +010010278#if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
10279 case TARGET_NR_getrandom:
10280 p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
10281 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010282 return -TARGET_EFAULT;
Laurent Vivierf894efd2016-02-21 10:56:23 +010010283 }
10284 ret = get_errno(getrandom(p, arg2, arg3));
10285 unlock_user(p, arg1, ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010286 return ret;
Laurent Vivierf894efd2016-02-21 10:56:23 +010010287#endif
bellard3532fa72006-06-24 15:06:03 +000010288#ifdef TARGET_NR_socket
10289 case TARGET_NR_socket:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010290 return do_socket(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +000010291#endif
10292#ifdef TARGET_NR_socketpair
10293 case TARGET_NR_socketpair:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010294 return do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +000010295#endif
10296#ifdef TARGET_NR_setsockopt
10297 case TARGET_NR_setsockopt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010298 return do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
bellard3532fa72006-06-24 15:06:03 +000010299#endif
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010300#if defined(TARGET_NR_syslog)
bellard31e31b82003-02-18 22:55:36 +000010301 case TARGET_NR_syslog:
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010302 {
10303 int len = arg2;
ths7494b0f2007-02-11 18:26:53 +000010304
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010305 switch (arg1) {
10306 case TARGET_SYSLOG_ACTION_CLOSE: /* Close log */
10307 case TARGET_SYSLOG_ACTION_OPEN: /* Open log */
10308 case TARGET_SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
10309 case TARGET_SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging */
10310 case TARGET_SYSLOG_ACTION_CONSOLE_ON: /* Enable logging */
10311 case TARGET_SYSLOG_ACTION_CONSOLE_LEVEL: /* Set messages level */
10312 case TARGET_SYSLOG_ACTION_SIZE_UNREAD: /* Number of chars */
10313 case TARGET_SYSLOG_ACTION_SIZE_BUFFER: /* Size of the buffer */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010314 return get_errno(sys_syslog((int)arg1, NULL, (int)arg3));
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010315 case TARGET_SYSLOG_ACTION_READ: /* Read from log */
10316 case TARGET_SYSLOG_ACTION_READ_CLEAR: /* Read/clear msgs */
10317 case TARGET_SYSLOG_ACTION_READ_ALL: /* Read last messages */
10318 {
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010319 if (len < 0) {
Richard Henderson259841c2018-08-18 12:01:09 -070010320 return -TARGET_EINVAL;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010321 }
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010322 if (len == 0) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010323 return 0;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010324 }
10325 p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
10326 if (!p) {
Richard Henderson259841c2018-08-18 12:01:09 -070010327 return -TARGET_EFAULT;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010328 }
10329 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
10330 unlock_user(p, arg2, arg3);
10331 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010332 return ret;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010333 default:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010334 return -TARGET_EINVAL;
Aleksandar Markovicda2c8ad2016-09-22 18:56:58 +020010335 }
10336 }
10337 break;
10338#endif
bellard31e31b82003-02-18 22:55:36 +000010339 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +000010340 {
bellard66fb9762003-03-23 01:06:05 +000010341 struct itimerval value, ovalue, *pvalue;
10342
pbrook53a59602006-03-25 19:31:22 +000010343 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +000010344 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +000010345 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
10346 || copy_from_user_timeval(&pvalue->it_value,
10347 arg2 + sizeof(struct target_timeval)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010348 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +000010349 } else {
10350 pvalue = NULL;
10351 }
10352 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +000010353 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +000010354 if (copy_to_user_timeval(arg3,
10355 &ovalue.it_interval)
10356 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
10357 &ovalue.it_value))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010358 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +000010359 }
10360 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010361 return ret;
bellard31e31b82003-02-18 22:55:36 +000010362 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +000010363 {
bellard66fb9762003-03-23 01:06:05 +000010364 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +000010365
bellard66fb9762003-03-23 01:06:05 +000010366 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +000010367 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +000010368 if (copy_to_user_timeval(arg2,
10369 &value.it_interval)
10370 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
10371 &value.it_value))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010372 return -TARGET_EFAULT;
bellard66fb9762003-03-23 01:06:05 +000010373 }
10374 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010375 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080010376#ifdef TARGET_NR_stat
bellard31e31b82003-02-18 22:55:36 +000010377 case TARGET_NR_stat:
Richard Henderson2852aaf2018-08-18 12:01:06 -070010378 if (!(p = lock_user_string(arg1))) {
10379 return -TARGET_EFAULT;
10380 }
pbrook53a59602006-03-25 19:31:22 +000010381 ret = get_errno(stat(path(p), &st));
10382 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +000010383 goto do_stat;
Chen Gang704eff62015-08-21 05:37:33 +080010384#endif
10385#ifdef TARGET_NR_lstat
bellard31e31b82003-02-18 22:55:36 +000010386 case TARGET_NR_lstat:
Richard Henderson2852aaf2018-08-18 12:01:06 -070010387 if (!(p = lock_user_string(arg1))) {
10388 return -TARGET_EFAULT;
10389 }
pbrook53a59602006-03-25 19:31:22 +000010390 ret = get_errno(lstat(path(p), &st));
10391 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +000010392 goto do_stat;
Chen Gang704eff62015-08-21 05:37:33 +080010393#endif
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010394#ifdef TARGET_NR_fstat
bellard31e31b82003-02-18 22:55:36 +000010395 case TARGET_NR_fstat:
10396 {
10397 ret = get_errno(fstat(arg1, &st));
Chen Gang704eff62015-08-21 05:37:33 +080010398#if defined(TARGET_NR_stat) || defined(TARGET_NR_lstat)
bellard31e31b82003-02-18 22:55:36 +000010399 do_stat:
Chen Gang704eff62015-08-21 05:37:33 +080010400#endif
bellard31e31b82003-02-18 22:55:36 +000010401 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +000010402 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +000010403
bellard579a97f2007-11-11 14:26:47 +000010404 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010405 return -TARGET_EFAULT;
Ulrich Hecht12727912009-07-24 19:10:32 +020010406 memset(target_st, 0, sizeof(*target_st));
bellardd2fd1af2007-11-14 18:08:56 +000010407 __put_user(st.st_dev, &target_st->st_dev);
10408 __put_user(st.st_ino, &target_st->st_ino);
10409 __put_user(st.st_mode, &target_st->st_mode);
10410 __put_user(st.st_uid, &target_st->st_uid);
10411 __put_user(st.st_gid, &target_st->st_gid);
10412 __put_user(st.st_nlink, &target_st->st_nlink);
10413 __put_user(st.st_rdev, &target_st->st_rdev);
10414 __put_user(st.st_size, &target_st->st_size);
10415 __put_user(st.st_blksize, &target_st->st_blksize);
10416 __put_user(st.st_blocks, &target_st->st_blocks);
10417 __put_user(st.st_atime, &target_st->target_st_atime);
10418 __put_user(st.st_mtime, &target_st->target_st_mtime);
10419 __put_user(st.st_ctime, &target_st->target_st_ctime);
Michael Forneyfebf6fa2021-05-25 20:55:31 -070010420#if defined(HAVE_STRUCT_STAT_ST_ATIM) && defined(TARGET_STAT_HAVE_NSEC)
Chen-Yu Tsai5f992db2019-05-23 00:21:47 +080010421 __put_user(st.st_atim.tv_nsec,
10422 &target_st->target_st_atime_nsec);
10423 __put_user(st.st_mtim.tv_nsec,
10424 &target_st->target_st_mtime_nsec);
10425 __put_user(st.st_ctim.tv_nsec,
10426 &target_st->target_st_ctime_nsec);
10427#endif
pbrook53a59602006-03-25 19:31:22 +000010428 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +000010429 }
10430 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010431 return ret;
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020010432#endif
bellard31e31b82003-02-18 22:55:36 +000010433 case TARGET_NR_vhangup:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010434 return get_errno(vhangup());
bellard42ad6ae2005-01-03 22:48:11 +000010435#ifdef TARGET_NR_syscall
10436 case TARGET_NR_syscall:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010437 return do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5,
10438 arg6, arg7, arg8, 0);
bellard42ad6ae2005-01-03 22:48:11 +000010439#endif
Alistair Francis859e8a82020-03-12 15:13:49 -070010440#if defined(TARGET_NR_wait4)
bellard31e31b82003-02-18 22:55:36 +000010441 case TARGET_NR_wait4:
10442 {
10443 int status;
blueswir1992f48a2007-10-14 16:27:31 +000010444 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +000010445 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +000010446 abi_ulong target_rusage = arg4;
Petar Jovanovica39fb272014-04-08 19:24:30 +020010447 abi_long rusage_err;
bellard31e31b82003-02-18 22:55:36 +000010448 if (target_rusage)
10449 rusage_ptr = &rusage;
10450 else
10451 rusage_ptr = NULL;
Timothy E Baldwin4af80a32016-05-12 18:47:49 +010010452 ret = get_errno(safe_wait4(arg1, &status, arg3, rusage_ptr));
bellard31e31b82003-02-18 22:55:36 +000010453 if (!is_error(ret)) {
Alexander Graf53795572011-11-24 00:44:43 +010010454 if (status_ptr && ret) {
pbrook1d9d8b52009-04-16 15:17:02 +000010455 status = host_to_target_waitstatus(status);
bellard2f619692007-11-16 10:46:05 +000010456 if (put_user_s32(status, status_ptr))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010457 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +000010458 }
Petar Jovanovica39fb272014-04-08 19:24:30 +020010459 if (target_rusage) {
10460 rusage_err = host_to_target_rusage(target_rusage, &rusage);
10461 if (rusage_err) {
10462 ret = rusage_err;
10463 }
10464 }
bellard31e31b82003-02-18 22:55:36 +000010465 }
10466 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010467 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070010468#endif
thse5febef2007-04-01 18:31:35 +000010469#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +000010470 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +000010471 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010472 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010473 ret = get_errno(swapoff(p));
10474 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010475 return ret;
thse5febef2007-04-01 18:31:35 +000010476#endif
bellard31e31b82003-02-18 22:55:36 +000010477 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +000010478 {
pbrook53a59602006-03-25 19:31:22 +000010479 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +000010480 struct sysinfo value;
10481 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +000010482 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +000010483 {
bellard579a97f2007-11-11 14:26:47 +000010484 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010485 return -TARGET_EFAULT;
bellarda5448a72004-06-19 16:59:03 +000010486 __put_user(value.uptime, &target_value->uptime);
10487 __put_user(value.loads[0], &target_value->loads[0]);
10488 __put_user(value.loads[1], &target_value->loads[1]);
10489 __put_user(value.loads[2], &target_value->loads[2]);
10490 __put_user(value.totalram, &target_value->totalram);
10491 __put_user(value.freeram, &target_value->freeram);
10492 __put_user(value.sharedram, &target_value->sharedram);
10493 __put_user(value.bufferram, &target_value->bufferram);
10494 __put_user(value.totalswap, &target_value->totalswap);
10495 __put_user(value.freeswap, &target_value->freeswap);
10496 __put_user(value.procs, &target_value->procs);
10497 __put_user(value.totalhigh, &target_value->totalhigh);
10498 __put_user(value.freehigh, &target_value->freehigh);
10499 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +000010500 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +000010501 }
10502 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010503 return ret;
thse5febef2007-04-01 18:31:35 +000010504#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +000010505 case TARGET_NR_ipc:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010506 return do_ipc(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
thse5febef2007-04-01 18:31:35 +000010507#endif
aurel32e5289082009-04-18 16:16:12 +000010508#ifdef TARGET_NR_semget
10509 case TARGET_NR_semget:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010510 return get_errno(semget(arg1, arg2, arg3));
aurel32e5289082009-04-18 16:16:12 +000010511#endif
10512#ifdef TARGET_NR_semop
10513 case TARGET_NR_semop:
Filip Bozutacac46eb2020-08-25 00:30:50 +020010514 return do_semtimedop(arg1, arg2, arg3, 0, false);
Matus Kyseld8c08b12020-06-26 14:46:11 +020010515#endif
10516#ifdef TARGET_NR_semtimedop
10517 case TARGET_NR_semtimedop:
Filip Bozutacac46eb2020-08-25 00:30:50 +020010518 return do_semtimedop(arg1, arg2, arg3, arg4, false);
10519#endif
10520#ifdef TARGET_NR_semtimedop_time64
10521 case TARGET_NR_semtimedop_time64:
10522 return do_semtimedop(arg1, arg2, arg3, arg4, true);
aurel32e5289082009-04-18 16:16:12 +000010523#endif
10524#ifdef TARGET_NR_semctl
10525 case TARGET_NR_semctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010526 return do_semctl(arg1, arg2, arg3, arg4);
aurel32e5289082009-04-18 16:16:12 +000010527#endif
aurel32eeb438c2008-10-13 21:08:55 +000010528#ifdef TARGET_NR_msgctl
10529 case TARGET_NR_msgctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010530 return do_msgctl(arg1, arg2, arg3);
aurel32eeb438c2008-10-13 21:08:55 +000010531#endif
10532#ifdef TARGET_NR_msgget
10533 case TARGET_NR_msgget:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010534 return get_errno(msgget(arg1, arg2));
aurel32eeb438c2008-10-13 21:08:55 +000010535#endif
10536#ifdef TARGET_NR_msgrcv
10537 case TARGET_NR_msgrcv:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010538 return do_msgrcv(arg1, arg2, arg3, arg4, arg5);
aurel32eeb438c2008-10-13 21:08:55 +000010539#endif
10540#ifdef TARGET_NR_msgsnd
10541 case TARGET_NR_msgsnd:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010542 return do_msgsnd(arg1, arg2, arg3, arg4);
aurel32eeb438c2008-10-13 21:08:55 +000010543#endif
Riku Voipio88a8c982009-04-03 10:42:00 +030010544#ifdef TARGET_NR_shmget
10545 case TARGET_NR_shmget:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010546 return get_errno(shmget(arg1, arg2, arg3));
Riku Voipio88a8c982009-04-03 10:42:00 +030010547#endif
10548#ifdef TARGET_NR_shmctl
10549 case TARGET_NR_shmctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010550 return do_shmctl(arg1, arg2, arg3);
Riku Voipio88a8c982009-04-03 10:42:00 +030010551#endif
10552#ifdef TARGET_NR_shmat
10553 case TARGET_NR_shmat:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010554 return do_shmat(cpu_env, arg1, arg2, arg3);
Riku Voipio88a8c982009-04-03 10:42:00 +030010555#endif
10556#ifdef TARGET_NR_shmdt
10557 case TARGET_NR_shmdt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010558 return do_shmdt(arg1);
Riku Voipio88a8c982009-04-03 10:42:00 +030010559#endif
bellard31e31b82003-02-18 22:55:36 +000010560 case TARGET_NR_fsync:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010561 return get_errno(fsync(arg1));
bellard31e31b82003-02-18 22:55:36 +000010562 case TARGET_NR_clone:
Peter Maydell4ce62432013-07-16 18:44:57 +010010563 /* Linux manages to have three different orderings for its
10564 * arguments to clone(); the BACKWARDS and BACKWARDS2 defines
10565 * match the kernel's CONFIG_CLONE_* settings.
10566 * Microblaze is further special in that it uses a sixth
10567 * implicit argument to clone for the TLS pointer.
10568 */
10569#if defined(TARGET_MICROBLAZE)
Edgar E. Iglesiasa5b3bdc2012-04-26 14:17:41 +020010570 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5));
Peter Maydell4ce62432013-07-16 18:44:57 +010010571#elif defined(TARGET_CLONE_BACKWARDS)
10572 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
10573#elif defined(TARGET_CLONE_BACKWARDS2)
Ulrich Hechta4c075f2009-07-24 16:57:31 +020010574 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
aurel320b6d3ae2008-09-15 07:43:43 +000010575#else
Peter Maydell4ce62432013-07-16 18:44:57 +010010576 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
aurel320b6d3ae2008-09-15 07:43:43 +000010577#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010578 return ret;
bellardec86b0f2003-04-11 00:15:04 +000010579#ifdef __NR_exit_group
10580 /* new thread calls */
10581 case TARGET_NR_exit_group:
Alex Bennée708b6a62018-06-22 17:09:10 +010010582 preexit_cleanup(cpu_env, arg1);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010583 return get_errno(exit_group(arg1));
bellardec86b0f2003-04-11 00:15:04 +000010584#endif
bellard31e31b82003-02-18 22:55:36 +000010585 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +000010586 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010587 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000010588 ret = get_errno(setdomainname(p, arg2));
10589 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010590 return ret;
bellard31e31b82003-02-18 22:55:36 +000010591 case TARGET_NR_uname:
10592 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +000010593 {
10594 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +000010595
bellard579a97f2007-11-11 14:26:47 +000010596 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070010597 return -TARGET_EFAULT;
bellard29e619b2004-09-13 21:41:04 +000010598 ret = get_errno(sys_uname(buf));
10599 if (!is_error(ret)) {
Peter Maydell332c9782016-07-12 13:02:16 +010010600 /* Overwrite the native machine name with whatever is being
bellard29e619b2004-09-13 21:41:04 +000010601 emulated. */
Philippe Mathieu-Daudé871f95c2017-07-24 15:27:47 -030010602 g_strlcpy(buf->machine, cpu_to_uname_machine(cpu_env),
10603 sizeof(buf->machine));
pbrookc5937222006-05-14 11:30:38 +000010604 /* Allow the user to override the reported release. */
Peter Maydell332c9782016-07-12 13:02:16 +010010605 if (qemu_uname_release && *qemu_uname_release) {
10606 g_strlcpy(buf->release, qemu_uname_release,
10607 sizeof(buf->release));
10608 }
bellard29e619b2004-09-13 21:41:04 +000010609 }
pbrook53a59602006-03-25 19:31:22 +000010610 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +000010611 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010612 return ret;
bellard6dbad632003-03-16 18:05:05 +000010613#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +000010614 case TARGET_NR_modify_ldt:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010615 return do_modify_ldt(cpu_env, arg1, arg2, arg3);
j_mayer84409dd2007-04-06 08:56:50 +000010616#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +000010617 case TARGET_NR_vm86:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010618 return do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +000010619#endif
j_mayer84409dd2007-04-06 08:56:50 +000010620#endif
Alistair Francis859e8a82020-03-12 15:13:49 -070010621#if defined(TARGET_NR_adjtimex)
bellard31e31b82003-02-18 22:55:36 +000010622 case TARGET_NR_adjtimex:
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +020010623 {
10624 struct timex host_buf;
10625
10626 if (target_to_host_timex(&host_buf, arg1) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010627 return -TARGET_EFAULT;
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +020010628 }
10629 ret = get_errno(adjtimex(&host_buf));
10630 if (!is_error(ret)) {
10631 if (host_to_target_timex(arg1, &host_buf) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010632 return -TARGET_EFAULT;
Aleksandar Markovic19f59bc2016-09-22 18:56:50 +020010633 }
10634 }
10635 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010636 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070010637#endif
Aleksandar Markovic38860a02016-10-10 13:23:29 +020010638#if defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME)
10639 case TARGET_NR_clock_adjtime:
10640 {
10641 struct timex htx, *phtx = &htx;
10642
10643 if (target_to_host_timex(phtx, arg2) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010644 return -TARGET_EFAULT;
Aleksandar Markovic38860a02016-10-10 13:23:29 +020010645 }
10646 ret = get_errno(clock_adjtime(arg1, phtx));
10647 if (!is_error(ret) && phtx) {
10648 if (host_to_target_timex(arg2, phtx) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010649 return -TARGET_EFAULT;
Aleksandar Markovic38860a02016-10-10 13:23:29 +020010650 }
10651 }
10652 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010653 return ret;
Aleksandar Markovic38860a02016-10-10 13:23:29 +020010654#endif
Filip Bozuta6ac03b22020-08-24 21:21:15 +020010655#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
10656 case TARGET_NR_clock_adjtime64:
10657 {
10658 struct timex htx;
10659
10660 if (target_to_host_timex64(&htx, arg2) != 0) {
10661 return -TARGET_EFAULT;
10662 }
10663 ret = get_errno(clock_adjtime(arg1, &htx));
10664 if (!is_error(ret) && host_to_target_timex64(arg2, &htx)) {
10665 return -TARGET_EFAULT;
10666 }
10667 }
10668 return ret;
10669#endif
bellard31e31b82003-02-18 22:55:36 +000010670 case TARGET_NR_getpgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010671 return get_errno(getpgid(arg1));
bellard31e31b82003-02-18 22:55:36 +000010672 case TARGET_NR_fchdir:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010673 return get_errno(fchdir(arg1));
bellard31e31b82003-02-18 22:55:36 +000010674 case TARGET_NR_personality:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010675 return get_errno(personality(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +000010676#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +000010677 case TARGET_NR__llseek:
10678 {
10679 int64_t res;
Peter Maydell0c1592d2011-02-22 13:02:26 +000010680#if !defined(__NR_llseek)
Peter Maydell9fea2732016-08-11 18:59:39 +010010681 res = lseek(arg1, ((uint64_t)arg2 << 32) | (abi_ulong)arg3, arg5);
Peter Maydell0c1592d2011-02-22 13:02:26 +000010682 if (res == -1) {
10683 ret = get_errno(res);
10684 } else {
10685 ret = 0;
10686 }
10687#else
bellard31e31b82003-02-18 22:55:36 +000010688 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard4f2ac232004-04-26 19:44:02 +000010689#endif
Peter Maydell0c1592d2011-02-22 13:02:26 +000010690 if ((ret == 0) && put_user_s64(res, arg4)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010691 return -TARGET_EFAULT;
Peter Maydell0c1592d2011-02-22 13:02:26 +000010692 }
bellard31e31b82003-02-18 22:55:36 +000010693 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010694 return ret;
j_mayer7a3148a2007-04-05 07:13:51 +000010695#endif
Chen Gang704eff62015-08-21 05:37:33 +080010696#ifdef TARGET_NR_getdents
bellard31e31b82003-02-18 22:55:36 +000010697 case TARGET_NR_getdents:
Richard Hendersonfd08ddb2021-11-14 11:35:36 +010010698 return do_getdents(arg1, arg2, arg3);
Chen Gang704eff62015-08-21 05:37:33 +080010699#endif /* TARGET_NR_getdents */
ths3ae43202007-09-16 21:39:48 +000010700#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +000010701 case TARGET_NR_getdents64:
Richard Hendersonfd08ddb2021-11-14 11:35:36 +010010702 return do_getdents64(arg1, arg2, arg3);
bellarda541f292004-04-12 20:39:29 +000010703#endif /* TARGET_NR_getdents64 */
Laurent Vivier9468a5d2013-01-10 22:30:50 +010010704#if defined(TARGET_NR__newselect)
bellard31e31b82003-02-18 22:55:36 +000010705 case TARGET_NR__newselect:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010706 return do_select(arg1, arg2, arg3, arg4, arg5);
thse5febef2007-04-01 18:31:35 +000010707#endif
Filip Bozutae5ce9682020-08-25 00:30:49 +020010708#ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +000010709 case TARGET_NR_poll:
Filip Bozutae5ce9682020-08-25 00:30:49 +020010710 return do_ppoll(arg1, arg2, arg3, arg4, arg5, false, false);
10711#endif
10712#ifdef TARGET_NR_ppoll
Mike Frysingerd8035d42011-02-07 01:05:51 -050010713 case TARGET_NR_ppoll:
Filip Bozutae5ce9682020-08-25 00:30:49 +020010714 return do_ppoll(arg1, arg2, arg3, arg4, arg5, true, false);
10715#endif
10716#ifdef TARGET_NR_ppoll_time64
10717 case TARGET_NR_ppoll_time64:
10718 return do_ppoll(arg1, arg2, arg3, arg4, arg5, true, true);
thse5febef2007-04-01 18:31:35 +000010719#endif
bellard31e31b82003-02-18 22:55:36 +000010720 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +000010721 /* NOTE: the flock constant seems to be the same for every
10722 Linux platform */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010723 return get_errno(safe_flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +000010724 case TARGET_NR_readv:
10725 {
Richard Hendersonf287b2c2012-09-15 13:20:25 -070010726 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
10727 if (vec != NULL) {
Peter Maydell918c03e2016-06-06 19:58:02 +010010728 ret = get_errno(safe_readv(arg1, vec, arg3));
Richard Hendersonf287b2c2012-09-15 13:20:25 -070010729 unlock_iovec(vec, arg2, arg3, 1);
10730 } else {
10731 ret = -host_to_target_errno(errno);
10732 }
bellard31e31b82003-02-18 22:55:36 +000010733 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010734 return ret;
bellard31e31b82003-02-18 22:55:36 +000010735 case TARGET_NR_writev:
10736 {
Richard Hendersonf287b2c2012-09-15 13:20:25 -070010737 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
10738 if (vec != NULL) {
Peter Maydell918c03e2016-06-06 19:58:02 +010010739 ret = get_errno(safe_writev(arg1, vec, arg3));
Richard Hendersonf287b2c2012-09-15 13:20:25 -070010740 unlock_iovec(vec, arg2, arg3, 0);
10741 } else {
10742 ret = -host_to_target_errno(errno);
10743 }
bellard31e31b82003-02-18 22:55:36 +000010744 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010745 return ret;
Dejan Jovicevic0f263862016-10-11 11:52:46 +020010746#if defined(TARGET_NR_preadv)
10747 case TARGET_NR_preadv:
10748 {
10749 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
10750 if (vec != NULL) {
Max Filippov9ac22512018-04-04 17:30:41 -070010751 unsigned long low, high;
10752
10753 target_to_host_low_high(arg4, arg5, &low, &high);
10754 ret = get_errno(safe_preadv(arg1, vec, arg3, low, high));
Dejan Jovicevic0f263862016-10-11 11:52:46 +020010755 unlock_iovec(vec, arg2, arg3, 1);
10756 } else {
10757 ret = -host_to_target_errno(errno);
10758 }
10759 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010760 return ret;
Dejan Jovicevic0f263862016-10-11 11:52:46 +020010761#endif
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +020010762#if defined(TARGET_NR_pwritev)
10763 case TARGET_NR_pwritev:
10764 {
10765 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
10766 if (vec != NULL) {
Max Filippov9ac22512018-04-04 17:30:41 -070010767 unsigned long low, high;
10768
10769 target_to_host_low_high(arg4, arg5, &low, &high);
10770 ret = get_errno(safe_pwritev(arg1, vec, arg3, low, high));
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +020010771 unlock_iovec(vec, arg2, arg3, 0);
10772 } else {
10773 ret = -host_to_target_errno(errno);
10774 }
10775 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010776 return ret;
Dejan Jovicevicf8d00fb2016-10-11 11:52:47 +020010777#endif
bellard31e31b82003-02-18 22:55:36 +000010778 case TARGET_NR_getsid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010779 return get_errno(getsid(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +000010780#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +000010781 case TARGET_NR_fdatasync:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010782 return get_errno(fdatasync(arg1));
j_mayer7a3148a2007-04-05 07:13:51 +000010783#endif
Mike Frysinger737de1d2011-02-07 01:05:55 -050010784 case TARGET_NR_sched_getaffinity:
10785 {
10786 unsigned int mask_size;
10787 unsigned long *mask;
10788
10789 /*
10790 * sched_getaffinity needs multiples of ulong, so need to take
10791 * care of mismatches between target ulong and host ulong sizes.
10792 */
10793 if (arg2 & (sizeof(abi_ulong) - 1)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010794 return -TARGET_EINVAL;
Mike Frysinger737de1d2011-02-07 01:05:55 -050010795 }
10796 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
10797
10798 mask = alloca(mask_size);
Samuel Thibault2e0a8712018-01-09 21:16:43 +010010799 memset(mask, 0, mask_size);
Mike Frysinger737de1d2011-02-07 01:05:55 -050010800 ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
10801
10802 if (!is_error(ret)) {
Peter Maydellbe3bd282014-05-15 14:40:23 +010010803 if (ret > arg2) {
10804 /* More data returned than the caller's buffer will fit.
10805 * This only happens if sizeof(abi_long) < sizeof(long)
10806 * and the caller passed us a buffer holding an odd number
10807 * of abi_longs. If the host kernel is actually using the
10808 * extra 4 bytes then fail EINVAL; otherwise we can just
10809 * ignore them and only copy the interesting part.
10810 */
10811 int numcpus = sysconf(_SC_NPROCESSORS_CONF);
10812 if (numcpus > arg2 * 8) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010813 return -TARGET_EINVAL;
Peter Maydellbe3bd282014-05-15 14:40:23 +010010814 }
10815 ret = arg2;
10816 }
10817
Samuel Thibault5fdefcf2018-02-11 18:47:04 +010010818 if (host_to_target_cpu_mask(mask, mask_size, arg3, ret)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010819 return -TARGET_EFAULT;
Samuel Thibault5fdefcf2018-02-11 18:47:04 +010010820 }
Mike Frysinger737de1d2011-02-07 01:05:55 -050010821 }
10822 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010823 return ret;
Mike Frysinger737de1d2011-02-07 01:05:55 -050010824 case TARGET_NR_sched_setaffinity:
10825 {
10826 unsigned int mask_size;
10827 unsigned long *mask;
10828
10829 /*
10830 * sched_setaffinity needs multiples of ulong, so need to take
10831 * care of mismatches between target ulong and host ulong sizes.
10832 */
10833 if (arg2 & (sizeof(abi_ulong) - 1)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010834 return -TARGET_EINVAL;
Mike Frysinger737de1d2011-02-07 01:05:55 -050010835 }
10836 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
Mike Frysinger737de1d2011-02-07 01:05:55 -050010837 mask = alloca(mask_size);
Samuel Thibault2e0a8712018-01-09 21:16:43 +010010838
10839 ret = target_to_host_cpu_mask(mask, mask_size, arg3, arg2);
10840 if (ret) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010841 return ret;
Mike Frysinger737de1d2011-02-07 01:05:55 -050010842 }
Mike Frysinger737de1d2011-02-07 01:05:55 -050010843
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010844 return get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
Mike Frysinger737de1d2011-02-07 01:05:55 -050010845 }
Samuel Thibaultb827c3e2018-01-12 09:14:35 +010010846 case TARGET_NR_getcpu:
10847 {
10848 unsigned cpu, node;
10849 ret = get_errno(sys_getcpu(arg1 ? &cpu : NULL,
10850 arg2 ? &node : NULL,
10851 NULL));
10852 if (is_error(ret)) {
Richard Henderson259841c2018-08-18 12:01:09 -070010853 return ret;
Samuel Thibaultb827c3e2018-01-12 09:14:35 +010010854 }
10855 if (arg1 && put_user_u32(cpu, arg1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010856 return -TARGET_EFAULT;
Samuel Thibaultb827c3e2018-01-12 09:14:35 +010010857 }
10858 if (arg2 && put_user_u32(node, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010859 return -TARGET_EFAULT;
Samuel Thibaultb827c3e2018-01-12 09:14:35 +010010860 }
10861 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010862 return ret;
bellard31e31b82003-02-18 22:55:36 +000010863 case TARGET_NR_sched_setparam:
bellard5cd43932003-03-29 16:54:36 +000010864 {
Tonis Tiigi407a1192022-01-04 20:18:19 -080010865 struct target_sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +000010866 struct sched_param schp;
pbrook53a59602006-03-25 19:31:22 +000010867
Tom Mustaa1d5c5b2014-08-12 13:53:38 -050010868 if (arg2 == 0) {
10869 return -TARGET_EINVAL;
10870 }
Tonis Tiigi407a1192022-01-04 20:18:19 -080010871 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010872 return -TARGET_EFAULT;
Tonis Tiigi407a1192022-01-04 20:18:19 -080010873 }
bellard5cd43932003-03-29 16:54:36 +000010874 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +000010875 unlock_user_struct(target_schp, arg2, 0);
Tonis Tiigi407a1192022-01-04 20:18:19 -080010876 return get_errno(sys_sched_setparam(arg1, &schp));
bellard5cd43932003-03-29 16:54:36 +000010877 }
bellard31e31b82003-02-18 22:55:36 +000010878 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +000010879 {
Tonis Tiigi407a1192022-01-04 20:18:19 -080010880 struct target_sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +000010881 struct sched_param schp;
Tom Mustaa1d5c5b2014-08-12 13:53:38 -050010882
10883 if (arg2 == 0) {
10884 return -TARGET_EINVAL;
10885 }
Tonis Tiigi407a1192022-01-04 20:18:19 -080010886 ret = get_errno(sys_sched_getparam(arg1, &schp));
bellard5cd43932003-03-29 16:54:36 +000010887 if (!is_error(ret)) {
Tonis Tiigi407a1192022-01-04 20:18:19 -080010888 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010889 return -TARGET_EFAULT;
Tonis Tiigi407a1192022-01-04 20:18:19 -080010890 }
bellard5cd43932003-03-29 16:54:36 +000010891 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +000010892 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +000010893 }
10894 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010895 return ret;
bellard31e31b82003-02-18 22:55:36 +000010896 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +000010897 {
Tonis Tiigi407a1192022-01-04 20:18:19 -080010898 struct target_sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +000010899 struct sched_param schp;
Tom Mustaa1d5c5b2014-08-12 13:53:38 -050010900 if (arg3 == 0) {
10901 return -TARGET_EINVAL;
10902 }
Tonis Tiigi407a1192022-01-04 20:18:19 -080010903 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070010904 return -TARGET_EFAULT;
Tonis Tiigi407a1192022-01-04 20:18:19 -080010905 }
bellard5cd43932003-03-29 16:54:36 +000010906 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +000010907 unlock_user_struct(target_schp, arg3, 0);
Tonis Tiigi407a1192022-01-04 20:18:19 -080010908 return get_errno(sys_sched_setscheduler(arg1, arg2, &schp));
bellard5cd43932003-03-29 16:54:36 +000010909 }
bellard31e31b82003-02-18 22:55:36 +000010910 case TARGET_NR_sched_getscheduler:
Tonis Tiigi407a1192022-01-04 20:18:19 -080010911 return get_errno(sys_sched_getscheduler(arg1));
Tonis Tiigi45ad7612022-01-04 20:18:18 -080010912 case TARGET_NR_sched_getattr:
10913 {
10914 struct target_sched_attr *target_scha;
10915 struct sched_attr scha;
10916 if (arg2 == 0) {
10917 return -TARGET_EINVAL;
10918 }
10919 if (arg3 > sizeof(scha)) {
10920 arg3 = sizeof(scha);
10921 }
10922 ret = get_errno(sys_sched_getattr(arg1, &scha, arg3, arg4));
10923 if (!is_error(ret)) {
10924 target_scha = lock_user(VERIFY_WRITE, arg2, arg3, 0);
10925 if (!target_scha) {
10926 return -TARGET_EFAULT;
10927 }
10928 target_scha->size = tswap32(scha.size);
10929 target_scha->sched_policy = tswap32(scha.sched_policy);
10930 target_scha->sched_flags = tswap64(scha.sched_flags);
10931 target_scha->sched_nice = tswap32(scha.sched_nice);
10932 target_scha->sched_priority = tswap32(scha.sched_priority);
10933 target_scha->sched_runtime = tswap64(scha.sched_runtime);
10934 target_scha->sched_deadline = tswap64(scha.sched_deadline);
10935 target_scha->sched_period = tswap64(scha.sched_period);
10936 if (scha.size > offsetof(struct sched_attr, sched_util_min)) {
10937 target_scha->sched_util_min = tswap32(scha.sched_util_min);
10938 target_scha->sched_util_max = tswap32(scha.sched_util_max);
10939 }
10940 unlock_user(target_scha, arg2, arg3);
10941 }
10942 return ret;
10943 }
10944 case TARGET_NR_sched_setattr:
10945 {
10946 struct target_sched_attr *target_scha;
10947 struct sched_attr scha;
10948 uint32_t size;
10949 int zeroed;
10950 if (arg2 == 0) {
10951 return -TARGET_EINVAL;
10952 }
10953 if (get_user_u32(size, arg2)) {
10954 return -TARGET_EFAULT;
10955 }
10956 if (!size) {
10957 size = offsetof(struct target_sched_attr, sched_util_min);
10958 }
10959 if (size < offsetof(struct target_sched_attr, sched_util_min)) {
10960 if (put_user_u32(sizeof(struct target_sched_attr), arg2)) {
10961 return -TARGET_EFAULT;
10962 }
10963 return -TARGET_E2BIG;
10964 }
10965
10966 zeroed = check_zeroed_user(arg2, sizeof(struct target_sched_attr), size);
10967 if (zeroed < 0) {
10968 return zeroed;
10969 } else if (zeroed == 0) {
10970 if (put_user_u32(sizeof(struct target_sched_attr), arg2)) {
10971 return -TARGET_EFAULT;
10972 }
10973 return -TARGET_E2BIG;
10974 }
10975 if (size > sizeof(struct target_sched_attr)) {
10976 size = sizeof(struct target_sched_attr);
10977 }
10978
10979 target_scha = lock_user(VERIFY_READ, arg2, size, 1);
10980 if (!target_scha) {
10981 return -TARGET_EFAULT;
10982 }
10983 scha.size = size;
10984 scha.sched_policy = tswap32(target_scha->sched_policy);
10985 scha.sched_flags = tswap64(target_scha->sched_flags);
10986 scha.sched_nice = tswap32(target_scha->sched_nice);
10987 scha.sched_priority = tswap32(target_scha->sched_priority);
10988 scha.sched_runtime = tswap64(target_scha->sched_runtime);
10989 scha.sched_deadline = tswap64(target_scha->sched_deadline);
10990 scha.sched_period = tswap64(target_scha->sched_period);
10991 if (size > offsetof(struct target_sched_attr, sched_util_min)) {
10992 scha.sched_util_min = tswap32(target_scha->sched_util_min);
10993 scha.sched_util_max = tswap32(target_scha->sched_util_max);
10994 }
10995 unlock_user(target_scha, arg2, 0);
10996 return get_errno(sys_sched_setattr(arg1, &scha, arg3));
10997 }
bellard31e31b82003-02-18 22:55:36 +000010998 case TARGET_NR_sched_yield:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070010999 return get_errno(sched_yield());
bellard31e31b82003-02-18 22:55:36 +000011000 case TARGET_NR_sched_get_priority_max:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011001 return get_errno(sched_get_priority_max(arg1));
bellard31e31b82003-02-18 22:55:36 +000011002 case TARGET_NR_sched_get_priority_min:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011003 return get_errno(sched_get_priority_min(arg1));
Alistair Francis859e8a82020-03-12 15:13:49 -070011004#ifdef TARGET_NR_sched_rr_get_interval
bellard31e31b82003-02-18 22:55:36 +000011005 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +000011006 {
bellard5cd43932003-03-29 16:54:36 +000011007 struct timespec ts;
11008 ret = get_errno(sched_rr_get_interval(arg1, &ts));
11009 if (!is_error(ret)) {
Tom Mustad4290c42014-08-12 13:53:39 -050011010 ret = host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +000011011 }
11012 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011013 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070011014#endif
Filip Bozutaddcbde12020-08-24 21:21:16 +020011015#ifdef TARGET_NR_sched_rr_get_interval_time64
11016 case TARGET_NR_sched_rr_get_interval_time64:
11017 {
11018 struct timespec ts;
11019 ret = get_errno(sched_rr_get_interval(arg1, &ts));
11020 if (!is_error(ret)) {
11021 ret = host_to_target_timespec64(arg2, &ts);
11022 }
11023 }
11024 return ret;
11025#endif
Alistair Francis859e8a82020-03-12 15:13:49 -070011026#if defined(TARGET_NR_nanosleep)
bellard31e31b82003-02-18 22:55:36 +000011027 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +000011028 {
bellard1b6b0292003-03-22 17:31:38 +000011029 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +000011030 target_to_host_timespec(&req, arg1);
Peter Maydell9e518222016-06-06 19:58:09 +010011031 ret = get_errno(safe_nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +000011032 if (is_error(ret) && arg2) {
11033 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +000011034 }
11035 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011036 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070011037#endif
bellard31e31b82003-02-18 22:55:36 +000011038 case TARGET_NR_prctl:
Richard Henderson87e9bf22021-12-27 07:01:22 -080011039 return do_prctl(cpu_env, arg1, arg2, arg3, arg4, arg5);
ths39b9aae2007-02-11 18:36:44 +000011040 break;
bellardd2fd1af2007-11-14 18:08:56 +000011041#ifdef TARGET_NR_arch_prctl
11042 case TARGET_NR_arch_prctl:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011043 return do_arch_prctl(cpu_env, arg1, arg2);
bellardd2fd1af2007-11-14 18:08:56 +000011044#endif
aurel32f2c7ba12008-03-28 22:32:06 +000011045#ifdef TARGET_NR_pread64
11046 case TARGET_NR_pread64:
James Clarke8bf8e9d2017-09-15 20:33:13 +010011047 if (regpairs_aligned(cpu_env, num)) {
Alexander Grafae017a52012-09-29 15:32:39 +000011048 arg4 = arg5;
11049 arg5 = arg6;
11050 }
Peter Maydell2bd3f892019-01-08 18:49:00 +000011051 if (arg2 == 0 && arg3 == 0) {
11052 /* Special-case NULL buffer and zero length, which should succeed */
11053 p = 0;
11054 } else {
11055 p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
11056 if (!p) {
11057 return -TARGET_EFAULT;
11058 }
11059 }
aurel32f2c7ba12008-03-28 22:32:06 +000011060 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
11061 unlock_user(p, arg2, ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011062 return ret;
aurel32f2c7ba12008-03-28 22:32:06 +000011063 case TARGET_NR_pwrite64:
James Clarke8bf8e9d2017-09-15 20:33:13 +010011064 if (regpairs_aligned(cpu_env, num)) {
Alexander Grafae017a52012-09-29 15:32:39 +000011065 arg4 = arg5;
11066 arg5 = arg6;
11067 }
Peter Maydell2bd3f892019-01-08 18:49:00 +000011068 if (arg2 == 0 && arg3 == 0) {
11069 /* Special-case NULL buffer and zero length, which should succeed */
11070 p = 0;
11071 } else {
11072 p = lock_user(VERIFY_READ, arg2, arg3, 1);
11073 if (!p) {
11074 return -TARGET_EFAULT;
11075 }
11076 }
aurel32f2c7ba12008-03-28 22:32:06 +000011077 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
11078 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011079 return ret;
aurel32f2c7ba12008-03-28 22:32:06 +000011080#endif
bellard31e31b82003-02-18 22:55:36 +000011081 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +000011082 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011083 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011084 ret = get_errno(sys_getcwd1(p, arg2));
11085 unlock_user(p, arg1, ret);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011086 return ret;
bellard31e31b82003-02-18 22:55:36 +000011087 case TARGET_NR_capget:
11088 case TARGET_NR_capset:
Peter Maydelle0eb2102014-03-17 12:15:35 +000011089 {
11090 struct target_user_cap_header *target_header;
11091 struct target_user_cap_data *target_data = NULL;
11092 struct __user_cap_header_struct header;
11093 struct __user_cap_data_struct data[2];
11094 struct __user_cap_data_struct *dataptr = NULL;
11095 int i, target_datalen;
11096 int data_items = 1;
11097
11098 if (!lock_user_struct(VERIFY_WRITE, target_header, arg1, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011099 return -TARGET_EFAULT;
Peter Maydelle0eb2102014-03-17 12:15:35 +000011100 }
11101 header.version = tswap32(target_header->version);
11102 header.pid = tswap32(target_header->pid);
11103
Peter Maydellec864872014-03-19 16:07:30 +000011104 if (header.version != _LINUX_CAPABILITY_VERSION) {
Peter Maydelle0eb2102014-03-17 12:15:35 +000011105 /* Version 2 and up takes pointer to two user_data structs */
11106 data_items = 2;
11107 }
11108
11109 target_datalen = sizeof(*target_data) * data_items;
11110
11111 if (arg2) {
11112 if (num == TARGET_NR_capget) {
11113 target_data = lock_user(VERIFY_WRITE, arg2, target_datalen, 0);
11114 } else {
11115 target_data = lock_user(VERIFY_READ, arg2, target_datalen, 1);
11116 }
11117 if (!target_data) {
11118 unlock_user_struct(target_header, arg1, 0);
Richard Henderson2852aaf2018-08-18 12:01:06 -070011119 return -TARGET_EFAULT;
Peter Maydelle0eb2102014-03-17 12:15:35 +000011120 }
11121
11122 if (num == TARGET_NR_capset) {
11123 for (i = 0; i < data_items; i++) {
11124 data[i].effective = tswap32(target_data[i].effective);
11125 data[i].permitted = tswap32(target_data[i].permitted);
11126 data[i].inheritable = tswap32(target_data[i].inheritable);
11127 }
11128 }
11129
11130 dataptr = data;
11131 }
11132
11133 if (num == TARGET_NR_capget) {
11134 ret = get_errno(capget(&header, dataptr));
11135 } else {
11136 ret = get_errno(capset(&header, dataptr));
11137 }
11138
11139 /* The kernel always updates version for both capget and capset */
11140 target_header->version = tswap32(header.version);
11141 unlock_user_struct(target_header, arg1, 1);
11142
11143 if (arg2) {
11144 if (num == TARGET_NR_capget) {
11145 for (i = 0; i < data_items; i++) {
11146 target_data[i].effective = tswap32(data[i].effective);
11147 target_data[i].permitted = tswap32(data[i].permitted);
11148 target_data[i].inheritable = tswap32(data[i].inheritable);
11149 }
11150 unlock_user(target_data, arg2, target_datalen);
11151 } else {
11152 unlock_user(target_data, arg2, 0);
11153 }
11154 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011155 return ret;
Peter Maydelle0eb2102014-03-17 12:15:35 +000011156 }
bellard31e31b82003-02-18 22:55:36 +000011157 case TARGET_NR_sigaltstack:
Richard Henderson6b208752021-04-25 19:53:12 -070011158 return do_sigaltstack(arg1, arg2, cpu_env);
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011159
11160#ifdef CONFIG_SENDFILE
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020011161#ifdef TARGET_NR_sendfile
bellard31e31b82003-02-18 22:55:36 +000011162 case TARGET_NR_sendfile:
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011163 {
11164 off_t *offp = NULL;
11165 off_t off;
11166 if (arg3) {
11167 ret = get_user_sal(off, arg3);
11168 if (is_error(ret)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011169 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011170 }
11171 offp = &off;
11172 }
11173 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
11174 if (!is_error(ret) && arg3) {
11175 abi_long ret2 = put_user_sal(off, arg3);
11176 if (is_error(ret2)) {
11177 ret = ret2;
11178 }
11179 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011180 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011181 }
Aleksandar Rikalo4f7f8922018-08-02 16:16:00 +020011182#endif
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011183#ifdef TARGET_NR_sendfile64
11184 case TARGET_NR_sendfile64:
11185 {
11186 off_t *offp = NULL;
11187 off_t off;
11188 if (arg3) {
11189 ret = get_user_s64(off, arg3);
11190 if (is_error(ret)) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011191 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011192 }
11193 offp = &off;
11194 }
11195 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
11196 if (!is_error(ret) && arg3) {
11197 abi_long ret2 = put_user_s64(off, arg3);
11198 if (is_error(ret2)) {
11199 ret = ret2;
11200 }
11201 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011202 return ret;
Peter Maydella8fd1ab2013-02-08 07:31:55 +000011203 }
11204#endif
bellardebc05482003-09-30 21:08:41 +000011205#endif
bellard048f6b42005-11-26 18:47:20 +000011206#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +000011207 case TARGET_NR_vfork:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011208 return get_errno(do_fork(cpu_env,
11209 CLONE_VFORK | CLONE_VM | TARGET_SIGCHLD,
11210 0, 0, 0, 0));
bellard048f6b42005-11-26 18:47:20 +000011211#endif
bellardebc05482003-09-30 21:08:41 +000011212#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +000011213 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +000011214 {
11215 struct rlimit rlim;
Wesley W. Terpstrae22b7012011-07-12 14:42:00 +030011216 int resource = target_to_host_resource(arg1);
11217 ret = get_errno(getrlimit(resource, &rlim));
bellard728584b2003-04-29 20:43:36 +000011218 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +000011219 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +000011220 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011221 return -TARGET_EFAULT;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +090011222 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
11223 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +000011224 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +000011225 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011226 return ret;
bellard728584b2003-04-29 20:43:36 +000011227 }
bellardebc05482003-09-30 21:08:41 +000011228#endif
bellarda315a142005-01-30 22:59:18 +000011229#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +000011230 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +000011231 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011232 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011233 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
11234 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011235 return ret;
bellarda315a142005-01-30 22:59:18 +000011236#endif
11237#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +000011238 case TARGET_NR_ftruncate64:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011239 return target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellarda315a142005-01-30 22:59:18 +000011240#endif
11241#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +000011242 case TARGET_NR_stat64:
Richard Henderson2852aaf2018-08-18 12:01:06 -070011243 if (!(p = lock_user_string(arg1))) {
11244 return -TARGET_EFAULT;
11245 }
pbrook53a59602006-03-25 19:31:22 +000011246 ret = get_errno(stat(path(p), &st));
11247 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +000011248 if (!is_error(ret))
11249 ret = host_to_target_stat64(cpu_env, arg2, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011250 return ret;
bellarda315a142005-01-30 22:59:18 +000011251#endif
11252#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +000011253 case TARGET_NR_lstat64:
Richard Henderson2852aaf2018-08-18 12:01:06 -070011254 if (!(p = lock_user_string(arg1))) {
11255 return -TARGET_EFAULT;
11256 }
pbrook53a59602006-03-25 19:31:22 +000011257 ret = get_errno(lstat(path(p), &st));
11258 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +000011259 if (!is_error(ret))
11260 ret = host_to_target_stat64(cpu_env, arg2, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011261 return ret;
bellarda315a142005-01-30 22:59:18 +000011262#endif
11263#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +000011264 case TARGET_NR_fstat64:
balrog6a24a772008-09-20 02:23:36 +000011265 ret = get_errno(fstat(arg1, &st));
11266 if (!is_error(ret))
11267 ret = host_to_target_stat64(cpu_env, arg2, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011268 return ret;
bellardec86b0f2003-04-11 00:15:04 +000011269#endif
Peter Maydellc0d472b2013-06-12 16:20:21 +010011270#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat))
aurel329d33b762009-04-08 23:07:05 +000011271#ifdef TARGET_NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +000011272 case TARGET_NR_fstatat64:
aurel329d33b762009-04-08 23:07:05 +000011273#endif
11274#ifdef TARGET_NR_newfstatat
11275 case TARGET_NR_newfstatat:
11276#endif
Richard Henderson2852aaf2018-08-18 12:01:06 -070011277 if (!(p = lock_user_string(arg2))) {
11278 return -TARGET_EFAULT;
11279 }
Peter Maydellc0d472b2013-06-12 16:20:21 +010011280 ret = get_errno(fstatat(arg1, path(p), &st, arg4));
Richard Henderson2852aaf2018-08-18 12:01:06 -070011281 unlock_user(p, arg2, 0);
balrog6a24a772008-09-20 02:23:36 +000011282 if (!is_error(ret))
11283 ret = host_to_target_stat64(cpu_env, arg3, &st);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011284 return ret;
bellarda315a142005-01-30 22:59:18 +000011285#endif
Aleksandar Rikaloefa92182019-06-28 12:43:34 +020011286#if defined(TARGET_NR_statx)
11287 case TARGET_NR_statx:
11288 {
11289 struct target_statx *target_stx;
11290 int dirfd = arg1;
11291 int flags = arg3;
11292
11293 p = lock_user_string(arg2);
11294 if (p == NULL) {
11295 return -TARGET_EFAULT;
11296 }
11297#if defined(__NR_statx)
11298 {
11299 /*
11300 * It is assumed that struct statx is architecture independent.
11301 */
11302 struct target_statx host_stx;
11303 int mask = arg4;
11304
11305 ret = get_errno(sys_statx(dirfd, p, flags, mask, &host_stx));
11306 if (!is_error(ret)) {
11307 if (host_to_target_statx(&host_stx, arg5) != 0) {
11308 unlock_user(p, arg2, 0);
11309 return -TARGET_EFAULT;
11310 }
11311 }
11312
11313 if (ret != -TARGET_ENOSYS) {
11314 unlock_user(p, arg2, 0);
11315 return ret;
11316 }
11317 }
11318#endif
11319 ret = get_errno(fstatat(dirfd, path(p), &st, flags));
11320 unlock_user(p, arg2, 0);
11321
11322 if (!is_error(ret)) {
11323 if (!lock_user_struct(VERIFY_WRITE, target_stx, arg5, 0)) {
11324 return -TARGET_EFAULT;
11325 }
11326 memset(target_stx, 0, sizeof(*target_stx));
11327 __put_user(major(st.st_dev), &target_stx->stx_dev_major);
11328 __put_user(minor(st.st_dev), &target_stx->stx_dev_minor);
11329 __put_user(st.st_ino, &target_stx->stx_ino);
11330 __put_user(st.st_mode, &target_stx->stx_mode);
11331 __put_user(st.st_uid, &target_stx->stx_uid);
11332 __put_user(st.st_gid, &target_stx->stx_gid);
11333 __put_user(st.st_nlink, &target_stx->stx_nlink);
11334 __put_user(major(st.st_rdev), &target_stx->stx_rdev_major);
11335 __put_user(minor(st.st_rdev), &target_stx->stx_rdev_minor);
11336 __put_user(st.st_size, &target_stx->stx_size);
11337 __put_user(st.st_blksize, &target_stx->stx_blksize);
11338 __put_user(st.st_blocks, &target_stx->stx_blocks);
11339 __put_user(st.st_atime, &target_stx->stx_atime.tv_sec);
11340 __put_user(st.st_mtime, &target_stx->stx_mtime.tv_sec);
11341 __put_user(st.st_ctime, &target_stx->stx_ctime.tv_sec);
11342 unlock_user_struct(target_stx, arg5, 1);
11343 }
11344 }
11345 return ret;
11346#endif
Chen Gang704eff62015-08-21 05:37:33 +080011347#ifdef TARGET_NR_lchown
bellard67867302003-11-23 17:05:30 +000011348 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +000011349 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011350 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011351 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
11352 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011353 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080011354#endif
Riku Voipio0c866a72011-04-18 15:23:06 +030011355#ifdef TARGET_NR_getuid
bellard67867302003-11-23 17:05:30 +000011356 case TARGET_NR_getuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011357 return get_errno(high2lowuid(getuid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030011358#endif
11359#ifdef TARGET_NR_getgid
bellard67867302003-11-23 17:05:30 +000011360 case TARGET_NR_getgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011361 return get_errno(high2lowgid(getgid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030011362#endif
11363#ifdef TARGET_NR_geteuid
bellard67867302003-11-23 17:05:30 +000011364 case TARGET_NR_geteuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011365 return get_errno(high2lowuid(geteuid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030011366#endif
11367#ifdef TARGET_NR_getegid
bellard67867302003-11-23 17:05:30 +000011368 case TARGET_NR_getegid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011369 return get_errno(high2lowgid(getegid()));
Riku Voipio0c866a72011-04-18 15:23:06 +030011370#endif
bellard67867302003-11-23 17:05:30 +000011371 case TARGET_NR_setreuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011372 return get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
bellard67867302003-11-23 17:05:30 +000011373 case TARGET_NR_setregid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011374 return get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
bellard67867302003-11-23 17:05:30 +000011375 case TARGET_NR_getgroups:
11376 {
11377 int gidsetsize = arg1;
Riku Voipio0c866a72011-04-18 15:23:06 +030011378 target_id *target_grouplist;
bellard67867302003-11-23 17:05:30 +000011379 gid_t *grouplist;
11380 int i;
11381
11382 grouplist = alloca(gidsetsize * sizeof(gid_t));
11383 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +000011384 if (gidsetsize == 0)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011385 return ret;
bellard67867302003-11-23 17:05:30 +000011386 if (!is_error(ret)) {
Andreas Schwab03903ff2013-04-09 05:41:33 +000011387 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * sizeof(target_id), 0);
bellard579a97f2007-11-11 14:26:47 +000011388 if (!target_grouplist)
Richard Henderson2852aaf2018-08-18 12:01:06 -070011389 return -TARGET_EFAULT;
balroga2155fc2008-09-20 02:12:08 +000011390 for(i = 0;i < ret; i++)
Riku Voipio0c866a72011-04-18 15:23:06 +030011391 target_grouplist[i] = tswapid(high2lowgid(grouplist[i]));
Andreas Schwab03903ff2013-04-09 05:41:33 +000011392 unlock_user(target_grouplist, arg2, gidsetsize * sizeof(target_id));
bellard67867302003-11-23 17:05:30 +000011393 }
11394 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011395 return ret;
bellard67867302003-11-23 17:05:30 +000011396 case TARGET_NR_setgroups:
11397 {
11398 int gidsetsize = arg1;
Riku Voipio0c866a72011-04-18 15:23:06 +030011399 target_id *target_grouplist;
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050011400 gid_t *grouplist = NULL;
bellard67867302003-11-23 17:05:30 +000011401 int i;
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050011402 if (gidsetsize) {
11403 grouplist = alloca(gidsetsize * sizeof(gid_t));
Andreas Schwab03903ff2013-04-09 05:41:33 +000011404 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * sizeof(target_id), 1);
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050011405 if (!target_grouplist) {
Richard Henderson259841c2018-08-18 12:01:09 -070011406 return -TARGET_EFAULT;
Dillon Amburgeyf2b79ce2013-02-02 18:04:48 -050011407 }
11408 for (i = 0; i < gidsetsize; i++) {
11409 grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
11410 }
11411 unlock_user(target_grouplist, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +000011412 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011413 return get_errno(setgroups(gidsetsize, grouplist));
bellard67867302003-11-23 17:05:30 +000011414 }
bellard67867302003-11-23 17:05:30 +000011415 case TARGET_NR_fchown:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011416 return get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
Peter Maydellc0d472b2013-06-12 16:20:21 +010011417#if defined(TARGET_NR_fchownat)
thsccfa72b2007-09-24 09:23:34 +000011418 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +000011419 if (!(p = lock_user_string(arg2)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011420 return -TARGET_EFAULT;
Peter Maydellc0d472b2013-06-12 16:20:21 +010011421 ret = get_errno(fchownat(arg1, p, low2highuid(arg3),
11422 low2highgid(arg4), arg5));
bellard579a97f2007-11-11 14:26:47 +000011423 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011424 return ret;
thsccfa72b2007-09-24 09:23:34 +000011425#endif
bellard67867302003-11-23 17:05:30 +000011426#ifdef TARGET_NR_setresuid
11427 case TARGET_NR_setresuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011428 return get_errno(sys_setresuid(low2highuid(arg1),
11429 low2highuid(arg2),
11430 low2highuid(arg3)));
bellard67867302003-11-23 17:05:30 +000011431#endif
11432#ifdef TARGET_NR_getresuid
11433 case TARGET_NR_getresuid:
11434 {
pbrook53a59602006-03-25 19:31:22 +000011435 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +000011436 ret = get_errno(getresuid(&ruid, &euid, &suid));
11437 if (!is_error(ret)) {
Peter Maydell76ca3102014-03-02 19:36:41 +000011438 if (put_user_id(high2lowuid(ruid), arg1)
11439 || put_user_id(high2lowuid(euid), arg2)
11440 || put_user_id(high2lowuid(suid), arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011441 return -TARGET_EFAULT;
bellard67867302003-11-23 17:05:30 +000011442 }
11443 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011444 return ret;
bellard67867302003-11-23 17:05:30 +000011445#endif
11446#ifdef TARGET_NR_getresgid
11447 case TARGET_NR_setresgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011448 return get_errno(sys_setresgid(low2highgid(arg1),
11449 low2highgid(arg2),
11450 low2highgid(arg3)));
bellard67867302003-11-23 17:05:30 +000011451#endif
11452#ifdef TARGET_NR_getresgid
11453 case TARGET_NR_getresgid:
11454 {
pbrook53a59602006-03-25 19:31:22 +000011455 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +000011456 ret = get_errno(getresgid(&rgid, &egid, &sgid));
11457 if (!is_error(ret)) {
Peter Maydell76ca3102014-03-02 19:36:41 +000011458 if (put_user_id(high2lowgid(rgid), arg1)
11459 || put_user_id(high2lowgid(egid), arg2)
11460 || put_user_id(high2lowgid(sgid), arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011461 return -TARGET_EFAULT;
bellard67867302003-11-23 17:05:30 +000011462 }
11463 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011464 return ret;
bellard67867302003-11-23 17:05:30 +000011465#endif
Chen Gang704eff62015-08-21 05:37:33 +080011466#ifdef TARGET_NR_chown
bellard67867302003-11-23 17:05:30 +000011467 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +000011468 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011469 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011470 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
11471 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011472 return ret;
Chen Gang704eff62015-08-21 05:37:33 +080011473#endif
bellard67867302003-11-23 17:05:30 +000011474 case TARGET_NR_setuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011475 return get_errno(sys_setuid(low2highuid(arg1)));
bellard67867302003-11-23 17:05:30 +000011476 case TARGET_NR_setgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011477 return get_errno(sys_setgid(low2highgid(arg1)));
bellard67867302003-11-23 17:05:30 +000011478 case TARGET_NR_setfsuid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011479 return get_errno(setfsuid(arg1));
bellard67867302003-11-23 17:05:30 +000011480 case TARGET_NR_setfsgid:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011481 return get_errno(setfsgid(arg1));
bellard67867302003-11-23 17:05:30 +000011482
bellarda315a142005-01-30 22:59:18 +000011483#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +000011484 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +000011485 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011486 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011487 ret = get_errno(lchown(p, arg2, arg3));
11488 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011489 return ret;
bellarda315a142005-01-30 22:59:18 +000011490#endif
11491#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +000011492 case TARGET_NR_getuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011493 return get_errno(getuid());
bellarda315a142005-01-30 22:59:18 +000011494#endif
aurel3264b4d282008-11-14 17:20:15 +000011495
11496#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
11497 /* Alpha specific */
11498 case TARGET_NR_getxuid:
Richard Hendersonba0e2762009-12-09 15:56:29 -080011499 {
11500 uid_t euid;
11501 euid=geteuid();
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020011502 cpu_env->ir[IR_A4]=euid;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011503 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011504 return get_errno(getuid());
aurel3264b4d282008-11-14 17:20:15 +000011505#endif
11506#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
11507 /* Alpha specific */
11508 case TARGET_NR_getxgid:
Richard Hendersonba0e2762009-12-09 15:56:29 -080011509 {
11510 uid_t egid;
11511 egid=getegid();
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020011512 cpu_env->ir[IR_A4]=egid;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011513 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011514 return get_errno(getgid());
aurel3264b4d282008-11-14 17:20:15 +000011515#endif
Richard Hendersonba0e2762009-12-09 15:56:29 -080011516#if defined(TARGET_NR_osf_getsysinfo) && defined(TARGET_ALPHA)
11517 /* Alpha specific */
11518 case TARGET_NR_osf_getsysinfo:
11519 ret = -TARGET_EOPNOTSUPP;
11520 switch (arg1) {
11521 case TARGET_GSI_IEEE_FP_CONTROL:
11522 {
Richard Henderson21ba8562019-04-26 15:20:51 -070011523 uint64_t fpcr = cpu_alpha_load_fpcr(cpu_env);
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020011524 uint64_t swcr = cpu_env->swcr;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011525
Richard Henderson21ba8562019-04-26 15:20:51 -070011526 swcr &= ~SWCR_STATUS_MASK;
11527 swcr |= (fpcr >> 35) & SWCR_STATUS_MASK;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011528
11529 if (put_user_u64 (swcr, arg2))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011530 return -TARGET_EFAULT;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011531 ret = 0;
11532 }
11533 break;
11534
11535 /* case GSI_IEEE_STATE_AT_SIGNAL:
11536 -- Not implemented in linux kernel.
11537 case GSI_UACPROC:
11538 -- Retrieves current unaligned access state; not much used.
11539 case GSI_PROC_TYPE:
11540 -- Retrieves implver information; surely not used.
11541 case GSI_GET_HWRPB:
11542 -- Grabs a copy of the HWRPB; surely not used.
11543 */
11544 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011545 return ret;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011546#endif
11547#if defined(TARGET_NR_osf_setsysinfo) && defined(TARGET_ALPHA)
11548 /* Alpha specific */
11549 case TARGET_NR_osf_setsysinfo:
11550 ret = -TARGET_EOPNOTSUPP;
11551 switch (arg1) {
11552 case TARGET_SSI_IEEE_FP_CONTROL:
Richard Hendersonba0e2762009-12-09 15:56:29 -080011553 {
Richard Henderson21ba8562019-04-26 15:20:51 -070011554 uint64_t swcr, fpcr;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011555
Richard Henderson6e06d512012-06-01 09:08:21 -070011556 if (get_user_u64 (swcr, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011557 return -TARGET_EFAULT;
Richard Henderson6e06d512012-06-01 09:08:21 -070011558 }
Richard Hendersonba0e2762009-12-09 15:56:29 -080011559
Richard Henderson21ba8562019-04-26 15:20:51 -070011560 /*
11561 * The kernel calls swcr_update_status to update the
11562 * status bits from the fpcr at every point that it
11563 * could be queried. Therefore, we store the status
11564 * bits only in FPCR.
11565 */
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020011566 cpu_env->swcr = swcr & (SWCR_TRAP_ENABLE_MASK | SWCR_MAP_MASK);
Richard Hendersonba0e2762009-12-09 15:56:29 -080011567
Richard Henderson21ba8562019-04-26 15:20:51 -070011568 fpcr = cpu_alpha_load_fpcr(cpu_env);
11569 fpcr &= ((uint64_t)FPCR_DYN_MASK << 32);
11570 fpcr |= alpha_ieee_swcr_to_fpcr(swcr);
Richard Henderson6e06d512012-06-01 09:08:21 -070011571 cpu_alpha_store_fpcr(cpu_env, fpcr);
11572 ret = 0;
11573 }
11574 break;
11575
11576 case TARGET_SSI_IEEE_RAISE_EXCEPTION:
11577 {
Richard Henderson21ba8562019-04-26 15:20:51 -070011578 uint64_t exc, fpcr, fex;
Richard Henderson6e06d512012-06-01 09:08:21 -070011579
11580 if (get_user_u64(exc, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070011581 return -TARGET_EFAULT;
Richard Henderson6e06d512012-06-01 09:08:21 -070011582 }
Richard Henderson21ba8562019-04-26 15:20:51 -070011583 exc &= SWCR_STATUS_MASK;
11584 fpcr = cpu_alpha_load_fpcr(cpu_env);
Richard Hendersonba0e2762009-12-09 15:56:29 -080011585
Richard Henderson6e06d512012-06-01 09:08:21 -070011586 /* Old exceptions are not signaled. */
Richard Henderson21ba8562019-04-26 15:20:51 -070011587 fex = alpha_ieee_fpcr_to_swcr(fpcr);
11588 fex = exc & ~fex;
11589 fex >>= SWCR_STATUS_TO_EXCSUM_SHIFT;
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020011590 fex &= (cpu_env)->swcr;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011591
Richard Henderson21ba8562019-04-26 15:20:51 -070011592 /* Update the hardware fpcr. */
11593 fpcr |= alpha_ieee_swcr_to_fpcr(exc);
11594 cpu_alpha_store_fpcr(cpu_env, fpcr);
11595
11596 if (fex) {
11597 int si_code = TARGET_FPE_FLTUNK;
Richard Henderson6e06d512012-06-01 09:08:21 -070011598 target_siginfo_t info;
Richard Henderson21ba8562019-04-26 15:20:51 -070011599
11600 if (fex & SWCR_TRAP_ENABLE_DNO) {
11601 si_code = TARGET_FPE_FLTUND;
11602 }
11603 if (fex & SWCR_TRAP_ENABLE_INE) {
11604 si_code = TARGET_FPE_FLTRES;
11605 }
11606 if (fex & SWCR_TRAP_ENABLE_UNF) {
11607 si_code = TARGET_FPE_FLTUND;
11608 }
11609 if (fex & SWCR_TRAP_ENABLE_OVF) {
11610 si_code = TARGET_FPE_FLTOVF;
11611 }
11612 if (fex & SWCR_TRAP_ENABLE_DZE) {
11613 si_code = TARGET_FPE_FLTDIV;
11614 }
11615 if (fex & SWCR_TRAP_ENABLE_INV) {
11616 si_code = TARGET_FPE_FLTINV;
11617 }
11618
Richard Henderson6e06d512012-06-01 09:08:21 -070011619 info.si_signo = SIGFPE;
11620 info.si_errno = 0;
11621 info.si_code = si_code;
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020011622 info._sifields._sigfault._addr = (cpu_env)->pc;
11623 queue_signal(cpu_env, info.si_signo,
Peter Maydell9d2803f2016-07-28 16:44:46 +010011624 QEMU_SI_FAULT, &info);
Richard Hendersonba0e2762009-12-09 15:56:29 -080011625 }
Richard Henderson21ba8562019-04-26 15:20:51 -070011626 ret = 0;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011627 }
11628 break;
11629
11630 /* case SSI_NVPAIRS:
11631 -- Used with SSIN_UACPROC to enable unaligned accesses.
11632 case SSI_IEEE_STATE_AT_SIGNAL:
11633 case SSI_IEEE_IGNORE_STATE_AT_SIGNAL:
11634 -- Not implemented in linux kernel
11635 */
11636 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011637 return ret;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011638#endif
11639#ifdef TARGET_NR_osf_sigprocmask
11640 /* Alpha specific. */
11641 case TARGET_NR_osf_sigprocmask:
11642 {
11643 abi_ulong mask;
Juan Quintelabc088ba2011-06-16 17:37:10 +010011644 int how;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011645 sigset_t set, oldset;
11646
11647 switch(arg1) {
11648 case TARGET_SIG_BLOCK:
11649 how = SIG_BLOCK;
11650 break;
11651 case TARGET_SIG_UNBLOCK:
11652 how = SIG_UNBLOCK;
11653 break;
11654 case TARGET_SIG_SETMASK:
11655 how = SIG_SETMASK;
11656 break;
11657 default:
Richard Henderson259841c2018-08-18 12:01:09 -070011658 return -TARGET_EINVAL;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011659 }
11660 mask = arg2;
11661 target_to_host_old_sigset(&set, &mask);
Peter Maydell3d3efba2016-05-27 15:51:49 +010011662 ret = do_sigprocmask(how, &set, &oldset);
11663 if (!ret) {
11664 host_to_target_old_sigset(&mask, &oldset);
11665 ret = mask;
11666 }
Richard Hendersonba0e2762009-12-09 15:56:29 -080011667 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011668 return ret;
Richard Hendersonba0e2762009-12-09 15:56:29 -080011669#endif
aurel3264b4d282008-11-14 17:20:15 +000011670
bellarda315a142005-01-30 22:59:18 +000011671#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +000011672 case TARGET_NR_getgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011673 return get_errno(getgid());
bellarda315a142005-01-30 22:59:18 +000011674#endif
11675#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +000011676 case TARGET_NR_geteuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011677 return get_errno(geteuid());
bellarda315a142005-01-30 22:59:18 +000011678#endif
11679#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +000011680 case TARGET_NR_getegid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011681 return get_errno(getegid());
bellarda315a142005-01-30 22:59:18 +000011682#endif
11683#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +000011684 case TARGET_NR_setreuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011685 return get_errno(setreuid(arg1, arg2));
bellarda315a142005-01-30 22:59:18 +000011686#endif
11687#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +000011688 case TARGET_NR_setregid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011689 return get_errno(setregid(arg1, arg2));
bellarda315a142005-01-30 22:59:18 +000011690#endif
11691#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +000011692 case TARGET_NR_getgroups32:
bellard99c475a2005-01-31 20:45:13 +000011693 {
11694 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +000011695 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +000011696 gid_t *grouplist;
11697 int i;
11698
11699 grouplist = alloca(gidsetsize * sizeof(gid_t));
11700 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +000011701 if (gidsetsize == 0)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011702 return ret;
bellard99c475a2005-01-31 20:45:13 +000011703 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +000011704 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
11705 if (!target_grouplist) {
Richard Henderson259841c2018-08-18 12:01:09 -070011706 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000011707 }
balroga2155fc2008-09-20 02:12:08 +000011708 for(i = 0;i < ret; i++)
pbrook53a59602006-03-25 19:31:22 +000011709 target_grouplist[i] = tswap32(grouplist[i]);
11710 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +000011711 }
11712 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011713 return ret;
bellarda315a142005-01-30 22:59:18 +000011714#endif
11715#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +000011716 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +000011717 {
11718 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +000011719 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +000011720 gid_t *grouplist;
11721 int i;
ths3b46e622007-09-17 08:09:54 +000011722
bellard99c475a2005-01-31 20:45:13 +000011723 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +000011724 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
11725 if (!target_grouplist) {
Richard Henderson259841c2018-08-18 12:01:09 -070011726 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000011727 }
bellard99c475a2005-01-31 20:45:13 +000011728 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +000011729 grouplist[i] = tswap32(target_grouplist[i]);
11730 unlock_user(target_grouplist, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011731 return get_errno(setgroups(gidsetsize, grouplist));
bellard99c475a2005-01-31 20:45:13 +000011732 }
bellarda315a142005-01-30 22:59:18 +000011733#endif
11734#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +000011735 case TARGET_NR_fchown32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011736 return get_errno(fchown(arg1, arg2, arg3));
bellarda315a142005-01-30 22:59:18 +000011737#endif
11738#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +000011739 case TARGET_NR_setresuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011740 return get_errno(sys_setresuid(arg1, arg2, arg3));
bellarda315a142005-01-30 22:59:18 +000011741#endif
11742#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +000011743 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +000011744 {
pbrook53a59602006-03-25 19:31:22 +000011745 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +000011746 ret = get_errno(getresuid(&ruid, &euid, &suid));
11747 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +000011748 if (put_user_u32(ruid, arg1)
11749 || put_user_u32(euid, arg2)
11750 || put_user_u32(suid, arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011751 return -TARGET_EFAULT;
bellardb03c60f2003-03-23 17:19:56 +000011752 }
11753 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011754 return ret;
bellarda315a142005-01-30 22:59:18 +000011755#endif
11756#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +000011757 case TARGET_NR_setresgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011758 return get_errno(sys_setresgid(arg1, arg2, arg3));
bellarda315a142005-01-30 22:59:18 +000011759#endif
11760#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +000011761 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +000011762 {
pbrook53a59602006-03-25 19:31:22 +000011763 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +000011764 ret = get_errno(getresgid(&rgid, &egid, &sgid));
11765 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +000011766 if (put_user_u32(rgid, arg1)
11767 || put_user_u32(egid, arg2)
11768 || put_user_u32(sgid, arg3))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011769 return -TARGET_EFAULT;
bellardb03c60f2003-03-23 17:19:56 +000011770 }
11771 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011772 return ret;
bellarda315a142005-01-30 22:59:18 +000011773#endif
11774#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +000011775 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +000011776 if (!(p = lock_user_string(arg1)))
Richard Henderson2852aaf2018-08-18 12:01:06 -070011777 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +000011778 ret = get_errno(chown(p, arg2, arg3));
11779 unlock_user(p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011780 return ret;
bellarda315a142005-01-30 22:59:18 +000011781#endif
11782#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +000011783 case TARGET_NR_setuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011784 return get_errno(sys_setuid(arg1));
bellarda315a142005-01-30 22:59:18 +000011785#endif
11786#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +000011787 case TARGET_NR_setgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011788 return get_errno(sys_setgid(arg1));
bellarda315a142005-01-30 22:59:18 +000011789#endif
11790#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +000011791 case TARGET_NR_setfsuid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011792 return get_errno(setfsuid(arg1));
bellarda315a142005-01-30 22:59:18 +000011793#endif
11794#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +000011795 case TARGET_NR_setfsgid32:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011796 return get_errno(setfsgid(arg1));
bellarda315a142005-01-30 22:59:18 +000011797#endif
bellardffa65c32004-01-04 23:57:22 +000011798#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +000011799 case TARGET_NR_mincore:
aurel3204bb9ac2008-10-01 21:46:41 +000011800 {
Richard Henderson259841c2018-08-18 12:01:09 -070011801 void *a = lock_user(VERIFY_READ, arg1, arg2, 0);
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000011802 if (!a) {
Richard Henderson259841c2018-08-18 12:01:09 -070011803 return -TARGET_ENOMEM;
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000011804 }
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000011805 p = lock_user_string(arg3);
11806 if (!p) {
Richard Henderson259841c2018-08-18 12:01:09 -070011807 ret = -TARGET_EFAULT;
11808 } else {
11809 ret = get_errno(mincore(a, arg2, p));
11810 unlock_user(p, arg3, ret);
Franklin \"Snaipe\" Mathieu98a33312017-02-17 08:58:00 +000011811 }
aurel3204bb9ac2008-10-01 21:46:41 +000011812 unlock_user(a, arg1, 0);
11813 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011814 return ret;
bellardffa65c32004-01-04 23:57:22 +000011815#endif
aurel32408321b2008-10-01 21:46:32 +000011816#ifdef TARGET_NR_arm_fadvise64_64
11817 case TARGET_NR_arm_fadvise64_64:
Peter Maydelle0156a92016-05-31 15:45:09 +010011818 /* arm_fadvise64_64 looks like fadvise64_64 but
11819 * with different argument order: fd, advice, offset, len
11820 * rather than the usual fd, offset, len, advice.
11821 * Note that offset and len are both 64-bit so appear as
11822 * pairs of 32-bit registers.
11823 */
11824 ret = posix_fadvise(arg1, target_offset64(arg3, arg4),
11825 target_offset64(arg5, arg6), arg2);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011826 return -host_to_target_errno(ret);
aurel32408321b2008-10-01 21:46:32 +000011827#endif
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011828
WANG Xueruieeed2292022-10-06 16:55:00 +080011829#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011830
11831#ifdef TARGET_NR_fadvise64_64
11832 case TARGET_NR_fadvise64_64:
Max Filippov64a563d2018-04-01 15:02:34 -070011833#if defined(TARGET_PPC) || defined(TARGET_XTENSA)
Laurent Vivier43046b52017-03-02 01:11:45 +010011834 /* 6 args: fd, advice, offset (high, low), len (high, low) */
11835 ret = arg2;
11836 arg2 = arg3;
11837 arg3 = arg4;
11838 arg4 = arg5;
11839 arg5 = arg6;
11840 arg6 = ret;
11841#else
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011842 /* 6 args: fd, offset (high, low), len (high, low), advice */
James Clarke8bf8e9d2017-09-15 20:33:13 +010011843 if (regpairs_aligned(cpu_env, num)) {
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011844 /* offset is in (3,4), len in (5,6) and advice in 7 */
11845 arg2 = arg3;
11846 arg3 = arg4;
11847 arg4 = arg5;
11848 arg5 = arg6;
11849 arg6 = arg7;
11850 }
Laurent Vivier43046b52017-03-02 01:11:45 +010011851#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011852 ret = posix_fadvise(arg1, target_offset64(arg2, arg3),
11853 target_offset64(arg4, arg5), arg6);
11854 return -host_to_target_errno(ret);
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011855#endif
11856
11857#ifdef TARGET_NR_fadvise64
11858 case TARGET_NR_fadvise64:
11859 /* 5 args: fd, offset (high, low), len, advice */
James Clarke8bf8e9d2017-09-15 20:33:13 +010011860 if (regpairs_aligned(cpu_env, num)) {
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011861 /* offset is in (3,4), len in 5 and advice in 6 */
11862 arg2 = arg3;
11863 arg3 = arg4;
11864 arg4 = arg5;
11865 arg5 = arg6;
11866 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011867 ret = posix_fadvise(arg1, target_offset64(arg2, arg3), arg4, arg5);
11868 return -host_to_target_errno(ret);
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011869#endif
11870
11871#else /* not a 32-bit ABI */
Peter Maydelle0156a92016-05-31 15:45:09 +010011872#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_fadvise64)
aurel32408321b2008-10-01 21:46:32 +000011873#ifdef TARGET_NR_fadvise64_64
11874 case TARGET_NR_fadvise64_64:
11875#endif
Ulrich Hechte72d2cc2009-07-24 19:10:31 +020011876#ifdef TARGET_NR_fadvise64
11877 case TARGET_NR_fadvise64:
11878#endif
11879#ifdef TARGET_S390X
11880 switch (arg4) {
11881 case 4: arg4 = POSIX_FADV_NOREUSE + 1; break; /* make sure it's an invalid value */
11882 case 5: arg4 = POSIX_FADV_NOREUSE + 2; break; /* ditto */
11883 case 6: arg4 = POSIX_FADV_DONTNEED; break;
11884 case 7: arg4 = POSIX_FADV_NOREUSE; break;
11885 default: break;
11886 }
11887#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011888 return -host_to_target_errno(posix_fadvise(arg1, arg2, arg3, arg4));
aurel32408321b2008-10-01 21:46:32 +000011889#endif
Peter Maydellbadd3cd2016-05-31 15:45:10 +010011890#endif /* end of 64-bit ABI fadvise handling */
11891
bellardffa65c32004-01-04 23:57:22 +000011892#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +000011893 case TARGET_NR_madvise:
Ilya Leoshkevich892a4f62022-06-21 16:42:05 +020011894 return target_madvise(arg1, arg2, arg3);
bellardffa65c32004-01-04 23:57:22 +000011895#endif
Alex Bennéebbf5f2a2020-04-03 20:11:40 +010011896#ifdef TARGET_NR_fcntl64
bellard31e31b82003-02-18 22:55:36 +000011897 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +000011898 {
Alex Bennéebbf5f2a2020-04-03 20:11:40 +010011899 int cmd;
11900 struct flock64 fl;
Peter Maydell213d3e92016-06-13 11:22:05 +010011901 from_flock64_fn *copyfrom = copy_from_user_flock64;
11902 to_flock64_fn *copyto = copy_to_user_flock64;
11903
pbrookce4defa2006-02-09 16:49:55 +000011904#ifdef TARGET_ARM
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020011905 if (!cpu_env->eabi) {
Laurent Vivier7f254c52018-05-02 23:57:30 +020011906 copyfrom = copy_from_user_oabi_flock64;
11907 copyto = copy_to_user_oabi_flock64;
Peter Maydell213d3e92016-06-13 11:22:05 +010011908 }
pbrookce4defa2006-02-09 16:49:55 +000011909#endif
bellard77e46722003-04-29 20:39:06 +000011910
Alex Bennéebbf5f2a2020-04-03 20:11:40 +010011911 cmd = target_to_host_fcntl_cmd(arg2);
Peter Maydell31b63192011-12-05 23:11:50 +000011912 if (cmd == -TARGET_EINVAL) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011913 return cmd;
Peter Maydell31b63192011-12-05 23:11:50 +000011914 }
thsb1e341e2007-03-20 21:50:52 +000011915
bellard60cd49d2003-03-16 22:53:56 +000011916 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +000011917 case TARGET_F_GETLK64:
Peter Maydell213d3e92016-06-13 11:22:05 +010011918 ret = copyfrom(&fl, arg3);
11919 if (ret) {
11920 break;
ths58134272007-03-31 18:59:32 +000011921 }
Laurent Vivieraf8ab2b2018-07-13 14:58:05 +020011922 ret = get_errno(safe_fcntl(arg1, cmd, &fl));
Peter Maydell213d3e92016-06-13 11:22:05 +010011923 if (ret == 0) {
11924 ret = copyto(arg3, &fl);
11925 }
bellard77e46722003-04-29 20:39:06 +000011926 break;
11927
thsb1e341e2007-03-20 21:50:52 +000011928 case TARGET_F_SETLK64:
11929 case TARGET_F_SETLKW64:
Peter Maydell213d3e92016-06-13 11:22:05 +010011930 ret = copyfrom(&fl, arg3);
11931 if (ret) {
11932 break;
pbrookce4defa2006-02-09 16:49:55 +000011933 }
Peter Maydell435da5e2016-06-13 11:22:05 +010011934 ret = get_errno(safe_fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +000011935 break;
bellard60cd49d2003-03-16 22:53:56 +000011936 default:
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +020011937 ret = do_fcntl(arg1, arg2, arg3);
bellard60cd49d2003-03-16 22:53:56 +000011938 break;
11939 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011940 return ret;
bellard77e46722003-04-29 20:39:06 +000011941 }
bellard60cd49d2003-03-16 22:53:56 +000011942#endif
ths7d600c82006-12-08 01:32:58 +000011943#ifdef TARGET_NR_cacheflush
11944 case TARGET_NR_cacheflush:
11945 /* self-modifying code is handled automatically, so nothing needed */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011946 return 0;
ths7d600c82006-12-08 01:32:58 +000011947#endif
bellardc573ff62004-01-04 15:51:36 +000011948#ifdef TARGET_NR_getpagesize
11949 case TARGET_NR_getpagesize:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011950 return TARGET_PAGE_SIZE;
bellardc573ff62004-01-04 15:51:36 +000011951#endif
bellard31e31b82003-02-18 22:55:36 +000011952 case TARGET_NR_gettid:
Daniel P. Berrangé71ba74f2019-03-20 16:18:42 +000011953 return get_errno(sys_gettid());
thse5febef2007-04-01 18:31:35 +000011954#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +000011955 case TARGET_NR_readahead:
WANG Xueruieeed2292022-10-06 16:55:00 +080011956#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
James Clarke8bf8e9d2017-09-15 20:33:13 +010011957 if (regpairs_aligned(cpu_env, num)) {
aurel322054ac92008-10-13 21:08:07 +000011958 arg2 = arg3;
11959 arg3 = arg4;
11960 arg4 = arg5;
11961 }
Lena Djokic77c68502016-11-24 17:08:56 +010011962 ret = get_errno(readahead(arg1, target_offset64(arg2, arg3) , arg4));
aurel322054ac92008-10-13 21:08:07 +000011963#else
11964 ret = get_errno(readahead(arg1, arg2, arg3));
11965#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011966 return ret;
thse5febef2007-04-01 18:31:35 +000011967#endif
An-Cheng Huanga790ae32011-08-09 12:34:06 -070011968#ifdef CONFIG_ATTR
bellardebc05482003-09-30 21:08:41 +000011969#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +000011970 case TARGET_NR_listxattr:
11971 case TARGET_NR_llistxattr:
Peter Maydellfb5590f2011-12-14 15:37:19 +000011972 {
11973 void *p, *b = 0;
11974 if (arg2) {
11975 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
11976 if (!b) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011977 return -TARGET_EFAULT;
Peter Maydellfb5590f2011-12-14 15:37:19 +000011978 }
11979 }
11980 p = lock_user_string(arg1);
11981 if (p) {
11982 if (num == TARGET_NR_listxattr) {
11983 ret = get_errno(listxattr(p, b, arg3));
11984 } else {
11985 ret = get_errno(llistxattr(p, b, arg3));
11986 }
11987 } else {
11988 ret = -TARGET_EFAULT;
11989 }
11990 unlock_user(p, arg1, 0);
11991 unlock_user(b, arg2, arg3);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070011992 return ret;
Peter Maydellfb5590f2011-12-14 15:37:19 +000011993 }
11994 case TARGET_NR_flistxattr:
11995 {
11996 void *b = 0;
11997 if (arg2) {
11998 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
11999 if (!b) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012000 return -TARGET_EFAULT;
Peter Maydellfb5590f2011-12-14 15:37:19 +000012001 }
12002 }
12003 ret = get_errno(flistxattr(arg1, b, arg3));
12004 unlock_user(b, arg2, arg3);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012005 return ret;
Peter Maydellfb5590f2011-12-14 15:37:19 +000012006 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012007 case TARGET_NR_setxattr:
Peter Maydell30297b52011-12-14 15:37:18 +000012008 case TARGET_NR_lsetxattr:
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012009 {
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012010 void *p, *n, *v = 0;
12011 if (arg3) {
12012 v = lock_user(VERIFY_READ, arg3, arg4, 1);
12013 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012014 return -TARGET_EFAULT;
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012015 }
12016 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012017 p = lock_user_string(arg1);
12018 n = lock_user_string(arg2);
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012019 if (p && n) {
Peter Maydell30297b52011-12-14 15:37:18 +000012020 if (num == TARGET_NR_setxattr) {
12021 ret = get_errno(setxattr(p, n, v, arg4, arg5));
12022 } else {
12023 ret = get_errno(lsetxattr(p, n, v, arg4, arg5));
12024 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012025 } else {
12026 ret = -TARGET_EFAULT;
12027 }
12028 unlock_user(p, arg1, 0);
12029 unlock_user(n, arg2, 0);
12030 unlock_user(v, arg3, 0);
12031 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012032 return ret;
Peter Maydell30297b52011-12-14 15:37:18 +000012033 case TARGET_NR_fsetxattr:
12034 {
12035 void *n, *v = 0;
12036 if (arg3) {
12037 v = lock_user(VERIFY_READ, arg3, arg4, 1);
12038 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012039 return -TARGET_EFAULT;
Peter Maydell30297b52011-12-14 15:37:18 +000012040 }
12041 }
12042 n = lock_user_string(arg2);
12043 if (n) {
12044 ret = get_errno(fsetxattr(arg1, n, v, arg4, arg5));
12045 } else {
12046 ret = -TARGET_EFAULT;
12047 }
12048 unlock_user(n, arg2, 0);
12049 unlock_user(v, arg3, 0);
12050 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012051 return ret;
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012052 case TARGET_NR_getxattr:
Peter Maydell30297b52011-12-14 15:37:18 +000012053 case TARGET_NR_lgetxattr:
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012054 {
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012055 void *p, *n, *v = 0;
12056 if (arg3) {
12057 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
12058 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012059 return -TARGET_EFAULT;
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012060 }
12061 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012062 p = lock_user_string(arg1);
12063 n = lock_user_string(arg2);
Peter Maydelle3c33ec2011-12-14 15:37:17 +000012064 if (p && n) {
Peter Maydell30297b52011-12-14 15:37:18 +000012065 if (num == TARGET_NR_getxattr) {
12066 ret = get_errno(getxattr(p, n, v, arg4));
12067 } else {
12068 ret = get_errno(lgetxattr(p, n, v, arg4));
12069 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012070 } else {
12071 ret = -TARGET_EFAULT;
12072 }
12073 unlock_user(p, arg1, 0);
12074 unlock_user(n, arg2, 0);
12075 unlock_user(v, arg3, arg4);
12076 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012077 return ret;
Peter Maydell30297b52011-12-14 15:37:18 +000012078 case TARGET_NR_fgetxattr:
12079 {
12080 void *n, *v = 0;
12081 if (arg3) {
12082 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
12083 if (!v) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012084 return -TARGET_EFAULT;
Peter Maydell30297b52011-12-14 15:37:18 +000012085 }
12086 }
12087 n = lock_user_string(arg2);
12088 if (n) {
12089 ret = get_errno(fgetxattr(arg1, n, v, arg4));
12090 } else {
12091 ret = -TARGET_EFAULT;
12092 }
12093 unlock_user(n, arg2, 0);
12094 unlock_user(v, arg3, arg4);
12095 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012096 return ret;
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012097 case TARGET_NR_removexattr:
Peter Maydell30297b52011-12-14 15:37:18 +000012098 case TARGET_NR_lremovexattr:
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012099 {
12100 void *p, *n;
12101 p = lock_user_string(arg1);
12102 n = lock_user_string(arg2);
12103 if (p && n) {
Peter Maydell30297b52011-12-14 15:37:18 +000012104 if (num == TARGET_NR_removexattr) {
12105 ret = get_errno(removexattr(p, n));
12106 } else {
12107 ret = get_errno(lremovexattr(p, n));
12108 }
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012109 } else {
12110 ret = -TARGET_EFAULT;
12111 }
12112 unlock_user(p, arg1, 0);
12113 unlock_user(n, arg2, 0);
12114 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012115 return ret;
Peter Maydell30297b52011-12-14 15:37:18 +000012116 case TARGET_NR_fremovexattr:
12117 {
12118 void *n;
12119 n = lock_user_string(arg2);
12120 if (n) {
12121 ret = get_errno(fremovexattr(arg1, n));
12122 } else {
12123 ret = -TARGET_EFAULT;
12124 }
12125 unlock_user(n, arg2, 0);
12126 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012127 return ret;
bellardebc05482003-09-30 21:08:41 +000012128#endif
An-Cheng Huanga790ae32011-08-09 12:34:06 -070012129#endif /* CONFIG_ATTR */
bellardebc05482003-09-30 21:08:41 +000012130#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +000012131 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +000012132#if defined(TARGET_MIPS)
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020012133 cpu_env->active_tc.CP0_UserLocal = arg1;
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012134 return 0;
edgar_iglef967792009-01-07 14:19:38 +000012135#elif defined(TARGET_CRIS)
12136 if (arg1 & 0xff)
12137 ret = -TARGET_EINVAL;
12138 else {
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020012139 cpu_env->pregs[PR_PID] = arg1;
edgar_iglef967792009-01-07 14:19:38 +000012140 ret = 0;
12141 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012142 return ret;
bellard8d18e892007-11-14 15:18:40 +000012143#elif defined(TARGET_I386) && defined(TARGET_ABI32)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012144 return do_set_thread_area(cpu_env, arg1);
Peter Maydell1ccd9372013-07-16 18:44:55 +010012145#elif defined(TARGET_M68K)
12146 {
Andreas Färber0429a972013-08-26 18:14:44 +020012147 TaskState *ts = cpu->opaque;
Peter Maydell1ccd9372013-07-16 18:44:55 +010012148 ts->tp_value = arg1;
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012149 return 0;
Peter Maydell1ccd9372013-07-16 18:44:55 +010012150 }
ths6f5b89a2007-03-02 20:48:00 +000012151#else
Richard Henderson10f45d92018-08-18 12:01:07 -070012152 return -TARGET_ENOSYS;
ths6f5b89a2007-03-02 20:48:00 +000012153#endif
12154#endif
12155#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +000012156 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +000012157#if defined(TARGET_I386) && defined(TARGET_ABI32)
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012158 return do_get_thread_area(cpu_env, arg1);
Peter Maydell1ccd9372013-07-16 18:44:55 +010012159#elif defined(TARGET_M68K)
12160 {
Andreas Färber0429a972013-08-26 18:14:44 +020012161 TaskState *ts = cpu->opaque;
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012162 return ts->tp_value;
Peter Maydell1ccd9372013-07-16 18:44:55 +010012163 }
bellard8d18e892007-11-14 15:18:40 +000012164#else
Richard Henderson10f45d92018-08-18 12:01:07 -070012165 return -TARGET_ENOSYS;
bellardebc05482003-09-30 21:08:41 +000012166#endif
bellard8d18e892007-11-14 15:18:40 +000012167#endif
bellard48dc41e2006-06-21 18:15:50 +000012168#ifdef TARGET_NR_getdomainname
12169 case TARGET_NR_getdomainname:
Richard Henderson10f45d92018-08-18 12:01:07 -070012170 return -TARGET_ENOSYS;
bellard48dc41e2006-06-21 18:15:50 +000012171#endif
ths6f5b89a2007-03-02 20:48:00 +000012172
Max Filippov12e33402018-04-01 13:13:49 -070012173#ifdef TARGET_NR_clock_settime
12174 case TARGET_NR_clock_settime:
12175 {
12176 struct timespec ts;
12177
12178 ret = target_to_host_timespec(&ts, arg2);
12179 if (!is_error(ret)) {
12180 ret = get_errno(clock_settime(arg1, &ts));
12181 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012182 return ret;
Max Filippov12e33402018-04-01 13:13:49 -070012183 }
12184#endif
Alistair Francisc6c8d102020-03-12 15:13:53 -070012185#ifdef TARGET_NR_clock_settime64
12186 case TARGET_NR_clock_settime64:
12187 {
12188 struct timespec ts;
12189
12190 ret = target_to_host_timespec64(&ts, arg2);
12191 if (!is_error(ret)) {
12192 ret = get_errno(clock_settime(arg1, &ts));
12193 }
12194 return ret;
12195 }
12196#endif
thsb5906f92007-03-19 13:32:45 +000012197#ifdef TARGET_NR_clock_gettime
12198 case TARGET_NR_clock_gettime:
12199 {
12200 struct timespec ts;
12201 ret = get_errno(clock_gettime(arg1, &ts));
12202 if (!is_error(ret)) {
Max Filippovb9f99082018-04-01 13:14:04 -070012203 ret = host_to_target_timespec(arg2, &ts);
thsb5906f92007-03-19 13:32:45 +000012204 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012205 return ret;
thsb5906f92007-03-19 13:32:45 +000012206 }
12207#endif
Alistair Francisc6c8d102020-03-12 15:13:53 -070012208#ifdef TARGET_NR_clock_gettime64
12209 case TARGET_NR_clock_gettime64:
12210 {
12211 struct timespec ts;
12212 ret = get_errno(clock_gettime(arg1, &ts));
12213 if (!is_error(ret)) {
12214 ret = host_to_target_timespec64(arg2, &ts);
12215 }
12216 return ret;
12217 }
12218#endif
thsb5906f92007-03-19 13:32:45 +000012219#ifdef TARGET_NR_clock_getres
12220 case TARGET_NR_clock_getres:
12221 {
12222 struct timespec ts;
12223 ret = get_errno(clock_getres(arg1, &ts));
12224 if (!is_error(ret)) {
12225 host_to_target_timespec(arg2, &ts);
12226 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012227 return ret;
thsb5906f92007-03-19 13:32:45 +000012228 }
12229#endif
Filip Bozuta828cb3a2020-07-22 17:34:21 +020012230#ifdef TARGET_NR_clock_getres_time64
12231 case TARGET_NR_clock_getres_time64:
12232 {
12233 struct timespec ts;
12234 ret = get_errno(clock_getres(arg1, &ts));
12235 if (!is_error(ret)) {
12236 host_to_target_timespec64(arg2, &ts);
12237 }
12238 return ret;
12239 }
12240#endif
pbrook63d76512008-05-29 13:43:29 +000012241#ifdef TARGET_NR_clock_nanosleep
12242 case TARGET_NR_clock_nanosleep:
12243 {
12244 struct timespec ts;
Filip Bozutab09d6402020-07-27 22:13:26 +020012245 if (target_to_host_timespec(&ts, arg3)) {
12246 return -TARGET_EFAULT;
12247 }
Peter Maydell9e518222016-06-06 19:58:09 +010012248 ret = get_errno(safe_clock_nanosleep(arg1, arg2,
12249 &ts, arg4 ? &ts : NULL));
Laurent Vivier8ec68a02020-07-24 07:45:05 +010012250 /*
12251 * if the call is interrupted by a signal handler, it fails
12252 * with error -TARGET_EINTR and if arg4 is not NULL and arg2 is not
12253 * TIMER_ABSTIME, it returns the remaining unslept time in arg4.
12254 */
Filip Bozutab09d6402020-07-27 22:13:26 +020012255 if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME &&
12256 host_to_target_timespec(arg4, &ts)) {
12257 return -TARGET_EFAULT;
Laurent Vivier8ec68a02020-07-24 07:45:05 +010012258 }
Tom Musta8fbe8fd2014-08-12 13:53:41 -050012259
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012260 return ret;
pbrook63d76512008-05-29 13:43:29 +000012261 }
12262#endif
Filip Bozuta6ac03b22020-08-24 21:21:15 +020012263#ifdef TARGET_NR_clock_nanosleep_time64
12264 case TARGET_NR_clock_nanosleep_time64:
12265 {
12266 struct timespec ts;
12267
12268 if (target_to_host_timespec64(&ts, arg3)) {
12269 return -TARGET_EFAULT;
12270 }
12271
12272 ret = get_errno(safe_clock_nanosleep(arg1, arg2,
12273 &ts, arg4 ? &ts : NULL));
12274
12275 if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME &&
12276 host_to_target_timespec64(arg4, &ts)) {
12277 return -TARGET_EFAULT;
12278 }
12279 return ret;
12280 }
12281#endif
thsb5906f92007-03-19 13:32:45 +000012282
Helge Deller9a7f6822022-05-28 12:52:10 +020012283#if defined(TARGET_NR_set_tid_address)
ths6f5b89a2007-03-02 20:48:00 +000012284 case TARGET_NR_set_tid_address:
Helge Deller9a7f6822022-05-28 12:52:10 +020012285 {
12286 TaskState *ts = cpu->opaque;
12287 ts->child_tidptr = arg1;
12288 /* do not call host set_tid_address() syscall, instead return tid() */
12289 return get_errno(sys_gettid());
12290 }
ths6f5b89a2007-03-02 20:48:00 +000012291#endif
12292
ths4cae1d12007-07-12 11:06:53 +000012293 case TARGET_NR_tkill:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012294 return get_errno(safe_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +000012295
ths71455572007-06-21 21:45:30 +000012296 case TARGET_NR_tgkill:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012297 return get_errno(safe_tgkill((int)arg1, (int)arg2,
12298 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +000012299
ths4f2b1fe2007-06-21 21:57:12 +000012300#ifdef TARGET_NR_set_robust_list
12301 case TARGET_NR_set_robust_list:
Peter Maydelle9a970a2013-02-08 04:34:54 +000012302 case TARGET_NR_get_robust_list:
12303 /* The ABI for supporting robust futexes has userspace pass
12304 * the kernel a pointer to a linked list which is updated by
12305 * userspace after the syscall; the list is walked by the kernel
12306 * when the thread exits. Since the linked list in QEMU guest
12307 * memory isn't a valid linked list for the host and we have
12308 * no way to reliably intercept the thread-death event, we can't
12309 * support these. Silently return ENOSYS so that guest userspace
12310 * falls back to a non-robust futex implementation (which should
12311 * be OK except in the corner case of the guest crashing while
12312 * holding a mutex that is shared with another process via
12313 * shared memory).
12314 */
Richard Henderson10f45d92018-08-18 12:01:07 -070012315 return -TARGET_ENOSYS;
ths4f2b1fe2007-06-21 21:57:12 +000012316#endif
12317
Peter Maydell1acae9f2013-07-02 14:04:12 +010012318#if defined(TARGET_NR_utimensat)
ths9007f0e2007-09-25 17:50:37 +000012319 case TARGET_NR_utimensat:
12320 {
Riku Voipioebc996f2009-04-21 15:01:51 +030012321 struct timespec *tsp, ts[2];
12322 if (!arg3) {
12323 tsp = NULL;
12324 } else {
Filip Bozutab3a3af72020-08-11 13:31:01 +020012325 if (target_to_host_timespec(ts, arg3)) {
12326 return -TARGET_EFAULT;
12327 }
12328 if (target_to_host_timespec(ts + 1, arg3 +
12329 sizeof(struct target_timespec))) {
12330 return -TARGET_EFAULT;
12331 }
Riku Voipioebc996f2009-04-21 15:01:51 +030012332 tsp = ts;
12333 }
ths9007f0e2007-09-25 17:50:37 +000012334 if (!arg2)
Riku Voipioebc996f2009-04-21 15:01:51 +030012335 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
ths9007f0e2007-09-25 17:50:37 +000012336 else {
bellard579a97f2007-11-11 14:26:47 +000012337 if (!(p = lock_user_string(arg2))) {
Richard Henderson259841c2018-08-18 12:01:09 -070012338 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +000012339 }
Riku Voipioebc996f2009-04-21 15:01:51 +030012340 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
bellard579a97f2007-11-11 14:26:47 +000012341 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +000012342 }
12343 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012344 return ret;
ths9007f0e2007-09-25 17:50:37 +000012345#endif
Filip Bozutacac46eb2020-08-25 00:30:50 +020012346#ifdef TARGET_NR_utimensat_time64
12347 case TARGET_NR_utimensat_time64:
12348 {
12349 struct timespec *tsp, ts[2];
12350 if (!arg3) {
12351 tsp = NULL;
12352 } else {
12353 if (target_to_host_timespec64(ts, arg3)) {
12354 return -TARGET_EFAULT;
12355 }
12356 if (target_to_host_timespec64(ts + 1, arg3 +
12357 sizeof(struct target__kernel_timespec))) {
12358 return -TARGET_EFAULT;
12359 }
12360 tsp = ts;
12361 }
12362 if (!arg2)
12363 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
12364 else {
12365 p = lock_user_string(arg2);
12366 if (!p) {
12367 return -TARGET_EFAULT;
12368 }
12369 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
12370 unlock_user(p, arg2, 0);
12371 }
12372 }
12373 return ret;
12374#endif
Alistair Francis859e8a82020-03-12 15:13:49 -070012375#ifdef TARGET_NR_futex
pbrookbd0c5662008-05-29 14:34:11 +000012376 case TARGET_NR_futex:
Richard Henderson0fbc0f82022-08-28 19:09:59 -070012377 return do_futex(cpu, false, arg1, arg2, arg3, arg4, arg5, arg6);
Alistair Francis859e8a82020-03-12 15:13:49 -070012378#endif
Alistair Francis14690292020-03-18 15:47:01 -070012379#ifdef TARGET_NR_futex_time64
12380 case TARGET_NR_futex_time64:
Richard Henderson0fbc0f82022-08-28 19:09:59 -070012381 return do_futex(cpu, true, arg1, arg2, arg3, arg4, arg5, arg6);
Alistair Francis14690292020-03-18 15:47:01 -070012382#endif
Paul Brook33f53ac2022-01-26 20:26:36 +000012383#ifdef CONFIG_INOTIFY
12384#if defined(TARGET_NR_inotify_init)
aurel3239b59762008-10-01 21:46:50 +000012385 case TARGET_NR_inotify_init:
Paul Brook33f53ac2022-01-26 20:26:36 +000012386 ret = get_errno(inotify_init());
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030012387 if (ret >= 0) {
12388 fd_trans_register(ret, &target_inotify_trans);
12389 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012390 return ret;
aurel3239b59762008-10-01 21:46:50 +000012391#endif
Paul Brook33f53ac2022-01-26 20:26:36 +000012392#if defined(TARGET_NR_inotify_init1) && defined(CONFIG_INOTIFY1)
Riku Voipioc05c7a72010-03-26 15:25:11 +000012393 case TARGET_NR_inotify_init1:
Paul Brook33f53ac2022-01-26 20:26:36 +000012394 ret = get_errno(inotify_init1(target_to_host_bitmask(arg1,
Lena Djokicfea243e2016-11-24 17:08:53 +010012395 fcntl_flags_tbl)));
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030012396 if (ret >= 0) {
12397 fd_trans_register(ret, &target_inotify_trans);
12398 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012399 return ret;
Riku Voipioc05c7a72010-03-26 15:25:11 +000012400#endif
Paul Brook33f53ac2022-01-26 20:26:36 +000012401#if defined(TARGET_NR_inotify_add_watch)
aurel3239b59762008-10-01 21:46:50 +000012402 case TARGET_NR_inotify_add_watch:
12403 p = lock_user_string(arg2);
Paul Brook33f53ac2022-01-26 20:26:36 +000012404 ret = get_errno(inotify_add_watch(arg1, path(p), arg3));
aurel3239b59762008-10-01 21:46:50 +000012405 unlock_user(p, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012406 return ret;
aurel3239b59762008-10-01 21:46:50 +000012407#endif
Paul Brook33f53ac2022-01-26 20:26:36 +000012408#if defined(TARGET_NR_inotify_rm_watch)
aurel3239b59762008-10-01 21:46:50 +000012409 case TARGET_NR_inotify_rm_watch:
Paul Brook33f53ac2022-01-26 20:26:36 +000012410 return get_errno(inotify_rm_watch(arg1, arg2));
12411#endif
aurel3239b59762008-10-01 21:46:50 +000012412#endif
ths9007f0e2007-09-25 17:50:37 +000012413
Nathan Froyd8ec9cf82009-07-22 09:14:36 -070012414#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
aurel3224e10032009-04-15 16:11:43 +000012415 case TARGET_NR_mq_open:
12416 {
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020012417 struct mq_attr posix_mq_attr;
Lena Djokic26400772016-11-24 17:08:58 +010012418 struct mq_attr *pposix_mq_attr;
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020012419 int host_flags;
aurel3224e10032009-04-15 16:11:43 +000012420
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020012421 host_flags = target_to_host_bitmask(arg2, fcntl_flags_tbl);
Lena Djokic26400772016-11-24 17:08:58 +010012422 pposix_mq_attr = NULL;
12423 if (arg4) {
12424 if (copy_from_user_mq_attr(&posix_mq_attr, arg4) != 0) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012425 return -TARGET_EFAULT;
Lena Djokic26400772016-11-24 17:08:58 +010012426 }
12427 pposix_mq_attr = &posix_mq_attr;
Tom Mustab6ce1f62014-08-12 13:53:36 -050012428 }
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020012429 p = lock_user_string(arg1 - 1);
12430 if (!p) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012431 return -TARGET_EFAULT;
Aleksandar Markovicc7536ab2016-09-22 18:56:55 +020012432 }
Lena Djokic26400772016-11-24 17:08:58 +010012433 ret = get_errno(mq_open(p, host_flags, arg3, pposix_mq_attr));
aurel3224e10032009-04-15 16:11:43 +000012434 unlock_user (p, arg1, 0);
12435 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012436 return ret;
aurel3224e10032009-04-15 16:11:43 +000012437
12438 case TARGET_NR_mq_unlink:
12439 p = lock_user_string(arg1 - 1);
Peter Maydell32112152016-07-12 13:02:13 +010012440 if (!p) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012441 return -TARGET_EFAULT;
Peter Maydell32112152016-07-12 13:02:13 +010012442 }
aurel3224e10032009-04-15 16:11:43 +000012443 ret = get_errno(mq_unlink(p));
12444 unlock_user (p, arg1, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012445 return ret;
aurel3224e10032009-04-15 16:11:43 +000012446
Alistair Francis859e8a82020-03-12 15:13:49 -070012447#ifdef TARGET_NR_mq_timedsend
aurel3224e10032009-04-15 16:11:43 +000012448 case TARGET_NR_mq_timedsend:
12449 {
12450 struct timespec ts;
12451
12452 p = lock_user (VERIFY_READ, arg2, arg3, 1);
12453 if (arg5 != 0) {
Filip Bozutadcbcf5c2020-08-24 21:37:51 +020012454 if (target_to_host_timespec(&ts, arg5)) {
12455 return -TARGET_EFAULT;
12456 }
Peter Maydelld40ecd62016-06-06 19:58:06 +010012457 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts));
Filip Bozutadcbcf5c2020-08-24 21:37:51 +020012458 if (!is_error(ret) && host_to_target_timespec(arg5, &ts)) {
12459 return -TARGET_EFAULT;
12460 }
Peter Maydelld40ecd62016-06-06 19:58:06 +010012461 } else {
12462 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL));
aurel3224e10032009-04-15 16:11:43 +000012463 }
aurel3224e10032009-04-15 16:11:43 +000012464 unlock_user (p, arg2, arg3);
12465 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012466 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070012467#endif
Filip Bozutad107e372020-08-24 21:37:52 +020012468#ifdef TARGET_NR_mq_timedsend_time64
12469 case TARGET_NR_mq_timedsend_time64:
12470 {
12471 struct timespec ts;
12472
12473 p = lock_user(VERIFY_READ, arg2, arg3, 1);
12474 if (arg5 != 0) {
12475 if (target_to_host_timespec64(&ts, arg5)) {
12476 return -TARGET_EFAULT;
12477 }
12478 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts));
12479 if (!is_error(ret) && host_to_target_timespec64(arg5, &ts)) {
12480 return -TARGET_EFAULT;
12481 }
12482 } else {
12483 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL));
12484 }
12485 unlock_user(p, arg2, arg3);
12486 }
12487 return ret;
12488#endif
aurel3224e10032009-04-15 16:11:43 +000012489
Alistair Francis859e8a82020-03-12 15:13:49 -070012490#ifdef TARGET_NR_mq_timedreceive
aurel3224e10032009-04-15 16:11:43 +000012491 case TARGET_NR_mq_timedreceive:
12492 {
12493 struct timespec ts;
12494 unsigned int prio;
12495
12496 p = lock_user (VERIFY_READ, arg2, arg3, 1);
12497 if (arg5 != 0) {
Filip Bozutadcbcf5c2020-08-24 21:37:51 +020012498 if (target_to_host_timespec(&ts, arg5)) {
12499 return -TARGET_EFAULT;
12500 }
Peter Maydelld40ecd62016-06-06 19:58:06 +010012501 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12502 &prio, &ts));
Filip Bozutadcbcf5c2020-08-24 21:37:51 +020012503 if (!is_error(ret) && host_to_target_timespec(arg5, &ts)) {
12504 return -TARGET_EFAULT;
12505 }
Peter Maydelld40ecd62016-06-06 19:58:06 +010012506 } else {
12507 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12508 &prio, NULL));
aurel3224e10032009-04-15 16:11:43 +000012509 }
aurel3224e10032009-04-15 16:11:43 +000012510 unlock_user (p, arg2, arg3);
12511 if (arg4 != 0)
12512 put_user_u32(prio, arg4);
12513 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012514 return ret;
Alistair Francis859e8a82020-03-12 15:13:49 -070012515#endif
Filip Bozutad107e372020-08-24 21:37:52 +020012516#ifdef TARGET_NR_mq_timedreceive_time64
12517 case TARGET_NR_mq_timedreceive_time64:
12518 {
12519 struct timespec ts;
12520 unsigned int prio;
12521
12522 p = lock_user(VERIFY_READ, arg2, arg3, 1);
12523 if (arg5 != 0) {
12524 if (target_to_host_timespec64(&ts, arg5)) {
12525 return -TARGET_EFAULT;
12526 }
12527 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12528 &prio, &ts));
12529 if (!is_error(ret) && host_to_target_timespec64(arg5, &ts)) {
12530 return -TARGET_EFAULT;
12531 }
12532 } else {
12533 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12534 &prio, NULL));
12535 }
12536 unlock_user(p, arg2, arg3);
12537 if (arg4 != 0) {
12538 put_user_u32(prio, arg4);
12539 }
12540 }
12541 return ret;
12542#endif
aurel3224e10032009-04-15 16:11:43 +000012543
12544 /* Not implemented for now... */
12545/* case TARGET_NR_mq_notify: */
12546/* break; */
12547
12548 case TARGET_NR_mq_getsetattr:
12549 {
12550 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
12551 ret = 0;
aurel3224e10032009-04-15 16:11:43 +000012552 if (arg2 != 0) {
12553 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
Max Filippova23ea402018-03-31 08:20:15 -070012554 ret = get_errno(mq_setattr(arg1, &posix_mq_attr_in,
12555 &posix_mq_attr_out));
12556 } else if (arg3 != 0) {
12557 ret = get_errno(mq_getattr(arg1, &posix_mq_attr_out));
aurel3224e10032009-04-15 16:11:43 +000012558 }
Max Filippova23ea402018-03-31 08:20:15 -070012559 if (ret == 0 && arg3 != 0) {
12560 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
12561 }
aurel3224e10032009-04-15 16:11:43 +000012562 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012563 return ret;
aurel3224e10032009-04-15 16:11:43 +000012564#endif
12565
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012566#ifdef CONFIG_SPLICE
12567#ifdef TARGET_NR_tee
12568 case TARGET_NR_tee:
12569 {
12570 ret = get_errno(tee(arg1,arg2,arg3,arg4));
12571 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012572 return ret;
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012573#endif
12574#ifdef TARGET_NR_splice
12575 case TARGET_NR_splice:
12576 {
12577 loff_t loff_in, loff_out;
12578 loff_t *ploff_in = NULL, *ploff_out = NULL;
Andreas Schwab17644b32015-03-10 17:11:35 +010012579 if (arg2) {
12580 if (get_user_u64(loff_in, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012581 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010012582 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012583 ploff_in = &loff_in;
12584 }
Andreas Schwab17644b32015-03-10 17:11:35 +010012585 if (arg4) {
12586 if (get_user_u64(loff_out, arg4)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012587 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010012588 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012589 ploff_out = &loff_out;
12590 }
12591 ret = get_errno(splice(arg1, ploff_in, arg3, ploff_out, arg5, arg6));
Andreas Schwab17644b32015-03-10 17:11:35 +010012592 if (arg2) {
12593 if (put_user_u64(loff_in, arg2)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012594 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010012595 }
12596 }
12597 if (arg4) {
12598 if (put_user_u64(loff_out, arg4)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012599 return -TARGET_EFAULT;
Andreas Schwab17644b32015-03-10 17:11:35 +010012600 }
12601 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012602 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012603 return ret;
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012604#endif
12605#ifdef TARGET_NR_vmsplice
12606 case TARGET_NR_vmsplice:
12607 {
Richard Hendersonf287b2c2012-09-15 13:20:25 -070012608 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
12609 if (vec != NULL) {
12610 ret = get_errno(vmsplice(arg1, vec, arg3, arg4));
12611 unlock_iovec(vec, arg2, arg3, 0);
12612 } else {
12613 ret = -host_to_target_errno(errno);
12614 }
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012615 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012616 return ret;
vibisreenivasan3ce34df2009-05-16 18:32:41 +053012617#endif
12618#endif /* CONFIG_SPLICE */
Riku Voipioc2882b92009-08-12 15:08:24 +030012619#ifdef CONFIG_EVENTFD
12620#if defined(TARGET_NR_eventfd)
12621 case TARGET_NR_eventfd:
12622 ret = get_errno(eventfd(arg1, 0));
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030012623 if (ret >= 0) {
12624 fd_trans_register(ret, &target_eventfd_trans);
12625 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012626 return ret;
Riku Voipioc2882b92009-08-12 15:08:24 +030012627#endif
12628#if defined(TARGET_NR_eventfd2)
12629 case TARGET_NR_eventfd2:
Petar Jovanovic5947c692013-04-08 20:26:10 +020012630 {
Helge Deller78721302021-02-10 07:12:14 +010012631 int host_flags = arg2 & (~(TARGET_O_NONBLOCK_MASK | TARGET_O_CLOEXEC));
Petar Jovanovic5947c692013-04-08 20:26:10 +020012632 if (arg2 & TARGET_O_NONBLOCK) {
12633 host_flags |= O_NONBLOCK;
12634 }
12635 if (arg2 & TARGET_O_CLOEXEC) {
12636 host_flags |= O_CLOEXEC;
12637 }
12638 ret = get_errno(eventfd(arg1, host_flags));
Philippe Mathieu-Daudéb929f7e2017-07-26 23:42:19 -030012639 if (ret >= 0) {
12640 fd_trans_register(ret, &target_eventfd_trans);
12641 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012642 return ret;
Petar Jovanovic5947c692013-04-08 20:26:10 +020012643 }
Riku Voipioc2882b92009-08-12 15:08:24 +030012644#endif
12645#endif /* CONFIG_EVENTFD */
Ulrich Hechtd0927932009-09-17 20:22:14 +030012646#if defined(CONFIG_FALLOCATE) && defined(TARGET_NR_fallocate)
12647 case TARGET_NR_fallocate:
WANG Xueruieeed2292022-10-06 16:55:00 +080012648#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
Alexander Graf20249ae2012-02-06 21:37:07 +010012649 ret = get_errno(fallocate(arg1, arg2, target_offset64(arg3, arg4),
12650 target_offset64(arg5, arg6)));
12651#else
Ulrich Hechtd0927932009-09-17 20:22:14 +030012652 ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
Alexander Graf20249ae2012-02-06 21:37:07 +010012653#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012654 return ret;
Ulrich Hechtd0927932009-09-17 20:22:14 +030012655#endif
Peter Maydellc727f472011-01-06 11:05:10 +000012656#if defined(CONFIG_SYNC_FILE_RANGE)
12657#if defined(TARGET_NR_sync_file_range)
12658 case TARGET_NR_sync_file_range:
WANG Xueruieeed2292022-10-06 16:55:00 +080012659#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
Riku Voipiobfcedc52011-06-20 16:24:39 +030012660#if defined(TARGET_MIPS)
12661 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
12662 target_offset64(arg5, arg6), arg7));
12663#else
Peter Maydellc727f472011-01-06 11:05:10 +000012664 ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3),
12665 target_offset64(arg4, arg5), arg6));
Riku Voipiobfcedc52011-06-20 16:24:39 +030012666#endif /* !TARGET_MIPS */
Peter Maydellc727f472011-01-06 11:05:10 +000012667#else
12668 ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4));
12669#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012670 return ret;
Peter Maydellc727f472011-01-06 11:05:10 +000012671#endif
Laurent Vivier5bcb4982020-03-10 11:33:50 +010012672#if defined(TARGET_NR_sync_file_range2) || \
12673 defined(TARGET_NR_arm_sync_file_range)
Peter Maydellc727f472011-01-06 11:05:10 +000012674#if defined(TARGET_NR_sync_file_range2)
12675 case TARGET_NR_sync_file_range2:
Laurent Vivier5bcb4982020-03-10 11:33:50 +010012676#endif
12677#if defined(TARGET_NR_arm_sync_file_range)
12678 case TARGET_NR_arm_sync_file_range:
12679#endif
Peter Maydellc727f472011-01-06 11:05:10 +000012680 /* This is like sync_file_range but the arguments are reordered */
WANG Xueruieeed2292022-10-06 16:55:00 +080012681#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
Peter Maydellc727f472011-01-06 11:05:10 +000012682 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
12683 target_offset64(arg5, arg6), arg2));
12684#else
12685 ret = get_errno(sync_file_range(arg1, arg3, arg4, arg2));
12686#endif
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012687 return ret;
Peter Maydellc727f472011-01-06 11:05:10 +000012688#endif
12689#endif
Laurent Viviere36800c2015-10-02 14:48:09 +020012690#if defined(TARGET_NR_signalfd4)
12691 case TARGET_NR_signalfd4:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012692 return do_signalfd4(arg1, arg2, arg4);
Laurent Viviere36800c2015-10-02 14:48:09 +020012693#endif
12694#if defined(TARGET_NR_signalfd)
12695 case TARGET_NR_signalfd:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012696 return do_signalfd4(arg1, arg2, 0);
Laurent Viviere36800c2015-10-02 14:48:09 +020012697#endif
Peter Maydell3b6edd12011-02-15 18:35:05 +000012698#if defined(CONFIG_EPOLL)
12699#if defined(TARGET_NR_epoll_create)
12700 case TARGET_NR_epoll_create:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012701 return get_errno(epoll_create(arg1));
Peter Maydell3b6edd12011-02-15 18:35:05 +000012702#endif
12703#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1)
12704 case TARGET_NR_epoll_create1:
Sergei Trofimovich386d3862020-04-15 23:05:08 +010012705 return get_errno(epoll_create1(target_to_host_bitmask(arg1, fcntl_flags_tbl)));
Peter Maydell3b6edd12011-02-15 18:35:05 +000012706#endif
12707#if defined(TARGET_NR_epoll_ctl)
12708 case TARGET_NR_epoll_ctl:
12709 {
12710 struct epoll_event ep;
12711 struct epoll_event *epp = 0;
12712 if (arg4) {
LemonBoyc7811022020-04-17 17:34:54 +020012713 if (arg2 != EPOLL_CTL_DEL) {
12714 struct target_epoll_event *target_ep;
12715 if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) {
12716 return -TARGET_EFAULT;
12717 }
12718 ep.events = tswap32(target_ep->events);
12719 /*
12720 * The epoll_data_t union is just opaque data to the kernel,
12721 * so we transfer all 64 bits across and need not worry what
12722 * actual data type it is.
12723 */
12724 ep.data.u64 = tswap64(target_ep->data.u64);
12725 unlock_user_struct(target_ep, arg4, 0);
Peter Maydell3b6edd12011-02-15 18:35:05 +000012726 }
LemonBoyc7811022020-04-17 17:34:54 +020012727 /*
12728 * before kernel 2.6.9, EPOLL_CTL_DEL operation required a
12729 * non-null pointer, even though this argument is ignored.
12730 *
Peter Maydell3b6edd12011-02-15 18:35:05 +000012731 */
Peter Maydell3b6edd12011-02-15 18:35:05 +000012732 epp = &ep;
12733 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012734 return get_errno(epoll_ctl(arg1, arg2, arg3, epp));
Peter Maydell3b6edd12011-02-15 18:35:05 +000012735 }
12736#endif
12737
Peter Maydell227f0212016-06-06 19:58:11 +010012738#if defined(TARGET_NR_epoll_wait) || defined(TARGET_NR_epoll_pwait)
Peter Maydell3b6edd12011-02-15 18:35:05 +000012739#if defined(TARGET_NR_epoll_wait)
12740 case TARGET_NR_epoll_wait:
12741#endif
Peter Maydell227f0212016-06-06 19:58:11 +010012742#if defined(TARGET_NR_epoll_pwait)
Peter Maydell3b6edd12011-02-15 18:35:05 +000012743 case TARGET_NR_epoll_pwait:
12744#endif
12745 {
12746 struct target_epoll_event *target_ep;
12747 struct epoll_event *ep;
12748 int epfd = arg1;
12749 int maxevents = arg3;
12750 int timeout = arg4;
12751
Peter Maydell2ba7fae32016-07-18 15:35:59 +010012752 if (maxevents <= 0 || maxevents > TARGET_EP_MAX_EVENTS) {
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012753 return -TARGET_EINVAL;
Peter Maydell2ba7fae32016-07-18 15:35:59 +010012754 }
12755
Peter Maydell3b6edd12011-02-15 18:35:05 +000012756 target_ep = lock_user(VERIFY_WRITE, arg2,
12757 maxevents * sizeof(struct target_epoll_event), 1);
12758 if (!target_ep) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012759 return -TARGET_EFAULT;
Peter Maydell3b6edd12011-02-15 18:35:05 +000012760 }
12761
Peter Maydell04c95f42016-07-18 15:36:00 +010012762 ep = g_try_new(struct epoll_event, maxevents);
12763 if (!ep) {
12764 unlock_user(target_ep, arg2, 0);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012765 return -TARGET_ENOMEM;
Peter Maydell04c95f42016-07-18 15:36:00 +010012766 }
Peter Maydell3b6edd12011-02-15 18:35:05 +000012767
12768 switch (num) {
Peter Maydell227f0212016-06-06 19:58:11 +010012769#if defined(TARGET_NR_epoll_pwait)
Peter Maydell3b6edd12011-02-15 18:35:05 +000012770 case TARGET_NR_epoll_pwait:
12771 {
Richard Hendersoncd0e31a2022-03-15 01:43:07 -070012772 sigset_t *set = NULL;
Peter Maydell3b6edd12011-02-15 18:35:05 +000012773
12774 if (arg5) {
Richard Hendersoncd0e31a2022-03-15 01:43:07 -070012775 ret = process_sigsuspend_mask(&set, arg5, arg6);
12776 if (ret != 0) {
Peter Maydellc8157012016-06-30 14:23:24 +010012777 break;
12778 }
Peter Maydell3b6edd12011-02-15 18:35:05 +000012779 }
12780
Peter Maydell227f0212016-06-06 19:58:11 +010012781 ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
12782 set, SIGSET_T_SIZE));
Richard Hendersoncd0e31a2022-03-15 01:43:07 -070012783
12784 if (set) {
12785 finish_sigsuspend_mask(ret);
12786 }
Peter Maydell3b6edd12011-02-15 18:35:05 +000012787 break;
12788 }
12789#endif
12790#if defined(TARGET_NR_epoll_wait)
12791 case TARGET_NR_epoll_wait:
Peter Maydell227f0212016-06-06 19:58:11 +010012792 ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
12793 NULL, 0));
Peter Maydell3b6edd12011-02-15 18:35:05 +000012794 break;
12795#endif
12796 default:
12797 ret = -TARGET_ENOSYS;
12798 }
12799 if (!is_error(ret)) {
12800 int i;
12801 for (i = 0; i < ret; i++) {
12802 target_ep[i].events = tswap32(ep[i].events);
12803 target_ep[i].data.u64 = tswap64(ep[i].data.u64);
12804 }
Peter Maydell04c95f42016-07-18 15:36:00 +010012805 unlock_user(target_ep, arg2,
12806 ret * sizeof(struct target_epoll_event));
12807 } else {
12808 unlock_user(target_ep, arg2, 0);
Peter Maydell3b6edd12011-02-15 18:35:05 +000012809 }
Peter Maydell04c95f42016-07-18 15:36:00 +010012810 g_free(ep);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012811 return ret;
Peter Maydell3b6edd12011-02-15 18:35:05 +000012812 }
12813#endif
12814#endif
Peter Maydell163a05a2011-06-27 17:44:52 +010012815#ifdef TARGET_NR_prlimit64
12816 case TARGET_NR_prlimit64:
12817 {
12818 /* args: pid, resource number, ptr to new rlimit, ptr to old rlimit */
12819 struct target_rlimit64 *target_rnew, *target_rold;
12820 struct host_rlimit64 rnew, rold, *rnewp = 0;
Felix Janda95018012014-12-02 22:11:17 +010012821 int resource = target_to_host_resource(arg2);
Tobias Koch055d92f2020-03-05 21:24:00 +010012822
12823 if (arg3 && (resource != RLIMIT_AS &&
12824 resource != RLIMIT_DATA &&
12825 resource != RLIMIT_STACK)) {
Peter Maydell163a05a2011-06-27 17:44:52 +010012826 if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012827 return -TARGET_EFAULT;
Peter Maydell163a05a2011-06-27 17:44:52 +010012828 }
12829 rnew.rlim_cur = tswap64(target_rnew->rlim_cur);
12830 rnew.rlim_max = tswap64(target_rnew->rlim_max);
12831 unlock_user_struct(target_rnew, arg3, 0);
12832 rnewp = &rnew;
12833 }
12834
Felix Janda95018012014-12-02 22:11:17 +010012835 ret = get_errno(sys_prlimit64(arg1, resource, rnewp, arg4 ? &rold : 0));
Peter Maydell163a05a2011-06-27 17:44:52 +010012836 if (!is_error(ret) && arg4) {
12837 if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012838 return -TARGET_EFAULT;
Peter Maydell163a05a2011-06-27 17:44:52 +010012839 }
12840 target_rold->rlim_cur = tswap64(rold.rlim_cur);
12841 target_rold->rlim_max = tswap64(rold.rlim_max);
12842 unlock_user_struct(target_rold, arg4, 1);
12843 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012844 return ret;
Peter Maydell163a05a2011-06-27 17:44:52 +010012845 }
12846#endif
Richard Henderson3d21d292012-09-15 13:20:46 -070012847#ifdef TARGET_NR_gethostname
12848 case TARGET_NR_gethostname:
12849 {
12850 char *name = lock_user(VERIFY_WRITE, arg1, arg2, 0);
12851 if (name) {
12852 ret = get_errno(gethostname(name, arg2));
12853 unlock_user(name, arg1, arg2);
12854 } else {
12855 ret = -TARGET_EFAULT;
12856 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012857 return ret;
Richard Henderson3d21d292012-09-15 13:20:46 -070012858 }
12859#endif
Riku Voipio89aaf1a2013-07-24 09:44:26 +030012860#ifdef TARGET_NR_atomic_cmpxchg_32
12861 case TARGET_NR_atomic_cmpxchg_32:
12862 {
12863 /* should use start_exclusive from main.c */
12864 abi_ulong mem_value;
12865 if (get_user_u32(mem_value, arg6)) {
12866 target_siginfo_t info;
12867 info.si_signo = SIGSEGV;
12868 info.si_errno = 0;
12869 info.si_code = TARGET_SEGV_MAPERR;
12870 info._sifields._sigfault._addr = arg6;
Philippe Mathieu-Daudé0effdc22022-05-09 22:57:28 +020012871 queue_signal(cpu_env, info.si_signo, QEMU_SI_FAULT, &info);
Riku Voipio89aaf1a2013-07-24 09:44:26 +030012872 ret = 0xdeadbeef;
12873
12874 }
12875 if (mem_value == arg2)
12876 put_user_u32(arg1, arg6);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012877 return mem_value;
Riku Voipio89aaf1a2013-07-24 09:44:26 +030012878 }
12879#endif
12880#ifdef TARGET_NR_atomic_barrier
12881 case TARGET_NR_atomic_barrier:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012882 /* Like the kernel implementation and the
12883 qemu arm barrier, no-op this? */
12884 return 0;
Riku Voipio89aaf1a2013-07-24 09:44:26 +030012885#endif
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012886
12887#ifdef TARGET_NR_timer_create
12888 case TARGET_NR_timer_create:
12889 {
12890 /* args: clockid_t clockid, struct sigevent *sevp, timer_t *timerid */
12891
12892 struct sigevent host_sevp = { {0}, }, *phost_sevp = NULL;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012893
12894 int clkid = arg1;
12895 int timer_index = next_free_host_timer();
12896
12897 if (timer_index < 0) {
12898 ret = -TARGET_EAGAIN;
12899 } else {
12900 timer_t *phtimer = g_posix_timers + timer_index;
12901
12902 if (arg2) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012903 phost_sevp = &host_sevp;
Peter Maydellc0659762014-08-09 15:42:32 +010012904 ret = target_to_host_sigevent(phost_sevp, arg2);
12905 if (ret != 0) {
Peter Maydell9e598992022-07-25 12:00:35 +010012906 free_host_timer_slot(timer_index);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012907 return ret;
Peter Maydellc0659762014-08-09 15:42:32 +010012908 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012909 }
12910
12911 ret = get_errno(timer_create(clkid, phost_sevp, phtimer));
12912 if (ret) {
Peter Maydell9e598992022-07-25 12:00:35 +010012913 free_host_timer_slot(timer_index);
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012914 } else {
Alexander Grafaecc8862014-11-10 21:33:03 +010012915 if (put_user(TIMER_MAGIC | timer_index, arg3, target_timer_t)) {
Peter Maydell9e598992022-07-25 12:00:35 +010012916 timer_delete(*phtimer);
12917 free_host_timer_slot(timer_index);
Richard Henderson2852aaf2018-08-18 12:01:06 -070012918 return -TARGET_EFAULT;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012919 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012920 }
12921 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012922 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012923 }
12924#endif
12925
12926#ifdef TARGET_NR_timer_settime
12927 case TARGET_NR_timer_settime:
12928 {
12929 /* args: timer_t timerid, int flags, const struct itimerspec *new_value,
12930 * struct itimerspec * old_value */
Alexander Grafaecc8862014-11-10 21:33:03 +010012931 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020012932
Alexander Grafaecc8862014-11-10 21:33:03 +010012933 if (timerid < 0) {
12934 ret = timerid;
12935 } else if (arg3 == 0) {
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012936 ret = -TARGET_EINVAL;
12937 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020012938 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012939 struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
12940
Marc-André Lureau40c80b52017-01-19 10:15:32 -050012941 if (target_to_host_itimerspec(&hspec_new, arg3)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012942 return -TARGET_EFAULT;
Marc-André Lureau40c80b52017-01-19 10:15:32 -050012943 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012944 ret = get_errno(
12945 timer_settime(htimer, arg2, &hspec_new, &hspec_old));
Marc-André Lureau40c80b52017-01-19 10:15:32 -050012946 if (arg4 && host_to_target_itimerspec(arg4, &hspec_old)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070012947 return -TARGET_EFAULT;
Marc-André Lureau40c80b52017-01-19 10:15:32 -050012948 }
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012949 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012950 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012951 }
12952#endif
12953
Filip Bozuta828cb3a2020-07-22 17:34:21 +020012954#ifdef TARGET_NR_timer_settime64
12955 case TARGET_NR_timer_settime64:
12956 {
12957 target_timer_t timerid = get_timer_id(arg1);
12958
12959 if (timerid < 0) {
12960 ret = timerid;
12961 } else if (arg3 == 0) {
12962 ret = -TARGET_EINVAL;
12963 } else {
12964 timer_t htimer = g_posix_timers[timerid];
12965 struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
12966
12967 if (target_to_host_itimerspec64(&hspec_new, arg3)) {
12968 return -TARGET_EFAULT;
12969 }
12970 ret = get_errno(
12971 timer_settime(htimer, arg2, &hspec_new, &hspec_old));
12972 if (arg4 && host_to_target_itimerspec64(arg4, &hspec_old)) {
12973 return -TARGET_EFAULT;
12974 }
12975 }
12976 return ret;
12977 }
12978#endif
12979
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012980#ifdef TARGET_NR_timer_gettime
12981 case TARGET_NR_timer_gettime:
12982 {
12983 /* args: timer_t timerid, struct itimerspec *curr_value */
Alexander Grafaecc8862014-11-10 21:33:03 +010012984 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020012985
Alexander Grafaecc8862014-11-10 21:33:03 +010012986 if (timerid < 0) {
12987 ret = timerid;
12988 } else if (!arg2) {
12989 ret = -TARGET_EFAULT;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012990 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020012991 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110012992 struct itimerspec hspec;
12993 ret = get_errno(timer_gettime(htimer, &hspec));
12994
12995 if (host_to_target_itimerspec(arg2, &hspec)) {
12996 ret = -TARGET_EFAULT;
12997 }
12998 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070012999 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013000 }
13001#endif
13002
Filip Bozuta828cb3a2020-07-22 17:34:21 +020013003#ifdef TARGET_NR_timer_gettime64
13004 case TARGET_NR_timer_gettime64:
13005 {
13006 /* args: timer_t timerid, struct itimerspec64 *curr_value */
13007 target_timer_t timerid = get_timer_id(arg1);
13008
13009 if (timerid < 0) {
13010 ret = timerid;
13011 } else if (!arg2) {
13012 ret = -TARGET_EFAULT;
13013 } else {
13014 timer_t htimer = g_posix_timers[timerid];
13015 struct itimerspec hspec;
13016 ret = get_errno(timer_gettime(htimer, &hspec));
13017
13018 if (host_to_target_itimerspec64(arg2, &hspec)) {
13019 ret = -TARGET_EFAULT;
13020 }
13021 }
13022 return ret;
13023 }
13024#endif
13025
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013026#ifdef TARGET_NR_timer_getoverrun
13027 case TARGET_NR_timer_getoverrun:
13028 {
13029 /* args: timer_t timerid */
Alexander Grafaecc8862014-11-10 21:33:03 +010013030 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020013031
Alexander Grafaecc8862014-11-10 21:33:03 +010013032 if (timerid < 0) {
13033 ret = timerid;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013034 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020013035 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013036 ret = get_errno(timer_getoverrun(htimer));
13037 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013038 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013039 }
13040#endif
13041
13042#ifdef TARGET_NR_timer_delete
13043 case TARGET_NR_timer_delete:
13044 {
13045 /* args: timer_t timerid */
Alexander Grafaecc8862014-11-10 21:33:03 +010013046 target_timer_t timerid = get_timer_id(arg1);
Alexander Grafe52a99f2014-08-22 13:56:18 +020013047
Alexander Grafaecc8862014-11-10 21:33:03 +010013048 if (timerid < 0) {
13049 ret = timerid;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013050 } else {
Alexander Grafe52a99f2014-08-22 13:56:18 +020013051 timer_t htimer = g_posix_timers[timerid];
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013052 ret = get_errno(timer_delete(htimer));
Peter Maydell9e598992022-07-25 12:00:35 +010013053 free_host_timer_slot(timerid);
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013054 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013055 return ret;
Erik de Castro Lopof4f1e102013-11-29 18:39:23 +110013056 }
13057#endif
13058
Riku Voipio51834342014-06-22 11:25:42 +010013059#if defined(TARGET_NR_timerfd_create) && defined(CONFIG_TIMERFD)
13060 case TARGET_NR_timerfd_create:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013061 return get_errno(timerfd_create(arg1,
13062 target_to_host_bitmask(arg2, fcntl_flags_tbl)));
Riku Voipio51834342014-06-22 11:25:42 +010013063#endif
13064
13065#if defined(TARGET_NR_timerfd_gettime) && defined(CONFIG_TIMERFD)
13066 case TARGET_NR_timerfd_gettime:
13067 {
13068 struct itimerspec its_curr;
13069
13070 ret = get_errno(timerfd_gettime(arg1, &its_curr));
13071
13072 if (arg2 && host_to_target_itimerspec(arg2, &its_curr)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013073 return -TARGET_EFAULT;
Riku Voipio51834342014-06-22 11:25:42 +010013074 }
13075 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013076 return ret;
Riku Voipio51834342014-06-22 11:25:42 +010013077#endif
13078
Filip Bozuta828cb3a2020-07-22 17:34:21 +020013079#if defined(TARGET_NR_timerfd_gettime64) && defined(CONFIG_TIMERFD)
13080 case TARGET_NR_timerfd_gettime64:
13081 {
13082 struct itimerspec its_curr;
13083
13084 ret = get_errno(timerfd_gettime(arg1, &its_curr));
13085
13086 if (arg2 && host_to_target_itimerspec64(arg2, &its_curr)) {
13087 return -TARGET_EFAULT;
13088 }
13089 }
13090 return ret;
13091#endif
13092
Riku Voipio51834342014-06-22 11:25:42 +010013093#if defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD)
13094 case TARGET_NR_timerfd_settime:
13095 {
13096 struct itimerspec its_new, its_old, *p_new;
13097
13098 if (arg3) {
13099 if (target_to_host_itimerspec(&its_new, arg3)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013100 return -TARGET_EFAULT;
Riku Voipio51834342014-06-22 11:25:42 +010013101 }
13102 p_new = &its_new;
13103 } else {
13104 p_new = NULL;
13105 }
13106
13107 ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
13108
13109 if (arg4 && host_to_target_itimerspec(arg4, &its_old)) {
Richard Henderson2852aaf2018-08-18 12:01:06 -070013110 return -TARGET_EFAULT;
Riku Voipio51834342014-06-22 11:25:42 +010013111 }
13112 }
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013113 return ret;
Riku Voipio51834342014-06-22 11:25:42 +010013114#endif
13115
Filip Bozuta828cb3a2020-07-22 17:34:21 +020013116#if defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)
13117 case TARGET_NR_timerfd_settime64:
13118 {
13119 struct itimerspec its_new, its_old, *p_new;
13120
13121 if (arg3) {
13122 if (target_to_host_itimerspec64(&its_new, arg3)) {
13123 return -TARGET_EFAULT;
13124 }
13125 p_new = &its_new;
13126 } else {
13127 p_new = NULL;
13128 }
13129
13130 ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
13131
13132 if (arg4 && host_to_target_itimerspec64(arg4, &its_old)) {
13133 return -TARGET_EFAULT;
13134 }
13135 }
13136 return ret;
13137#endif
13138
Paul Burtonab31cda2014-06-22 11:25:43 +010013139#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
13140 case TARGET_NR_ioprio_get:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013141 return get_errno(ioprio_get(arg1, arg2));
Paul Burtonab31cda2014-06-22 11:25:43 +010013142#endif
13143
13144#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
13145 case TARGET_NR_ioprio_set:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013146 return get_errno(ioprio_set(arg1, arg2, arg3));
Paul Burtonab31cda2014-06-22 11:25:43 +010013147#endif
13148
Riku Voipio9af5c902014-08-12 15:58:57 +030013149#if defined(TARGET_NR_setns) && defined(CONFIG_SETNS)
13150 case TARGET_NR_setns:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013151 return get_errno(setns(arg1, arg2));
Riku Voipio9af5c902014-08-12 15:58:57 +030013152#endif
13153#if defined(TARGET_NR_unshare) && defined(CONFIG_SETNS)
13154 case TARGET_NR_unshare:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013155 return get_errno(unshare(arg1));
Riku Voipio9af5c902014-08-12 15:58:57 +030013156#endif
Laurent Vivier2f147882016-09-25 22:20:20 +020013157#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
13158 case TARGET_NR_kcmp:
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013159 return get_errno(kcmp(arg1, arg2, arg3, arg4, arg5));
Laurent Vivier2f147882016-09-25 22:20:20 +020013160#endif
Richard Hendersonfa97e382018-07-18 13:06:48 -070013161#ifdef TARGET_NR_swapcontext
13162 case TARGET_NR_swapcontext:
13163 /* PowerPC specific. */
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013164 return do_swapcontext(cpu_env, arg1, arg2, arg3);
Richard Hendersonfa97e382018-07-18 13:06:48 -070013165#endif
Shu-Chun Weng9bdfa4d2019-08-19 11:09:47 -070013166#ifdef TARGET_NR_memfd_create
13167 case TARGET_NR_memfd_create:
13168 p = lock_user_string(arg1);
13169 if (!p) {
13170 return -TARGET_EFAULT;
13171 }
13172 ret = get_errno(memfd_create(p, arg2));
13173 fd_trans_unregister(ret);
13174 unlock_user(p, arg1, 0);
13175 return ret;
13176#endif
Andreas Schwab85004762019-05-13 11:02:53 +020013177#if defined TARGET_NR_membarrier && defined __NR_membarrier
13178 case TARGET_NR_membarrier:
13179 return get_errno(membarrier(arg1, arg2));
13180#endif
Riku Voipio9af5c902014-08-12 15:58:57 +030013181
Andreas Schwab84946452020-11-12 12:45:16 +010013182#if defined(TARGET_NR_copy_file_range) && defined(__NR_copy_file_range)
13183 case TARGET_NR_copy_file_range:
13184 {
13185 loff_t inoff, outoff;
13186 loff_t *pinoff = NULL, *poutoff = NULL;
13187
13188 if (arg2) {
13189 if (get_user_u64(inoff, arg2)) {
13190 return -TARGET_EFAULT;
13191 }
13192 pinoff = &inoff;
13193 }
13194 if (arg4) {
13195 if (get_user_u64(outoff, arg4)) {
13196 return -TARGET_EFAULT;
13197 }
13198 poutoff = &outoff;
13199 }
Giuseppe Musacchio0fa259d2021-05-03 19:41:59 +020013200 /* Do not sign-extend the count parameter. */
Andreas Schwab84946452020-11-12 12:45:16 +010013201 ret = get_errno(safe_copy_file_range(arg1, pinoff, arg3, poutoff,
Giuseppe Musacchio0fa259d2021-05-03 19:41:59 +020013202 (abi_ulong)arg5, arg6));
Andreas Schwab84946452020-11-12 12:45:16 +010013203 if (!is_error(ret) && ret > 0) {
13204 if (arg2) {
13205 if (put_user_u64(inoff, arg2)) {
13206 return -TARGET_EFAULT;
13207 }
13208 }
13209 if (arg4) {
13210 if (put_user_u64(outoff, arg4)) {
13211 return -TARGET_EFAULT;
13212 }
13213 }
13214 }
13215 }
13216 return ret;
13217#endif
13218
YAMAMOTO Takashie10fbe82021-05-31 14:50:12 +090013219#if defined(TARGET_NR_pivot_root)
13220 case TARGET_NR_pivot_root:
13221 {
13222 void *p2;
13223 p = lock_user_string(arg1); /* new_root */
13224 p2 = lock_user_string(arg2); /* put_old */
13225 if (!p || !p2) {
13226 ret = -TARGET_EFAULT;
13227 } else {
13228 ret = get_errno(pivot_root(p, p2));
13229 }
13230 unlock_user(p2, arg2, 0);
13231 unlock_user(p, arg1, 0);
13232 }
13233 return ret;
13234#endif
13235
bellard31e31b82003-02-18 22:55:36 +000013236 default:
Philippe Mathieu-Daudé122f9c82018-07-06 12:51:25 -030013237 qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num);
Richard Henderson72eb7ea2018-08-18 12:01:05 -070013238 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +000013239 }
bellard31e31b82003-02-18 22:55:36 +000013240 return ret;
13241}
Richard Hendersondc1ce182018-08-18 12:01:04 -070013242
Philippe Mathieu-Daudéa0939b82022-05-09 22:57:27 +020013243abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1,
Richard Hendersondc1ce182018-08-18 12:01:04 -070013244 abi_long arg2, abi_long arg3, abi_long arg4,
13245 abi_long arg5, abi_long arg6, abi_long arg7,
13246 abi_long arg8)
13247{
Richard Henderson29a0af62019-03-22 16:07:18 -070013248 CPUState *cpu = env_cpu(cpu_env);
Richard Hendersondc1ce182018-08-18 12:01:04 -070013249 abi_long ret;
13250
13251#ifdef DEBUG_ERESTARTSYS
13252 /* Debug-only code for exercising the syscall-restart code paths
13253 * in the per-architecture cpu main loops: restart every syscall
13254 * the guest makes once before letting it through.
13255 */
13256 {
13257 static bool flag;
13258 flag = !flag;
13259 if (flag) {
Richard Hendersonaf254a22021-11-22 19:47:33 +010013260 return -QEMU_ERESTARTSYS;
Richard Hendersondc1ce182018-08-18 12:01:04 -070013261 }
13262 }
13263#endif
13264
Emilio G. Cotac36f7a62018-10-21 13:27:44 -040013265 record_syscall_start(cpu, num, arg1,
13266 arg2, arg3, arg4, arg5, arg6, arg7, arg8);
Richard Hendersondc1ce182018-08-18 12:01:04 -070013267
Josh Kunz4b25a502020-02-03 18:54:14 -080013268 if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
Filip Bozutae400e112020-08-11 18:45:49 +020013269 print_syscall(cpu_env, num, arg1, arg2, arg3, arg4, arg5, arg6);
Josh Kunz4b25a502020-02-03 18:54:14 -080013270 }
13271
13272 ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4,
13273 arg5, arg6, arg7, arg8);
13274
13275 if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
Filip Bozutae400e112020-08-11 18:45:49 +020013276 print_syscall_ret(cpu_env, num, ret, arg1, arg2,
13277 arg3, arg4, arg5, arg6);
Richard Hendersondc1ce182018-08-18 12:01:04 -070013278 }
13279
Emilio G. Cotac36f7a62018-10-21 13:27:44 -040013280 record_syscall_return(cpu, num, ret);
Richard Hendersondc1ce182018-08-18 12:01:04 -070013281 return ret;
13282}