|
@@ -35,6 +35,7 @@
|
|
#include <sys/swap.h>
|
|
#include <sys/swap.h>
|
|
#include <linux/capability.h>
|
|
#include <linux/capability.h>
|
|
#include <sched.h>
|
|
#include <sched.h>
|
|
|
|
+#include <sys/timex.h>
|
|
#ifdef __ia64__
|
|
#ifdef __ia64__
|
|
int __clone2(int (*fn)(void *), void *child_stack_base,
|
|
int __clone2(int (*fn)(void *), void *child_stack_base,
|
|
size_t stack_size, int flags, void *arg, ...);
|
|
size_t stack_size, int flags, void *arg, ...);
|
|
@@ -47,6 +48,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
|
|
#include <sys/shm.h>
|
|
#include <sys/shm.h>
|
|
#include <sys/sem.h>
|
|
#include <sys/sem.h>
|
|
#include <sys/statfs.h>
|
|
#include <sys/statfs.h>
|
|
|
|
+#include <time.h>
|
|
#include <utime.h>
|
|
#include <utime.h>
|
|
#include <sys/sysinfo.h>
|
|
#include <sys/sysinfo.h>
|
|
#include <sys/signalfd.h>
|
|
#include <sys/signalfd.h>
|
|
@@ -304,6 +306,11 @@ _syscall3(int, ioprio_set, int, which, int, who, int, ioprio)
|
|
_syscall3(int, getrandom, void *, buf, size_t, buflen, unsigned int, flags)
|
|
_syscall3(int, getrandom, void *, buf, size_t, buflen, unsigned int, flags)
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
|
|
|
|
+_syscall5(int, kcmp, pid_t, pid1, pid_t, pid2, int, type,
|
|
|
|
+ unsigned long, idx1, unsigned long, idx2)
|
|
|
|
+#endif
|
|
|
|
+
|
|
static bitmask_transtbl fcntl_flags_tbl[] = {
|
|
static bitmask_transtbl fcntl_flags_tbl[] = {
|
|
{ TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
|
|
{ TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
|
|
{ TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
|
|
{ TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
|
|
@@ -788,6 +795,9 @@ static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
|
|
#ifdef ENOTRECOVERABLE
|
|
#ifdef ENOTRECOVERABLE
|
|
[ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
|
|
[ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
|
|
#endif
|
|
#endif
|
|
|
|
+#ifdef ENOMSG
|
|
|
|
+ [ENOMSG] = TARGET_ENOMSG,
|
|
|
|
+#endif
|
|
};
|
|
};
|
|
|
|
|
|
static inline int host_to_target_errno(int err)
|
|
static inline int host_to_target_errno(int err)
|
|
@@ -908,6 +918,10 @@ safe_syscall2(int, tkill, int, tid, int, sig)
|
|
safe_syscall3(int, tgkill, int, tgid, int, pid, int, sig)
|
|
safe_syscall3(int, tgkill, int, tgid, int, pid, int, sig)
|
|
safe_syscall3(ssize_t, readv, int, fd, const struct iovec *, iov, int, iovcnt)
|
|
safe_syscall3(ssize_t, readv, int, fd, const struct iovec *, iov, int, iovcnt)
|
|
safe_syscall3(ssize_t, writev, int, fd, const struct iovec *, iov, int, iovcnt)
|
|
safe_syscall3(ssize_t, writev, int, fd, const struct iovec *, iov, int, iovcnt)
|
|
|
|
+safe_syscall5(ssize_t, preadv, int, fd, const struct iovec *, iov, int, iovcnt,
|
|
|
|
+ unsigned long, pos_l, unsigned long, pos_h)
|
|
|
|
+safe_syscall5(ssize_t, pwritev, int, fd, const struct iovec *, iov, int, iovcnt,
|
|
|
|
+ unsigned long, pos_l, unsigned long, pos_h)
|
|
safe_syscall3(int, connect, int, fd, const struct sockaddr *, addr,
|
|
safe_syscall3(int, connect, int, fd, const struct sockaddr *, addr,
|
|
socklen_t, addrlen)
|
|
socklen_t, addrlen)
|
|
safe_syscall6(ssize_t, sendto, int, fd, const void *, buf, size_t, len,
|
|
safe_syscall6(ssize_t, sendto, int, fd, const void *, buf, size_t, len,
|
|
@@ -2591,6 +2605,7 @@ static abi_long target_to_host_data_route_rtattr(struct rtattr *rtattr)
|
|
case RTA_GATEWAY:
|
|
case RTA_GATEWAY:
|
|
break;
|
|
break;
|
|
/* u32 */
|
|
/* u32 */
|
|
|
|
+ case RTA_PRIORITY:
|
|
case RTA_OIF:
|
|
case RTA_OIF:
|
|
u32 = RTA_DATA(rtattr);
|
|
u32 = RTA_DATA(rtattr);
|
|
*u32 = tswap32(*u32);
|
|
*u32 = tswap32(*u32);
|
|
@@ -3893,89 +3908,94 @@ fail:
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef TARGET_NR_socketcall
|
|
#ifdef TARGET_NR_socketcall
|
|
-/* do_socketcall() Must return target values and target errnos. */
|
|
|
|
|
|
+/* do_socketcall() must return target values and target errnos. */
|
|
static abi_long do_socketcall(int num, abi_ulong vptr)
|
|
static abi_long do_socketcall(int num, abi_ulong vptr)
|
|
{
|
|
{
|
|
- static const unsigned ac[] = { /* number of arguments per call */
|
|
|
|
- [SOCKOP_socket] = 3, /* domain, type, protocol */
|
|
|
|
- [SOCKOP_bind] = 3, /* sockfd, addr, addrlen */
|
|
|
|
- [SOCKOP_connect] = 3, /* sockfd, addr, addrlen */
|
|
|
|
- [SOCKOP_listen] = 2, /* sockfd, backlog */
|
|
|
|
- [SOCKOP_accept] = 3, /* sockfd, addr, addrlen */
|
|
|
|
- [SOCKOP_accept4] = 4, /* sockfd, addr, addrlen, flags */
|
|
|
|
- [SOCKOP_getsockname] = 3, /* sockfd, addr, addrlen */
|
|
|
|
- [SOCKOP_getpeername] = 3, /* sockfd, addr, addrlen */
|
|
|
|
- [SOCKOP_socketpair] = 4, /* domain, type, protocol, tab */
|
|
|
|
- [SOCKOP_send] = 4, /* sockfd, msg, len, flags */
|
|
|
|
- [SOCKOP_recv] = 4, /* sockfd, msg, len, flags */
|
|
|
|
- [SOCKOP_sendto] = 6, /* sockfd, msg, len, flags, addr, addrlen */
|
|
|
|
- [SOCKOP_recvfrom] = 6, /* sockfd, msg, len, flags, addr, addrlen */
|
|
|
|
- [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 */
|
|
|
|
|
|
+ static const unsigned nargs[] = { /* number of arguments per operation */
|
|
|
|
+ [TARGET_SYS_SOCKET] = 3, /* domain, type, protocol */
|
|
|
|
+ [TARGET_SYS_BIND] = 3, /* fd, addr, addrlen */
|
|
|
|
+ [TARGET_SYS_CONNECT] = 3, /* fd, addr, addrlen */
|
|
|
|
+ [TARGET_SYS_LISTEN] = 2, /* fd, backlog */
|
|
|
|
+ [TARGET_SYS_ACCEPT] = 3, /* fd, addr, addrlen */
|
|
|
|
+ [TARGET_SYS_GETSOCKNAME] = 3, /* fd, addr, addrlen */
|
|
|
|
+ [TARGET_SYS_GETPEERNAME] = 3, /* fd, addr, addrlen */
|
|
|
|
+ [TARGET_SYS_SOCKETPAIR] = 4, /* domain, type, protocol, tab */
|
|
|
|
+ [TARGET_SYS_SEND] = 4, /* fd, msg, len, flags */
|
|
|
|
+ [TARGET_SYS_RECV] = 4, /* fd, msg, len, flags */
|
|
|
|
+ [TARGET_SYS_SENDTO] = 6, /* fd, msg, len, flags, addr, addrlen */
|
|
|
|
+ [TARGET_SYS_RECVFROM] = 6, /* fd, msg, len, flags, addr, addrlen */
|
|
|
|
+ [TARGET_SYS_SHUTDOWN] = 2, /* fd, how */
|
|
|
|
+ [TARGET_SYS_SETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
|
|
|
|
+ [TARGET_SYS_GETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
|
|
|
|
+ [TARGET_SYS_SENDMSG] = 3, /* fd, msg, flags */
|
|
|
|
+ [TARGET_SYS_RECVMSG] = 3, /* fd, msg, flags */
|
|
|
|
+ [TARGET_SYS_ACCEPT4] = 4, /* fd, addr, addrlen, flags */
|
|
|
|
+ [TARGET_SYS_RECVMMSG] = 4, /* fd, msgvec, vlen, flags */
|
|
|
|
+ [TARGET_SYS_SENDMMSG] = 4, /* fd, msgvec, vlen, flags */
|
|
};
|
|
};
|
|
abi_long a[6]; /* max 6 args */
|
|
abi_long a[6]; /* max 6 args */
|
|
|
|
+ unsigned i;
|
|
|
|
|
|
- /* first, collect the arguments in a[] according to ac[] */
|
|
|
|
- if (num >= 0 && num < ARRAY_SIZE(ac)) {
|
|
|
|
- unsigned i;
|
|
|
|
- assert(ARRAY_SIZE(a) >= ac[num]); /* ensure we have space for args */
|
|
|
|
- for (i = 0; i < ac[num]; ++i) {
|
|
|
|
- if (get_user_ual(a[i], vptr + i * sizeof(abi_long)) != 0) {
|
|
|
|
- return -TARGET_EFAULT;
|
|
|
|
- }
|
|
|
|
|
|
+ /* check the range of the first argument num */
|
|
|
|
+ /* (TARGET_SYS_SENDMMSG is the highest among TARGET_SYS_xxx) */
|
|
|
|
+ if (num < 1 || num > TARGET_SYS_SENDMMSG) {
|
|
|
|
+ return -TARGET_EINVAL;
|
|
|
|
+ }
|
|
|
|
+ /* ensure we have space for args */
|
|
|
|
+ if (nargs[num] > ARRAY_SIZE(a)) {
|
|
|
|
+ return -TARGET_EINVAL;
|
|
|
|
+ }
|
|
|
|
+ /* collect the arguments in a[] according to nargs[] */
|
|
|
|
+ for (i = 0; i < nargs[num]; ++i) {
|
|
|
|
+ if (get_user_ual(a[i], vptr + i * sizeof(abi_long)) != 0) {
|
|
|
|
+ return -TARGET_EFAULT;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
- /* now when we have the args, actually handle the call */
|
|
|
|
|
|
+ /* now when we have the args, invoke the appropriate underlying function */
|
|
switch (num) {
|
|
switch (num) {
|
|
- case SOCKOP_socket: /* domain, type, protocol */
|
|
|
|
|
|
+ case TARGET_SYS_SOCKET: /* domain, type, protocol */
|
|
return do_socket(a[0], a[1], a[2]);
|
|
return do_socket(a[0], a[1], a[2]);
|
|
- case SOCKOP_bind: /* sockfd, addr, addrlen */
|
|
|
|
|
|
+ case TARGET_SYS_BIND: /* sockfd, addr, addrlen */
|
|
return do_bind(a[0], a[1], a[2]);
|
|
return do_bind(a[0], a[1], a[2]);
|
|
- case SOCKOP_connect: /* sockfd, addr, addrlen */
|
|
|
|
|
|
+ case TARGET_SYS_CONNECT: /* sockfd, addr, addrlen */
|
|
return do_connect(a[0], a[1], a[2]);
|
|
return do_connect(a[0], a[1], a[2]);
|
|
- case SOCKOP_listen: /* sockfd, backlog */
|
|
|
|
|
|
+ case TARGET_SYS_LISTEN: /* sockfd, backlog */
|
|
return get_errno(listen(a[0], a[1]));
|
|
return get_errno(listen(a[0], a[1]));
|
|
- case SOCKOP_accept: /* sockfd, addr, addrlen */
|
|
|
|
|
|
+ case TARGET_SYS_ACCEPT: /* sockfd, addr, addrlen */
|
|
return do_accept4(a[0], a[1], a[2], 0);
|
|
return do_accept4(a[0], a[1], a[2], 0);
|
|
- case SOCKOP_accept4: /* sockfd, addr, addrlen, flags */
|
|
|
|
- return do_accept4(a[0], a[1], a[2], a[3]);
|
|
|
|
- case SOCKOP_getsockname: /* sockfd, addr, addrlen */
|
|
|
|
|
|
+ case TARGET_SYS_GETSOCKNAME: /* sockfd, addr, addrlen */
|
|
return do_getsockname(a[0], a[1], a[2]);
|
|
return do_getsockname(a[0], a[1], a[2]);
|
|
- case SOCKOP_getpeername: /* sockfd, addr, addrlen */
|
|
|
|
|
|
+ case TARGET_SYS_GETPEERNAME: /* sockfd, addr, addrlen */
|
|
return do_getpeername(a[0], a[1], a[2]);
|
|
return do_getpeername(a[0], a[1], a[2]);
|
|
- case SOCKOP_socketpair: /* domain, type, protocol, tab */
|
|
|
|
|
|
+ case TARGET_SYS_SOCKETPAIR: /* domain, type, protocol, tab */
|
|
return do_socketpair(a[0], a[1], a[2], a[3]);
|
|
return do_socketpair(a[0], a[1], a[2], a[3]);
|
|
- case SOCKOP_send: /* sockfd, msg, len, flags */
|
|
|
|
|
|
+ case TARGET_SYS_SEND: /* sockfd, msg, len, flags */
|
|
return do_sendto(a[0], a[1], a[2], a[3], 0, 0);
|
|
return do_sendto(a[0], a[1], a[2], a[3], 0, 0);
|
|
- case SOCKOP_recv: /* sockfd, msg, len, flags */
|
|
|
|
|
|
+ case TARGET_SYS_RECV: /* sockfd, msg, len, flags */
|
|
return do_recvfrom(a[0], a[1], a[2], a[3], 0, 0);
|
|
return do_recvfrom(a[0], a[1], a[2], a[3], 0, 0);
|
|
- case SOCKOP_sendto: /* sockfd, msg, len, flags, addr, addrlen */
|
|
|
|
|
|
+ case TARGET_SYS_SENDTO: /* sockfd, msg, len, flags, addr, addrlen */
|
|
return do_sendto(a[0], a[1], a[2], a[3], a[4], a[5]);
|
|
return do_sendto(a[0], a[1], a[2], a[3], a[4], a[5]);
|
|
- case SOCKOP_recvfrom: /* sockfd, msg, len, flags, addr, addrlen */
|
|
|
|
|
|
+ case TARGET_SYS_RECVFROM: /* sockfd, msg, len, flags, addr, addrlen */
|
|
return do_recvfrom(a[0], a[1], a[2], a[3], a[4], a[5]);
|
|
return do_recvfrom(a[0], a[1], a[2], a[3], a[4], a[5]);
|
|
- case SOCKOP_shutdown: /* sockfd, how */
|
|
|
|
|
|
+ case TARGET_SYS_SHUTDOWN: /* sockfd, how */
|
|
return get_errno(shutdown(a[0], a[1]));
|
|
return get_errno(shutdown(a[0], a[1]));
|
|
- case SOCKOP_sendmsg: /* sockfd, msg, flags */
|
|
|
|
|
|
+ case TARGET_SYS_SETSOCKOPT: /* sockfd, level, optname, optval, optlen */
|
|
|
|
+ return do_setsockopt(a[0], a[1], a[2], a[3], a[4]);
|
|
|
|
+ case TARGET_SYS_GETSOCKOPT: /* sockfd, level, optname, optval, optlen */
|
|
|
|
+ return do_getsockopt(a[0], a[1], a[2], a[3], a[4]);
|
|
|
|
+ case TARGET_SYS_SENDMSG: /* sockfd, msg, flags */
|
|
return do_sendrecvmsg(a[0], a[1], a[2], 1);
|
|
return do_sendrecvmsg(a[0], a[1], a[2], 1);
|
|
- case SOCKOP_recvmsg: /* sockfd, msg, flags */
|
|
|
|
|
|
+ case TARGET_SYS_RECVMSG: /* sockfd, msg, flags */
|
|
return do_sendrecvmsg(a[0], a[1], a[2], 0);
|
|
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 */
|
|
|
|
|
|
+ case TARGET_SYS_ACCEPT4: /* sockfd, addr, addrlen, flags */
|
|
|
|
+ return do_accept4(a[0], a[1], a[2], a[3]);
|
|
|
|
+ case TARGET_SYS_RECVMMSG: /* sockfd, msgvec, vlen, flags */
|
|
return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0);
|
|
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 */
|
|
|
|
- return do_getsockopt(a[0], a[1], a[2], a[3], a[4]);
|
|
|
|
|
|
+ case TARGET_SYS_SENDMMSG: /* sockfd, msgvec, vlen, flags */
|
|
|
|
+ return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 1);
|
|
default:
|
|
default:
|
|
gemu_log("Unsupported socketcall: %d\n", num);
|
|
gemu_log("Unsupported socketcall: %d\n", num);
|
|
- return -TARGET_ENOSYS;
|
|
|
|
|
|
+ return -TARGET_EINVAL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
@@ -6770,6 +6790,77 @@ static inline abi_long host_to_target_itimerspec(abi_ulong target_addr,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static inline abi_long target_to_host_timex(struct timex *host_tx,
|
|
|
|
+ abi_long target_addr)
|
|
|
|
+{
|
|
|
|
+ struct target_timex *target_tx;
|
|
|
|
+
|
|
|
|
+ if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) {
|
|
|
|
+ return -TARGET_EFAULT;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ __get_user(host_tx->modes, &target_tx->modes);
|
|
|
|
+ __get_user(host_tx->offset, &target_tx->offset);
|
|
|
|
+ __get_user(host_tx->freq, &target_tx->freq);
|
|
|
|
+ __get_user(host_tx->maxerror, &target_tx->maxerror);
|
|
|
|
+ __get_user(host_tx->esterror, &target_tx->esterror);
|
|
|
|
+ __get_user(host_tx->status, &target_tx->status);
|
|
|
|
+ __get_user(host_tx->constant, &target_tx->constant);
|
|
|
|
+ __get_user(host_tx->precision, &target_tx->precision);
|
|
|
|
+ __get_user(host_tx->tolerance, &target_tx->tolerance);
|
|
|
|
+ __get_user(host_tx->time.tv_sec, &target_tx->time.tv_sec);
|
|
|
|
+ __get_user(host_tx->time.tv_usec, &target_tx->time.tv_usec);
|
|
|
|
+ __get_user(host_tx->tick, &target_tx->tick);
|
|
|
|
+ __get_user(host_tx->ppsfreq, &target_tx->ppsfreq);
|
|
|
|
+ __get_user(host_tx->jitter, &target_tx->jitter);
|
|
|
|
+ __get_user(host_tx->shift, &target_tx->shift);
|
|
|
|
+ __get_user(host_tx->stabil, &target_tx->stabil);
|
|
|
|
+ __get_user(host_tx->jitcnt, &target_tx->jitcnt);
|
|
|
|
+ __get_user(host_tx->calcnt, &target_tx->calcnt);
|
|
|
|
+ __get_user(host_tx->errcnt, &target_tx->errcnt);
|
|
|
|
+ __get_user(host_tx->stbcnt, &target_tx->stbcnt);
|
|
|
|
+ __get_user(host_tx->tai, &target_tx->tai);
|
|
|
|
+
|
|
|
|
+ unlock_user_struct(target_tx, target_addr, 0);
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static inline abi_long host_to_target_timex(abi_long target_addr,
|
|
|
|
+ struct timex *host_tx)
|
|
|
|
+{
|
|
|
|
+ struct target_timex *target_tx;
|
|
|
|
+
|
|
|
|
+ if (!lock_user_struct(VERIFY_WRITE, target_tx, target_addr, 0)) {
|
|
|
|
+ return -TARGET_EFAULT;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ __put_user(host_tx->modes, &target_tx->modes);
|
|
|
|
+ __put_user(host_tx->offset, &target_tx->offset);
|
|
|
|
+ __put_user(host_tx->freq, &target_tx->freq);
|
|
|
|
+ __put_user(host_tx->maxerror, &target_tx->maxerror);
|
|
|
|
+ __put_user(host_tx->esterror, &target_tx->esterror);
|
|
|
|
+ __put_user(host_tx->status, &target_tx->status);
|
|
|
|
+ __put_user(host_tx->constant, &target_tx->constant);
|
|
|
|
+ __put_user(host_tx->precision, &target_tx->precision);
|
|
|
|
+ __put_user(host_tx->tolerance, &target_tx->tolerance);
|
|
|
|
+ __put_user(host_tx->time.tv_sec, &target_tx->time.tv_sec);
|
|
|
|
+ __put_user(host_tx->time.tv_usec, &target_tx->time.tv_usec);
|
|
|
|
+ __put_user(host_tx->tick, &target_tx->tick);
|
|
|
|
+ __put_user(host_tx->ppsfreq, &target_tx->ppsfreq);
|
|
|
|
+ __put_user(host_tx->jitter, &target_tx->jitter);
|
|
|
|
+ __put_user(host_tx->shift, &target_tx->shift);
|
|
|
|
+ __put_user(host_tx->stabil, &target_tx->stabil);
|
|
|
|
+ __put_user(host_tx->jitcnt, &target_tx->jitcnt);
|
|
|
|
+ __put_user(host_tx->calcnt, &target_tx->calcnt);
|
|
|
|
+ __put_user(host_tx->errcnt, &target_tx->errcnt);
|
|
|
|
+ __put_user(host_tx->stbcnt, &target_tx->stbcnt);
|
|
|
|
+ __put_user(host_tx->tai, &target_tx->tai);
|
|
|
|
+
|
|
|
|
+ unlock_user_struct(target_tx, target_addr, 1);
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
static inline abi_long target_to_host_sigevent(struct sigevent *host_sevp,
|
|
static inline abi_long target_to_host_sigevent(struct sigevent *host_sevp,
|
|
abi_ulong target_addr)
|
|
abi_ulong target_addr)
|
|
{
|
|
{
|
|
@@ -8003,6 +8094,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|
sync();
|
|
sync();
|
|
ret = 0;
|
|
ret = 0;
|
|
break;
|
|
break;
|
|
|
|
+#if defined(TARGET_NR_syncfs) && defined(CONFIG_SYNCFS)
|
|
|
|
+ case TARGET_NR_syncfs:
|
|
|
|
+ ret = get_errno(syncfs(arg1));
|
|
|
|
+ break;
|
|
|
|
+#endif
|
|
case TARGET_NR_kill:
|
|
case TARGET_NR_kill:
|
|
ret = get_errno(safe_kill(arg1, target_to_host_signal(arg2)));
|
|
ret = get_errno(safe_kill(arg1, target_to_host_signal(arg2)));
|
|
break;
|
|
break;
|
|
@@ -9240,14 +9336,52 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|
ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
|
|
ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
|
|
break;
|
|
break;
|
|
#endif
|
|
#endif
|
|
-
|
|
|
|
|
|
+#if defined(TARGET_NR_syslog)
|
|
case TARGET_NR_syslog:
|
|
case TARGET_NR_syslog:
|
|
- if (!(p = lock_user_string(arg2)))
|
|
|
|
- goto efault;
|
|
|
|
- ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
|
|
|
|
- unlock_user(p, arg2, 0);
|
|
|
|
- break;
|
|
|
|
|
|
+ {
|
|
|
|
+ int len = arg2;
|
|
|
|
|
|
|
|
+ switch (arg1) {
|
|
|
|
+ case TARGET_SYSLOG_ACTION_CLOSE: /* Close log */
|
|
|
|
+ case TARGET_SYSLOG_ACTION_OPEN: /* Open log */
|
|
|
|
+ case TARGET_SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
|
|
|
|
+ case TARGET_SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging */
|
|
|
|
+ case TARGET_SYSLOG_ACTION_CONSOLE_ON: /* Enable logging */
|
|
|
|
+ case TARGET_SYSLOG_ACTION_CONSOLE_LEVEL: /* Set messages level */
|
|
|
|
+ case TARGET_SYSLOG_ACTION_SIZE_UNREAD: /* Number of chars */
|
|
|
|
+ case TARGET_SYSLOG_ACTION_SIZE_BUFFER: /* Size of the buffer */
|
|
|
|
+ {
|
|
|
|
+ ret = get_errno(sys_syslog((int)arg1, NULL, (int)arg3));
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case TARGET_SYSLOG_ACTION_READ: /* Read from log */
|
|
|
|
+ case TARGET_SYSLOG_ACTION_READ_CLEAR: /* Read/clear msgs */
|
|
|
|
+ case TARGET_SYSLOG_ACTION_READ_ALL: /* Read last messages */
|
|
|
|
+ {
|
|
|
|
+ ret = -TARGET_EINVAL;
|
|
|
|
+ if (len < 0) {
|
|
|
|
+ goto fail;
|
|
|
|
+ }
|
|
|
|
+ ret = 0;
|
|
|
|
+ if (len == 0) {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
|
|
|
|
+ if (!p) {
|
|
|
|
+ ret = -TARGET_EFAULT;
|
|
|
|
+ goto fail;
|
|
|
|
+ }
|
|
|
|
+ ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
|
|
|
|
+ unlock_user(p, arg2, arg3);
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ ret = -EINVAL;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+#endif
|
|
case TARGET_NR_setitimer:
|
|
case TARGET_NR_setitimer:
|
|
{
|
|
{
|
|
struct itimerval value, ovalue, *pvalue;
|
|
struct itimerval value, ovalue, *pvalue;
|
|
@@ -9543,7 +9677,37 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#endif
|
|
case TARGET_NR_adjtimex:
|
|
case TARGET_NR_adjtimex:
|
|
- goto unimplemented;
|
|
|
|
|
|
+ {
|
|
|
|
+ struct timex host_buf;
|
|
|
|
+
|
|
|
|
+ if (target_to_host_timex(&host_buf, arg1) != 0) {
|
|
|
|
+ goto efault;
|
|
|
|
+ }
|
|
|
|
+ ret = get_errno(adjtimex(&host_buf));
|
|
|
|
+ if (!is_error(ret)) {
|
|
|
|
+ if (host_to_target_timex(arg1, &host_buf) != 0) {
|
|
|
|
+ goto efault;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+#if defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME)
|
|
|
|
+ case TARGET_NR_clock_adjtime:
|
|
|
|
+ {
|
|
|
|
+ struct timex htx, *phtx = &htx;
|
|
|
|
+
|
|
|
|
+ if (target_to_host_timex(phtx, arg2) != 0) {
|
|
|
|
+ goto efault;
|
|
|
|
+ }
|
|
|
|
+ ret = get_errno(clock_adjtime(arg1, phtx));
|
|
|
|
+ if (!is_error(ret) && phtx) {
|
|
|
|
+ if (host_to_target_timex(arg2, phtx) != 0) {
|
|
|
|
+ goto efault;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+#endif
|
|
#ifdef TARGET_NR_create_module
|
|
#ifdef TARGET_NR_create_module
|
|
case TARGET_NR_create_module:
|
|
case TARGET_NR_create_module:
|
|
#endif
|
|
#endif
|
|
@@ -9899,6 +10063,32 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
|
|
+#if defined(TARGET_NR_preadv)
|
|
|
|
+ case TARGET_NR_preadv:
|
|
|
|
+ {
|
|
|
|
+ struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
|
|
|
|
+ if (vec != NULL) {
|
|
|
|
+ ret = get_errno(safe_preadv(arg1, vec, arg3, arg4, arg5));
|
|
|
|
+ unlock_iovec(vec, arg2, arg3, 1);
|
|
|
|
+ } else {
|
|
|
|
+ ret = -host_to_target_errno(errno);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+#endif
|
|
|
|
+#if defined(TARGET_NR_pwritev)
|
|
|
|
+ case TARGET_NR_pwritev:
|
|
|
|
+ {
|
|
|
|
+ struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
|
|
|
|
+ if (vec != NULL) {
|
|
|
|
+ ret = get_errno(safe_pwritev(arg1, vec, arg3, arg4, arg5));
|
|
|
|
+ unlock_iovec(vec, arg2, arg3, 0);
|
|
|
|
+ } else {
|
|
|
|
+ ret = -host_to_target_errno(errno);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+#endif
|
|
case TARGET_NR_getsid:
|
|
case TARGET_NR_getsid:
|
|
ret = get_errno(getsid(arg1));
|
|
ret = get_errno(getsid(arg1));
|
|
break;
|
|
break;
|
|
@@ -11372,16 +11562,18 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|
#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
|
|
#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
|
|
case TARGET_NR_mq_open:
|
|
case TARGET_NR_mq_open:
|
|
{
|
|
{
|
|
- struct mq_attr posix_mq_attr, *attrp;
|
|
|
|
|
|
+ struct mq_attr posix_mq_attr;
|
|
|
|
+ int host_flags;
|
|
|
|
|
|
|
|
+ host_flags = target_to_host_bitmask(arg2, fcntl_flags_tbl);
|
|
|
|
+ if (copy_from_user_mq_attr(&posix_mq_attr, arg4) != 0) {
|
|
|
|
+ goto efault;
|
|
|
|
+ }
|
|
p = lock_user_string(arg1 - 1);
|
|
p = lock_user_string(arg1 - 1);
|
|
- if (arg4 != 0) {
|
|
|
|
- copy_from_user_mq_attr (&posix_mq_attr, arg4);
|
|
|
|
- attrp = &posix_mq_attr;
|
|
|
|
- } else {
|
|
|
|
- attrp = 0;
|
|
|
|
|
|
+ if (!p) {
|
|
|
|
+ goto efault;
|
|
}
|
|
}
|
|
- ret = get_errno(mq_open(p, arg2, arg3, attrp));
|
|
|
|
|
|
+ ret = get_errno(mq_open(p, host_flags, arg3, &posix_mq_attr));
|
|
unlock_user (p, arg1, 0);
|
|
unlock_user (p, arg1, 0);
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
@@ -11638,7 +11830,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|
goto efault;
|
|
goto efault;
|
|
}
|
|
}
|
|
|
|
|
|
- ep = alloca(maxevents * sizeof(struct epoll_event));
|
|
|
|
|
|
+ ep = g_try_new(struct epoll_event, maxevents);
|
|
|
|
+ if (!ep) {
|
|
|
|
+ unlock_user(target_ep, arg2, 0);
|
|
|
|
+ ret = -TARGET_ENOMEM;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
|
|
switch (num) {
|
|
switch (num) {
|
|
#if defined(TARGET_NR_epoll_pwait)
|
|
#if defined(TARGET_NR_epoll_pwait)
|
|
@@ -11656,8 +11853,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|
target_set = lock_user(VERIFY_READ, arg5,
|
|
target_set = lock_user(VERIFY_READ, arg5,
|
|
sizeof(target_sigset_t), 1);
|
|
sizeof(target_sigset_t), 1);
|
|
if (!target_set) {
|
|
if (!target_set) {
|
|
- unlock_user(target_ep, arg2, 0);
|
|
|
|
- goto efault;
|
|
|
|
|
|
+ ret = -TARGET_EFAULT;
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
target_to_host_sigset(set, target_set);
|
|
target_to_host_sigset(set, target_set);
|
|
unlock_user(target_set, arg5, 0);
|
|
unlock_user(target_set, arg5, 0);
|
|
@@ -11685,8 +11882,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|
target_ep[i].events = tswap32(ep[i].events);
|
|
target_ep[i].events = tswap32(ep[i].events);
|
|
target_ep[i].data.u64 = tswap64(ep[i].data.u64);
|
|
target_ep[i].data.u64 = tswap64(ep[i].data.u64);
|
|
}
|
|
}
|
|
|
|
+ unlock_user(target_ep, arg2,
|
|
|
|
+ ret * sizeof(struct target_epoll_event));
|
|
|
|
+ } else {
|
|
|
|
+ unlock_user(target_ep, arg2, 0);
|
|
}
|
|
}
|
|
- unlock_user(target_ep, arg2, ret * sizeof(struct target_epoll_event));
|
|
|
|
|
|
+ g_free(ep);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
@@ -11947,6 +12148,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|
ret = get_errno(unshare(arg1));
|
|
ret = get_errno(unshare(arg1));
|
|
break;
|
|
break;
|
|
#endif
|
|
#endif
|
|
|
|
+#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
|
|
|
|
+ case TARGET_NR_kcmp:
|
|
|
|
+ ret = get_errno(kcmp(arg1, arg2, arg3, arg4, arg5));
|
|
|
|
+ break;
|
|
|
|
+#endif
|
|
|
|
|
|
default:
|
|
default:
|
|
unimplemented:
|
|
unimplemented:
|