(linenum→info "unix/slp.c:2238")

qemu/0.9.1/linux-user/syscall.c

    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, write to the Free Software
   18:  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   19:  */
   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 <sys/types.h>
   31: #include <sys/ipc.h>
   32: #include <sys/msg.h>
   33: #include <sys/wait.h>
   34: #include <sys/time.h>
   35: #include <sys/stat.h>
   36: #include <sys/mount.h>
   37: #include <sys/prctl.h>
   38: #include <sys/resource.h>
   39: #include <sys/mman.h>
   40: #include <sys/swap.h>
   41: #include <signal.h>
   42: #include <sched.h>
   43: #include <sys/socket.h>
   44: #include <sys/uio.h>
   45: #include <sys/poll.h>
   46: #include <sys/times.h>
   47: #include <sys/shm.h>
   48: #include <sys/sem.h>
   49: #include <sys/statfs.h>
   50: #include <utime.h>
   51: #include <sys/sysinfo.h>
   52: //#include <sys/user.h>
   53: #include <netinet/ip.h>
   54: #include <netinet/tcp.h>
   55: 
   56: #define termios host_termios
   57: #define winsize host_winsize
   58: #define termio host_termio
   59: #define sgttyb host_sgttyb /* same as target */
   60: #define tchars host_tchars /* same as target */
   61: #define ltchars host_ltchars /* same as target */
   62: 
   63: #include <linux/termios.h>
   64: #include <linux/unistd.h>
   65: #include <linux/utsname.h>
   66: #include <linux/cdrom.h>
   67: #include <linux/hdreg.h>
   68: #include <linux/soundcard.h>
   69: #include <linux/dirent.h>
   70: #include <linux/kd.h>
   71: 
   72: #include "qemu.h"
   73: 
   74: //#define DEBUG
   75: 
   76: #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
   77:     || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS)
   78: /* 16 bit uid wrappers emulation */
   79: #define USE_UID16
   80: #endif
   81: 
   82: //#include <linux/msdos_fs.h>
   83: #define VFAT_IOCTL_READDIR_BOTH         _IOR('r', 1, struct dirent [2])
   84: #define VFAT_IOCTL_READDIR_SHORT        _IOR('r', 2, struct dirent [2])
   85: 
   86: 
   87: #undef _syscall0
   88: #undef _syscall1
   89: #undef _syscall2
   90: #undef _syscall3
   91: #undef _syscall4
   92: #undef _syscall5
   93: #undef _syscall6
   94: 
   95: #define _syscall0(type,name)            \
   96: type name (void)                        \
   97: {                                       \
   98:         return syscall(__NR_##name);   \
   99: }
  100: 
  101: #define _syscall1(type,name,type1,arg1)         \
  102: type name (type1 arg1)                          \
  103: {                                               \
  104:         return syscall(__NR_##name, arg1);     \
  105: }
  106: 
  107: #define _syscall2(type,name,type1,arg1,type2,arg2)      \
  108: type name (type1 arg1,type2 arg2)                       \
  109: {                                                       \
  110:         return syscall(__NR_##name, arg1, arg2);       \
  111: }
  112: 
  113: #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)   \
  114: type name (type1 arg1,type2 arg2,type3 arg3)                    \
  115: {                                                               \
  116:         return syscall(__NR_##name, arg1, arg2, arg3);         \
  117: }
  118: 
  119: #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)        \
  120: type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4)                         \
  121: {                                                                               \
  122:         return syscall(__NR_##name, arg1, arg2, arg3, arg4);                   \
  123: }
  124: 
  125: #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,        \
  126:                   type5,arg5)                                                 \
  127: type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5)              \
  128: {                                                                               \
  129:         return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5);             \
  130: }
  131: 
  132: 
  133: #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,        \
  134:                   type5,arg5,type6,arg6)                                      \
  135: type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6)   \
  136: {                                                                               \
  137:         return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6);       \
  138: }
  139: 
  140: 
  141: #define __NR_sys_uname __NR_uname
  142: #define __NR_sys_faccessat __NR_faccessat
  143: #define __NR_sys_fchmodat __NR_fchmodat
  144: #define __NR_sys_fchownat __NR_fchownat
  145: #define __NR_sys_getcwd1 __NR_getcwd
  146: #define __NR_sys_getdents __NR_getdents
  147: #define __NR_sys_getdents64 __NR_getdents64
  148: #define __NR_sys_getpriority __NR_getpriority
  149: #define __NR_sys_linkat __NR_linkat
  150: #define __NR_sys_mkdirat __NR_mkdirat
  151: #define __NR_sys_mknodat __NR_mknodat
  152: #define __NR_sys_openat __NR_openat
  153: #define __NR_sys_readlinkat __NR_readlinkat
  154: #define __NR_sys_renameat __NR_renameat
  155: #define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
  156: #define __NR_sys_symlinkat __NR_symlinkat
  157: #define __NR_sys_syslog __NR_syslog
  158: #define __NR_sys_tgkill __NR_tgkill
  159: #define __NR_sys_tkill __NR_tkill
  160: #define __NR_sys_unlinkat __NR_unlinkat
  161: #define __NR_sys_utimensat __NR_utimensat
  162: 
  163: #if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
  164: #define __NR__llseek __NR_lseek
  165: #endif
  166: 
  167: #ifdef __NR_gettid
  168: _syscall0(int, gettid)
  169: #else
  170: /* This is a replacement for the host gettid() and must return a host
  171:    errno. */
  172: static int gettid(void) {
  173:     return -ENOSYS;
  174: }
  175: #endif
  176: _syscall1(int,sys_uname,struct new_utsname *,buf)
  177: #if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
  178: _syscall4(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode,int,flags)
  179: #endif
  180: #if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
  181: _syscall4(int,sys_fchmodat,int,dirfd,const char *,pathname,
  182:           mode_t,mode,int,flags)
  183: #endif
  184: #if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
  185: _syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
  186:           uid_t,owner,gid_t,group,int,flags)
  187: #endif
  188: _syscall2(int,sys_getcwd1,char *,buf,size_t,size)
  189: _syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count);
  190: #if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
  191: _syscall3(int, sys_getdents64, uint, fd, struct dirent64 *, dirp, uint, count);
  192: #endif
  193: _syscall2(int, sys_getpriority, int, which, int, who);
  194: _syscall5(int, _llseek,  uint,  fd, ulong, hi, ulong, lo,
  195:           loff_t *, res, uint, wh);
  196: #if defined(TARGET_NR_linkat) && defined(__NR_linkat)
  197: _syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
  198:           int,newdirfd,const char *,newpath,int,flags)
  199: #endif
  200: #if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
  201: _syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
  202: #endif
  203: #if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
  204: _syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
  205:           mode_t,mode,dev_t,dev)
  206: #endif
  207: #if defined(TARGET_NR_openat) && defined(__NR_openat)
  208: _syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
  209: #endif
  210: #if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
  211: _syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
  212:           char *,buf,size_t,bufsize)
  213: #endif
  214: #if defined(TARGET_NR_renameat) && defined(__NR_renameat)
  215: _syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
  216:           int,newdirfd,const char *,newpath)
  217: #endif
  218: _syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
  219: #if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
  220: _syscall3(int,sys_symlinkat,const char *,oldpath,
  221:           int,newdirfd,const char *,newpath)
  222: #endif
  223: _syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
  224: #if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
  225: _syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
  226: #endif
  227: #if defined(TARGET_NR_tkill) && defined(__NR_tkill)
  228: _syscall2(int,sys_tkill,int,tid,int,sig)
  229: #endif
  230: #ifdef __NR_exit_group
  231: _syscall1(int,exit_group,int,error_code)
  232: #endif
  233: #if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
  234: _syscall1(int,set_tid_address,int *,tidptr)
  235: #endif
  236: #if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
  237: _syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
  238: #endif
  239: #if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
  240: _syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
  241:           const struct timespec *,tsp,int,flags)
  242: #endif
  243: 
  244: extern int personality(int);
  245: extern int flock(int, int);
  246: extern int setfsuid(int);
  247: extern int setfsgid(int);
  248: extern int setresuid(uid_t, uid_t, uid_t);
  249: extern int getresuid(uid_t *, uid_t *, uid_t *);
  250: extern int setresgid(gid_t, gid_t, gid_t);
  251: extern int getresgid(gid_t *, gid_t *, gid_t *);
  252: extern int setgroups(int, gid_t *);
  253: 
  254: #define ERRNO_TABLE_SIZE 1200
  255: 
  256: /* target_to_host_errno_table[] is initialized from
  257:  * host_to_target_errno_table[] in syscall_init(). */
  258: static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
  259: };
  260: 
  261: /*
  262:  * This list is the union of errno values overridden in asm-<arch>/errno.h
  263:  * minus the errnos that are not actually generic to all archs.
  264:  */
  265: static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
  266:     [EIDRM]             = TARGET_EIDRM,
  267:     [ECHRNG]            = TARGET_ECHRNG,
  268:     [EL2NSYNC]          = TARGET_EL2NSYNC,
  269:     [EL3HLT]            = TARGET_EL3HLT,
  270:     [EL3RST]            = TARGET_EL3RST,
  271:     [ELNRNG]            = TARGET_ELNRNG,
  272:     [EUNATCH]           = TARGET_EUNATCH,
  273:     [ENOCSI]            = TARGET_ENOCSI,
  274:     [EL2HLT]            = TARGET_EL2HLT,
  275:     [EDEADLK]           = TARGET_EDEADLK,
  276:     [ENOLCK]            = TARGET_ENOLCK,
  277:     [EBADE]             = TARGET_EBADE,
  278:     [EBADR]             = TARGET_EBADR,
  279:     [EXFULL]            = TARGET_EXFULL,
  280:     [ENOANO]            = TARGET_ENOANO,
  281:     [EBADRQC]           = TARGET_EBADRQC,
  282:     [EBADSLT]           = TARGET_EBADSLT,
  283:     [EBFONT]            = TARGET_EBFONT,
  284:     [ENOSTR]            = TARGET_ENOSTR,
  285:     [ENODATA]           = TARGET_ENODATA,
  286:     [ETIME]             = TARGET_ETIME,
  287:     [ENOSR]             = TARGET_ENOSR,
  288:     [ENONET]            = TARGET_ENONET,
  289:     [ENOPKG]            = TARGET_ENOPKG,
  290:     [EREMOTE]           = TARGET_EREMOTE,
  291:     [ENOLINK]           = TARGET_ENOLINK,
  292:     [EADV]              = TARGET_EADV,
  293:     [ESRMNT]            = TARGET_ESRMNT,
  294:     [ECOMM]             = TARGET_ECOMM,
  295:     [EPROTO]            = TARGET_EPROTO,
  296:     [EDOTDOT]           = TARGET_EDOTDOT,
  297:     [EMULTIHOP]         = TARGET_EMULTIHOP,
  298:     [EBADMSG]           = TARGET_EBADMSG,
  299:     [ENAMETOOLONG]      = TARGET_ENAMETOOLONG,
  300:     [EOVERFLOW]         = TARGET_EOVERFLOW,
  301:     [ENOTUNIQ]          = TARGET_ENOTUNIQ,
  302:     [EBADFD]            = TARGET_EBADFD,
  303:     [EREMCHG]           = TARGET_EREMCHG,
  304:     [ELIBACC]           = TARGET_ELIBACC,
  305:     [ELIBBAD]           = TARGET_ELIBBAD,
  306:     [ELIBSCN]           = TARGET_ELIBSCN,
  307:     [ELIBMAX]           = TARGET_ELIBMAX,
  308:     [ELIBEXEC]          = TARGET_ELIBEXEC,
  309:     [EILSEQ]            = TARGET_EILSEQ,
  310:     [ENOSYS]            = TARGET_ENOSYS,
  311:     [ELOOP]             = TARGET_ELOOP,
  312:     [ERESTART]          = TARGET_ERESTART,
  313:     [ESTRPIPE]          = TARGET_ESTRPIPE,
  314:     [ENOTEMPTY]         = TARGET_ENOTEMPTY,
  315:     [EUSERS]            = TARGET_EUSERS,
  316:     [ENOTSOCK]          = TARGET_ENOTSOCK,
  317:     [EDESTADDRREQ]      = TARGET_EDESTADDRREQ,
  318:     [EMSGSIZE]          = TARGET_EMSGSIZE,
  319:     [EPROTOTYPE]        = TARGET_EPROTOTYPE,
  320:     [ENOPROTOOPT]       = TARGET_ENOPROTOOPT,
  321:     [EPROTONOSUPPORT]   = TARGET_EPROTONOSUPPORT,
  322:     [ESOCKTNOSUPPORT]   = TARGET_ESOCKTNOSUPPORT,
  323:     [EOPNOTSUPP]        = TARGET_EOPNOTSUPP,
  324:     [EPFNOSUPPORT]      = TARGET_EPFNOSUPPORT,
  325:     [EAFNOSUPPORT]      = TARGET_EAFNOSUPPORT,
  326:     [EADDRINUSE]        = TARGET_EADDRINUSE,
  327:     [EADDRNOTAVAIL]     = TARGET_EADDRNOTAVAIL,
  328:     [ENETDOWN]          = TARGET_ENETDOWN,
  329:     [ENETUNREACH]       = TARGET_ENETUNREACH,
  330:     [ENETRESET]         = TARGET_ENETRESET,
  331:     [ECONNABORTED]      = TARGET_ECONNABORTED,
  332:     [ECONNRESET]        = TARGET_ECONNRESET,
  333:     [ENOBUFS]           = TARGET_ENOBUFS,
  334:     [EISCONN]           = TARGET_EISCONN,
  335:     [ENOTCONN]          = TARGET_ENOTCONN,
  336:     [EUCLEAN]           = TARGET_EUCLEAN,
  337:     [ENOTNAM]           = TARGET_ENOTNAM,
  338:     [ENAVAIL]           = TARGET_ENAVAIL,
  339:     [EISNAM]            = TARGET_EISNAM,
  340:     [EREMOTEIO]         = TARGET_EREMOTEIO,
  341:     [ESHUTDOWN]         = TARGET_ESHUTDOWN,
  342:     [ETOOMANYREFS]      = TARGET_ETOOMANYREFS,
  343:     [ETIMEDOUT]         = TARGET_ETIMEDOUT,
  344:     [ECONNREFUSED]      = TARGET_ECONNREFUSED,
  345:     [EHOSTDOWN]         = TARGET_EHOSTDOWN,
  346:     [EHOSTUNREACH]      = TARGET_EHOSTUNREACH,
  347:     [EALREADY]          = TARGET_EALREADY,
  348:     [EINPROGRESS]       = TARGET_EINPROGRESS,
  349:     [ESTALE]            = TARGET_ESTALE,
  350:     [ECANCELED]         = TARGET_ECANCELED,
  351:     [ENOMEDIUM]         = TARGET_ENOMEDIUM,
  352:     [EMEDIUMTYPE]       = TARGET_EMEDIUMTYPE,
  353: #ifdef ENOKEY
  354:     [ENOKEY]            = TARGET_ENOKEY,
  355: #endif
  356: #ifdef EKEYEXPIRED
  357:     [EKEYEXPIRED]       = TARGET_EKEYEXPIRED,
  358: #endif
  359: #ifdef EKEYREVOKED
  360:     [EKEYREVOKED]       = TARGET_EKEYREVOKED,
  361: #endif
  362: #ifdef EKEYREJECTED
  363:     [EKEYREJECTED]      = TARGET_EKEYREJECTED,
  364: #endif
  365: #ifdef EOWNERDEAD
  366:     [EOWNERDEAD]        = TARGET_EOWNERDEAD,
  367: #endif
  368: #ifdef ENOTRECOVERABLE
  369:     [ENOTRECOVERABLE]   = TARGET_ENOTRECOVERABLE,
  370: #endif
  371: };
  372: 
  373: static inline int host_to_target_errno(int err)
  374: {
  375:     if(host_to_target_errno_table[err])
  376:         return host_to_target_errno_table[err];
  377:     return err;
  378: }
  379: 
  380: static inline int target_to_host_errno(int err)
  381: {
  382:     if (target_to_host_errno_table[err])
  383:         return target_to_host_errno_table[err];
  384:     return err;
  385: }
  386: 
  387: static inline abi_long get_errno(abi_long ret)
  388: {
  389:     if (ret == -1)
  390:         return -host_to_target_errno(errno);
  391:     else
  392:         return ret;
  393: }
  394: 
  395: static inline int is_error(abi_long ret)
  396: {
  397:     return (abi_ulong)ret >= (abi_ulong)(-4096);
  398: }
  399: 
  400: char *target_strerror(int err)
  401: {
  402:     return strerror(target_to_host_errno(err));
  403: }
  404: 
  405: static abi_ulong target_brk;
  406: static abi_ulong target_original_brk;
  407: 
  408: void target_set_brk(abi_ulong new_brk)
  409: {
  410:     target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
  411: }
  412: 
  413: /* do_brk() must return target values and target errnos. */
  414: abi_long do_brk(abi_ulong new_brk)
  415: {
  416:     abi_ulong brk_page;
  417:     abi_long mapped_addr;
  418:     int new_alloc_size;
  419: 
  420:     if (!new_brk)
  421:         return target_brk;
  422:     if (new_brk < target_original_brk)
  423:         return -TARGET_ENOMEM;
  424: 
  425:     brk_page = HOST_PAGE_ALIGN(target_brk);
  426: 
  427:     /* If the new brk is less than this, set it and we're done... */
  428:     if (new_brk < brk_page) {
  429:         target_brk = new_brk;
  430:         return target_brk;
  431:     }
  432: 
  433:     /* We need to allocate more memory after the brk... */
  434:     new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
  435:     mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
  436:                                         PROT_READ|PROT_WRITE,
  437:                                         MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
  438:     if (is_error(mapped_addr)) {
  439:         return mapped_addr;
  440:     } else {
  441:         target_brk = new_brk;
  442:         return target_brk;
  443:     }
  444: }
  445: 
  446: static inline abi_long copy_from_user_fdset(fd_set *fds,
  447:                                             abi_ulong target_fds_addr,
  448:                                             int n)
  449: {
  450:     int i, nw, j, k;
  451:     abi_ulong b, *target_fds;
  452: 
  453:     nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
  454:     if (!(target_fds = lock_user(VERIFY_READ,
  455:                                  target_fds_addr,
  456:                                  sizeof(abi_ulong) * nw,
  457:                                  1)))
  458:         return -TARGET_EFAULT;
  459: 
  460:     FD_ZERO(fds);
  461:     k = 0;
  462:     for (i = 0; i < nw; i++) {
  463:         /* grab the abi_ulong */
  464:         __get_user(b, &target_fds[i]);
  465:         for (j = 0; j < TARGET_ABI_BITS; j++) {
  466:             /* check the bit inside the abi_ulong */
  467:             if ((b >> j) & 1)
  468:                 FD_SET(k, fds);
  469:             k++;
  470:         }
  471:     }
  472: 
  473:     unlock_user(target_fds, target_fds_addr, 0);
  474: 
  475:     return 0;
  476: }
  477: 
  478: static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
  479:                                           const fd_set *fds,
  480:                                           int n)
  481: {
  482:     int i, nw, j, k;
  483:     abi_long v;
  484:     abi_ulong *target_fds;
  485: