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:
commit
9f9a03b981
@ -88,8 +88,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
IOCTL(SIOCATMARK, 0, TYPE_NULL)
|
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(SIOCGIFNAME, IOC_RW, MK_PTR(TYPE_INT))
|
||||||
IOCTL(SIOCGIFFLAGS, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
|
IOCTL(SIOCGIFFLAGS, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
|
||||||
IOCTL(SIOCSIFFLAGS, IOC_W, 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)))
|
MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
|
||||||
IOCTL_SPECIAL(DM_DEV_SET_GEOMETRY, IOC_RW, do_ioctl_dm,
|
IOCTL_SPECIAL(DM_DEV_SET_GEOMETRY, IOC_RW, do_ioctl_dm,
|
||||||
MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
|
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)))
|
||||||
|
@ -483,6 +483,10 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
|||||||
if (!(flags & MAP_ANONYMOUS)) {
|
if (!(flags & MAP_ANONYMOUS)) {
|
||||||
p = mmap(g2h(start), len, prot,
|
p = mmap(g2h(start), len, prot,
|
||||||
flags | MAP_FIXED, fd, host_offset);
|
flags | MAP_FIXED, fd, host_offset);
|
||||||
|
if (p == MAP_FAILED) {
|
||||||
|
munmap(g2h(start), host_len);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
host_start += offset - host_offset;
|
host_start += offset - host_offset;
|
||||||
}
|
}
|
||||||
start = h2g(host_start);
|
start = h2g(host_start);
|
||||||
|
@ -102,14 +102,14 @@ static inline int sas_ss_flags(unsigned long sp)
|
|||||||
|
|
||||||
int host_to_target_signal(int sig)
|
int host_to_target_signal(int sig)
|
||||||
{
|
{
|
||||||
if (sig >= _NSIG)
|
if (sig < 0 || sig >= _NSIG)
|
||||||
return sig;
|
return sig;
|
||||||
return host_to_target_signal_table[sig];
|
return host_to_target_signal_table[sig];
|
||||||
}
|
}
|
||||||
|
|
||||||
int target_to_host_signal(int sig)
|
int target_to_host_signal(int sig)
|
||||||
{
|
{
|
||||||
if (sig >= _NSIG)
|
if (sig < 0 || sig >= _NSIG)
|
||||||
return sig;
|
return sig;
|
||||||
return target_to_host_signal_table[sig];
|
return target_to_host_signal_table[sig];
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
#if defined(TARGET_MIPS)
|
#if defined(TARGET_MIPS)
|
||||||
// MIPS special values for constants
|
/* MIPS special values for constants */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For setsockopt(2)
|
* For setsockopt(2)
|
||||||
@ -17,10 +17,13 @@
|
|||||||
#define TARGET_SO_BROADCAST 0x0020 /* Allow transmission of
|
#define TARGET_SO_BROADCAST 0x0020 /* Allow transmission of
|
||||||
broadcast messages. */
|
broadcast messages. */
|
||||||
#define TARGET_SO_LINGER 0x0080 /* Block on close of a reliable
|
#define TARGET_SO_LINGER 0x0080 /* Block on close of a reliable
|
||||||
socket to transmit pending data. */
|
* socket to transmit pending data.
|
||||||
#define TARGET_SO_OOBINLINE 0x0100 /* Receive out-of-band data in-band. */
|
*/
|
||||||
|
#define TARGET_SO_OOBINLINE 0x0100 /* Receive out-of-band data in-band.
|
||||||
|
*/
|
||||||
#if 0
|
#if 0
|
||||||
To add: #define TARGET_SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */
|
/* To add: Allow local address and port reuse. */
|
||||||
|
#define TARGET_SO_REUSEPORT 0x0200
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TARGET_SO_TYPE 0x1008 /* Compatible name for SO_STYLE. */
|
#define TARGET_SO_TYPE 0x1008 /* Compatible name for SO_STYLE. */
|
||||||
@ -72,9 +75,16 @@
|
|||||||
* @SOCK_RAW - raw socket
|
* @SOCK_RAW - raw socket
|
||||||
* @SOCK_RDM - reliably-delivered message
|
* @SOCK_RDM - reliably-delivered message
|
||||||
* @SOCK_SEQPACKET - sequential packet socket
|
* @SOCK_SEQPACKET - sequential packet socket
|
||||||
|
* @SOCK_DCCP - Datagram Congestion Control Protocol socket
|
||||||
* @SOCK_PACKET - linux specific way of getting packets at the dev level.
|
* @SOCK_PACKET - linux specific way of getting packets at the dev level.
|
||||||
* For writing rarp and other similar things on the user 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 {
|
enum sock_type {
|
||||||
TARGET_SOCK_DGRAM = 1,
|
TARGET_SOCK_DGRAM = 1,
|
||||||
TARGET_SOCK_STREAM = 2,
|
TARGET_SOCK_STREAM = 2,
|
||||||
@ -83,9 +93,12 @@
|
|||||||
TARGET_SOCK_SEQPACKET = 5,
|
TARGET_SOCK_SEQPACKET = 5,
|
||||||
TARGET_SOCK_DCCP = 6,
|
TARGET_SOCK_DCCP = 6,
|
||||||
TARGET_SOCK_PACKET = 10,
|
TARGET_SOCK_PACKET = 10,
|
||||||
|
TARGET_SOCK_CLOEXEC = 02000000,
|
||||||
|
TARGET_SOCK_NONBLOCK = 0200,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TARGET_SOCK_MAX (SOCK_PACKET + 1)
|
#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)
|
#elif defined(TARGET_ALPHA)
|
||||||
|
|
||||||
@ -156,8 +169,81 @@
|
|||||||
/* Instruct lower device to use last 4-bytes of skb data as FCS */
|
/* Instruct lower device to use last 4-bytes of skb data as FCS */
|
||||||
#define TARGET_SO_NOFCS 43
|
#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
|
#else
|
||||||
|
|
||||||
|
#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) */
|
/* For setsockopt(2) */
|
||||||
#define TARGET_SOL_SOCKET 1
|
#define TARGET_SOL_SOCKET 1
|
||||||
|
|
||||||
@ -214,3 +300,36 @@
|
|||||||
#define TARGET_SO_PEERSEC 31
|
#define TARGET_SO_PEERSEC 31
|
||||||
|
|
||||||
#endif
|
#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
|
||||||
|
@ -105,6 +105,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
|
|||||||
#include <linux/vt.h>
|
#include <linux/vt.h>
|
||||||
#include <linux/dm-ioctl.h>
|
#include <linux/dm-ioctl.h>
|
||||||
#include <linux/reboot.h>
|
#include <linux/reboot.h>
|
||||||
|
#include <linux/route.h>
|
||||||
#include "linux_loop.h"
|
#include "linux_loop.h"
|
||||||
#include "cpu-uname.h"
|
#include "cpu-uname.h"
|
||||||
|
|
||||||
@ -338,6 +339,7 @@ static int sys_openat(int dirfd, const char *pathname, int flags, mode_t mode)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef TARGET_NR_utimensat
|
||||||
#ifdef CONFIG_UTIMENSAT
|
#ifdef CONFIG_UTIMENSAT
|
||||||
static int sys_utimensat(int dirfd, const char *pathname,
|
static int sys_utimensat(int dirfd, const char *pathname,
|
||||||
const struct timespec times[2], int flags)
|
const struct timespec times[2], int flags)
|
||||||
@ -347,12 +349,19 @@ static int sys_utimensat(int dirfd, const char *pathname,
|
|||||||
else
|
else
|
||||||
return utimensat(dirfd, pathname, times, flags);
|
return utimensat(dirfd, pathname, times, flags);
|
||||||
}
|
}
|
||||||
#else
|
#elif defined(__NR_utimensat)
|
||||||
#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
|
#define __NR_sys_utimensat __NR_utimensat
|
||||||
_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
|
_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
|
||||||
const struct timespec *,tsp,int,flags)
|
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
|
||||||
#endif /* CONFIG_UTIMENSAT */
|
#endif /* TARGET_NR_utimensat */
|
||||||
|
|
||||||
#ifdef CONFIG_INOTIFY
|
#ifdef CONFIG_INOTIFY
|
||||||
#include <sys/inotify.h>
|
#include <sys/inotify.h>
|
||||||
@ -1696,31 +1705,36 @@ static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
|
|||||||
free(vec);
|
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. */
|
/* do_socket() Must return target values and target errnos. */
|
||||||
static abi_long do_socket(int domain, int type, int protocol)
|
static abi_long do_socket(int domain, int type, int protocol)
|
||||||
{
|
{
|
||||||
#if defined(TARGET_MIPS)
|
target_to_host_sock_type(&type);
|
||||||
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
|
|
||||||
if (domain == PF_NETLINK)
|
if (domain == PF_NETLINK)
|
||||||
return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
|
return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
|
||||||
return get_errno(socket(domain, type, protocol));
|
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];
|
int tab[2];
|
||||||
abi_long ret;
|
abi_long ret;
|
||||||
|
|
||||||
|
target_to_host_sock_type(&type);
|
||||||
|
|
||||||
ret = get_errno(socketpair(domain, type, protocol, tab));
|
ret = get_errno(socketpair(domain, type, protocol, tab));
|
||||||
if (!is_error(ret)) {
|
if (!is_error(ret)) {
|
||||||
if (put_user_s32(tab[0], target_tab_addr)
|
if (put_user_s32(tab[0], target_tab_addr)
|
||||||
@ -3551,6 +3567,69 @@ out:
|
|||||||
return ret;
|
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[] = {
|
static IOCTLEntry ioctl_entries[] = {
|
||||||
#define IOCTL(cmd, access, ...) \
|
#define IOCTL(cmd, access, ...) \
|
||||||
{ TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
|
{ TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
|
||||||
@ -4973,6 +5052,30 @@ static int open_self_auxv(void *cpu_env, int fd)
|
|||||||
return 0;
|
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)
|
static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode)
|
||||||
{
|
{
|
||||||
struct fake_open {
|
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;
|
const struct fake_open *fake_open;
|
||||||
static const struct fake_open fakes[] = {
|
static const struct fake_open fakes[] = {
|
||||||
{ "/proc/self/maps", open_self_maps },
|
{ "maps", open_self_maps },
|
||||||
{ "/proc/self/stat", open_self_stat },
|
{ "stat", open_self_stat },
|
||||||
{ "/proc/self/auxv", open_self_auxv },
|
{ "auxv", open_self_auxv },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
for (fake_open = fakes; fake_open->filename; fake_open++) {
|
for (fake_open = fakes; fake_open->filename; fake_open++) {
|
||||||
if (!strncmp(pathname, fake_open->filename,
|
if (is_proc_myself(pathname, fake_open->filename)) {
|
||||||
strlen(fake_open->filename))) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6262,19 +6364,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||||||
#endif
|
#endif
|
||||||
case TARGET_NR_readlink:
|
case TARGET_NR_readlink:
|
||||||
{
|
{
|
||||||
void *p2, *temp;
|
void *p2;
|
||||||
p = lock_user_string(arg1);
|
p = lock_user_string(arg1);
|
||||||
p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
|
p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
|
||||||
if (!p || !p2)
|
if (!p || !p2) {
|
||||||
ret = -TARGET_EFAULT;
|
ret = -TARGET_EFAULT;
|
||||||
else {
|
} else if (is_proc_myself((const char *)p, "exe")) {
|
||||||
if (strncmp((const char *)p, "/proc/self/exe", 14) == 0) {
|
char real[PATH_MAX], *temp;
|
||||||
char real[PATH_MAX];
|
|
||||||
temp = realpath(exec_path, real);
|
temp = realpath(exec_path, real);
|
||||||
ret = (temp==NULL) ? get_errno(-1) : strlen(real) ;
|
ret = temp == NULL ? get_errno(-1) : strlen(real) ;
|
||||||
snprintf((char *)p2, arg3, "%s", real);
|
snprintf((char *)p2, arg3, "%s", real);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
ret = get_errno(readlink(path(p), p2, arg3));
|
ret = get_errno(readlink(path(p), p2, arg3));
|
||||||
}
|
}
|
||||||
unlock_user(p2, arg2, ret);
|
unlock_user(p2, arg2, ret);
|
||||||
@ -6287,10 +6387,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||||||
void *p2;
|
void *p2;
|
||||||
p = lock_user_string(arg2);
|
p = lock_user_string(arg2);
|
||||||
p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
|
p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
|
||||||
if (!p || !p2)
|
if (!p || !p2) {
|
||||||
ret = -TARGET_EFAULT;
|
ret = -TARGET_EFAULT;
|
||||||
else
|
} 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));
|
ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
|
||||||
|
}
|
||||||
unlock_user(p2, arg3, ret);
|
unlock_user(p2, arg3, ret);
|
||||||
unlock_user(p, arg2, 0);
|
unlock_user(p, arg2, 0);
|
||||||
}
|
}
|
||||||
@ -8536,7 +8642,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||||||
goto unimplemented_nowarn;
|
goto unimplemented_nowarn;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
|
#if defined(TARGET_NR_utimensat)
|
||||||
case TARGET_NR_utimensat:
|
case TARGET_NR_utimensat:
|
||||||
{
|
{
|
||||||
struct timespec *tsp, ts[2];
|
struct timespec *tsp, ts[2];
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "disas/disas.h"
|
#include "disas/disas.h"
|
||||||
#include "tcg.h"
|
#include "tcg.h"
|
||||||
|
#include "qemu/bitops.h"
|
||||||
|
|
||||||
#undef EAX
|
#undef EAX
|
||||||
#undef ECX
|
#undef ECX
|
||||||
@ -441,8 +442,11 @@ int cpu_signal_handler(int host_signum, void *pinfo,
|
|||||||
#else
|
#else
|
||||||
pc = uc->uc_mcontext.arm_pc;
|
pc = uc->uc_mcontext.arm_pc;
|
||||||
#endif
|
#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,
|
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
|
||||||
is_write,
|
is_write,
|
||||||
&uc->uc_sigmask, puc);
|
&uc->uc_sigmask, puc);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user