Merge remote-tracking branch 'riku/linux-user-for-upstream' into staging

# By Andreas Schwab (2) and others
# Via Riku Voipio
* riku/linux-user-for-upstream:
  linux-user: Do not ignore mmap failure from host
  linux-user: improve target_to_host_sock_type conversion
  user-exec.c: Set is_write correctly in the ARM cpu_signal_handler()
  linux-user: Fix sys_utimensat (would not compile on old glibc)
  linux-user: fix signal number range check
  linux-user: add SIOCADDRT/SIOCDELRT support
  linux-user: handle /proc/$$ like /proc/self

Message-id: cover.1373051589.git.riku.voipio@linaro.org
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Anthony Liguori 2013-07-10 10:54:09 -05:00
commit 9f9a03b981
6 changed files with 404 additions and 169 deletions

View File

@ -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)))

View File

@ -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);

View File

@ -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];
}

View File

@ -1,91 +1,104 @@
#if defined(TARGET_MIPS)
// MIPS special values for constants
/* MIPS special values for constants */
/*
* For setsockopt(2)
*
* This defines are ABI conformant as far as Linux supports these ...
*/
#define TARGET_SOL_SOCKET 0xffff
/*
* 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_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
#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
/* 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
#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
/* 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 SCM_TIMESTAMP SO_TIMESTAMP
#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
#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,
};
/** 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 TARGET_SOCK_MAX (SOCK_PACKET + 1)
#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
#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 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 */
#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
#define TARGET_SO_PEERSEC 31
#endif
#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

View File

@ -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);
}
static inline void target_to_host_sock_type(int *type)
{
int host_type = 0;
int target_type = *type;
switch (target_type & TARGET_SOCK_TYPE_MASK) {
case TARGET_SOCK_DGRAM:
host_type = SOCK_DGRAM;
break;
case TARGET_SOCK_STREAM:
host_type = SOCK_STREAM;
break;
default:
host_type = target_type & TARGET_SOCK_TYPE_MASK;
break;
}
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)
{
#if defined(TARGET_MIPS)
switch(type) {
case TARGET_SOCK_DGRAM:
type = SOCK_DGRAM;
break;
case TARGET_SOCK_STREAM:
type = SOCK_STREAM;
break;
case TARGET_SOCK_RAW:
type = SOCK_RAW;
break;
case TARGET_SOCK_RDM:
type = SOCK_RDM;
break;
case TARGET_SOCK_SEQPACKET:
type = SOCK_SEQPACKET;
break;
case TARGET_SOCK_PACKET:
type = SOCK_PACKET;
break;
}
#endif
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];

View File

@ -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);