xref: /illumos-kvm-cmd/linux-user/syscall.c (revision 68396ea9)
1 /*
2  *  Linux syscalls
3  *
4  *  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
17  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19 #define _ATFILE_SOURCE
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <string.h>
24 #include <elf.h>
25 #include <endian.h>
26 #include <errno.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <time.h>
30 #include <limits.h>
31 #include <sys/types.h>
32 #include <sys/ipc.h>
33 #include <sys/msg.h>
34 #include <sys/wait.h>
35 #include <sys/time.h>
36 #include <sys/stat.h>
37 #include <sys/mount.h>
38 #include <sys/prctl.h>
39 #include <sys/resource.h>
40 #include <sys/mman.h>
41 #include <sys/swap.h>
42 #include <signal.h>
43 #include <sched.h>
44 #ifdef __ia64__
45 int __clone2(int (*fn)(void *), void *child_stack_base,
46              size_t stack_size, int flags, void *arg, ...);
47 #endif
48 #include <sys/socket.h>
49 #include <sys/un.h>
50 #include <sys/uio.h>
51 #include <sys/poll.h>
52 #include <sys/times.h>
53 #include <sys/shm.h>
54 #include <sys/sem.h>
55 #include <sys/statfs.h>
56 #include <utime.h>
57 #include <sys/sysinfo.h>
58 #include <sys/utsname.h>
59 //#include <sys/user.h>
60 #include <netinet/ip.h>
61 #include <netinet/tcp.h>
62 #include <qemu-common.h>
63 #ifdef TARGET_GPROF
64 #include <sys/gmon.h>
65 #endif
66 #ifdef CONFIG_EVENTFD
67 #include <sys/eventfd.h>
68 #endif
69 
70 #define termios host_termios
71 #define winsize host_winsize
72 #define termio host_termio
73 #define sgttyb host_sgttyb /* same as target */
74 #define tchars host_tchars /* same as target */
75 #define ltchars host_ltchars /* same as target */
76 
77 #include <linux/termios.h>
78 #include <linux/unistd.h>
79 #include <linux/utsname.h>
80 #include <linux/cdrom.h>
81 #include <linux/hdreg.h>
82 #include <linux/soundcard.h>
83 #include <linux/kd.h>
84 #include <linux/mtio.h>
85 #include <linux/fs.h>
86 #if defined(CONFIG_FIEMAP)
87 #include <linux/fiemap.h>
88 #endif
89 #include <linux/fb.h>
90 #include <linux/vt.h>
91 #include "linux_loop.h"
92 #include "cpu-uname.h"
93 
94 #include "qemu.h"
95 #include "qemu-common.h"
96 
97 #if defined(CONFIG_USE_NPTL)
98 #define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \
99     CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)
100 #else
101 /* XXX: Hardcode the above values.  */
102 #define CLONE_NPTL_FLAGS2 0
103 #endif
104 
105 //#define DEBUG
106 
107 //#include <linux/msdos_fs.h>
108 #define	VFAT_IOCTL_READDIR_BOTH		_IOR('r', 1, struct linux_dirent [2])
109 #define	VFAT_IOCTL_READDIR_SHORT	_IOR('r', 2, struct linux_dirent [2])
110 
111 
112 #undef _syscall0
113 #undef _syscall1
114 #undef _syscall2
115 #undef _syscall3
116 #undef _syscall4
117 #undef _syscall5
118 #undef _syscall6
119 
120 #define _syscall0(type,name)		\
121 static type name (void)			\
122 {					\
123 	return syscall(__NR_##name);	\
124 }
125 
126 #define _syscall1(type,name,type1,arg1)		\
127 static type name (type1 arg1)			\
128 {						\
129 	return syscall(__NR_##name, arg1);	\
130 }
131 
132 #define _syscall2(type,name,type1,arg1,type2,arg2)	\
133 static type name (type1 arg1,type2 arg2)		\
134 {							\
135 	return syscall(__NR_##name, arg1, arg2);	\
136 }
137 
138 #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)	\
139 static type name (type1 arg1,type2 arg2,type3 arg3)		\
140 {								\
141 	return syscall(__NR_##name, arg1, arg2, arg3);		\
142 }
143 
144 #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)	\
145 static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4)			\
146 {										\
147 	return syscall(__NR_##name, arg1, arg2, arg3, arg4);			\
148 }
149 
150 #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,	\
151 		  type5,arg5)							\
152 static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5)	\
153 {										\
154 	return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5);		\
155 }
156 
157 
158 #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,	\
159 		  type5,arg5,type6,arg6)					\
160 static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,	\
161                   type6 arg6)							\
162 {										\
163 	return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6);	\
164 }
165 
166 
167 #define __NR_sys_uname __NR_uname
168 #define __NR_sys_faccessat __NR_faccessat
169 #define __NR_sys_fchmodat __NR_fchmodat
170 #define __NR_sys_fchownat __NR_fchownat
171 #define __NR_sys_fstatat64 __NR_fstatat64
172 #define __NR_sys_futimesat __NR_futimesat
173 #define __NR_sys_getcwd1 __NR_getcwd
174 #define __NR_sys_getdents __NR_getdents
175 #define __NR_sys_getdents64 __NR_getdents64
176 #define __NR_sys_getpriority __NR_getpriority
177 #define __NR_sys_linkat __NR_linkat
178 #define __NR_sys_mkdirat __NR_mkdirat
179 #define __NR_sys_mknodat __NR_mknodat
180 #define __NR_sys_newfstatat __NR_newfstatat
181 #define __NR_sys_openat __NR_openat
182 #define __NR_sys_readlinkat __NR_readlinkat
183 #define __NR_sys_renameat __NR_renameat
184 #define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
185 #define __NR_sys_symlinkat __NR_symlinkat
186 #define __NR_sys_syslog __NR_syslog
187 #define __NR_sys_tgkill __NR_tgkill
188 #define __NR_sys_tkill __NR_tkill
189 #define __NR_sys_unlinkat __NR_unlinkat
190 #define __NR_sys_utimensat __NR_utimensat
191 #define __NR_sys_futex __NR_futex
192 #define __NR_sys_inotify_init __NR_inotify_init
193 #define __NR_sys_inotify_add_watch __NR_inotify_add_watch
194 #define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch
195 
196 #if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
197 #define __NR__llseek __NR_lseek
198 #endif
199 
200 #ifdef __NR_gettid
201 _syscall0(int, gettid)
202 #else
203 /* This is a replacement for the host gettid() and must return a host
204    errno. */
205 static int gettid(void) {
206     return -ENOSYS;
207 }
208 #endif
209 _syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
210 #if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
211 _syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
212 #endif
213 _syscall2(int, sys_getpriority, int, which, int, who);
214 #if defined(TARGET_NR__llseek) && defined(__NR_llseek)
215 _syscall5(int, _llseek,  uint,  fd, ulong, hi, ulong, lo,
216           loff_t *, res, uint, wh);
217 #endif
218 _syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
219 _syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
220 #if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
221 _syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
222 #endif
223 #if defined(TARGET_NR_tkill) && defined(__NR_tkill)
224 _syscall2(int,sys_tkill,int,tid,int,sig)
225 #endif
226 #ifdef __NR_exit_group
227 _syscall1(int,exit_group,int,error_code)
228 #endif
229 #if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
230 _syscall1(int,set_tid_address,int *,tidptr)
231 #endif
232 #if defined(CONFIG_USE_NPTL)
233 #if defined(TARGET_NR_futex) && defined(__NR_futex)
234 _syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
235           const struct timespec *,timeout,int *,uaddr2,int,val3)
236 #endif
237 #endif
238 
239 static bitmask_transtbl fcntl_flags_tbl[] = {
240   { TARGET_O_ACCMODE,   TARGET_O_WRONLY,    O_ACCMODE,   O_WRONLY,    },
241   { TARGET_O_ACCMODE,   TARGET_O_RDWR,      O_ACCMODE,   O_RDWR,      },
242   { TARGET_O_CREAT,     TARGET_O_CREAT,     O_CREAT,     O_CREAT,     },
243   { TARGET_O_EXCL,      TARGET_O_EXCL,      O_EXCL,      O_EXCL,      },
244   { TARGET_O_NOCTTY,    TARGET_O_NOCTTY,    O_NOCTTY,    O_NOCTTY,    },
245   { TARGET_O_TRUNC,     TARGET_O_TRUNC,     O_TRUNC,     O_TRUNC,     },
246   { TARGET_O_APPEND,    TARGET_O_APPEND,    O_APPEND,    O_APPEND,    },
247   { TARGET_O_NONBLOCK,  TARGET_O_NONBLOCK,  O_NONBLOCK,  O_NONBLOCK,  },
248   { TARGET_O_SYNC,      TARGET_O_SYNC,      O_SYNC,      O_SYNC,      },
249   { TARGET_FASYNC,      TARGET_FASYNC,      FASYNC,      FASYNC,      },
250   { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
251   { TARGET_O_NOFOLLOW,  TARGET_O_NOFOLLOW,  O_NOFOLLOW,  O_NOFOLLOW,  },
252   { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
253 #if defined(O_DIRECT)
254   { TARGET_O_DIRECT,    TARGET_O_DIRECT,    O_DIRECT,    O_DIRECT,    },
255 #endif
256   { 0, 0, 0, 0 }
257 };
258 
259 #define COPY_UTSNAME_FIELD(dest, src) \
260   do { \
261       /* __NEW_UTS_LEN doesn't include terminating null */ \
262       (void) strncpy((dest), (src), __NEW_UTS_LEN); \
263       (dest)[__NEW_UTS_LEN] = '\0'; \
264   } while (0)
265 
sys_uname(struct new_utsname * buf)266 static int sys_uname(struct new_utsname *buf)
267 {
268   struct utsname uts_buf;
269 
270   if (uname(&uts_buf) < 0)
271       return (-1);
272 
273   /*
274    * Just in case these have some differences, we
275    * translate utsname to new_utsname (which is the
276    * struct linux kernel uses).
277    */
278 
279   bzero(buf, sizeof (*buf));
280   COPY_UTSNAME_FIELD(buf->sysname, uts_buf.sysname);
281   COPY_UTSNAME_FIELD(buf->nodename, uts_buf.nodename);
282   COPY_UTSNAME_FIELD(buf->release, uts_buf.release);
283   COPY_UTSNAME_FIELD(buf->version, uts_buf.version);
284   COPY_UTSNAME_FIELD(buf->machine, uts_buf.machine);
285 #ifdef _GNU_SOURCE
286   COPY_UTSNAME_FIELD(buf->domainname, uts_buf.domainname);
287 #endif
288   return (0);
289 
290 #undef COPY_UTSNAME_FIELD
291 }
292 
sys_getcwd1(char * buf,size_t size)293 static int sys_getcwd1(char *buf, size_t size)
294 {
295   if (getcwd(buf, size) == NULL) {
296       /* getcwd() sets errno */
297       return (-1);
298   }
299   return strlen(buf)+1;
300 }
301 
302 #ifdef CONFIG_ATFILE
303 /*
304  * Host system seems to have atfile syscall stubs available.  We
305  * now enable them one by one as specified by target syscall_nr.h.
306  */
307 
308 #ifdef TARGET_NR_faccessat
sys_faccessat(int dirfd,const char * pathname,int mode)309 static int sys_faccessat(int dirfd, const char *pathname, int mode)
310 {
311   return (faccessat(dirfd, pathname, mode, 0));
312 }
313 #endif
314 #ifdef TARGET_NR_fchmodat
sys_fchmodat(int dirfd,const char * pathname,mode_t mode)315 static int sys_fchmodat(int dirfd, const char *pathname, mode_t mode)
316 {
317   return (fchmodat(dirfd, pathname, mode, 0));
318 }
319 #endif
320 #if defined(TARGET_NR_fchownat) && defined(USE_UID16)
sys_fchownat(int dirfd,const char * pathname,uid_t owner,gid_t group,int flags)321 static int sys_fchownat(int dirfd, const char *pathname, uid_t owner,
322     gid_t group, int flags)
323 {
324   return (fchownat(dirfd, pathname, owner, group, flags));
325 }
326 #endif
327 #ifdef __NR_fstatat64
sys_fstatat64(int dirfd,const char * pathname,struct stat * buf,int flags)328 static int sys_fstatat64(int dirfd, const char *pathname, struct stat *buf,
329     int flags)
330 {
331   return (fstatat(dirfd, pathname, buf, flags));
332 }
333 #endif
334 #ifdef __NR_newfstatat
sys_newfstatat(int dirfd,const char * pathname,struct stat * buf,int flags)335 static int sys_newfstatat(int dirfd, const char *pathname, struct stat *buf,
336     int flags)
337 {
338   return (fstatat(dirfd, pathname, buf, flags));
339 }
340 #endif
341 #ifdef TARGET_NR_futimesat
sys_futimesat(int dirfd,const char * pathname,const struct timeval times[2])342 static int sys_futimesat(int dirfd, const char *pathname,
343     const struct timeval times[2])
344 {
345   return (futimesat(dirfd, pathname, times));
346 }
347 #endif
348 #ifdef TARGET_NR_linkat
sys_linkat(int olddirfd,const char * oldpath,int newdirfd,const char * newpath,int flags)349 static int sys_linkat(int olddirfd, const char *oldpath,
350     int newdirfd, const char *newpath, int flags)
351 {
352   return (linkat(olddirfd, oldpath, newdirfd, newpath, flags));
353 }
354 #endif
355 #ifdef TARGET_NR_mkdirat
sys_mkdirat(int dirfd,const char * pathname,mode_t mode)356 static int sys_mkdirat(int dirfd, const char *pathname, mode_t mode)
357 {
358   return (mkdirat(dirfd, pathname, mode));
359 }
360 #endif
361 #ifdef TARGET_NR_mknodat
sys_mknodat(int dirfd,const char * pathname,mode_t mode,dev_t dev)362 static int sys_mknodat(int dirfd, const char *pathname, mode_t mode,
363     dev_t dev)
364 {
365   return (mknodat(dirfd, pathname, mode, dev));
366 }
367 #endif
368 #ifdef TARGET_NR_openat
sys_openat(int dirfd,const char * pathname,int flags,...)369 static int sys_openat(int dirfd, const char *pathname, int flags, ...)
370 {
371   /*
372    * open(2) has extra parameter 'mode' when called with
373    * flag O_CREAT.
374    */
375   if ((flags & O_CREAT) != 0) {
376       va_list ap;
377       mode_t mode;
378 
379       /*
380        * Get the 'mode' parameter and translate it to
381        * host bits.
382        */
383       va_start(ap, flags);
384       mode = va_arg(ap, mode_t);
385       mode = target_to_host_bitmask(mode, fcntl_flags_tbl);
386       va_end(ap);
387 
388       return (openat(dirfd, pathname, flags, mode));
389   }
390   return (openat(dirfd, pathname, flags));
391 }
392 #endif
393 #ifdef TARGET_NR_readlinkat
sys_readlinkat(int dirfd,const char * pathname,char * buf,size_t bufsiz)394 static int sys_readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz)
395 {
396   return (readlinkat(dirfd, pathname, buf, bufsiz));
397 }
398 #endif
399 #ifdef TARGET_NR_renameat
sys_renameat(int olddirfd,const char * oldpath,int newdirfd,const char * newpath)400 static int sys_renameat(int olddirfd, const char *oldpath,
401     int newdirfd, const char *newpath)
402 {
403   return (renameat(olddirfd, oldpath, newdirfd, newpath));
404 }
405 #endif
406 #ifdef TARGET_NR_symlinkat
sys_symlinkat(const char * oldpath,int newdirfd,const char * newpath)407 static int sys_symlinkat(const char *oldpath, int newdirfd, const char *newpath)
408 {
409   return (symlinkat(oldpath, newdirfd, newpath));
410 }
411 #endif
412 #ifdef TARGET_NR_unlinkat
sys_unlinkat(int dirfd,const char * pathname,int flags)413 static int sys_unlinkat(int dirfd, const char *pathname, int flags)
414 {
415   return (unlinkat(dirfd, pathname, flags));
416 }
417 #endif
418 #else /* !CONFIG_ATFILE */
419 
420 /*
421  * Try direct syscalls instead
422  */
423 #if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
_syscall3(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode)424 _syscall3(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode)
425 #endif
426 #if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
427 _syscall3(int,sys_fchmodat,int,dirfd,const char *,pathname, mode_t,mode)
428 #endif
429 #if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) && defined(USE_UID16)
430 _syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
431           uid_t,owner,gid_t,group,int,flags)
432 #endif
433 #if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
434         defined(__NR_fstatat64)
435 _syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname,
436           struct stat *,buf,int,flags)
437 #endif
438 #if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
439 _syscall3(int,sys_futimesat,int,dirfd,const char *,pathname,
440          const struct timeval *,times)
441 #endif
442 #if (defined(TARGET_NR_newfstatat) || defined(TARGET_NR_fstatat64) ) && \
443         defined(__NR_newfstatat)
444 _syscall4(int,sys_newfstatat,int,dirfd,const char *,pathname,
445           struct stat *,buf,int,flags)
446 #endif
447 #if defined(TARGET_NR_linkat) && defined(__NR_linkat)
448 _syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
449       int,newdirfd,const char *,newpath,int,flags)
450 #endif
451 #if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
452 _syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
453 #endif
454 #if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
455 _syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
456           mode_t,mode,dev_t,dev)
457 #endif
458 #if defined(TARGET_NR_openat) && defined(__NR_openat)
459 _syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
460 #endif
461 #if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
462 _syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
463           char *,buf,size_t,bufsize)
464 #endif
465 #if defined(TARGET_NR_renameat) && defined(__NR_renameat)
466 _syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
467           int,newdirfd,const char *,newpath)
468 #endif
469 #if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
470 _syscall3(int,sys_symlinkat,const char *,oldpath,
471           int,newdirfd,const char *,newpath)
472 #endif
473 #if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
474 _syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
475 #endif
476 
477 #endif /* CONFIG_ATFILE */
478 
479 #ifdef CONFIG_UTIMENSAT
480 static int sys_utimensat(int dirfd, const char *pathname,
481     const struct timespec times[2], int flags)
482 {
483     if (pathname == NULL)
484         return futimens(dirfd, times);
485     else
486         return utimensat(dirfd, pathname, times, flags);
487 }
488 #else
489 #if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
490 _syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
491           const struct timespec *,tsp,int,flags)
492 #endif
493 #endif /* CONFIG_UTIMENSAT  */
494 
495 #ifdef CONFIG_INOTIFY
496 #include <sys/inotify.h>
497 
498 #if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
sys_inotify_init(void)499 static int sys_inotify_init(void)
500 {
501   return (inotify_init());
502 }
503 #endif
504 #if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
sys_inotify_add_watch(int fd,const char * pathname,int32_t mask)505 static int sys_inotify_add_watch(int fd,const char *pathname, int32_t mask)
506 {
507   return (inotify_add_watch(fd, pathname, mask));
508 }
509 #endif
510 #if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
sys_inotify_rm_watch(int fd,int32_t wd)511 static int sys_inotify_rm_watch(int fd, int32_t wd)
512 {
513   return (inotify_rm_watch(fd, wd));
514 }
515 #endif
516 #ifdef CONFIG_INOTIFY1
517 #if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1)
sys_inotify_init1(int flags)518 static int sys_inotify_init1(int flags)
519 {
520   return (inotify_init1(flags));
521 }
522 #endif
523 #endif
524 #else
525 /* Userspace can usually survive runtime without inotify */
526 #undef TARGET_NR_inotify_init
527 #undef TARGET_NR_inotify_init1
528 #undef TARGET_NR_inotify_add_watch
529 #undef TARGET_NR_inotify_rm_watch
530 #endif /* CONFIG_INOTIFY  */
531 
532 
533 extern int personality(int);
534 extern int flock(int, int);
535 extern int setfsuid(int);
536 extern int setfsgid(int);
537 extern int setgroups(int, gid_t *);
538 
539 #define ERRNO_TABLE_SIZE 1200
540 
541 /* target_to_host_errno_table[] is initialized from
542  * host_to_target_errno_table[] in syscall_init(). */
543 static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
544 };
545 
546 /*
547  * This list is the union of errno values overridden in asm-<arch>/errno.h
548  * minus the errnos that are not actually generic to all archs.
549  */
550 static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
551     [EIDRM]		= TARGET_EIDRM,
552     [ECHRNG]		= TARGET_ECHRNG,
553     [EL2NSYNC]		= TARGET_EL2NSYNC,
554     [EL3HLT]		= TARGET_EL3HLT,
555     [EL3RST]		= TARGET_EL3RST,
556     [ELNRNG]		= TARGET_ELNRNG,
557     [EUNATCH]		= TARGET_EUNATCH,
558     [ENOCSI]		= TARGET_ENOCSI,
559     [EL2HLT]		= TARGET_EL2HLT,
560     [EDEADLK]		= TARGET_EDEADLK,
561     [ENOLCK]		= TARGET_ENOLCK,
562     [EBADE]		= TARGET_EBADE,
563     [EBADR]		= TARGET_EBADR,
564     [EXFULL]		= TARGET_EXFULL,
565     [ENOANO]		= TARGET_ENOANO,
566     [EBADRQC]		= TARGET_EBADRQC,
567     [EBADSLT]		= TARGET_EBADSLT,
568     [EBFONT]		= TARGET_EBFONT,
569     [ENOSTR]		= TARGET_ENOSTR,
570     [ENODATA]		= TARGET_ENODATA,
571     [ETIME]		= TARGET_ETIME,
572     [ENOSR]		= TARGET_ENOSR,
573     [ENONET]		= TARGET_ENONET,
574     [ENOPKG]		= TARGET_ENOPKG,
575     [EREMOTE]		= TARGET_EREMOTE,
576     [ENOLINK]		= TARGET_ENOLINK,
577     [EADV]		= TARGET_EADV,
578     [ESRMNT]		= TARGET_ESRMNT,
579     [ECOMM]		= TARGET_ECOMM,
580     [EPROTO]		= TARGET_EPROTO,
581     [EDOTDOT]		= TARGET_EDOTDOT,
582     [EMULTIHOP]		= TARGET_EMULTIHOP,
583     [EBADMSG]		= TARGET_EBADMSG,
584     [ENAMETOOLONG]	= TARGET_ENAMETOOLONG,
585     [EOVERFLOW]		= TARGET_EOVERFLOW,
586     [ENOTUNIQ]		= TARGET_ENOTUNIQ,
587     [EBADFD]		= TARGET_EBADFD,
588     [EREMCHG]		= TARGET_EREMCHG,
589     [ELIBACC]		= TARGET_ELIBACC,
590     [ELIBBAD]		= TARGET_ELIBBAD,
591     [ELIBSCN]		= TARGET_ELIBSCN,
592     [ELIBMAX]		= TARGET_ELIBMAX,
593     [ELIBEXEC]		= TARGET_ELIBEXEC,
594     [EILSEQ]		= TARGET_EILSEQ,
595     [ENOSYS]		= TARGET_ENOSYS,
596     [ELOOP]		= TARGET_ELOOP,
597     [ERESTART]		= TARGET_ERESTART,
598     [ESTRPIPE]		= TARGET_ESTRPIPE,
599     [ENOTEMPTY]		= TARGET_ENOTEMPTY,
600     [EUSERS]		= TARGET_EUSERS,
601     [ENOTSOCK]		= TARGET_ENOTSOCK,
602     [EDESTADDRREQ]	= TARGET_EDESTADDRREQ,
603     [EMSGSIZE]		= TARGET_EMSGSIZE,
604     [EPROTOTYPE]	= TARGET_EPROTOTYPE,
605     [ENOPROTOOPT]	= TARGET_ENOPROTOOPT,
606     [EPROTONOSUPPORT]	= TARGET_EPROTONOSUPPORT,
607     [ESOCKTNOSUPPORT]	= TARGET_ESOCKTNOSUPPORT,
608     [EOPNOTSUPP]	= TARGET_EOPNOTSUPP,
609     [EPFNOSUPPORT]	= TARGET_EPFNOSUPPORT,
610     [EAFNOSUPPORT]	= TARGET_EAFNOSUPPORT,
611     [EADDRINUSE]	= TARGET_EADDRINUSE,
612     [EADDRNOTAVAIL]	= TARGET_EADDRNOTAVAIL,
613     [ENETDOWN]		= TARGET_ENETDOWN,
614     [ENETUNREACH]	= TARGET_ENETUNREACH,
615     [ENETRESET]		= TARGET_ENETRESET,
616     [ECONNABORTED]	= TARGET_ECONNABORTED,
617     [ECONNRESET]	= TARGET_ECONNRESET,
618     [ENOBUFS]		= TARGET_ENOBUFS,
619     [EISCONN]		= TARGET_EISCONN,
620     [ENOTCONN]		= TARGET_ENOTCONN,
621     [EUCLEAN]		= TARGET_EUCLEAN,
622     [ENOTNAM]		= TARGET_ENOTNAM,
623     [ENAVAIL]		= TARGET_ENAVAIL,
624     [EISNAM]		= TARGET_EISNAM,
625     [EREMOTEIO]		= TARGET_EREMOTEIO,
626     [ESHUTDOWN]		= TARGET_ESHUTDOWN,
627     [ETOOMANYREFS]	= TARGET_ETOOMANYREFS,
628     [ETIMEDOUT]		= TARGET_ETIMEDOUT,
629     [ECONNREFUSED]	= TARGET_ECONNREFUSED,
630     [EHOSTDOWN]		= TARGET_EHOSTDOWN,
631     [EHOSTUNREACH]	= TARGET_EHOSTUNREACH,
632     [EALREADY]		= TARGET_EALREADY,
633     [EINPROGRESS]	= TARGET_EINPROGRESS,
634     [ESTALE]		= TARGET_ESTALE,
635     [ECANCELED]		= TARGET_ECANCELED,
636     [ENOMEDIUM]		= TARGET_ENOMEDIUM,
637     [EMEDIUMTYPE]	= TARGET_EMEDIUMTYPE,
638 #ifdef ENOKEY
639     [ENOKEY]		= TARGET_ENOKEY,
640 #endif
641 #ifdef EKEYEXPIRED
642     [EKEYEXPIRED]	= TARGET_EKEYEXPIRED,
643 #endif
644 #ifdef EKEYREVOKED
645     [EKEYREVOKED]	= TARGET_EKEYREVOKED,
646 #endif
647 #ifdef EKEYREJECTED
648     [EKEYREJECTED]	= TARGET_EKEYREJECTED,
649 #endif
650 #ifdef EOWNERDEAD
651     [EOWNERDEAD]	= TARGET_EOWNERDEAD,
652 #endif
653 #ifdef ENOTRECOVERABLE
654     [ENOTRECOVERABLE]	= TARGET_ENOTRECOVERABLE,
655 #endif
656 };
657 
host_to_target_errno(int err)658 static inline int host_to_target_errno(int err)
659 {
660     if(host_to_target_errno_table[err])
661         return host_to_target_errno_table[err];
662     return err;
663 }
664 
target_to_host_errno(int err)665 static inline int target_to_host_errno(int err)
666 {
667     if (target_to_host_errno_table[err])
668         return target_to_host_errno_table[err];
669     return err;
670 }
671 
get_errno(abi_long ret)672 static inline abi_long get_errno(abi_long ret)
673 {
674     if (ret == -1)
675         return -host_to_target_errno(errno);
676     else
677         return ret;
678 }
679 
is_error(abi_long ret)680 static inline int is_error(abi_long ret)
681 {
682     return (abi_ulong)ret >= (abi_ulong)(-4096);
683 }
684 
target_strerror(int err)685 char *target_strerror(int err)
686 {
687     return strerror(target_to_host_errno(err));
688 }
689 
690 static abi_ulong target_brk;
691 static abi_ulong target_original_brk;
692 
target_set_brk(abi_ulong new_brk)693 void target_set_brk(abi_ulong new_brk)
694 {
695     target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
696 }
697 
698 /* do_brk() must return target values and target errnos. */
do_brk(abi_ulong new_brk)699 abi_long do_brk(abi_ulong new_brk)
700 {
701     abi_ulong brk_page;
702     abi_long mapped_addr;
703     int	new_alloc_size;
704 
705     if (!new_brk)
706         return target_brk;
707     if (new_brk < target_original_brk)
708         return target_brk;
709 
710     brk_page = HOST_PAGE_ALIGN(target_brk);
711 
712     /* If the new brk is less than this, set it and we're done... */
713     if (new_brk < brk_page) {
714 	target_brk = new_brk;
715     	return target_brk;
716     }
717 
718     /* We need to allocate more memory after the brk... */
719     new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
720     mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
721                                         PROT_READ|PROT_WRITE,
722                                         MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
723 
724 #if defined(TARGET_ALPHA)
725     /* We (partially) emulate OSF/1 on Alpha, which requires we
726        return a proper errno, not an unchanged brk value.  */
727     if (is_error(mapped_addr)) {
728         return -TARGET_ENOMEM;
729     }
730 #endif
731 
732     if (!is_error(mapped_addr)) {
733 	target_brk = new_brk;
734     }
735     return target_brk;
736 }
737 
copy_from_user_fdset(fd_set * fds,abi_ulong target_fds_addr,int n)738 static inline abi_long copy_from_user_fdset(fd_set *fds,
739                                             abi_ulong target_fds_addr,
740                                             int n)
741 {
742     int i, nw, j, k;
743     abi_ulong b, *target_fds;
744 
745     nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
746     if (!(target_fds = lock_user(VERIFY_READ,
747                                  target_fds_addr,
748                                  sizeof(abi_ulong) * nw,
749                                  1)))
750         return -TARGET_EFAULT;
751 
752     FD_ZERO(fds);
753     k = 0;
754     for (i = 0; i < nw; i++) {
755         /* grab the abi_ulong */
756         __get_user(b, &target_fds[i]);
757         for (j = 0; j < TARGET_ABI_BITS; j++) {
758             /* check the bit inside the abi_ulong */
759             if ((b >> j) & 1)
760                 FD_SET(k, fds);
761             k++;
762         }
763     }
764 
765     unlock_user(target_fds, target_fds_addr, 0);
766 
767     return 0;
768 }
769 
copy_to_user_fdset(abi_ulong target_fds_addr,const fd_set * fds,int n)770 static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
771                                           const fd_set *fds,
772                                           int n)
773 {
774     int i, nw, j, k;
775     abi_long v;
776     abi_ulong *target_fds;
777 
778     nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
779     if (!(target_fds = lock_user(VERIFY_WRITE,
780                                  target_fds_addr,
781                                  sizeof(abi_ulong) * nw,
782                                  0)))
783         return -TARGET_EFAULT;
784 
785     k = 0;
786     for (i = 0; i < nw; i++) {
787         v = 0;
788         for (j = 0; j < TARGET_ABI_BITS; j++) {
789             v |= ((FD_ISSET(k, fds) != 0) << j);
790             k++;
791         }
792         __put_user(v, &target_fds[i]);
793     }
794 
795     unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
796 
797     return 0;
798 }
799 
800 #if defined(__alpha__)
801 #define HOST_HZ 1024
802 #else
803 #define HOST_HZ 100
804 #endif
805 
host_to_target_clock_t(long ticks)806 static inline abi_long host_to_target_clock_t(long ticks)
807 {
808 #if HOST_HZ == TARGET_HZ
809     return ticks;
810 #else
811     return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
812 #endif
813 }
814 
host_to_target_rusage(abi_ulong target_addr,const struct rusage * rusage)815 static inline abi_long host_to_target_rusage(abi_ulong target_addr,
816                                              const struct rusage *rusage)
817 {
818     struct target_rusage *target_rusage;
819 
820     if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
821         return -TARGET_EFAULT;
822     target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec);
823     target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec);
824     target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec);
825     target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec);
826     target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss);
827     target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss);
828     target_rusage->ru_idrss = tswapl(rusage->ru_idrss);
829     target_rusage->ru_isrss = tswapl(rusage->ru_isrss);
830     target_rusage->ru_minflt = tswapl(rusage->ru_minflt);
831     target_rusage->ru_majflt = tswapl(rusage->ru_majflt);
832     target_rusage->ru_nswap = tswapl(rusage->ru_nswap);
833     target_rusage->ru_inblock = tswapl(rusage->ru_inblock);
834     target_rusage->ru_oublock = tswapl(rusage->ru_oublock);
835     target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd);
836     target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv);
837     target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals);
838     target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw);
839     target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw);
840     unlock_user_struct(target_rusage, target_addr, 1);
841 
842     return 0;
843 }
844 
target_to_host_rlim(target_ulong target_rlim)845 static inline rlim_t target_to_host_rlim(target_ulong target_rlim)
846 {
847     if (target_rlim == TARGET_RLIM_INFINITY)
848         return RLIM_INFINITY;
849     else
850         return tswapl(target_rlim);
851 }
852 
host_to_target_rlim(rlim_t rlim)853 static inline target_ulong host_to_target_rlim(rlim_t rlim)
854 {
855     if (rlim == RLIM_INFINITY || rlim != (target_long)rlim)
856         return TARGET_RLIM_INFINITY;
857     else
858         return tswapl(rlim);
859 }
860 
copy_from_user_timeval(struct timeval * tv,abi_ulong target_tv_addr)861 static inline abi_long copy_from_user_timeval(struct timeval *tv,
862                                               abi_ulong target_tv_addr)
863 {
864     struct target_timeval *target_tv;
865 
866     if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
867         return -TARGET_EFAULT;
868 
869     __get_user(tv->tv_sec, &target_tv->tv_sec);
870     __get_user(tv->tv_usec, &target_tv->tv_usec);
871 
872     unlock_user_struct(target_tv, target_tv_addr, 0);
873 
874     return 0;
875 }
876 
copy_to_user_timeval(abi_ulong target_tv_addr,const struct timeval * tv)877 static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
878                                             const struct timeval *tv)
879 {
880     struct target_timeval *target_tv;
881 
882     if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
883         return -TARGET_EFAULT;
884 
885     __put_user(tv->tv_sec, &target_tv->tv_sec);
886     __put_user(tv->tv_usec, &target_tv->tv_usec);
887 
888     unlock_user_struct(target_tv, target_tv_addr, 1);
889 
890     return 0;
891 }
892 
893 #if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
894 #include <mqueue.h>
895 
copy_from_user_mq_attr(struct mq_attr * attr,abi_ulong target_mq_attr_addr)896 static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr,
897                                               abi_ulong target_mq_attr_addr)
898 {
899     struct target_mq_attr *target_mq_attr;
900 
901     if (!lock_user_struct(VERIFY_READ, target_mq_attr,
902                           target_mq_attr_addr, 1))
903         return -TARGET_EFAULT;
904 
905     __get_user(attr->mq_flags, &target_mq_attr->mq_flags);
906     __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
907     __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
908     __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
909 
910     unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0);
911 
912     return 0;
913 }
914 
copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,const struct mq_attr * attr)915 static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
916                                             const struct mq_attr *attr)
917 {
918     struct target_mq_attr *target_mq_attr;
919 
920     if (!lock_user_struct(VERIFY_WRITE, target_mq_attr,
921                           target_mq_attr_addr, 0))
922         return -TARGET_EFAULT;
923 
924     __put_user(attr->mq_flags, &target_mq_attr->mq_flags);
925     __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
926     __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
927     __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
928 
929     unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1);
930 
931     return 0;
932 }
933 #endif
934 
935 /* do_select() must return target values and target errnos. */
do_select(int n,abi_ulong rfd_addr,abi_ulong wfd_addr,abi_ulong efd_addr,abi_ulong target_tv_addr)936 static abi_long do_select(int n,
937                           abi_ulong rfd_addr, abi_ulong wfd_addr,
938                           abi_ulong efd_addr, abi_ulong target_tv_addr)
939 {
940     fd_set rfds, wfds, efds;
941     fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
942     struct timeval tv, *tv_ptr;
943     abi_long ret;
944 
945     if (rfd_addr) {
946         if (copy_from_user_fdset(&rfds, rfd_addr, n))
947             return -TARGET_EFAULT;
948         rfds_ptr = &rfds;
949     } else {
950         rfds_ptr = NULL;
951     }
952     if (wfd_addr) {
953         if (copy_from_user_fdset(&wfds, wfd_addr, n))
954             return -TARGET_EFAULT;
955         wfds_ptr = &wfds;
956     } else {
957         wfds_ptr = NULL;
958     }
959     if (efd_addr) {
960         if (copy_from_user_fdset(&efds, efd_addr, n))
961             return -TARGET_EFAULT;
962         efds_ptr = &efds;
963     } else {
964         efds_ptr = NULL;
965     }
966 
967     if (target_tv_addr) {
968         if (copy_from_user_timeval(&tv, target_tv_addr))
969             return -TARGET_EFAULT;
970         tv_ptr = &tv;
971     } else {
972         tv_ptr = NULL;
973     }
974 
975     ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
976 
977     if (!is_error(ret)) {
978         if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
979             return -TARGET_EFAULT;
980         if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
981             return -TARGET_EFAULT;
982         if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
983             return -TARGET_EFAULT;
984 
985         if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv))
986             return -TARGET_EFAULT;
987     }
988 
989     return ret;
990 }
991 
do_pipe2(int host_pipe[],int flags)992 static abi_long do_pipe2(int host_pipe[], int flags)
993 {
994 #ifdef CONFIG_PIPE2
995     return pipe2(host_pipe, flags);
996 #else
997     return -ENOSYS;
998 #endif
999 }
1000 
do_pipe(void * cpu_env,abi_ulong pipedes,int flags,int is_pipe2)1001 static abi_long do_pipe(void *cpu_env, abi_ulong pipedes,
1002                         int flags, int is_pipe2)
1003 {
1004     int host_pipe[2];
1005     abi_long ret;
1006     ret = flags ? do_pipe2(host_pipe, flags) : pipe(host_pipe);
1007 
1008     if (is_error(ret))
1009         return get_errno(ret);
1010 
1011     /* Several targets have special calling conventions for the original
1012        pipe syscall, but didn't replicate this into the pipe2 syscall.  */
1013     if (!is_pipe2) {
1014 #if defined(TARGET_ALPHA)
1015         ((CPUAlphaState *)cpu_env)->ir[IR_A4] = host_pipe[1];
1016         return host_pipe[0];
1017 #elif defined(TARGET_MIPS)
1018         ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1];
1019         return host_pipe[0];
1020 #elif defined(TARGET_SH4)
1021         ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
1022         return host_pipe[0];
1023 #endif
1024     }
1025 
1026     if (put_user_s32(host_pipe[0], pipedes)
1027         || put_user_s32(host_pipe[1], pipedes + sizeof(host_pipe[0])))
1028         return -TARGET_EFAULT;
1029     return get_errno(ret);
1030 }
1031 
target_to_host_ip_mreq(struct ip_mreqn * mreqn,abi_ulong target_addr,socklen_t len)1032 static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
1033                                               abi_ulong target_addr,
1034                                               socklen_t len)
1035 {
1036     struct target_ip_mreqn *target_smreqn;
1037 
1038     target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
1039     if (!target_smreqn)
1040         return -TARGET_EFAULT;
1041     mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
1042     mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
1043     if (len == sizeof(struct target_ip_mreqn))
1044         mreqn->imr_ifindex = tswapl(target_smreqn->imr_ifindex);
1045     unlock_user(target_smreqn, target_addr, 0);
1046 
1047     return 0;
1048 }
1049 
target_to_host_sockaddr(struct sockaddr * addr,abi_ulong target_addr,socklen_t len)1050 static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
1051                                                abi_ulong target_addr,
1052                                                socklen_t len)
1053 {
1054     const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
1055     sa_family_t sa_family;
1056     struct target_sockaddr *target_saddr;
1057 
1058     target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
1059     if (!target_saddr)
1060         return -TARGET_EFAULT;
1061 
1062     sa_family = tswap16(target_saddr->sa_family);
1063 
1064     /* Oops. The caller might send a incomplete sun_path; sun_path
1065      * must be terminated by \0 (see the manual page), but
1066      * unfortunately it is quite common to specify sockaddr_un
1067      * length as "strlen(x->sun_path)" while it should be
1068      * "strlen(...) + 1". We'll fix that here if needed.
1069      * Linux kernel has a similar feature.
1070      */
1071 
1072     if (sa_family == AF_UNIX) {
1073         if (len < unix_maxlen && len > 0) {
1074             char *cp = (char*)target_saddr;
1075 
1076             if ( cp[len-1] && !cp[len] )
1077                 len++;
1078         }
1079         if (len > unix_maxlen)
1080             len = unix_maxlen;
1081     }
1082 
1083     memcpy(addr, target_saddr, len);
1084     addr->sa_family = sa_family;
1085     unlock_user(target_saddr, target_addr, 0);
1086 
1087     return 0;
1088 }
1089 
host_to_target_sockaddr(abi_ulong target_addr,struct sockaddr * addr,socklen_t len)1090 static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
1091                                                struct sockaddr *addr,
1092                                                socklen_t len)
1093 {
1094     struct target_sockaddr *target_saddr;
1095 
1096     target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
1097     if (!target_saddr)
1098         return -TARGET_EFAULT;
1099     memcpy(target_saddr, addr, len);
1100     target_saddr->sa_family = tswap16(addr->sa_family);
1101     unlock_user(target_saddr, target_addr, len);
1102 
1103     return 0;
1104 }
1105 
1106 /* ??? Should this also swap msgh->name?  */
target_to_host_cmsg(struct msghdr * msgh,struct target_msghdr * target_msgh)1107 static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
1108                                            struct target_msghdr *target_msgh)
1109 {
1110     struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
1111     abi_long msg_controllen;
1112     abi_ulong target_cmsg_addr;
1113     struct target_cmsghdr *target_cmsg;
1114     socklen_t space = 0;
1115 
1116     msg_controllen = tswapl(target_msgh->msg_controllen);
1117     if (msg_controllen < sizeof (struct target_cmsghdr))
1118         goto the_end;
1119     target_cmsg_addr = tswapl(target_msgh->msg_control);
1120     target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
1121     if (!target_cmsg)
1122         return -TARGET_EFAULT;
1123 
1124     while (cmsg && target_cmsg) {
1125         void *data = CMSG_DATA(cmsg);
1126         void *target_data = TARGET_CMSG_DATA(target_cmsg);
1127 
1128         int len = tswapl(target_cmsg->cmsg_len)
1129                   - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
1130 
1131         space += CMSG_SPACE(len);
1132         if (space > msgh->msg_controllen) {
1133             space -= CMSG_SPACE(len);
1134             gemu_log("Host cmsg overflow\n");
1135             break;
1136         }
1137 
1138         cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
1139         cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
1140         cmsg->cmsg_len = CMSG_LEN(len);
1141 
1142         if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
1143             gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
1144             memcpy(data, target_data, len);
1145         } else {
1146             int *fd = (int *)data;
1147             int *target_fd = (int *)target_data;
1148             int i, numfds = len / sizeof(int);
1149 
1150             for (i = 0; i < numfds; i++)
1151                 fd[i] = tswap32(target_fd[i]);
1152         }
1153 
1154         cmsg = CMSG_NXTHDR(msgh, cmsg);
1155         target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1156     }
1157     unlock_user(target_cmsg, target_cmsg_addr, 0);
1158  the_end:
1159     msgh->msg_controllen = space;
1160     return 0;
1161 }
1162 
1163 /* ??? Should this also swap msgh->name?  */
host_to_target_cmsg(struct target_msghdr * target_msgh,struct msghdr * msgh)1164 static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
1165                                            struct msghdr *msgh)
1166 {
1167     struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
1168     abi_long msg_controllen;
1169     abi_ulong target_cmsg_addr;
1170     struct target_cmsghdr *target_cmsg;
1171     socklen_t space = 0;
1172 
1173     msg_controllen = tswapl(target_msgh->msg_controllen);
1174     if (msg_controllen < sizeof (struct target_cmsghdr))
1175         goto the_end;
1176     target_cmsg_addr = tswapl(target_msgh->msg_control);
1177     target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
1178     if (!target_cmsg)
1179         return -TARGET_EFAULT;
1180 
1181     while (cmsg && target_cmsg) {
1182         void *data = CMSG_DATA(cmsg);
1183         void *target_data = TARGET_CMSG_DATA(target_cmsg);
1184 
1185         int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
1186 
1187         space += TARGET_CMSG_SPACE(len);
1188         if (space > msg_controllen) {
1189             space -= TARGET_CMSG_SPACE(len);
1190             gemu_log("Target cmsg overflow\n");
1191             break;
1192         }
1193 
1194         target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
1195         target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
1196         target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));
1197 
1198         if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
1199             gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
1200             memcpy(target_data, data, len);
1201         } else {
1202             int *fd = (int *)data;
1203             int *target_fd = (int *)target_data;
1204             int i, numfds = len / sizeof(int);
1205 
1206             for (i = 0; i < numfds; i++)
1207                 target_fd[i] = tswap32(fd[i]);
1208         }
1209 
1210         cmsg = CMSG_NXTHDR(msgh, cmsg);
1211         target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1212     }
1213     unlock_user(target_cmsg, target_cmsg_addr, space);
1214  the_end:
1215     target_msgh->msg_controllen = tswapl(space);
1216     return 0;
1217 }
1218 
1219 /* do_setsockopt() Must return target values and target errnos. */
do_setsockopt(int sockfd,int level,int optname,abi_ulong optval_addr,socklen_t optlen)1220 static abi_long do_setsockopt(int sockfd, int level, int optname,
1221                               abi_ulong optval_addr, socklen_t optlen)
1222 {
1223     abi_long ret;
1224     int val;
1225     struct ip_mreqn *ip_mreq;
1226     struct ip_mreq_source *ip_mreq_source;
1227 
1228     switch(level) {
1229     case SOL_TCP:
1230         /* TCP options all take an 'int' value.  */
1231         if (optlen < sizeof(uint32_t))
1232             return -TARGET_EINVAL;
1233 
1234         if (get_user_u32(val, optval_addr))
1235             return -TARGET_EFAULT;
1236         ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1237         break;
1238     case SOL_IP:
1239         switch(optname) {
1240         case IP_TOS:
1241         case IP_TTL:
1242         case IP_HDRINCL:
1243         case IP_ROUTER_ALERT:
1244         case IP_RECVOPTS:
1245         case IP_RETOPTS:
1246         case IP_PKTINFO:
1247         case IP_MTU_DISCOVER:
1248         case IP_RECVERR:
1249         case IP_RECVTOS:
1250 #ifdef IP_FREEBIND
1251         case IP_FREEBIND:
1252 #endif
1253         case IP_MULTICAST_TTL:
1254         case IP_MULTICAST_LOOP:
1255             val = 0;
1256             if (optlen >= sizeof(uint32_t)) {
1257                 if (get_user_u32(val, optval_addr))
1258                     return -TARGET_EFAULT;
1259             } else if (optlen >= 1) {
1260                 if (get_user_u8(val, optval_addr))
1261                     return -TARGET_EFAULT;
1262             }
1263             ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1264             break;
1265         case IP_ADD_MEMBERSHIP:
1266         case IP_DROP_MEMBERSHIP:
1267             if (optlen < sizeof (struct target_ip_mreq) ||
1268                 optlen > sizeof (struct target_ip_mreqn))
1269                 return -TARGET_EINVAL;
1270 
1271             ip_mreq = (struct ip_mreqn *) alloca(optlen);
1272             target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
1273             ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen));
1274             break;
1275 
1276         case IP_BLOCK_SOURCE:
1277         case IP_UNBLOCK_SOURCE:
1278         case IP_ADD_SOURCE_MEMBERSHIP:
1279         case IP_DROP_SOURCE_MEMBERSHIP:
1280             if (optlen != sizeof (struct target_ip_mreq_source))
1281                 return -TARGET_EINVAL;
1282 
1283             ip_mreq_source = lock_user(VERIFY_READ, optval_addr, optlen, 1);
1284             ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen));
1285             unlock_user (ip_mreq_source, optval_addr, 0);
1286             break;
1287 
1288         default:
1289             goto unimplemented;
1290         }
1291         break;
1292     case TARGET_SOL_SOCKET:
1293         switch (optname) {
1294             /* Options with 'int' argument.  */
1295         case TARGET_SO_DEBUG:
1296 		optname = SO_DEBUG;
1297 		break;
1298         case TARGET_SO_REUSEADDR:
1299 		optname = SO_REUSEADDR;
1300 		break;
1301         case TARGET_SO_TYPE:
1302 		optname = SO_TYPE;
1303 		break;
1304         case TARGET_SO_ERROR:
1305 		optname = SO_ERROR;
1306 		break;
1307         case TARGET_SO_DONTROUTE:
1308 		optname = SO_DONTROUTE;
1309 		break;
1310         case TARGET_SO_BROADCAST:
1311 		optname = SO_BROADCAST;
1312 		break;
1313         case TARGET_SO_SNDBUF:
1314 		optname = SO_SNDBUF;
1315 		break;
1316         case TARGET_SO_RCVBUF:
1317 		optname = SO_RCVBUF;
1318 		break;
1319         case TARGET_SO_KEEPALIVE:
1320 		optname = SO_KEEPALIVE;
1321 		break;
1322         case TARGET_SO_OOBINLINE:
1323 		optname = SO_OOBINLINE;
1324 		break;
1325         case TARGET_SO_NO_CHECK:
1326 		optname = SO_NO_CHECK;
1327 		break;
1328         case TARGET_SO_PRIORITY:
1329 		optname = SO_PRIORITY;
1330 		break;
1331 #ifdef SO_BSDCOMPAT
1332         case TARGET_SO_BSDCOMPAT:
1333 		optname = SO_BSDCOMPAT;
1334 		break;
1335 #endif
1336         case TARGET_SO_PASSCRED:
1337 		optname = SO_PASSCRED;
1338 		break;
1339         case TARGET_SO_TIMESTAMP:
1340 		optname = SO_TIMESTAMP;
1341 		break;
1342         case TARGET_SO_RCVLOWAT:
1343 		optname = SO_RCVLOWAT;
1344 		break;
1345         case TARGET_SO_RCVTIMEO:
1346 		optname = SO_RCVTIMEO;
1347 		break;
1348         case TARGET_SO_SNDTIMEO:
1349 		optname = SO_SNDTIMEO;
1350 		break;
1351             break;
1352         default:
1353             goto unimplemented;
1354         }
1355 	if (optlen < sizeof(uint32_t))
1356             return -TARGET_EINVAL;
1357 
1358 	if (get_user_u32(val, optval_addr))
1359             return -TARGET_EFAULT;
1360 	ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
1361         break;
1362     default:
1363     unimplemented:
1364         gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
1365         ret = -TARGET_ENOPROTOOPT;
1366     }
1367     return ret;
1368 }
1369 
1370 /* do_getsockopt() Must return target values and target errnos. */
do_getsockopt(int sockfd,int level,int optname,abi_ulong optval_addr,abi_ulong optlen)1371 static abi_long do_getsockopt(int sockfd, int level, int optname,
1372                               abi_ulong optval_addr, abi_ulong optlen)
1373 {
1374     abi_long ret;
1375     int len, val;
1376     socklen_t lv;
1377 
1378     switch(level) {
1379     case TARGET_SOL_SOCKET:
1380         level = SOL_SOCKET;
1381         switch (optname) {
1382         /* These don't just return a single integer */
1383         case TARGET_SO_LINGER:
1384         case TARGET_SO_RCVTIMEO:
1385         case TARGET_SO_SNDTIMEO:
1386         case TARGET_SO_PEERCRED:
1387         case TARGET_SO_PEERNAME:
1388             goto unimplemented;
1389         /* Options with 'int' argument.  */
1390         case TARGET_SO_DEBUG:
1391             optname = SO_DEBUG;
1392             goto int_case;
1393         case TARGET_SO_REUSEADDR:
1394             optname = SO_REUSEADDR;
1395             goto int_case;
1396         case TARGET_SO_TYPE:
1397             optname = SO_TYPE;
1398             goto int_case;
1399         case TARGET_SO_ERROR:
1400             optname = SO_ERROR;
1401             goto int_case;
1402         case TARGET_SO_DONTROUTE:
1403             optname = SO_DONTROUTE;
1404             goto int_case;
1405         case TARGET_SO_BROADCAST:
1406             optname = SO_BROADCAST;
1407             goto int_case;
1408         case TARGET_SO_SNDBUF:
1409             optname = SO_SNDBUF;
1410             goto int_case;
1411         case TARGET_SO_RCVBUF:
1412             optname = SO_RCVBUF;
1413             goto int_case;
1414         case TARGET_SO_KEEPALIVE:
1415             optname = SO_KEEPALIVE;
1416             goto int_case;
1417         case TARGET_SO_OOBINLINE:
1418             optname = SO_OOBINLINE;
1419             goto int_case;
1420         case TARGET_SO_NO_CHECK:
1421             optname = SO_NO_CHECK;
1422             goto int_case;
1423         case TARGET_SO_PRIORITY:
1424             optname = SO_PRIORITY;
1425             goto int_case;
1426 #ifdef SO_BSDCOMPAT
1427         case TARGET_SO_BSDCOMPAT:
1428             optname = SO_BSDCOMPAT;
1429             goto int_case;
1430 #endif
1431         case TARGET_SO_PASSCRED:
1432             optname = SO_PASSCRED;
1433             goto int_case;
1434         case TARGET_SO_TIMESTAMP:
1435             optname = SO_TIMESTAMP;
1436             goto int_case;
1437         case TARGET_SO_RCVLOWAT:
1438             optname = SO_RCVLOWAT;
1439             goto int_case;
1440         default:
1441             goto int_case;
1442         }
1443         break;
1444     case SOL_TCP:
1445         /* TCP options all take an 'int' value.  */
1446     int_case:
1447         if (get_user_u32(len, optlen))
1448             return -TARGET_EFAULT;
1449         if (len < 0)
1450             return -TARGET_EINVAL;
1451         lv = sizeof(int);
1452         ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1453         if (ret < 0)
1454             return ret;
1455         if (len > lv)
1456             len = lv;
1457         if (len == 4) {
1458             if (put_user_u32(val, optval_addr))
1459                 return -TARGET_EFAULT;
1460         } else {
1461             if (put_user_u8(val, optval_addr))
1462                 return -TARGET_EFAULT;
1463         }
1464         if (put_user_u32(len, optlen))
1465             return -TARGET_EFAULT;
1466         break;
1467     case SOL_IP:
1468         switch(optname) {
1469         case IP_TOS:
1470         case IP_TTL:
1471         case IP_HDRINCL:
1472         case IP_ROUTER_ALERT:
1473         case IP_RECVOPTS:
1474         case IP_RETOPTS:
1475         case IP_PKTINFO:
1476         case IP_MTU_DISCOVER:
1477         case IP_RECVERR:
1478         case IP_RECVTOS:
1479 #ifdef IP_FREEBIND
1480         case IP_FREEBIND:
1481 #endif
1482         case IP_MULTICAST_TTL:
1483         case IP_MULTICAST_LOOP:
1484             if (get_user_u32(len, optlen))
1485                 return -TARGET_EFAULT;
1486             if (len < 0)
1487                 return -TARGET_EINVAL;
1488             lv = sizeof(int);
1489             ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1490             if (ret < 0)
1491                 return ret;
1492             if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
1493                 len = 1;
1494                 if (put_user_u32(len, optlen)
1495                     || put_user_u8(val, optval_addr))
1496                     return -TARGET_EFAULT;
1497             } else {
1498                 if (len > sizeof(int))
1499                     len = sizeof(int);
1500                 if (put_user_u32(len, optlen)
1501                     || put_user_u32(val, optval_addr))
1502                     return -TARGET_EFAULT;
1503             }
1504             break;
1505         default:
1506             ret = -TARGET_ENOPROTOOPT;
1507             break;
1508         }
1509         break;
1510     default:
1511     unimplemented:
1512         gemu_log("getsockopt level=%d optname=%d not yet supported\n",
1513                  level, optname);
1514         ret = -TARGET_EOPNOTSUPP;
1515         break;
1516     }
1517     return ret;
1518 }
1519 
1520 /* FIXME
1521  * lock_iovec()/unlock_iovec() have a return code of 0 for success where
1522  * other lock functions have a return code of 0 for failure.
1523  */
lock_iovec(int type,struct iovec * vec,abi_ulong target_addr,int count,int copy)1524 static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
1525                            int count, int copy)
1526 {
1527     struct target_iovec *target_vec;
1528     abi_ulong base;
1529     int i;
1530 
1531     target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1532     if (!target_vec)
1533         return -TARGET_EFAULT;
1534     for(i = 0;i < count; i++) {
1535         base = tswapl(target_vec[i].iov_base);
1536         vec[i].iov_len = tswapl(target_vec[i].iov_len);
1537         if (vec[i].iov_len != 0) {
1538             vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
1539             /* Don't check lock_user return value. We must call writev even
1540                if a element has invalid base address. */
1541         } else {
1542             /* zero length pointer is ignored */
1543             vec[i].iov_base = NULL;
1544         }
1545     }
1546     unlock_user (target_vec, target_addr, 0);
1547     return 0;
1548 }
1549 
unlock_iovec(struct iovec * vec,abi_ulong target_addr,int count,int copy)1550 static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
1551                              int count, int copy)
1552 {
1553     struct target_iovec *target_vec;
1554     abi_ulong base;
1555     int i;
1556 
1557     target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1558     if (!target_vec)
1559         return -TARGET_EFAULT;
1560     for(i = 0;i < count; i++) {
1561         if (target_vec[i].iov_base) {
1562             base = tswapl(target_vec[i].iov_base);
1563             unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
1564         }
1565     }
1566     unlock_user (target_vec, target_addr, 0);
1567 
1568     return 0;
1569 }
1570 
1571 /* do_socket() Must return target values and target errnos. */
do_socket(int domain,int type,int protocol)1572 static abi_long do_socket(int domain, int type, int protocol)
1573 {
1574 #if defined(TARGET_MIPS)
1575     switch(type) {
1576     case TARGET_SOCK_DGRAM:
1577         type = SOCK_DGRAM;
1578         break;
1579     case TARGET_SOCK_STREAM:
1580         type = SOCK_STREAM;
1581         break;
1582     case TARGET_SOCK_RAW:
1583         type = SOCK_RAW;
1584         break;
1585     case TARGET_SOCK_RDM:
1586         type = SOCK_RDM;
1587         break;
1588     case TARGET_SOCK_SEQPACKET:
1589         type = SOCK_SEQPACKET;
1590         break;
1591     case TARGET_SOCK_PACKET:
1592         type = SOCK_PACKET;
1593         break;
1594     }
1595 #endif
1596     if (domain == PF_NETLINK)
1597         return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
1598     return get_errno(socket(domain, type, protocol));
1599 }
1600 
1601 /* do_bind() Must return target values and target errnos. */
do_bind(int sockfd,abi_ulong target_addr,socklen_t addrlen)1602 static abi_long do_bind(int sockfd, abi_ulong target_addr,
1603                         socklen_t addrlen)
1604 {
1605     void *addr;
1606     abi_long ret;
1607 
1608     if ((int)addrlen < 0) {
1609         return -TARGET_EINVAL;
1610     }
1611 
1612     addr = alloca(addrlen+1);
1613 
1614     ret = target_to_host_sockaddr(addr, target_addr, addrlen);
1615     if (ret)
1616         return ret;
1617 
1618     return get_errno(bind(sockfd, addr, addrlen));
1619 }
1620 
1621 /* do_connect() Must return target values and target errnos. */
do_connect(int sockfd,abi_ulong target_addr,socklen_t addrlen)1622 static abi_long do_connect(int sockfd, abi_ulong target_addr,
1623                            socklen_t addrlen)
1624 {
1625     void *addr;
1626     abi_long ret;
1627 
1628     if ((int)addrlen < 0) {
1629         return -TARGET_EINVAL;
1630     }
1631 
1632     addr = alloca(addrlen);
1633 
1634     ret = target_to_host_sockaddr(addr, target_addr, addrlen);
1635     if (ret)
1636         return ret;
1637 
1638     return get_errno(connect(sockfd, addr, addrlen));
1639 }
1640 
1641 /* do_sendrecvmsg() Must return target values and target errnos. */
do_sendrecvmsg(int fd,abi_ulong target_msg,int flags,int send)1642 static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
1643                                int flags, int send)
1644 {
1645     abi_long ret, len;
1646     struct target_msghdr *msgp;
1647     struct msghdr msg;
1648     int count;
1649     struct iovec *vec;
1650     abi_ulong target_vec;
1651 
1652     /* FIXME */
1653     if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
1654                           msgp,
1655                           target_msg,
1656                           send ? 1 : 0))
1657         return -TARGET_EFAULT;
1658     if (msgp->msg_name) {
1659         msg.msg_namelen = tswap32(msgp->msg_namelen);
1660         msg.msg_name = alloca(msg.msg_namelen);
1661         ret = target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
1662                                 msg.msg_namelen);
1663         if (ret) {
1664             unlock_user_struct(msgp, target_msg, send ? 0 : 1);
1665             return ret;
1666         }
1667     } else {
1668         msg.msg_name = NULL;
1669         msg.msg_namelen = 0;
1670     }
1671     msg.msg_controllen = 2 * tswapl(msgp->msg_controllen);
1672     msg.msg_control = alloca(msg.msg_controllen);
1673     msg.msg_flags = tswap32(msgp->msg_flags);
1674 
1675     count = tswapl(msgp->msg_iovlen);
1676     vec = alloca(count * sizeof(struct iovec));
1677     target_vec = tswapl(msgp->msg_iov);
1678     lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
1679     msg.msg_iovlen = count;
1680     msg.msg_iov = vec;
1681 
1682     if (send) {
1683         ret = target_to_host_cmsg(&msg, msgp);
1684         if (ret == 0)
1685             ret = get_errno(sendmsg(fd, &msg, flags));
1686     } else {
1687         ret = get_errno(recvmsg(fd, &msg, flags));
1688         if (!is_error(ret)) {
1689             len = ret;
1690             ret = host_to_target_cmsg(msgp, &msg);
1691             if (!is_error(ret))
1692                 ret = len;
1693         }
1694     }
1695     unlock_iovec(vec, target_vec, count, !send);
1696     unlock_user_struct(msgp, target_msg, send ? 0 : 1);
1697     return ret;
1698 }
1699 
1700 /* do_accept() Must return target values and target errnos. */
do_accept(int fd,abi_ulong target_addr,abi_ulong target_addrlen_addr)1701 static abi_long do_accept(int fd, abi_ulong target_addr,
1702                           abi_ulong target_addrlen_addr)
1703 {
1704     socklen_t addrlen;
1705     void *addr;
1706     abi_long ret;
1707 
1708     if (target_addr == 0)
1709        return get_errno(accept(fd, NULL, NULL));
1710 
1711     /* linux returns EINVAL if addrlen pointer is invalid */
1712     if (get_user_u32(addrlen, target_addrlen_addr))
1713         return -TARGET_EINVAL;
1714 
1715     if ((int)addrlen < 0) {
1716         return -TARGET_EINVAL;
1717     }
1718 
1719     if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
1720         return -TARGET_EINVAL;
1721 
1722     addr = alloca(addrlen);
1723 
1724     ret = get_errno(accept(fd, addr, &addrlen));
1725     if (!is_error(ret)) {
1726         host_to_target_sockaddr(target_addr, addr, addrlen);
1727         if (put_user_u32(addrlen, target_addrlen_addr))
1728             ret = -TARGET_EFAULT;
1729     }
1730     return ret;
1731 }
1732 
1733 /* do_getpeername() Must return target values and target errnos. */
do_getpeername(int fd,abi_ulong target_addr,abi_ulong target_addrlen_addr)1734 static abi_long do_getpeername(int fd, abi_ulong target_addr,
1735                                abi_ulong target_addrlen_addr)
1736 {
1737     socklen_t addrlen;
1738     void *addr;
1739     abi_long ret;
1740 
1741     if (get_user_u32(addrlen, target_addrlen_addr))
1742         return -TARGET_EFAULT;
1743 
1744     if ((int)addrlen < 0) {
1745         return -TARGET_EINVAL;
1746     }
1747 
1748     if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
1749         return -TARGET_EFAULT;
1750 
1751     addr = alloca(addrlen);
1752 
1753     ret = get_errno(getpeername(fd, addr, &addrlen));
1754     if (!is_error(ret)) {
1755         host_to_target_sockaddr(target_addr, addr, addrlen);
1756         if (put_user_u32(addrlen, target_addrlen_addr))
1757             ret = -TARGET_EFAULT;
1758     }
1759     return ret;
1760 }
1761 
1762 /* do_getsockname() Must return target values and target errnos. */
do_getsockname(int fd,abi_ulong target_addr,abi_ulong target_addrlen_addr)1763 static abi_long do_getsockname(int fd, abi_ulong target_addr,
1764                                abi_ulong target_addrlen_addr)
1765 {
1766     socklen_t addrlen;
1767     void *addr;
1768     abi_long ret;
1769 
1770     if (get_user_u32(addrlen, target_addrlen_addr))
1771         return -TARGET_EFAULT;
1772 
1773     if ((int)addrlen < 0) {
1774         return -TARGET_EINVAL;
1775     }
1776 
1777     if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
1778         return -TARGET_EFAULT;
1779 
1780     addr = alloca(addrlen);
1781 
1782     ret = get_errno(getsockname(fd, addr, &addrlen));
1783     if (!is_error(ret)) {
1784         host_to_target_sockaddr(target_addr, addr, addrlen);
1785         if (put_user_u32(addrlen, target_addrlen_addr))
1786             ret = -TARGET_EFAULT;
1787     }
1788     return ret;
1789 }
1790 
1791 /* do_socketpair() Must return target values and target errnos. */
do_socketpair(int domain,int type,int protocol,abi_ulong target_tab_addr)1792 static abi_long do_socketpair(int domain, int type, int protocol,
1793                               abi_ulong target_tab_addr)
1794 {
1795     int tab[2];
1796     abi_long ret;
1797 
1798     ret = get_errno(socketpair(domain, type, protocol, tab));
1799     if (!is_error(ret)) {
1800         if (put_user_s32(tab[0], target_tab_addr)
1801             || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
1802             ret = -TARGET_EFAULT;
1803     }
1804     return ret;
1805 }
1806 
1807 /* do_sendto() Must return target values and target errnos. */
do_sendto(int fd,abi_ulong msg,size_t len,int flags,abi_ulong target_addr,socklen_t addrlen)1808 static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
1809                           abi_ulong target_addr, socklen_t addrlen)
1810 {
1811     void *addr;
1812     void *host_msg;
1813     abi_long ret;
1814 
1815     if ((int)addrlen < 0) {
1816         return -TARGET_EINVAL;
1817     }
1818 
1819     host_msg = lock_user(VERIFY_READ, msg, len, 1);
1820     if (!host_msg)
1821         return -TARGET_EFAULT;
1822     if (target_addr) {
1823         addr = alloca(addrlen);
1824         ret = target_to_host_sockaddr(addr, target_addr, addrlen);
1825         if (ret) {
1826             unlock_user(host_msg, msg, 0);
1827             return ret;
1828         }
1829         ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
1830     } else {
1831         ret = get_errno(send(fd, host_msg, len, flags));
1832     }
1833     unlock_user(host_msg, msg, 0);
1834     return ret;
1835 }
1836 
1837 /* do_recvfrom() Must return target values and target errnos. */
do_recvfrom(int fd,abi_ulong msg,size_t len,int flags,abi_ulong target_addr,abi_ulong target_addrlen)1838 static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
1839                             abi_ulong target_addr,
1840                             abi_ulong target_addrlen)
1841 {
1842     socklen_t addrlen;
1843     void *addr;
1844     void *host_msg;
1845     abi_long ret;
1846 
1847     host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
1848     if (!host_msg)
1849         return -TARGET_EFAULT;
1850     if (target_addr) {
1851         if (get_user_u32(addrlen, target_addrlen)) {
1852             ret = -TARGET_EFAULT;
1853             goto fail;
1854         }
1855         if ((int)addrlen < 0) {
1856             ret = -TARGET_EINVAL;
1857             goto fail;
1858         }
1859         addr = alloca(addrlen);
1860         ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
1861     } else {
1862         addr = NULL; /* To keep compiler quiet.  */
1863         ret = get_errno(recv(fd, host_msg, len, flags));
1864     }
1865     if (!is_error(ret)) {
1866         if (target_addr) {
1867             host_to_target_sockaddr(target_addr, addr, addrlen);
1868             if (put_user_u32(addrlen, target_addrlen)) {
1869                 ret = -TARGET_EFAULT;
1870                 goto fail;
1871             }
1872         }
1873         unlock_user(host_msg, msg, len);
1874     } else {
1875 fail:
1876         unlock_user(host_msg, msg, 0);
1877     }
1878     return ret;
1879 }
1880 
1881 #ifdef TARGET_NR_socketcall
1882 /* do_socketcall() Must return target values and target errnos. */
do_socketcall(int num,abi_ulong vptr)1883 static abi_long do_socketcall(int num, abi_ulong vptr)
1884 {
1885     abi_long ret;
1886     const int n = sizeof(abi_ulong);
1887 
1888     switch(num) {
1889     case SOCKOP_socket:
1890 	{
1891             abi_ulong domain, type, protocol;
1892 
1893             if (get_user_ual(domain, vptr)
1894                 || get_user_ual(type, vptr + n)
1895                 || get_user_ual(protocol, vptr + 2 * n))
1896                 return -TARGET_EFAULT;
1897 
1898             ret = do_socket(domain, type, protocol);
1899 	}
1900         break;
1901     case SOCKOP_bind:
1902 	{
1903             abi_ulong sockfd;
1904             abi_ulong target_addr;
1905             socklen_t addrlen;
1906 
1907             if (get_user_ual(sockfd, vptr)
1908                 || get_user_ual(target_addr, vptr + n)
1909                 || get_user_ual(addrlen, vptr + 2 * n))
1910                 return -TARGET_EFAULT;
1911 
1912             ret = do_bind(sockfd, target_addr, addrlen);
1913         }
1914         break;
1915     case SOCKOP_connect:
1916         {
1917             abi_ulong sockfd;
1918             abi_ulong target_addr;
1919             socklen_t addrlen;
1920 
1921             if (get_user_ual(sockfd, vptr)
1922                 || get_user_ual(target_addr, vptr + n)
1923                 || get_user_ual(addrlen, vptr + 2 * n))
1924                 return -TARGET_EFAULT;
1925 
1926             ret = do_connect(sockfd, target_addr, addrlen);
1927         }
1928         break;
1929     case SOCKOP_listen:
1930         {
1931             abi_ulong sockfd, backlog;
1932 
1933             if (get_user_ual(sockfd, vptr)
1934                 || get_user_ual(backlog, vptr + n))
1935                 return -TARGET_EFAULT;
1936 
1937             ret = get_errno(listen(sockfd, backlog));
1938         }
1939         break;
1940     case SOCKOP_accept:
1941         {
1942             abi_ulong sockfd;
1943             abi_ulong target_addr, target_addrlen;
1944 
1945             if (get_user_ual(sockfd, vptr)
1946                 || get_user_ual(target_addr, vptr + n)
1947                 || get_user_ual(target_addrlen, vptr + 2 * n))
1948                 return -TARGET_EFAULT;
1949 
1950             ret = do_accept(sockfd, target_addr, target_addrlen);
1951         }
1952         break;
1953     case SOCKOP_getsockname:
1954         {
1955             abi_ulong sockfd;
1956             abi_ulong target_addr, target_addrlen;
1957 
1958             if (get_user_ual(sockfd, vptr)
1959                 || get_user_ual(target_addr, vptr + n)
1960                 || get_user_ual(target_addrlen, vptr + 2 * n))
1961                 return -TARGET_EFAULT;
1962 
1963             ret = do_getsockname(sockfd, target_addr, target_addrlen);
1964         }
1965         break;
1966     case SOCKOP_getpeername:
1967         {
1968             abi_ulong sockfd;
1969             abi_ulong target_addr, target_addrlen;
1970 
1971             if (get_user_ual(sockfd, vptr)
1972                 || get_user_ual(target_addr, vptr + n)
1973                 || get_user_ual(target_addrlen, vptr + 2 * n))
1974                 return -TARGET_EFAULT;
1975 
1976             ret = do_getpeername(sockfd, target_addr, target_addrlen);
1977         }
1978         break;
1979     case SOCKOP_socketpair:
1980         {
1981             abi_ulong domain, type, protocol;
1982             abi_ulong tab;
1983 
1984             if (get_user_ual(domain, vptr)
1985                 || get_user_ual(type, vptr + n)
1986                 || get_user_ual(protocol, vptr + 2 * n)
1987                 || get_user_ual(tab, vptr + 3 * n))
1988                 return -TARGET_EFAULT;
1989 
1990             ret = do_socketpair(domain, type, protocol, tab);
1991         }
1992         break;
1993     case SOCKOP_send:
1994         {
1995             abi_ulong sockfd;
1996             abi_ulong msg;
1997             size_t len;
1998             abi_ulong flags;
1999 
2000             if (get_user_ual(sockfd, vptr)
2001                 || get_user_ual(msg, vptr + n)
2002                 || get_user_ual(len, vptr + 2 * n)
2003                 || get_user_ual(flags, vptr + 3 * n))
2004                 return -TARGET_EFAULT;
2005 
2006             ret = do_sendto(sockfd, msg, len, flags, 0, 0);
2007         }
2008         break;
2009     case SOCKOP_recv:
2010         {
2011             abi_ulong sockfd;
2012             abi_ulong msg;
2013             size_t len;
2014             abi_ulong flags;
2015 
2016             if (get_user_ual(sockfd, vptr)
2017                 || get_user_ual(msg, vptr + n)
2018                 || get_user_ual(len, vptr + 2 * n)
2019                 || get_user_ual(flags, vptr + 3 * n))
2020                 return -TARGET_EFAULT;
2021 
2022             ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
2023         }
2024         break;
2025     case SOCKOP_sendto:
2026         {
2027             abi_ulong sockfd;
2028             abi_ulong msg;
2029             size_t len;
2030             abi_ulong flags;
2031             abi_ulong addr;
2032             socklen_t addrlen;
2033 
2034             if (get_user_ual(sockfd, vptr)
2035                 || get_user_ual(msg, vptr + n)
2036                 || get_user_ual(len, vptr + 2 * n)
2037                 || get_user_ual(flags, vptr + 3 * n)
2038                 || get_user_ual(addr, vptr + 4 * n)
2039                 || get_user_ual(addrlen, vptr + 5 * n))
2040                 return -TARGET_EFAULT;
2041 
2042             ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
2043         }
2044         break;
2045     case SOCKOP_recvfrom:
2046         {
2047             abi_ulong sockfd;
2048             abi_ulong msg;
2049             size_t len;
2050             abi_ulong flags;
2051             abi_ulong addr;
2052             socklen_t addrlen;
2053 
2054             if (get_user_ual(sockfd, vptr)
2055                 || get_user_ual(msg, vptr + n)
2056                 || get_user_ual(len, vptr + 2 * n)
2057                 || get_user_ual(flags, vptr + 3 * n)
2058                 || get_user_ual(addr, vptr + 4 * n)
2059                 || get_user_ual(addrlen, vptr + 5 * n))
2060                 return -TARGET_EFAULT;
2061 
2062             ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
2063         }
2064         break;
2065     case SOCKOP_shutdown:
2066         {
2067             abi_ulong sockfd, how;
2068 
2069             if (get_user_ual(sockfd, vptr)
2070                 || get_user_ual(how, vptr + n))
2071                 return -TARGET_EFAULT;
2072 
2073             ret = get_errno(shutdown(sockfd, how));
2074         }
2075         break;
2076     case SOCKOP_sendmsg:
2077     case SOCKOP_recvmsg:
2078         {
2079             abi_ulong fd;
2080             abi_ulong target_msg;
2081             abi_ulong flags;
2082 
2083             if (get_user_ual(fd, vptr)
2084                 || get_user_ual(target_msg, vptr + n)
2085                 || get_user_ual(flags, vptr + 2 * n))
2086                 return -TARGET_EFAULT;
2087 
2088             ret = do_sendrecvmsg(fd, target_msg, flags,
2089                                  (num == SOCKOP_sendmsg));
2090         }
2091         break;
2092     case SOCKOP_setsockopt:
2093         {
2094             abi_ulong sockfd;
2095             abi_ulong level;
2096             abi_ulong optname;
2097             abi_ulong optval;
2098             socklen_t optlen;
2099 
2100             if (get_user_ual(sockfd, vptr)
2101                 || get_user_ual(level, vptr + n)
2102                 || get_user_ual(optname, vptr + 2 * n)
2103                 || get_user_ual(optval, vptr + 3 * n)
2104                 || get_user_ual(optlen, vptr + 4 * n))
2105                 return -TARGET_EFAULT;
2106 
2107             ret = do_setsockopt(sockfd, level, optname, optval, optlen);
2108         }
2109         break;
2110     case SOCKOP_getsockopt:
2111         {
2112             abi_ulong sockfd;
2113             abi_ulong level;
2114             abi_ulong optname;
2115             abi_ulong optval;
2116             socklen_t optlen;
2117 
2118             if (get_user_ual(sockfd, vptr)
2119                 || get_user_ual(level, vptr + n)
2120                 || get_user_ual(optname, vptr + 2 * n)
2121                 || get_user_ual(optval, vptr + 3 * n)
2122                 || get_user_ual(optlen, vptr + 4 * n))
2123                 return -TARGET_EFAULT;
2124 
2125             ret = do_getsockopt(sockfd, level, optname, optval, optlen);
2126         }
2127         break;
2128     default:
2129         gemu_log("Unsupported socketcall: %d\n", num);
2130         ret = -TARGET_ENOSYS;
2131         break;
2132     }
2133     return ret;
2134 }
2135 #endif
2136 
2137 #define N_SHM_REGIONS	32
2138 
2139 static struct shm_region {
2140     abi_ulong	start;
2141     abi_ulong	size;
2142 } shm_regions[N_SHM_REGIONS];
2143 
2144 struct target_ipc_perm
2145 {
2146     abi_long __key;
2147     abi_ulong uid;
2148     abi_ulong gid;
2149     abi_ulong cuid;
2150     abi_ulong cgid;
2151     unsigned short int mode;
2152     unsigned short int __pad1;
2153     unsigned short int __seq;
2154     unsigned short int __pad2;
2155     abi_ulong __unused1;
2156     abi_ulong __unused2;
2157 };
2158 
2159 struct target_semid_ds
2160 {
2161   struct target_ipc_perm sem_perm;
2162   abi_ulong sem_otime;
2163   abi_ulong __unused1;
2164   abi_ulong sem_ctime;
2165   abi_ulong __unused2;
2166   abi_ulong sem_nsems;
2167   abi_ulong __unused3;
2168   abi_ulong __unused4;
2169 };
2170 
target_to_host_ipc_perm(struct ipc_perm * host_ip,abi_ulong target_addr)2171 static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
2172                                                abi_ulong target_addr)
2173 {
2174     struct target_ipc_perm *target_ip;
2175     struct target_semid_ds *target_sd;
2176 
2177     if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2178         return -TARGET_EFAULT;
2179     target_ip = &(target_sd->sem_perm);
2180     host_ip->__key = tswapl(target_ip->__key);
2181     host_ip->uid = tswapl(target_ip->uid);
2182     host_ip->gid = tswapl(target_ip->gid);
2183     host_ip->cuid = tswapl(target_ip->cuid);
2184     host_ip->cgid = tswapl(target_ip->cgid);
2185     host_ip->mode = tswapl(target_ip->mode);
2186     unlock_user_struct(target_sd, target_addr, 0);
2187     return 0;
2188 }
2189 
host_to_target_ipc_perm(abi_ulong target_addr,struct ipc_perm * host_ip)2190 static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
2191                                                struct ipc_perm *host_ip)
2192 {
2193     struct target_ipc_perm *target_ip;
2194     struct target_semid_ds *target_sd;
2195 
2196     if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2197         return -TARGET_EFAULT;
2198     target_ip = &(target_sd->sem_perm);
2199     target_ip->__key = tswapl(host_ip->__key);
2200     target_ip->uid = tswapl(host_ip->uid);
2201     target_ip->gid = tswapl(host_ip->gid);
2202     target_ip->cuid = tswapl(host_ip->cuid);
2203     target_ip->cgid = tswapl(host_ip->cgid);
2204     target_ip->mode = tswapl(host_ip->mode);
2205     unlock_user_struct(target_sd, target_addr, 1);
2206     return 0;
2207 }
2208 
target_to_host_semid_ds(struct semid_ds * host_sd,abi_ulong target_addr)2209 static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
2210                                                abi_ulong target_addr)
2211 {
2212     struct target_semid_ds *target_sd;
2213 
2214     if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2215         return -TARGET_EFAULT;
2216     if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
2217         return -TARGET_EFAULT;
2218     host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
2219     host_sd->sem_otime = tswapl(target_sd->sem_otime);
2220     host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
2221     unlock_user_struct(target_sd, target_addr, 0);
2222     return 0;
2223 }
2224 
host_to_target_semid_ds(abi_ulong target_addr,struct semid_ds * host_sd)2225 static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
2226                                                struct semid_ds *host_sd)
2227 {
2228     struct target_semid_ds *target_sd;
2229 
2230     if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2231         return -TARGET_EFAULT;
2232     if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
2233         return -TARGET_EFAULT;;
2234     target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
2235     target_sd->sem_otime = tswapl(host_sd->sem_otime);
2236     target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
2237     unlock_user_struct(target_sd, target_addr, 1);
2238     return 0;
2239 }
2240 
2241 struct target_seminfo {
2242     int semmap;
2243     int semmni;
2244     int semmns;
2245     int semmnu;
2246     int semmsl;
2247     int semopm;
2248     int semume;
2249     int semusz;
2250     int semvmx;
2251     int semaem;
2252 };
2253 
host_to_target_seminfo(abi_ulong target_addr,struct seminfo * host_seminfo)2254 static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
2255                                               struct seminfo *host_seminfo)
2256 {
2257     struct target_seminfo *target_seminfo;
2258     if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
2259         return -TARGET_EFAULT;
2260     __put_user(host_seminfo->semmap, &target_seminfo->semmap);
2261     __put_user(host_seminfo->semmni, &target_seminfo->semmni);
2262     __put_user(host_seminfo->semmns, &target_seminfo->semmns);
2263     __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
2264     __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
2265     __put_user(host_seminfo->semopm, &target_seminfo->semopm);
2266     __put_user(host_seminfo->semume, &target_seminfo->semume);
2267     __put_user(host_seminfo->semusz, &target_seminfo->semusz);
2268     __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
2269     __put_user(host_seminfo->semaem, &target_seminfo->semaem);
2270     unlock_user_struct(target_seminfo, target_addr, 1);
2271     return 0;
2272 }
2273 
2274 union semun {
2275 	int val;
2276 	struct semid_ds *buf;
2277 	unsigned short *array;
2278 	struct seminfo *__buf;
2279 };
2280 
2281 union target_semun {
2282 	int val;
2283 	abi_ulong buf;
2284 	abi_ulong array;
2285 	abi_ulong __buf;
2286 };
2287 
target_to_host_semarray(int semid,unsigned short ** host_array,abi_ulong target_addr)2288 static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
2289                                                abi_ulong target_addr)
2290 {
2291     int nsems;
2292     unsigned short *array;
2293     union semun semun;
2294     struct semid_ds semid_ds;
2295     int i, ret;
2296 
2297     semun.buf = &semid_ds;
2298 
2299     ret = semctl(semid, 0, IPC_STAT, semun);
2300     if (ret == -1)
2301         return get_errno(ret);
2302 
2303     nsems = semid_ds.sem_nsems;
2304 
2305     *host_array = malloc(nsems*sizeof(unsigned short));
2306     array = lock_user(VERIFY_READ, target_addr,
2307                       nsems*sizeof(unsigned short), 1);
2308     if (!array)
2309         return -TARGET_EFAULT;
2310 
2311     for(i=0; i<nsems; i++) {
2312         __get_user((*host_array)[i], &array[i]);
2313     }
2314     unlock_user(array, target_addr, 0);
2315 
2316     return 0;
2317 }
2318 
host_to_target_semarray(int semid,abi_ulong target_addr,unsigned short ** host_array)2319 static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
2320                                                unsigned short **host_array)
2321 {
2322     int nsems;
2323     unsigned short *array;
2324     union semun semun;
2325     struct semid_ds semid_ds;
2326     int i, ret;
2327 
2328     semun.buf = &semid_ds;
2329 
2330     ret = semctl(semid, 0, IPC_STAT, semun);
2331     if (ret == -1)
2332         return get_errno(ret);
2333 
2334     nsems = semid_ds.sem_nsems;
2335 
2336     array = lock_user(VERIFY_WRITE, target_addr,
2337                       nsems*sizeof(unsigned short), 0);
2338     if (!array)
2339         return -TARGET_EFAULT;
2340 
2341     for(i=0; i<nsems; i++) {
2342         __put_user((*host_array)[i], &array[i]);
2343     }
2344     free(*host_array);
2345     unlock_user(array, target_addr, 1);
2346 
2347     return 0;
2348 }
2349 
do_semctl(int semid,int semnum,int cmd,union target_semun target_su)2350 static inline abi_long do_semctl(int semid, int semnum, int cmd,
2351                                  union target_semun target_su)
2352 {
2353     union semun arg;
2354     struct semid_ds dsarg;
2355     unsigned short *array = NULL;
2356     struct seminfo seminfo;
2357     abi_long ret = -TARGET_EINVAL;
2358     abi_long err;
2359     cmd &= 0xff;
2360 
2361     switch( cmd ) {
2362 	case GETVAL:
2363 	case SETVAL:
2364             arg.val = tswapl(target_su.val);
2365             ret = get_errno(semctl(semid, semnum, cmd, arg));
2366             target_su.val = tswapl(arg.val);
2367             break;
2368 	case GETALL:
2369 	case SETALL:
2370             err = target_to_host_semarray(semid, &array, target_su.array);
2371             if (err)
2372                 return err;
2373             arg.array = array;
2374             ret = get_errno(semctl(semid, semnum, cmd, arg));
2375             err = host_to_target_semarray(semid, target_su.array, &array);
2376             if (err)
2377                 return err;
2378             break;
2379 	case IPC_STAT:
2380 	case IPC_SET:
2381 	case SEM_STAT:
2382             err = target_to_host_semid_ds(&dsarg, target_su.buf);
2383             if (err)
2384                 return err;
2385             arg.buf = &dsarg;
2386             ret = get_errno(semctl(semid, semnum, cmd, arg));
2387             err = host_to_target_semid_ds(target_su.buf, &dsarg);
2388             if (err)
2389                 return err;
2390             break;
2391 	case IPC_INFO:
2392 	case SEM_INFO:
2393             arg.__buf = &seminfo;
2394             ret = get_errno(semctl(semid, semnum, cmd, arg));
2395             err = host_to_target_seminfo(target_su.__buf, &seminfo);
2396             if (err)
2397                 return err;
2398             break;
2399 	case IPC_RMID:
2400 	case GETPID:
2401 	case GETNCNT:
2402 	case GETZCNT:
2403             ret = get_errno(semctl(semid, semnum, cmd, NULL));
2404             break;
2405     }
2406 
2407     return ret;
2408 }
2409 
2410 struct target_sembuf {
2411     unsigned short sem_num;
2412     short sem_op;
2413     short sem_flg;
2414 };
2415 
target_to_host_sembuf(struct sembuf * host_sembuf,abi_ulong target_addr,unsigned nsops)2416 static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
2417                                              abi_ulong target_addr,
2418                                              unsigned nsops)
2419 {
2420     struct target_sembuf *target_sembuf;
2421     int i;
2422 
2423     target_sembuf = lock_user(VERIFY_READ, target_addr,
2424                               nsops*sizeof(struct target_sembuf), 1);
2425     if (!target_sembuf)
2426         return -TARGET_EFAULT;
2427 
2428     for(i=0; i<nsops; i++) {
2429         __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
2430         __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
2431         __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
2432     }
2433 
2434     unlock_user(target_sembuf, target_addr, 0);
2435 
2436     return 0;
2437 }
2438 
do_semop(int semid,abi_long ptr,unsigned nsops)2439 static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops)
2440 {
2441     struct sembuf sops[nsops];
2442 
2443     if (target_to_host_sembuf(sops, ptr, nsops))
2444         return -TARGET_EFAULT;
2445 
2446     return semop(semid, sops, nsops);
2447 }
2448 
2449 struct target_msqid_ds
2450 {
2451     struct target_ipc_perm msg_perm;
2452     abi_ulong msg_stime;
2453 #if TARGET_ABI_BITS == 32
2454     abi_ulong __unused1;
2455 #endif
2456     abi_ulong msg_rtime;
2457 #if TARGET_ABI_BITS == 32
2458     abi_ulong __unused2;
2459 #endif
2460     abi_ulong msg_ctime;
2461 #if TARGET_ABI_BITS == 32
2462     abi_ulong __unused3;
2463 #endif
2464     abi_ulong __msg_cbytes;
2465     abi_ulong msg_qnum;
2466     abi_ulong msg_qbytes;
2467     abi_ulong msg_lspid;
2468     abi_ulong msg_lrpid;
2469     abi_ulong __unused4;
2470     abi_ulong __unused5;
2471 };
2472 
target_to_host_msqid_ds(struct msqid_ds * host_md,abi_ulong target_addr)2473 static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
2474                                                abi_ulong target_addr)
2475 {
2476     struct target_msqid_ds *target_md;
2477 
2478     if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
2479         return -TARGET_EFAULT;
2480     if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
2481         return -TARGET_EFAULT;
2482     host_md->msg_stime = tswapl(target_md->msg_stime);
2483     host_md->msg_rtime = tswapl(target_md->msg_rtime);
2484     host_md->msg_ctime = tswapl(target_md->msg_ctime);
2485     host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes);
2486     host_md->msg_qnum = tswapl(target_md->msg_qnum);
2487     host_md->msg_qbytes = tswapl(target_md->msg_qbytes);
2488     host_md->msg_lspid = tswapl(target_md->msg_lspid);
2489     host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
2490     unlock_user_struct(target_md, target_addr, 0);
2491     return 0;
2492 }
2493 
host_to_target_msqid_ds(abi_ulong target_addr,struct msqid_ds * host_md)2494 static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
2495                                                struct msqid_ds *host_md)
2496 {
2497     struct target_msqid_ds *target_md;
2498 
2499     if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
2500         return -TARGET_EFAULT;
2501     if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
2502         return -TARGET_EFAULT;
2503     target_md->msg_stime = tswapl(host_md->msg_stime);
2504     target_md->msg_rtime = tswapl(host_md->msg_rtime);
2505     target_md->msg_ctime = tswapl(host_md->msg_ctime);
2506     target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes);
2507     target_md->msg_qnum = tswapl(host_md->msg_qnum);
2508     target_md->msg_qbytes = tswapl(host_md->msg_qbytes);
2509     target_md->msg_lspid = tswapl(host_md->msg_lspid);
2510     target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
2511     unlock_user_struct(target_md, target_addr, 1);
2512     return 0;
2513 }
2514 
2515 struct target_msginfo {
2516     int msgpool;
2517     int msgmap;
2518     int msgmax;
2519     int msgmnb;
2520     int msgmni;
2521     int msgssz;
2522     int msgtql;
2523     unsigned short int msgseg;
2524 };
2525 
host_to_target_msginfo(abi_ulong target_addr,struct msginfo * host_msginfo)2526 static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
2527                                               struct msginfo *host_msginfo)
2528 {
2529     struct target_msginfo *target_msginfo;
2530     if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
2531         return -TARGET_EFAULT;
2532     __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
2533     __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
2534     __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
2535     __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
2536     __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
2537     __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
2538     __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
2539     __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
2540     unlock_user_struct(target_msginfo, target_addr, 1);
2541     return 0;
2542 }
2543 
do_msgctl(int msgid,int cmd,abi_long ptr)2544 static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
2545 {
2546     struct msqid_ds dsarg;
2547     struct msginfo msginfo;
2548     abi_long ret = -TARGET_EINVAL;
2549 
2550     cmd &= 0xff;
2551 
2552     switch (cmd) {
2553     case IPC_STAT:
2554     case IPC_SET:
2555     case MSG_STAT:
2556         if (target_to_host_msqid_ds(&dsarg,ptr))
2557             return -TARGET_EFAULT;
2558         ret = get_errno(msgctl(msgid, cmd, &dsarg));
2559         if (host_to_target_msqid_ds(ptr,&dsarg))
2560             return -TARGET_EFAULT;
2561         break;
2562     case IPC_RMID:
2563         ret = get_errno(msgctl(msgid, cmd, NULL));
2564         break;
2565     case IPC_INFO:
2566     case MSG_INFO:
2567         ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
2568         if (host_to_target_msginfo(ptr, &msginfo))
2569             return -TARGET_EFAULT;
2570         break;
2571     }
2572 
2573     return ret;
2574 }
2575 
2576 struct target_msgbuf {
2577     abi_long mtype;
2578     char	mtext[1];
2579 };
2580 
do_msgsnd(int msqid,abi_long msgp,unsigned int msgsz,int msgflg)2581 static inline abi_long do_msgsnd(int msqid, abi_long msgp,
2582                                  unsigned int msgsz, int msgflg)
2583 {
2584     struct target_msgbuf *target_mb;
2585     struct msgbuf *host_mb;
2586     abi_long ret = 0;
2587 
2588     if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
2589         return -TARGET_EFAULT;
2590     host_mb = malloc(msgsz+sizeof(long));
2591     host_mb->mtype = (abi_long) tswapl(target_mb->mtype);
2592     memcpy(host_mb->mtext, target_mb->mtext, msgsz);
2593     ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
2594     free(host_mb);
2595     unlock_user_struct(target_mb, msgp, 0);
2596 
2597     return ret;
2598 }
2599 
do_msgrcv(int msqid,abi_long msgp,unsigned int msgsz,abi_long msgtyp,int msgflg)2600 static inline abi_long do_msgrcv(int msqid, abi_long msgp,
2601                                  unsigned int msgsz, abi_long msgtyp,
2602                                  int msgflg)
2603 {
2604     struct target_msgbuf *target_mb;
2605     char *target_mtext;
2606     struct msgbuf *host_mb;
2607     abi_long ret = 0;
2608 
2609     if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
2610         return -TARGET_EFAULT;
2611 
2612     host_mb = malloc(msgsz+sizeof(long));
2613     ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapl(msgtyp), msgflg));
2614 
2615     if (ret > 0) {
2616         abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
2617         target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
2618         if (!target_mtext) {
2619             ret = -TARGET_EFAULT;
2620             goto end;
2621         }
2622         memcpy(target_mb->mtext, host_mb->mtext, ret);
2623         unlock_user(target_mtext, target_mtext_addr, ret);
2624     }
2625 
2626     target_mb->mtype = tswapl(host_mb->mtype);
2627     free(host_mb);
2628 
2629 end:
2630     if (target_mb)
2631         unlock_user_struct(target_mb, msgp, 1);
2632     return ret;
2633 }
2634 
2635 struct target_shmid_ds
2636 {
2637     struct target_ipc_perm shm_perm;
2638     abi_ulong shm_segsz;
2639     abi_ulong shm_atime;
2640 #if TARGET_ABI_BITS == 32
2641     abi_ulong __unused1;
2642 #endif
2643     abi_ulong shm_dtime;
2644 #if TARGET_ABI_BITS == 32
2645     abi_ulong __unused2;
2646 #endif
2647     abi_ulong shm_ctime;
2648 #if TARGET_ABI_BITS == 32
2649     abi_ulong __unused3;
2650 #endif
2651     int shm_cpid;
2652     int shm_lpid;
2653     abi_ulong shm_nattch;
2654     unsigned long int __unused4;
2655     unsigned long int __unused5;
2656 };
2657 
target_to_host_shmid_ds(struct shmid_ds * host_sd,abi_ulong target_addr)2658 static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
2659                                                abi_ulong target_addr)
2660 {
2661     struct target_shmid_ds *target_sd;
2662 
2663     if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2664         return -TARGET_EFAULT;
2665     if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
2666         return -TARGET_EFAULT;
2667     __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
2668     __get_user(host_sd->shm_atime, &target_sd->shm_atime);
2669     __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
2670     __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
2671     __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
2672     __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
2673     __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
2674     unlock_user_struct(target_sd, target_addr, 0);
2675     return 0;
2676 }
2677 
host_to_target_shmid_ds(abi_ulong target_addr,struct shmid_ds * host_sd)2678 static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
2679                                                struct shmid_ds *host_sd)
2680 {
2681     struct target_shmid_ds *target_sd;
2682 
2683     if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2684         return -TARGET_EFAULT;
2685     if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
2686         return -TARGET_EFAULT;
2687     __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
2688     __put_user(host_sd->shm_atime, &target_sd->shm_atime);
2689     __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
2690     __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
2691     __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
2692     __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
2693     __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
2694     unlock_user_struct(target_sd, target_addr, 1);
2695     return 0;
2696 }
2697 
2698 struct  target_shminfo {
2699     abi_ulong shmmax;
2700     abi_ulong shmmin;
2701     abi_ulong shmmni;
2702     abi_ulong shmseg;
2703     abi_ulong shmall;
2704 };
2705 
host_to_target_shminfo(abi_ulong target_addr,struct shminfo * host_shminfo)2706 static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
2707                                               struct shminfo *host_shminfo)
2708 {
2709     struct target_shminfo *target_shminfo;
2710     if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
2711         return -TARGET_EFAULT;
2712     __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
2713     __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
2714     __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
2715     __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
2716     __put_user(host_shminfo->shmall, &target_shminfo->shmall);
2717     unlock_user_struct(target_shminfo, target_addr, 1);
2718     return 0;
2719 }
2720 
2721 struct target_shm_info {
2722     int used_ids;
2723     abi_ulong shm_tot;
2724     abi_ulong shm_rss;
2725     abi_ulong shm_swp;
2726     abi_ulong swap_attempts;
2727     abi_ulong swap_successes;
2728 };
2729 
host_to_target_shm_info(abi_ulong target_addr,struct shm_info * host_shm_info)2730 static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
2731                                                struct shm_info *host_shm_info)
2732 {
2733     struct target_shm_info *target_shm_info;
2734     if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
2735         return -TARGET_EFAULT;
2736     __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
2737     __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
2738     __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
2739     __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
2740     __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
2741     __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
2742     unlock_user_struct(target_shm_info, target_addr, 1);
2743     return 0;
2744 }
2745 
do_shmctl(int shmid,int cmd,abi_long buf)2746 static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
2747 {
2748     struct shmid_ds dsarg;
2749     struct shminfo shminfo;
2750     struct shm_info shm_info;
2751     abi_long ret = -TARGET_EINVAL;
2752 
2753     cmd &= 0xff;
2754 
2755     switch(cmd) {
2756     case IPC_STAT:
2757     case IPC_SET:
2758     case SHM_STAT:
2759         if (target_to_host_shmid_ds(&dsarg, buf))
2760             return -TARGET_EFAULT;
2761         ret = get_errno(shmctl(shmid, cmd, &dsarg));
2762         if (host_to_target_shmid_ds(buf, &dsarg))
2763             return -TARGET_EFAULT;
2764         break;
2765     case IPC_INFO:
2766         ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
2767         if (host_to_target_shminfo(buf, &shminfo))
2768             return -TARGET_EFAULT;
2769         break;
2770     case SHM_INFO:
2771         ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
2772         if (host_to_target_shm_info(buf, &shm_info))
2773             return -TARGET_EFAULT;
2774         break;
2775     case IPC_RMID:
2776     case SHM_LOCK:
2777     case SHM_UNLOCK:
2778         ret = get_errno(shmctl(shmid, cmd, NULL));
2779         break;
2780     }
2781 
2782     return ret;
2783 }
2784 
do_shmat(int shmid,abi_ulong shmaddr,int shmflg)2785 static inline abi_ulong do_shmat(int shmid, abi_ulong shmaddr, int shmflg)
2786 {
2787     abi_long raddr;
2788     void *host_raddr;
2789     struct shmid_ds shm_info;
2790     int i,ret;
2791 
2792     /* find out the length of the shared memory segment */
2793     ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
2794     if (is_error(ret)) {
2795         /* can't get length, bail out */
2796         return ret;
2797     }
2798 
2799     mmap_lock();
2800 
2801     if (shmaddr)
2802         host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg);
2803     else {
2804         abi_ulong mmap_start;
2805 
2806         mmap_start = mmap_find_vma(0, shm_info.shm_segsz);
2807 
2808         if (mmap_start == -1) {
2809             errno = ENOMEM;
2810             host_raddr = (void *)-1;
2811         } else
2812             host_raddr = shmat(