mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-23 11:39:53 +00:00
January 2016 Linux-user queque
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIVAwUAVpO4pbRIkN7ePJvAAQjbgBAAzdQ3j5oBFCxZepHPO/PYiS7Mgw6xcKQq cVbc0wZpR2kawSPkqe/or7Zf2IywvBW/Tgt+G+aHciGrognQi3pmLYMv0WIOrkPl mm4b/nEhrTYRfObBnjaqMILFPKIYdBAPqcR7/QIFAoVUTRZiQzRg2mctwi73/+sH EMYet1MPcOsspmGR/uZK1Tbja88NzsYvOtOPt1Buy4A8YDyqBc4cIORoiLDN/o+k jn3mkDWysPM6S6h6tEm3OWOK4iX5Qlz/tvQoXaDJrfk4jZ+seftkJFuIrqRv8xmw 2DZ0BRQ1/T7fiQ7TwZW+CczauF0AezvYe5nWSfg8T8TYJzSTyaVWC6PwupoNRpHt KHQ/tAwaHT8tenIbHbX6MhTinlHuPj9U9gkh8K21CDp9iNnDco3uW+6pxtPP4EdY 9PlXXKE8gNjzMVtJAQRnBfQl8qPAFYU5dvU99/IcKq62he2W5nvCmnx/uA2asp/E KVYwZphKYdVKl6fTzYEd2eAnDVqHZ80suCVjofHUdZ3mzYskkpPrLoOjKk5oZK3C DdWLMJ+UMK57Bb6/ciNOngd7oNgbZlWfI2AI9yajQYIbCqstc9rCNQX9DcbcUgwT Ed+RgmhthIvoyfqywwaE4iisoTqctKP1pzX430ObQemMfFrzFi9DB6qeVXipicPB FEfee4OU2po= =WeIo -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/riku/tags/pull-linux-user-20160111' into staging January 2016 Linux-user queque # gpg: Signature made Mon 11 Jan 2016 14:13:57 GMT using RSA key ID DE3C9BC0 # gpg: Good signature from "Riku Voipio <riku.voipio@iki.fi>" # gpg: aka "Riku Voipio <riku.voipio@linaro.org>" * remotes/riku/tags/pull-linux-user-20160111: linux-user/mmap.c: Use end instead of real_end in target_mmap linux-user: Add SOCKOP_sendmmsg and SOCKOP_recvmmsg socket call, wire them up. linux-user: Update m68k syscall definitions to match Linux 4.4. linux-user/syscall.c: Use SOL_SOCKET instead of level for setsockopt() linux-user: enable sigaltstack for all architectures unicore32: convert get_sp_from_cpustate from macro to inline linux-user/mmap.c: Always zero MAP_ANONYMOUS memory in mmap_frag() linux-user,sh4: fix signal retcode address linux-user: check fd is >= 0 in fd_trans_host_to_target_data/fd_trans_host_to_target_addr linux-user: manage bind with a socket of SOCK_PACKET type. linux-user: add a function hook to translate sockaddr linux-user: rename TargetFdFunc to TargetFdDataFunc, and structure fields accordingly linux-user: SOCK_PACKET uses network endian to encode protocol in socket() linux-user/syscall.c: malloc()/calloc() to g_malloc()/g_try_malloc()/g_new0() linux-user: in poll(), if nfds is 0, pfd can be NULL linux-user: correctly align target_epoll_event linux-user: add signalfd/signalfd4 syscalls Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
ac0d9dbf33
@ -349,3 +349,30 @@
|
||||
#define TARGET_NR_process_vm_writev 346
|
||||
#define TARGET_NR_kcmp 347
|
||||
#define TARGET_NR_finit_module 348
|
||||
#define TARGET_NR_sched_setattr 349
|
||||
#define TARGET_NR_sched_getattr 350
|
||||
#define TARGET_NR_renameat2 351
|
||||
#define TARGET_NR_getrandom 352
|
||||
#define TARGET_NR_memfd_create 353
|
||||
#define TARGET_NR_bpf 354
|
||||
#define TARGET_NR_execveat 355
|
||||
#define TARGET_NR_socket 356
|
||||
#define TARGET_NR_socketpair 357
|
||||
#define TARGET_NR_bind 358
|
||||
#define TARGET_NR_connect 359
|
||||
#define TARGET_NR_listen 360
|
||||
#define TARGET_NR_accept4 361
|
||||
#define TARGET_NR_getsockopt 362
|
||||
#define TARGET_NR_setsockopt 363
|
||||
#define TARGET_NR_getsockname 364
|
||||
#define TARGET_NR_getpeername 365
|
||||
#define TARGET_NR_sendto 366
|
||||
#define TARGET_NR_sendmsg 367
|
||||
#define TARGET_NR_recvfrom 368
|
||||
#define TARGET_NR_recvmsg 369
|
||||
#define TARGET_NR_shutdown 370
|
||||
#define TARGET_NR_recvmmsg 371
|
||||
#define TARGET_NR_sendmmsg 372
|
||||
#define TARGET_NR_userfaultfd 373
|
||||
#define TARGET_NR_membarrier 374
|
||||
#define TARGET_NR_mlock2 375
|
||||
|
@ -186,10 +186,12 @@ static int mmap_frag(abi_ulong real_start,
|
||||
if (prot_new != (prot1 | PROT_WRITE))
|
||||
mprotect(host_start, qemu_host_page_size, prot_new);
|
||||
} else {
|
||||
/* just update the protection */
|
||||
if (prot_new != prot1) {
|
||||
mprotect(host_start, qemu_host_page_size, prot_new);
|
||||
}
|
||||
if (prot_new & PROT_WRITE) {
|
||||
memset(g2h(start), 0, end - start);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -536,7 +538,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||
/* handle the end of the mapping */
|
||||
if (end < real_end) {
|
||||
ret = mmap_frag(real_end - qemu_host_page_size,
|
||||
real_end - qemu_host_page_size, real_end,
|
||||
real_end - qemu_host_page_size, end,
|
||||
prot, flags, fd,
|
||||
offset + real_end - qemu_host_page_size - start);
|
||||
if (ret == -1)
|
||||
|
@ -3210,7 +3210,6 @@ static void setup_frame(int sig, struct target_sigaction *ka,
|
||||
struct target_sigframe *frame;
|
||||
abi_ulong frame_addr;
|
||||
int i;
|
||||
int err = 0;
|
||||
|
||||
frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
|
||||
trace_user_setup_frame(regs, frame_addr);
|
||||
@ -3229,15 +3228,14 @@ static void setup_frame(int sig, struct target_sigaction *ka,
|
||||
regs->pr = (unsigned long) ka->sa_restorer;
|
||||
} else {
|
||||
/* Generate return code (system call to sigreturn) */
|
||||
abi_ulong retcode_addr = frame_addr +
|
||||
offsetof(struct target_sigframe, retcode);
|
||||
__put_user(MOVW(2), &frame->retcode[0]);
|
||||
__put_user(TRAP_NOARG, &frame->retcode[1]);
|
||||
__put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
|
||||
regs->pr = (unsigned long) frame->retcode;
|
||||
regs->pr = (unsigned long) retcode_addr;
|
||||
}
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
|
||||
/* Set up registers for signal handler */
|
||||
regs->gregs[15] = frame_addr;
|
||||
regs->gregs[4] = sig; /* Arg for signal handler */
|
||||
@ -3260,7 +3258,6 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
struct target_rt_sigframe *frame;
|
||||
abi_ulong frame_addr;
|
||||
int i;
|
||||
int err = 0;
|
||||
|
||||
frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
|
||||
trace_user_setup_rt_frame(regs, frame_addr);
|
||||
@ -3290,15 +3287,14 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
regs->pr = (unsigned long) ka->sa_restorer;
|
||||
} else {
|
||||
/* Generate return code (system call to sigreturn) */
|
||||
abi_ulong retcode_addr = frame_addr +
|
||||
offsetof(struct target_rt_sigframe, retcode);
|
||||
__put_user(MOVW(2), &frame->retcode[0]);
|
||||
__put_user(TRAP_NOARG, &frame->retcode[1]);
|
||||
__put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
|
||||
regs->pr = (unsigned long) frame->retcode;
|
||||
regs->pr = (unsigned long) retcode_addr;
|
||||
}
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
|
||||
/* Set up registers for signal handler */
|
||||
regs->gregs[15] = frame_addr;
|
||||
regs->gregs[4] = sig; /* Arg for signal handler */
|
||||
|
@ -60,6 +60,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
|
||||
#include <sys/statfs.h>
|
||||
#include <utime.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/signalfd.h>
|
||||
//#include <sys/user.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
@ -294,6 +295,64 @@ static bitmask_transtbl fcntl_flags_tbl[] = {
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
typedef abi_long (*TargetFdDataFunc)(void *, size_t);
|
||||
typedef abi_long (*TargetFdAddrFunc)(void *, abi_ulong, socklen_t);
|
||||
typedef struct TargetFdTrans {
|
||||
TargetFdDataFunc host_to_target_data;
|
||||
TargetFdDataFunc target_to_host_data;
|
||||
TargetFdAddrFunc target_to_host_addr;
|
||||
} TargetFdTrans;
|
||||
|
||||
static TargetFdTrans **target_fd_trans;
|
||||
|
||||
static unsigned int target_fd_max;
|
||||
|
||||
static TargetFdDataFunc fd_trans_host_to_target_data(int fd)
|
||||
{
|
||||
if (fd >= 0 && fd < target_fd_max && target_fd_trans[fd]) {
|
||||
return target_fd_trans[fd]->host_to_target_data;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static TargetFdAddrFunc fd_trans_target_to_host_addr(int fd)
|
||||
{
|
||||
if (fd >= 0 && fd < target_fd_max && target_fd_trans[fd]) {
|
||||
return target_fd_trans[fd]->target_to_host_addr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void fd_trans_register(int fd, TargetFdTrans *trans)
|
||||
{
|
||||
unsigned int oldmax;
|
||||
|
||||
if (fd >= target_fd_max) {
|
||||
oldmax = target_fd_max;
|
||||
target_fd_max = ((fd >> 6) + 1) << 6; /* by slice of 64 entries */
|
||||
target_fd_trans = g_realloc(target_fd_trans,
|
||||
target_fd_max * sizeof(TargetFdTrans));
|
||||
memset((void *)(target_fd_trans + oldmax), 0,
|
||||
(target_fd_max - oldmax) * sizeof(TargetFdTrans *));
|
||||
}
|
||||
target_fd_trans[fd] = trans;
|
||||
}
|
||||
|
||||
static void fd_trans_unregister(int fd)
|
||||
{
|
||||
if (fd >= 0 && fd < target_fd_max) {
|
||||
target_fd_trans[fd] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void fd_trans_dup(int oldfd, int newfd)
|
||||
{
|
||||
fd_trans_unregister(newfd);
|
||||
if (oldfd < target_fd_max && target_fd_trans[oldfd]) {
|
||||
fd_trans_register(newfd, target_fd_trans[oldfd]);
|
||||
}
|
||||
}
|
||||
|
||||
static int sys_getcwd1(char *buf, size_t size)
|
||||
{
|
||||
if (getcwd(buf, size) == NULL) {
|
||||
@ -1113,7 +1172,7 @@ static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
|
||||
static inline abi_long target_to_host_sockaddr(int fd, struct sockaddr *addr,
|
||||
abi_ulong target_addr,
|
||||
socklen_t len)
|
||||
{
|
||||
@ -1121,6 +1180,10 @@ static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
|
||||
sa_family_t sa_family;
|
||||
struct target_sockaddr *target_saddr;
|
||||
|
||||
if (fd_trans_target_to_host_addr(fd)) {
|
||||
return fd_trans_target_to_host_addr(fd)(addr, target_addr, len);
|
||||
}
|
||||
|
||||
target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
|
||||
if (!target_saddr)
|
||||
return -TARGET_EFAULT;
|
||||
@ -1559,7 +1622,7 @@ set_timeout:
|
||||
}
|
||||
|
||||
fprog.len = tswap16(tfprog->len);
|
||||
filter = malloc(fprog.len * sizeof(*filter));
|
||||
filter = g_try_new(struct sock_filter, fprog.len);
|
||||
if (filter == NULL) {
|
||||
unlock_user_struct(tfilter, tfprog->filter, 1);
|
||||
unlock_user_struct(tfprog, optval_addr, 1);
|
||||
@ -1575,7 +1638,7 @@ set_timeout:
|
||||
|
||||
ret = get_errno(setsockopt(sockfd, SOL_SOCKET,
|
||||
SO_ATTACH_FILTER, &fprog, sizeof(fprog)));
|
||||
free(filter);
|
||||
g_free(filter);
|
||||
|
||||
unlock_user_struct(tfilter, tfprog->filter, 1);
|
||||
unlock_user_struct(tfprog, optval_addr, 1);
|
||||
@ -1596,7 +1659,8 @@ set_timeout:
|
||||
addr_ifname = alloca(IFNAMSIZ);
|
||||
memcpy(addr_ifname, dev_ifname, optlen);
|
||||
addr_ifname[optlen] = 0;
|
||||
ret = get_errno(setsockopt(sockfd, level, optname, addr_ifname, optlen));
|
||||
ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
|
||||
addr_ifname, optlen));
|
||||
unlock_user (dev_ifname, optval_addr, 0);
|
||||
return ret;
|
||||
}
|
||||
@ -1886,7 +1950,7 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vec = calloc(count, sizeof(struct iovec));
|
||||
vec = g_try_new0(struct iovec, count);
|
||||
if (vec == NULL) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
@ -1950,7 +2014,7 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr,
|
||||
}
|
||||
unlock_user(target_vec, target_addr, 0);
|
||||
fail2:
|
||||
free(vec);
|
||||
g_free(vec);
|
||||
errno = err;
|
||||
return NULL;
|
||||
}
|
||||
@ -1975,7 +2039,7 @@ static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
|
||||
unlock_user(target_vec, target_addr, 0);
|
||||
}
|
||||
|
||||
free(vec);
|
||||
g_free(vec);
|
||||
}
|
||||
|
||||
static inline int target_to_host_sock_type(int *type)
|
||||
@ -2027,6 +2091,30 @@ static int sock_flags_fixup(int fd, int target_type)
|
||||
return fd;
|
||||
}
|
||||
|
||||
static abi_long packet_target_to_host_sockaddr(void *host_addr,
|
||||
abi_ulong target_addr,
|
||||
socklen_t len)
|
||||
{
|
||||
struct sockaddr *addr = host_addr;
|
||||
struct target_sockaddr *target_saddr;
|
||||
|
||||
target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
|
||||
if (!target_saddr) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
|
||||
memcpy(addr, target_saddr, len);
|
||||
addr->sa_family = tswap16(target_saddr->sa_family);
|
||||
/* spkt_protocol is big-endian */
|
||||
|
||||
unlock_user(target_saddr, target_addr, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static TargetFdTrans target_packet_trans = {
|
||||
.target_to_host_addr = packet_target_to_host_sockaddr,
|
||||
};
|
||||
|
||||
/* do_socket() Must return target values and target errnos. */
|
||||
static abi_long do_socket(int domain, int type, int protocol)
|
||||
{
|
||||
@ -2040,9 +2128,21 @@ static abi_long do_socket(int domain, int type, int protocol)
|
||||
|
||||
if (domain == PF_NETLINK)
|
||||
return -TARGET_EAFNOSUPPORT;
|
||||
|
||||
if (domain == AF_PACKET ||
|
||||
(domain == AF_INET && type == SOCK_PACKET)) {
|
||||
protocol = tswap16(protocol);
|
||||
}
|
||||
|
||||
ret = get_errno(socket(domain, type, protocol));
|
||||
if (ret >= 0) {
|
||||
ret = sock_flags_fixup(ret, target_type);
|
||||
if (type == SOCK_PACKET) {
|
||||
/* Manage an obsolete case :
|
||||
* if socket type is SOCK_PACKET, bind by name
|
||||
*/
|
||||
fd_trans_register(ret, &target_packet_trans);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -2060,7 +2160,7 @@ static abi_long do_bind(int sockfd, abi_ulong target_addr,
|
||||
|
||||
addr = alloca(addrlen+1);
|
||||
|
||||
ret = target_to_host_sockaddr(addr, target_addr, addrlen);
|
||||
ret = target_to_host_sockaddr(sockfd, addr, target_addr, addrlen);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -2080,7 +2180,7 @@ static abi_long do_connect(int sockfd, abi_ulong target_addr,
|
||||
|
||||
addr = alloca(addrlen+1);
|
||||
|
||||
ret = target_to_host_sockaddr(addr, target_addr, addrlen);
|
||||
ret = target_to_host_sockaddr(sockfd, addr, target_addr, addrlen);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -2100,8 +2200,9 @@ static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
|
||||
if (msgp->msg_name) {
|
||||
msg.msg_namelen = tswap32(msgp->msg_namelen);
|
||||
msg.msg_name = alloca(msg.msg_namelen+1);
|
||||
ret = target_to_host_sockaddr(msg.msg_name, tswapal(msgp->msg_name),
|
||||
msg.msg_namelen);
|
||||
ret = target_to_host_sockaddr(fd, msg.msg_name,
|
||||
tswapal(msgp->msg_name),
|
||||
msg.msg_namelen);
|
||||
if (ret) {
|
||||
goto out2;
|
||||
}
|
||||
@ -2171,7 +2272,6 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef TARGET_NR_sendmmsg
|
||||
/* We don't rely on the C library to have sendmmsg/recvmmsg support,
|
||||
* so it might not have this *mmsg-specific flag either.
|
||||
*/
|
||||
@ -2218,7 +2318,6 @@ static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec,
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If we don't have a system accept4() then just call accept.
|
||||
* The callsites to do_accept4() will ensure that they don't
|
||||
@ -2363,7 +2462,7 @@ static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
|
||||
return -TARGET_EFAULT;
|
||||
if (target_addr) {
|
||||
addr = alloca(addrlen+1);
|
||||
ret = target_to_host_sockaddr(addr, target_addr, addrlen);
|
||||
ret = target_to_host_sockaddr(fd, addr, target_addr, addrlen);
|
||||
if (ret) {
|
||||
unlock_user(host_msg, msg, 0);
|
||||
return ret;
|
||||
@ -2441,6 +2540,8 @@ static abi_long do_socketcall(int num, abi_ulong vptr)
|
||||
[SOCKOP_shutdown] = 2, /* sockfd, how */
|
||||
[SOCKOP_sendmsg] = 3, /* sockfd, msg, flags */
|
||||
[SOCKOP_recvmsg] = 3, /* sockfd, msg, flags */
|
||||
[SOCKOP_sendmmsg] = 4, /* sockfd, msgvec, vlen, flags */
|
||||
[SOCKOP_recvmmsg] = 4, /* sockfd, msgvec, vlen, flags */
|
||||
[SOCKOP_setsockopt] = 5, /* sockfd, level, optname, optval, optlen */
|
||||
[SOCKOP_getsockopt] = 5, /* sockfd, level, optname, optval, optlen */
|
||||
};
|
||||
@ -2491,6 +2592,10 @@ static abi_long do_socketcall(int num, abi_ulong vptr)
|
||||
return do_sendrecvmsg(a[0], a[1], a[2], 1);
|
||||
case SOCKOP_recvmsg: /* sockfd, msg, flags */
|
||||
return do_sendrecvmsg(a[0], a[1], a[2], 0);
|
||||
case SOCKOP_sendmmsg: /* sockfd, msgvec, vlen, flags */
|
||||
return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 1);
|
||||
case SOCKOP_recvmmsg: /* sockfd, msgvec, vlen, flags */
|
||||
return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0);
|
||||
case SOCKOP_setsockopt: /* sockfd, level, optname, optval, optlen */
|
||||
return do_setsockopt(a[0], a[1], a[2], a[3], a[4]);
|
||||
case SOCKOP_getsockopt: /* sockfd, level, optname, optval, optlen */
|
||||
@ -2677,14 +2782,14 @@ static inline abi_long target_to_host_semarray(int semid, unsigned short **host_
|
||||
|
||||
nsems = semid_ds.sem_nsems;
|
||||
|
||||
*host_array = malloc(nsems*sizeof(unsigned short));
|
||||
*host_array = g_try_new(unsigned short, nsems);
|
||||
if (!*host_array) {
|
||||
return -TARGET_ENOMEM;
|
||||
}
|
||||
array = lock_user(VERIFY_READ, target_addr,
|
||||
nsems*sizeof(unsigned short), 1);
|
||||
if (!array) {
|
||||
free(*host_array);
|
||||
g_free(*host_array);
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
|
||||
@ -2721,7 +2826,7 @@ static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
|
||||
for(i=0; i<nsems; i++) {
|
||||
__put_user((*host_array)[i], &array[i]);
|
||||
}
|
||||
free(*host_array);
|
||||
g_free(*host_array);
|
||||
unlock_user(array, target_addr, 1);
|
||||
|
||||
return 0;
|
||||
@ -2981,7 +3086,7 @@ static inline abi_long do_msgsnd(int msqid, abi_long msgp,
|
||||
|
||||
if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
|
||||
return -TARGET_EFAULT;
|
||||
host_mb = malloc(msgsz+sizeof(long));
|
||||
host_mb = g_try_malloc(msgsz + sizeof(long));
|
||||
if (!host_mb) {
|
||||
unlock_user_struct(target_mb, msgp, 0);
|
||||
return -TARGET_ENOMEM;
|
||||
@ -2989,7 +3094,7 @@ static inline abi_long do_msgsnd(int msqid, abi_long msgp,
|
||||
host_mb->mtype = (abi_long) tswapal(target_mb->mtype);
|
||||
memcpy(host_mb->mtext, target_mb->mtext, msgsz);
|
||||
ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
|
||||
free(host_mb);
|
||||
g_free(host_mb);
|
||||
unlock_user_struct(target_mb, msgp, 0);
|
||||
|
||||
return ret;
|
||||
@ -3416,7 +3521,7 @@ static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||||
/* We can't fit all the extents into the fixed size buffer.
|
||||
* Allocate one that is large enough and use it instead.
|
||||
*/
|
||||
fm = malloc(outbufsz);
|
||||
fm = g_try_malloc(outbufsz);
|
||||
if (!fm) {
|
||||
return -TARGET_ENOMEM;
|
||||
}
|
||||
@ -3451,7 +3556,7 @@ static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||||
}
|
||||
}
|
||||
if (free_fm) {
|
||||
free(fm);
|
||||
g_free(fm);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -5340,6 +5445,92 @@ static abi_long do_open_by_handle_at(abi_long mount_fd, abi_long handle,
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_signalfd) || defined(TARGET_NR_signalfd4)
|
||||
|
||||
/* signalfd siginfo conversion */
|
||||
|
||||
static void
|
||||
host_to_target_signalfd_siginfo(struct signalfd_siginfo *tinfo,
|
||||
const struct signalfd_siginfo *info)
|
||||
{
|
||||
int sig = host_to_target_signal(info->ssi_signo);
|
||||
|
||||
/* linux/signalfd.h defines a ssi_addr_lsb
|
||||
* not defined in sys/signalfd.h but used by some kernels
|
||||
*/
|
||||
|
||||
#ifdef BUS_MCEERR_AO
|
||||
if (tinfo->ssi_signo == SIGBUS &&
|
||||
(tinfo->ssi_code == BUS_MCEERR_AR ||
|
||||
tinfo->ssi_code == BUS_MCEERR_AO)) {
|
||||
uint16_t *ssi_addr_lsb = (uint16_t *)(&info->ssi_addr + 1);
|
||||
uint16_t *tssi_addr_lsb = (uint16_t *)(&tinfo->ssi_addr + 1);
|
||||
*tssi_addr_lsb = tswap16(*ssi_addr_lsb);
|
||||
}
|
||||
#endif
|
||||
|
||||
tinfo->ssi_signo = tswap32(sig);
|
||||
tinfo->ssi_errno = tswap32(tinfo->ssi_errno);
|
||||
tinfo->ssi_code = tswap32(info->ssi_code);
|
||||
tinfo->ssi_pid = tswap32(info->ssi_pid);
|
||||
tinfo->ssi_uid = tswap32(info->ssi_uid);
|
||||
tinfo->ssi_fd = tswap32(info->ssi_fd);
|
||||
tinfo->ssi_tid = tswap32(info->ssi_tid);
|
||||
tinfo->ssi_band = tswap32(info->ssi_band);
|
||||
tinfo->ssi_overrun = tswap32(info->ssi_overrun);
|
||||
tinfo->ssi_trapno = tswap32(info->ssi_trapno);
|
||||
tinfo->ssi_status = tswap32(info->ssi_status);
|
||||
tinfo->ssi_int = tswap32(info->ssi_int);
|
||||
tinfo->ssi_ptr = tswap64(info->ssi_ptr);
|
||||
tinfo->ssi_utime = tswap64(info->ssi_utime);
|
||||
tinfo->ssi_stime = tswap64(info->ssi_stime);
|
||||
tinfo->ssi_addr = tswap64(info->ssi_addr);
|
||||
}
|
||||
|
||||
static abi_long host_to_target_data_signalfd(void *buf, size_t len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i += sizeof(struct signalfd_siginfo)) {
|
||||
host_to_target_signalfd_siginfo(buf + i, buf + i);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static TargetFdTrans target_signalfd_trans = {
|
||||
.host_to_target_data = host_to_target_data_signalfd,
|
||||
};
|
||||
|
||||
static abi_long do_signalfd4(int fd, abi_long mask, int flags)
|
||||
{
|
||||
int host_flags;
|
||||
target_sigset_t *target_mask;
|
||||
sigset_t host_mask;
|
||||
abi_long ret;
|
||||
|
||||
if (flags & ~(TARGET_O_NONBLOCK | TARGET_O_CLOEXEC)) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
if (!lock_user_struct(VERIFY_READ, target_mask, mask, 1)) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
|
||||
target_to_host_sigset(&host_mask, target_mask);
|
||||
|
||||
host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
|
||||
|
||||
ret = get_errno(signalfd(fd, &host_mask, host_flags));
|
||||
if (ret >= 0) {
|
||||
fd_trans_register(ret, &target_signalfd_trans);
|
||||
}
|
||||
|
||||
unlock_user_struct(target_mask, mask, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Map host to target signal numbers for the wait family of syscalls.
|
||||
Assume all other status bits are the same. */
|
||||
int host_to_target_waitstatus(int status)
|
||||
@ -5724,6 +5915,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
|
||||
goto efault;
|
||||
ret = get_errno(read(arg1, p, arg3));
|
||||
if (ret >= 0 &&
|
||||
fd_trans_host_to_target_data(arg1)) {
|
||||
ret = fd_trans_host_to_target_data(arg1)(p, ret);
|
||||
}
|
||||
unlock_user(p, arg2, ret);
|
||||
}
|
||||
break;
|
||||
@ -5740,6 +5935,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
ret = get_errno(do_openat(cpu_env, AT_FDCWD, p,
|
||||
target_to_host_bitmask(arg2, fcntl_flags_tbl),
|
||||
arg3));
|
||||
fd_trans_unregister(ret);
|
||||
unlock_user(p, arg1, 0);
|
||||
break;
|
||||
#endif
|
||||
@ -5749,6 +5945,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
ret = get_errno(do_openat(cpu_env, arg1, p,
|
||||
target_to_host_bitmask(arg3, fcntl_flags_tbl),
|
||||
arg4));
|
||||
fd_trans_unregister(ret);
|
||||
unlock_user(p, arg2, 0);
|
||||
break;
|
||||
#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
|
||||
@ -5759,9 +5956,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
|
||||
case TARGET_NR_open_by_handle_at:
|
||||
ret = do_open_by_handle_at(arg1, arg2, arg3);
|
||||
fd_trans_unregister(ret);
|
||||
break;
|
||||
#endif
|
||||
case TARGET_NR_close:
|
||||
fd_trans_unregister(arg1);
|
||||
ret = get_errno(close(arg1));
|
||||
break;
|
||||
case TARGET_NR_brk:
|
||||
@ -5803,6 +6002,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
if (!(p = lock_user_string(arg1)))
|
||||
goto efault;
|
||||
ret = get_errno(creat(p, arg2));
|
||||
fd_trans_unregister(ret);
|
||||
unlock_user(p, arg1, 0);
|
||||
break;
|
||||
#endif
|
||||
@ -6250,6 +6450,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
#endif
|
||||
case TARGET_NR_dup:
|
||||
ret = get_errno(dup(arg1));
|
||||
if (ret >= 0) {
|
||||
fd_trans_dup(arg1, ret);
|
||||
}
|
||||
break;
|
||||
#ifdef TARGET_NR_pipe
|
||||
case TARGET_NR_pipe:
|
||||
@ -6347,11 +6550,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
#ifdef TARGET_NR_dup2
|
||||
case TARGET_NR_dup2:
|
||||
ret = get_errno(dup2(arg1, arg2));
|
||||
if (ret >= 0) {
|
||||
fd_trans_dup(arg1, arg2);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3)
|
||||
case TARGET_NR_dup3:
|
||||
ret = get_errno(dup3(arg1, arg2, arg3));
|
||||
if (ret >= 0) {
|
||||
fd_trans_dup(arg1, arg2);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef TARGET_NR_getppid /* not on alpha */
|
||||
@ -7347,6 +7556,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
#ifdef TARGET_NR_socket
|
||||
case TARGET_NR_socket:
|
||||
ret = do_socket(arg1, arg2, arg3);
|
||||
fd_trans_unregister(ret);
|
||||
break;
|
||||
#endif
|
||||
#ifdef TARGET_NR_socketpair
|
||||
@ -7722,8 +7932,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
struct linux_dirent *dirp;
|
||||
abi_long count = arg3;
|
||||
|
||||
dirp = malloc(count);
|
||||
if (!dirp) {
|
||||
dirp = g_try_malloc(count);
|
||||
if (!dirp) {
|
||||
ret = -TARGET_ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
@ -7759,7 +7969,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
ret = count1;
|
||||
unlock_user(target_dirp, arg2, ret);
|
||||
}
|
||||
free(dirp);
|
||||
g_free(dirp);
|
||||
}
|
||||
#else
|
||||
{
|
||||
@ -7892,14 +8102,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
struct pollfd *pfd;
|
||||
unsigned int i;
|
||||
|
||||
target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
|
||||
if (!target_pfd)
|
||||
goto efault;
|
||||
pfd = NULL;
|
||||
target_pfd = NULL;
|
||||
if (nfds) {
|
||||
target_pfd = lock_user(VERIFY_WRITE, arg1,
|
||||
sizeof(struct target_pollfd) * nfds, 1);
|
||||
if (!target_pfd) {
|
||||
goto efault;
|
||||
}
|
||||
|
||||
pfd = alloca(sizeof(struct pollfd) * nfds);
|
||||
for(i = 0; i < nfds; i++) {
|
||||
pfd[i].fd = tswap32(target_pfd[i].fd);
|
||||
pfd[i].events = tswap16(target_pfd[i].events);
|
||||
pfd = alloca(sizeof(struct pollfd) * nfds);
|
||||
for (i = 0; i < nfds; i++) {
|
||||
pfd[i].fd = tswap32(target_pfd[i].fd);
|
||||
pfd[i].events = tswap16(target_pfd[i].events);
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef TARGET_NR_ppoll
|
||||
@ -9594,6 +9810,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
#if defined(TARGET_NR_eventfd)
|
||||
case TARGET_NR_eventfd:
|
||||
ret = get_errno(eventfd(arg1, 0));
|
||||
fd_trans_unregister(ret);
|
||||
break;
|
||||
#endif
|
||||
#if defined(TARGET_NR_eventfd2)
|
||||
@ -9607,6 +9824,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
host_flags |= O_CLOEXEC;
|
||||
}
|
||||
ret = get_errno(eventfd(arg1, host_flags));
|
||||
fd_trans_unregister(ret);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@ -9649,6 +9867,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
#if defined(TARGET_NR_signalfd4)
|
||||
case TARGET_NR_signalfd4:
|
||||
ret = do_signalfd4(arg1, arg2, arg4);
|
||||
break;
|
||||
#endif
|
||||
#if defined(TARGET_NR_signalfd)
|
||||
case TARGET_NR_signalfd:
|
||||
ret = do_signalfd4(arg1, arg2, 0);
|
||||
break;
|
||||
#endif
|
||||
#if defined(CONFIG_EPOLL)
|
||||
#if defined(TARGET_NR_epoll_create)
|
||||
case TARGET_NR_epoll_create:
|
||||
@ -9920,6 +10148,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
timer_t htimer = g_posix_timers[timerid];
|
||||
ret = get_errno(timer_getoverrun(htimer));
|
||||
}
|
||||
fd_trans_unregister(ret);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
@ -28,6 +28,8 @@
|
||||
#define SOCKOP_sendmsg 16
|
||||
#define SOCKOP_recvmsg 17
|
||||
#define SOCKOP_accept4 18
|
||||
#define SOCKOP_recvmmsg 19
|
||||
#define SOCKOP_sendmmsg 20
|
||||
|
||||
#define IPCOP_semop 1
|
||||
#define IPCOP_semget 2
|
||||
@ -2514,20 +2516,23 @@ struct target_mq_attr {
|
||||
#define FUTEX_CMD_MASK ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME)
|
||||
|
||||
#ifdef CONFIG_EPOLL
|
||||
#if defined(TARGET_X86_64)
|
||||
#define TARGET_EPOLL_PACKED QEMU_PACKED
|
||||
#else
|
||||
#define TARGET_EPOLL_PACKED
|
||||
#endif
|
||||
|
||||
typedef union target_epoll_data {
|
||||
abi_ulong ptr;
|
||||
abi_ulong fd;
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
abi_int fd;
|
||||
abi_uint u32;
|
||||
abi_ullong u64;
|
||||
} target_epoll_data_t;
|
||||
|
||||
struct target_epoll_event {
|
||||
uint32_t events;
|
||||
#if defined(TARGET_ARM) || defined(TARGET_MIPS) || defined(TARGET_MIPS64)
|
||||
uint32_t __pad;
|
||||
#endif
|
||||
abi_uint events;
|
||||
target_epoll_data_t data;
|
||||
} QEMU_PACKED;
|
||||
} TARGET_EPOLL_PACKED;
|
||||
#endif
|
||||
struct target_rlimit64 {
|
||||
uint64_t rlim_cur;
|
||||
|
Loading…
Reference in New Issue
Block a user