diff options
-rw-r--r-- | linux-user/ioctls.h | 6 | ||||
-rw-r--r-- | linux-user/mmap.c | 4 | ||||
-rw-r--r-- | linux-user/signal.c | 4 | ||||
-rw-r--r-- | linux-user/socket.h | 381 | ||||
-rw-r--r-- | linux-user/syscall.c | 188 | ||||
-rw-r--r-- | user-exec.c | 8 |
6 files changed, 413 insertions, 178 deletions
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 8a4776756a..439c2a9e32 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -88,8 +88,6 @@ #endif IOCTL(SIOCATMARK, 0, TYPE_NULL) - IOCTL(SIOCADDRT, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtentry))) - IOCTL(SIOCDELRT, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtentry))) IOCTL(SIOCGIFNAME, IOC_RW, MK_PTR(TYPE_INT)) IOCTL(SIOCGIFFLAGS, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq))) IOCTL(SIOCSIFFLAGS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_short_ifreq))) @@ -379,3 +377,7 @@ MK_PTR(MK_STRUCT(STRUCT_dm_ioctl))) IOCTL_SPECIAL(DM_DEV_SET_GEOMETRY, IOC_RW, do_ioctl_dm, MK_PTR(MK_STRUCT(STRUCT_dm_ioctl))) + IOCTL_SPECIAL(SIOCADDRT, IOC_W, do_ioctl_rt, + MK_PTR(MK_STRUCT(STRUCT_rtentry))) + IOCTL_SPECIAL(SIOCDELRT, IOC_W, do_ioctl_rt, + MK_PTR(MK_STRUCT(STRUCT_rtentry))) diff --git a/linux-user/mmap.c b/linux-user/mmap.c index b412e3fe0a..de2219768d 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -483,6 +483,10 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, if (!(flags & MAP_ANONYMOUS)) { p = mmap(g2h(start), len, prot, flags | MAP_FIXED, fd, host_offset); + if (p == MAP_FAILED) { + munmap(g2h(start), host_len); + goto fail; + } host_start += offset - host_offset; } start = h2g(host_start); diff --git a/linux-user/signal.c b/linux-user/signal.c index c4e20dc8b9..d84e189bc8 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -102,14 +102,14 @@ static inline int sas_ss_flags(unsigned long sp) int host_to_target_signal(int sig) { - if (sig >= _NSIG) + if (sig < 0 || sig >= _NSIG) return sig; return host_to_target_signal_table[sig]; } int target_to_host_signal(int sig) { - if (sig >= _NSIG) + if (sig < 0 || sig >= _NSIG) return sig; return target_to_host_signal_table[sig]; } diff --git a/linux-user/socket.h b/linux-user/socket.h index 339cae5a16..ae17959902 100644 --- a/linux-user/socket.h +++ b/linux-user/socket.h @@ -1,91 +1,104 @@ #if defined(TARGET_MIPS) - // MIPS special values for constants - - /* - * For setsockopt(2) - * - * This defines are ABI conformant as far as Linux supports these ... - */ - #define TARGET_SOL_SOCKET 0xffff - - #define TARGET_SO_DEBUG 0x0001 /* Record debugging information. */ - #define TARGET_SO_REUSEADDR 0x0004 /* Allow reuse of local addresses. */ - #define TARGET_SO_KEEPALIVE 0x0008 /* Keep connections alive and send - SIGPIPE when they die. */ - #define TARGET_SO_DONTROUTE 0x0010 /* Don't do local routing. */ - #define TARGET_SO_BROADCAST 0x0020 /* Allow transmission of - broadcast messages. */ - #define TARGET_SO_LINGER 0x0080 /* Block on close of a reliable - socket to transmit pending data. */ - #define TARGET_SO_OOBINLINE 0x0100 /* Receive out-of-band data in-band. */ - #if 0 - To add: #define TARGET_SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */ - #endif - - #define TARGET_SO_TYPE 0x1008 /* Compatible name for SO_STYLE. */ - #define TARGET_SO_STYLE SO_TYPE /* Synonym */ - #define TARGET_SO_ERROR 0x1007 /* get error status and clear */ - #define TARGET_SO_SNDBUF 0x1001 /* Send buffer size. */ - #define TARGET_SO_RCVBUF 0x1002 /* Receive buffer. */ - #define TARGET_SO_SNDLOWAT 0x1003 /* send low-water mark */ - #define TARGET_SO_RCVLOWAT 0x1004 /* receive low-water mark */ - #define TARGET_SO_SNDTIMEO 0x1005 /* send timeout */ - #define TARGET_SO_RCVTIMEO 0x1006 /* receive timeout */ - #define TARGET_SO_ACCEPTCONN 0x1009 - - /* linux-specific, might as well be the same as on i386 */ - #define TARGET_SO_NO_CHECK 11 - #define TARGET_SO_PRIORITY 12 - #define TARGET_SO_BSDCOMPAT 14 - - #define TARGET_SO_PASSCRED 17 - #define TARGET_SO_PEERCRED 18 - - /* Security levels - as per NRL IPv6 - don't actually do anything */ - #define TARGET_SO_SECURITY_AUTHENTICATION 22 - #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT 23 - #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK 24 - - #define TARGET_SO_BINDTODEVICE 25 - - /* Socket filtering */ - #define TARGET_SO_ATTACH_FILTER 26 - #define TARGET_SO_DETACH_FILTER 27 - - #define TARGET_SO_PEERNAME 28 - #define TARGET_SO_TIMESTAMP 29 - #define SCM_TIMESTAMP SO_TIMESTAMP - - #define TARGET_SO_PEERSEC 30 - #define TARGET_SO_SNDBUFFORCE 31 - #define TARGET_SO_RCVBUFFORCE 33 - - /** sock_type - Socket types - * - * Please notice that for binary compat reasons MIPS has to - * override the enum sock_type in include/linux/net.h, so - * we define ARCH_HAS_SOCKET_TYPES here. - * - * @SOCK_DGRAM - datagram (conn.less) socket - * @SOCK_STREAM - stream (connection) socket - * @SOCK_RAW - raw socket - * @SOCK_RDM - reliably-delivered message - * @SOCK_SEQPACKET - sequential packet socket - * @SOCK_PACKET - linux specific way of getting packets at the dev level. - * For writing rarp and other similar things on the user level. - */ - enum sock_type { - TARGET_SOCK_DGRAM = 1, - TARGET_SOCK_STREAM = 2, - TARGET_SOCK_RAW = 3, - TARGET_SOCK_RDM = 4, - TARGET_SOCK_SEQPACKET = 5, - TARGET_SOCK_DCCP = 6, - TARGET_SOCK_PACKET = 10, - }; - - #define TARGET_SOCK_MAX (SOCK_PACKET + 1) + /* MIPS special values for constants */ + + /* + * For setsockopt(2) + * + * This defines are ABI conformant as far as Linux supports these ... + */ + #define TARGET_SOL_SOCKET 0xffff + + #define TARGET_SO_DEBUG 0x0001 /* Record debugging information. */ + #define TARGET_SO_REUSEADDR 0x0004 /* Allow reuse of local addresses. */ + #define TARGET_SO_KEEPALIVE 0x0008 /* Keep connections alive and send + SIGPIPE when they die. */ + #define TARGET_SO_DONTROUTE 0x0010 /* Don't do local routing. */ + #define TARGET_SO_BROADCAST 0x0020 /* Allow transmission of + broadcast messages. */ + #define TARGET_SO_LINGER 0x0080 /* Block on close of a reliable + * socket to transmit pending data. + */ + #define TARGET_SO_OOBINLINE 0x0100 /* Receive out-of-band data in-band. + */ + #if 0 + /* To add: Allow local address and port reuse. */ + #define TARGET_SO_REUSEPORT 0x0200 + #endif + + #define TARGET_SO_TYPE 0x1008 /* Compatible name for SO_STYLE. */ + #define TARGET_SO_STYLE SO_TYPE /* Synonym */ + #define TARGET_SO_ERROR 0x1007 /* get error status and clear */ + #define TARGET_SO_SNDBUF 0x1001 /* Send buffer size. */ + #define TARGET_SO_RCVBUF 0x1002 /* Receive buffer. */ + #define TARGET_SO_SNDLOWAT 0x1003 /* send low-water mark */ + #define TARGET_SO_RCVLOWAT 0x1004 /* receive low-water mark */ + #define TARGET_SO_SNDTIMEO 0x1005 /* send timeout */ + #define TARGET_SO_RCVTIMEO 0x1006 /* receive timeout */ + #define TARGET_SO_ACCEPTCONN 0x1009 + + /* linux-specific, might as well be the same as on i386 */ + #define TARGET_SO_NO_CHECK 11 + #define TARGET_SO_PRIORITY 12 + #define TARGET_SO_BSDCOMPAT 14 + + #define TARGET_SO_PASSCRED 17 + #define TARGET_SO_PEERCRED 18 + + /* Security levels - as per NRL IPv6 - don't actually do anything */ + #define TARGET_SO_SECURITY_AUTHENTICATION 22 + #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT 23 + #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK 24 + + #define TARGET_SO_BINDTODEVICE 25 + + /* Socket filtering */ + #define TARGET_SO_ATTACH_FILTER 26 + #define TARGET_SO_DETACH_FILTER 27 + + #define TARGET_SO_PEERNAME 28 + #define TARGET_SO_TIMESTAMP 29 + #define SCM_TIMESTAMP SO_TIMESTAMP + + #define TARGET_SO_PEERSEC 30 + #define TARGET_SO_SNDBUFFORCE 31 + #define TARGET_SO_RCVBUFFORCE 33 + + /** sock_type - Socket types + * + * Please notice that for binary compat reasons MIPS has to + * override the enum sock_type in include/linux/net.h, so + * we define ARCH_HAS_SOCKET_TYPES here. + * + * @SOCK_DGRAM - datagram (conn.less) socket + * @SOCK_STREAM - stream (connection) socket + * @SOCK_RAW - raw socket + * @SOCK_RDM - reliably-delivered message + * @SOCK_SEQPACKET - sequential packet socket + * @SOCK_DCCP - Datagram Congestion Control Protocol socket + * @SOCK_PACKET - linux specific way of getting packets at the dev level. + * For writing rarp and other similar things on the user + * level. + * @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag. + * @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag. + */ + + #define ARCH_HAS_SOCKET_TYPES 1 + + enum sock_type { + TARGET_SOCK_DGRAM = 1, + TARGET_SOCK_STREAM = 2, + TARGET_SOCK_RAW = 3, + TARGET_SOCK_RDM = 4, + TARGET_SOCK_SEQPACKET = 5, + TARGET_SOCK_DCCP = 6, + TARGET_SOCK_PACKET = 10, + TARGET_SOCK_CLOEXEC = 02000000, + TARGET_SOCK_NONBLOCK = 0200, + }; + + #define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1) + #define TARGET_SOCK_TYPE_MASK 0xf /* Covers up to TARGET_SOCK_MAX-1. */ #elif defined(TARGET_ALPHA) @@ -156,61 +169,167 @@ /* Instruct lower device to use last 4-bytes of skb data as FCS */ #define TARGET_SO_NOFCS 43 + /** sock_type - Socket types + * + * Please notice that for binary compat reasons ALPHA has to + * override the enum sock_type in include/linux/net.h, so + * we define ARCH_HAS_SOCKET_TYPES here. + * + * @SOCK_DGRAM - datagram (conn.less) socket + * @SOCK_STREAM - stream (connection) socket + * @SOCK_RAW - raw socket + * @SOCK_RDM - reliably-delivered message + * @SOCK_SEQPACKET - sequential packet socket + * @SOCK_DCCP - Datagram Congestion Control Protocol socket + * @SOCK_PACKET - linux specific way of getting packets at the dev level. + * For writing rarp and other similar things on the user + * level. + * @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag. + * @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag. + */ + + #define ARCH_HAS_SOCKET_TYPES 1 + + enum sock_type { + TARGET_SOCK_STREAM = 1, + TARGET_SOCK_DGRAM = 2, + TARGET_SOCK_RAW = 3, + TARGET_SOCK_RDM = 4, + TARGET_SOCK_SEQPACKET = 5, + TARGET_SOCK_DCCP = 6, + TARGET_SOCK_PACKET = 10, + TARGET_SOCK_CLOEXEC = 010000000, + TARGET_SOCK_NONBLOCK = 010000000000, + }; + + #define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1) + #define TARGET_SOCK_TYPE_MASK 0xf /* Covers up to TARGET_SOCK_MAX-1. */ #else - /* For setsockopt(2) */ - #define TARGET_SOL_SOCKET 1 - - #define TARGET_SO_DEBUG 1 - #define TARGET_SO_REUSEADDR 2 - #define TARGET_SO_TYPE 3 - #define TARGET_SO_ERROR 4 - #define TARGET_SO_DONTROUTE 5 - #define TARGET_SO_BROADCAST 6 - #define TARGET_SO_SNDBUF 7 - #define TARGET_SO_RCVBUF 8 - #define TARGET_SO_SNDBUFFORCE 32 - #define TARGET_SO_RCVBUFFORCE 33 - #define TARGET_SO_KEEPALIVE 9 - #define TARGET_SO_OOBINLINE 10 - #define TARGET_SO_NO_CHECK 11 - #define TARGET_SO_PRIORITY 12 - #define TARGET_SO_LINGER 13 - #define TARGET_SO_BSDCOMPAT 14 - /* To add :#define TARGET_SO_REUSEPORT 15 */ +#if defined(TARGET_SPARC) + /** sock_type - Socket types + * + * Please notice that for binary compat reasons SPARC has to + * override the enum sock_type in include/linux/net.h, so + * we define ARCH_HAS_SOCKET_TYPES here. + * + * @SOCK_DGRAM - datagram (conn.less) socket + * @SOCK_STREAM - stream (connection) socket + * @SOCK_RAW - raw socket + * @SOCK_RDM - reliably-delivered message + * @SOCK_SEQPACKET - sequential packet socket + * @SOCK_DCCP - Datagram Congestion Control Protocol socket + * @SOCK_PACKET - linux specific way of getting packets at the dev level. + * For writing rarp and other similar things on the user + * level. + * @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag. + * @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag. + */ + + #define ARCH_HAS_SOCKET_TYPES 1 + + enum sock_type { + TARGET_SOCK_STREAM = 1, + TARGET_SOCK_DGRAM = 2, + TARGET_SOCK_RAW = 3, + TARGET_SOCK_RDM = 4, + TARGET_SOCK_SEQPACKET = 5, + TARGET_SOCK_DCCP = 6, + TARGET_SOCK_PACKET = 10, + TARGET_SOCK_CLOEXEC = 020000000, + TARGET_SOCK_NONBLOCK = 040000, + }; + + #define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1) + #define TARGET_SOCK_TYPE_MASK 0xf /* Covers up to TARGET_SOCK_MAX-1. */ +#endif + + /* For setsockopt(2) */ + #define TARGET_SOL_SOCKET 1 + + #define TARGET_SO_DEBUG 1 + #define TARGET_SO_REUSEADDR 2 + #define TARGET_SO_TYPE 3 + #define TARGET_SO_ERROR 4 + #define TARGET_SO_DONTROUTE 5 + #define TARGET_SO_BROADCAST 6 + #define TARGET_SO_SNDBUF 7 + #define TARGET_SO_RCVBUF 8 + #define TARGET_SO_SNDBUFFORCE 32 + #define TARGET_SO_RCVBUFFORCE 33 + #define TARGET_SO_KEEPALIVE 9 + #define TARGET_SO_OOBINLINE 10 + #define TARGET_SO_NO_CHECK 11 + #define TARGET_SO_PRIORITY 12 + #define TARGET_SO_LINGER 13 + #define TARGET_SO_BSDCOMPAT 14 + /* To add :#define TARGET_SO_REUSEPORT 15 */ #if defined(TARGET_PPC) - #define TARGET_SO_RCVLOWAT 16 - #define TARGET_SO_SNDLOWAT 17 - #define TARGET_SO_RCVTIMEO 18 - #define TARGET_SO_SNDTIMEO 19 - #define TARGET_SO_PASSCRED 20 - #define TARGET_SO_PEERCRED 21 + #define TARGET_SO_RCVLOWAT 16 + #define TARGET_SO_SNDLOWAT 17 + #define TARGET_SO_RCVTIMEO 18 + #define TARGET_SO_SNDTIMEO 19 + #define TARGET_SO_PASSCRED 20 + #define TARGET_SO_PEERCRED 21 #else - #define TARGET_SO_PASSCRED 16 - #define TARGET_SO_PEERCRED 17 - #define TARGET_SO_RCVLOWAT 18 - #define TARGET_SO_SNDLOWAT 19 - #define TARGET_SO_RCVTIMEO 20 - #define TARGET_SO_SNDTIMEO 21 + #define TARGET_SO_PASSCRED 16 + #define TARGET_SO_PEERCRED 17 + #define TARGET_SO_RCVLOWAT 18 + #define TARGET_SO_SNDLOWAT 19 + #define TARGET_SO_RCVTIMEO 20 + #define TARGET_SO_SNDTIMEO 21 #endif - /* Security levels - as per NRL IPv6 - don't actually do anything */ - #define TARGET_SO_SECURITY_AUTHENTICATION 22 - #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT 23 - #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK 24 + /* Security levels - as per NRL IPv6 - don't actually do anything */ + #define TARGET_SO_SECURITY_AUTHENTICATION 22 + #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT 23 + #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK 24 - #define TARGET_SO_BINDTODEVICE 25 + #define TARGET_SO_BINDTODEVICE 25 - /* Socket filtering */ - #define TARGET_SO_ATTACH_FILTER 26 - #define TARGET_SO_DETACH_FILTER 27 + /* Socket filtering */ + #define TARGET_SO_ATTACH_FILTER 26 + #define TARGET_SO_DETACH_FILTER 27 + + #define TARGET_SO_PEERNAME 28 + #define TARGET_SO_TIMESTAMP 29 + #define TARGET_SCM_TIMESTAMP TARGET_SO_TIMESTAMP - #define TARGET_SO_PEERNAME 28 - #define TARGET_SO_TIMESTAMP 29 - #define TARGET_SCM_TIMESTAMP TARGET_SO_TIMESTAMP + #define TARGET_SO_ACCEPTCONN 30 - #define TARGET_SO_ACCEPTCONN 30 + #define TARGET_SO_PEERSEC 31 + +#endif - #define TARGET_SO_PEERSEC 31 +#ifndef ARCH_HAS_SOCKET_TYPES + /** sock_type - Socket types - default values + * + * + * @SOCK_STREAM - stream (connection) socket + * @SOCK_DGRAM - datagram (conn.less) socket + * @SOCK_RAW - raw socket + * @SOCK_RDM - reliably-delivered message + * @SOCK_SEQPACKET - sequential packet socket + * @SOCK_DCCP - Datagram Congestion Control Protocol socket + * @SOCK_PACKET - linux specific way of getting packets at the dev level. + * For writing rarp and other similar things on the user + * level. + * @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag. + * @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag. + */ + enum sock_type { + TARGET_SOCK_STREAM = 1, + TARGET_SOCK_DGRAM = 2, + TARGET_SOCK_RAW = 3, + TARGET_SOCK_RDM = 4, + TARGET_SOCK_SEQPACKET = 5, + TARGET_SOCK_DCCP = 6, + TARGET_SOCK_PACKET = 10, + TARGET_SOCK_CLOEXEC = 02000000, + TARGET_SOCK_NONBLOCK = 04000, + }; + + #define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1) + #define TARGET_SOCK_TYPE_MASK 0xf /* Covers up to TARGET_SOCK_MAX-1. */ #endif diff --git a/linux-user/syscall.c b/linux-user/syscall.c index cdd0c28fff..a6a7828cc3 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -105,6 +105,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base, #include <linux/vt.h> #include <linux/dm-ioctl.h> #include <linux/reboot.h> +#include <linux/route.h> #include "linux_loop.h" #include "cpu-uname.h" @@ -338,6 +339,7 @@ static int sys_openat(int dirfd, const char *pathname, int flags, mode_t mode) } #endif +#ifdef TARGET_NR_utimensat #ifdef CONFIG_UTIMENSAT static int sys_utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags) @@ -347,12 +349,19 @@ static int sys_utimensat(int dirfd, const char *pathname, else return utimensat(dirfd, pathname, times, flags); } -#else -#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat) +#elif defined(__NR_utimensat) +#define __NR_sys_utimensat __NR_utimensat _syscall4(int,sys_utimensat,int,dirfd,const char *,pathname, const struct timespec *,tsp,int,flags) +#else +static int sys_utimensat(int dirfd, const char *pathname, + const struct timespec times[2], int flags) +{ + errno = ENOSYS; + return -1; +} #endif -#endif /* CONFIG_UTIMENSAT */ +#endif /* TARGET_NR_utimensat */ #ifdef CONFIG_INOTIFY #include <sys/inotify.h> @@ -1696,31 +1705,36 @@ static void unlock_iovec(struct iovec *vec, abi_ulong target_addr, free(vec); } -/* do_socket() Must return target values and target errnos. */ -static abi_long do_socket(int domain, int type, int protocol) +static inline void target_to_host_sock_type(int *type) { -#if defined(TARGET_MIPS) - switch(type) { + int host_type = 0; + int target_type = *type; + + switch (target_type & TARGET_SOCK_TYPE_MASK) { case TARGET_SOCK_DGRAM: - type = SOCK_DGRAM; + host_type = SOCK_DGRAM; break; case TARGET_SOCK_STREAM: - type = SOCK_STREAM; - break; - case TARGET_SOCK_RAW: - type = SOCK_RAW; + host_type = SOCK_STREAM; break; - case TARGET_SOCK_RDM: - type = SOCK_RDM; - break; - case TARGET_SOCK_SEQPACKET: - type = SOCK_SEQPACKET; - break; - case TARGET_SOCK_PACKET: - type = SOCK_PACKET; + default: + host_type = target_type & TARGET_SOCK_TYPE_MASK; break; } -#endif + if (target_type & TARGET_SOCK_CLOEXEC) { + host_type |= SOCK_CLOEXEC; + } + if (target_type & TARGET_SOCK_NONBLOCK) { + host_type |= SOCK_NONBLOCK; + } + *type = host_type; +} + +/* do_socket() Must return target values and target errnos. */ +static abi_long do_socket(int domain, int type, int protocol) +{ + target_to_host_sock_type(&type); + if (domain == PF_NETLINK) return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */ return get_errno(socket(domain, type, protocol)); @@ -1953,6 +1967,8 @@ static abi_long do_socketpair(int domain, int type, int protocol, int tab[2]; abi_long ret; + target_to_host_sock_type(&type); + ret = get_errno(socketpair(domain, type, protocol, tab)); if (!is_error(ret)) { if (put_user_s32(tab[0], target_tab_addr) @@ -3551,6 +3567,69 @@ out: return ret; } +static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp, + int fd, abi_long cmd, abi_long arg) +{ + const argtype *arg_type = ie->arg_type; + const StructEntry *se; + const argtype *field_types; + const int *dst_offsets, *src_offsets; + int target_size; + void *argptr; + abi_ulong *target_rt_dev_ptr; + unsigned long *host_rt_dev_ptr; + abi_long ret; + int i; + + assert(ie->access == IOC_W); + assert(*arg_type == TYPE_PTR); + arg_type++; + assert(*arg_type == TYPE_STRUCT); + target_size = thunk_type_size(arg_type, 0); + argptr = lock_user(VERIFY_READ, arg, target_size, 1); + if (!argptr) { + return -TARGET_EFAULT; + } + arg_type++; + assert(*arg_type == (int)STRUCT_rtentry); + se = struct_entries + *arg_type++; + assert(se->convert[0] == NULL); + /* convert struct here to be able to catch rt_dev string */ + field_types = se->field_types; + dst_offsets = se->field_offsets[THUNK_HOST]; + src_offsets = se->field_offsets[THUNK_TARGET]; + for (i = 0; i < se->nb_fields; i++) { + if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) { + assert(*field_types == TYPE_PTRVOID); + target_rt_dev_ptr = (abi_ulong *)(argptr + src_offsets[i]); + host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]); + if (*target_rt_dev_ptr != 0) { + *host_rt_dev_ptr = (unsigned long)lock_user_string( + tswapal(*target_rt_dev_ptr)); + if (!*host_rt_dev_ptr) { + unlock_user(argptr, arg, 0); + return -TARGET_EFAULT; + } + } else { + *host_rt_dev_ptr = 0; + } + field_types++; + continue; + } + field_types = thunk_convert(buf_temp + dst_offsets[i], + argptr + src_offsets[i], + field_types, THUNK_HOST); + } + unlock_user(argptr, arg, 0); + + ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); + if (*host_rt_dev_ptr != 0) { + unlock_user((void *)*host_rt_dev_ptr, + *target_rt_dev_ptr, 0); + } + return ret; +} + static IOCTLEntry ioctl_entries[] = { #define IOCTL(cmd, access, ...) \ { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } }, @@ -4973,6 +5052,30 @@ static int open_self_auxv(void *cpu_env, int fd) return 0; } +static int is_proc_myself(const char *filename, const char *entry) +{ + if (!strncmp(filename, "/proc/", strlen("/proc/"))) { + filename += strlen("/proc/"); + if (!strncmp(filename, "self/", strlen("self/"))) { + filename += strlen("self/"); + } else if (*filename >= '1' && *filename <= '9') { + char myself[80]; + snprintf(myself, sizeof(myself), "%d/", getpid()); + if (!strncmp(filename, myself, strlen(myself))) { + filename += strlen(myself); + } else { + return 0; + } + } else { + return 0; + } + if (!strcmp(filename, entry)) { + return 1; + } + } + return 0; +} + static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode) { struct fake_open { @@ -4981,15 +5084,14 @@ static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode) }; const struct fake_open *fake_open; static const struct fake_open fakes[] = { - { "/proc/self/maps", open_self_maps }, - { "/proc/self/stat", open_self_stat }, - { "/proc/self/auxv", open_self_auxv }, + { "maps", open_self_maps }, + { "stat", open_self_stat }, + { "auxv", open_self_auxv }, { NULL, NULL } }; for (fake_open = fakes; fake_open->filename; fake_open++) { - if (!strncmp(pathname, fake_open->filename, - strlen(fake_open->filename))) { + if (is_proc_myself(pathname, fake_open->filename)) { break; } } @@ -6262,20 +6364,18 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif case TARGET_NR_readlink: { - void *p2, *temp; + void *p2; p = lock_user_string(arg1); p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0); - if (!p || !p2) + if (!p || !p2) { ret = -TARGET_EFAULT; - else { - if (strncmp((const char *)p, "/proc/self/exe", 14) == 0) { - char real[PATH_MAX]; - temp = realpath(exec_path,real); - ret = (temp==NULL) ? get_errno(-1) : strlen(real) ; - snprintf((char *)p2, arg3, "%s", real); - } - else - ret = get_errno(readlink(path(p), p2, arg3)); + } else if (is_proc_myself((const char *)p, "exe")) { + char real[PATH_MAX], *temp; + temp = realpath(exec_path, real); + ret = temp == NULL ? get_errno(-1) : strlen(real) ; + snprintf((char *)p2, arg3, "%s", real); + } else { + ret = get_errno(readlink(path(p), p2, arg3)); } unlock_user(p2, arg2, ret); unlock_user(p, arg1, 0); @@ -6287,10 +6387,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, void *p2; p = lock_user_string(arg2); p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0); - if (!p || !p2) - ret = -TARGET_EFAULT; - else + if (!p || !p2) { + ret = -TARGET_EFAULT; + } else if (is_proc_myself((const char *)p, "exe")) { + char real[PATH_MAX], *temp; + temp = realpath(exec_path, real); + ret = temp == NULL ? get_errno(-1) : strlen(real) ; + snprintf((char *)p2, arg4, "%s", real); + } else { ret = get_errno(readlinkat(arg1, path(p), p2, arg4)); + } unlock_user(p2, arg3, ret); unlock_user(p, arg2, 0); } @@ -8536,7 +8642,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, goto unimplemented_nowarn; #endif -#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat) +#if defined(TARGET_NR_utimensat) case TARGET_NR_utimensat: { struct timespec *tsp, ts[2]; diff --git a/user-exec.c b/user-exec.c index fa7f1f1de9..57c8e8de26 100644 --- a/user-exec.c +++ b/user-exec.c @@ -20,6 +20,7 @@ #include "cpu.h" #include "disas/disas.h" #include "tcg.h" +#include "qemu/bitops.h" #undef EAX #undef ECX @@ -441,8 +442,11 @@ int cpu_signal_handler(int host_signum, void *pinfo, #else pc = uc->uc_mcontext.arm_pc; #endif - /* XXX: compute is_write */ - is_write = 0; + + /* error_code is the FSR value, in which bit 11 is WnR (assuming a v6 or + * later processor; on v5 we will always report this as a read). + */ + is_write = extract32(uc->uc_mcontext.error_code, 11, 1); return handle_cpu_signal(pc, (unsigned long)info->si_addr, is_write, &uc->uc_sigmask, puc); |