Misc linux-user updates
-----BEGIN PGP SIGNATURE----- iQJLBAABCAA1FiEE/4IDyMORmK4FgUHvtEiQ3t48m8AFAlkuqf0XHHJpa3Uudm9p cGlvQGxpbmFyby5vcmcACgkQtEiQ3t48m8ABhA/9GFdYQYZrPZirj7zRPX8LvklO abLhftG99yg/wUFz68Di2Zg7uJT52SLzHgCsint4iYG1fp13hXx2lLdjZPmFGs1O CvEuuATzIaoQtJgQQ2Qn7HOagmjNI3KvoSUiVOVlZ1Q/oHjfZuMkseL1JMwPdonl AQyE2zCAVN4LE29G7OGspP1t22yGzqRHrxhwMQ1hC0gnmVMHZhNNbPAeQwt31yFd kNQHmyfA0IXbGIkNXcMeJxgi+AhXALXqx6v3+1Nz4sAf9O/trCGMealqfzyZSRUw 3L6RvzJ1QHTZZa3FurdUMUEBRD8n2gjOnahprjIWgzrjmXguC4wi0isrkweWmGUt KN8ef3IZG10eqFo0TPGM4vMerHiheIs65VBuXdVZRq+duALA8U+tXZN4U4LDEFcc 2vg4LYIJ4Mp36aORK2PJ97zxYVV8rUJVfhZWuIdkW6xKIIhsaens3dA3kffE6PEz 2MDzn7JMW5DwCXAetib3rkXJP2ZNRzxfIT3kyfrzVk5osBav/ZUzfoh7mAPyFObK qatQXPCx8LlFXbvCnaJCj4kwUxRa+BZW7HO9YSWh/eWlMmfJWq7zyZ1ou6IcJzTJ jFto00jhnBOk7TLfdHNY6lTQ/9GMDmFPbJEJabFMjnNkwr5JuG3HutyHss1IgTwG 1SkbWvg2QulDLR3Nr9g= =s6sW -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/riku/tags/pull-linux-user-20170531' into staging Misc linux-user updates # gpg: Signature made Wed 31 May 2017 12:33:17 BST # gpg: using RSA key 0xB44890DEDE3C9BC0 # gpg: Good signature from "Riku Voipio <riku.voipio@iki.fi>" # gpg: aka "Riku Voipio <riku.voipio@linaro.org>" # Primary key fingerprint: FF82 03C8 C391 98AE 0581 41EF B448 90DE DE3C 9BC0 * remotes/riku/tags/pull-linux-user-20170531: linux-user: add strace support for uinfo structure of rt_sigqueueinfo() and rt_tgsigqueueinfo() linux-user: fix inconsistent spaces in print_siginfo() output linux-user: add rt_tgsigqueueinfo() strace linux-user: add support for rt_tgsigqueueinfo() system call linux-user: fix argument type declaration of rt_sigqueinfo() syscall linux-user: fix mismatch of lock/unlock_user() invocations in rt_sigqueinfo() syscall linux-user: fix ssetmask() system call linux-user: add tkill(), tgkill() and rt_sigqueueinfo() strace linux-user: add strace for getuid(), gettid(), getppid(), geteuid() linux-user: remove all traces of qemu from /proc/self/cmdline linux-user: allocate heap memory for execve arguments linux-user: fix inotify linux-user: fix fadvise64_64() on ppc linux-user: fix eventfd linux-user: call fd_trans_target_to_host_data() for write() Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
c077a998eb
@ -188,6 +188,93 @@ static void print_si_code(int arg)
|
||||
gemu_log("%s", codename);
|
||||
}
|
||||
|
||||
static void get_target_siginfo(target_siginfo_t *tinfo,
|
||||
const target_siginfo_t *info)
|
||||
{
|
||||
abi_ulong sival_ptr;
|
||||
|
||||
int sig;
|
||||
int si_errno;
|
||||
int si_code;
|
||||
int si_type;
|
||||
|
||||
__get_user(sig, &info->si_signo);
|
||||
__get_user(si_errno, &tinfo->si_errno);
|
||||
__get_user(si_code, &info->si_code);
|
||||
|
||||
tinfo->si_signo = sig;
|
||||
tinfo->si_errno = si_errno;
|
||||
tinfo->si_code = si_code;
|
||||
|
||||
/* Ensure we don't leak random junk to the guest later */
|
||||
memset(tinfo->_sifields._pad, 0, sizeof(tinfo->_sifields._pad));
|
||||
|
||||
/* This is awkward, because we have to use a combination of
|
||||
* the si_code and si_signo to figure out which of the union's
|
||||
* members are valid. (Within the host kernel it is always possible
|
||||
* to tell, but the kernel carefully avoids giving userspace the
|
||||
* high 16 bits of si_code, so we don't have the information to
|
||||
* do this the easy way...) We therefore make our best guess,
|
||||
* bearing in mind that a guest can spoof most of the si_codes
|
||||
* via rt_sigqueueinfo() if it likes.
|
||||
*
|
||||
* Once we have made our guess, we record it in the top 16 bits of
|
||||
* the si_code, so that print_siginfo() later can use it.
|
||||
* print_siginfo() will strip these top bits out before printing
|
||||
* the si_code.
|
||||
*/
|
||||
|
||||
switch (si_code) {
|
||||
case SI_USER:
|
||||
case SI_TKILL:
|
||||
case SI_KERNEL:
|
||||
/* Sent via kill(), tkill() or tgkill(), or direct from the kernel.
|
||||
* These are the only unspoofable si_code values.
|
||||
*/
|
||||
__get_user(tinfo->_sifields._kill._pid, &info->_sifields._kill._pid);
|
||||
__get_user(tinfo->_sifields._kill._uid, &info->_sifields._kill._uid);
|
||||
si_type = QEMU_SI_KILL;
|
||||
break;
|
||||
default:
|
||||
/* Everything else is spoofable. Make best guess based on signal */
|
||||
switch (sig) {
|
||||
case TARGET_SIGCHLD:
|
||||
__get_user(tinfo->_sifields._sigchld._pid,
|
||||
&info->_sifields._sigchld._pid);
|
||||
__get_user(tinfo->_sifields._sigchld._uid,
|
||||
&info->_sifields._sigchld._uid);
|
||||
__get_user(tinfo->_sifields._sigchld._status,
|
||||
&info->_sifields._sigchld._status);
|
||||
__get_user(tinfo->_sifields._sigchld._utime,
|
||||
&info->_sifields._sigchld._utime);
|
||||
__get_user(tinfo->_sifields._sigchld._stime,
|
||||
&info->_sifields._sigchld._stime);
|
||||
si_type = QEMU_SI_CHLD;
|
||||
break;
|
||||
case TARGET_SIGIO:
|
||||
__get_user(tinfo->_sifields._sigpoll._band,
|
||||
&info->_sifields._sigpoll._band);
|
||||
__get_user(tinfo->_sifields._sigpoll._fd,
|
||||
&info->_sifields._sigpoll._fd);
|
||||
si_type = QEMU_SI_POLL;
|
||||
break;
|
||||
default:
|
||||
/* Assume a sigqueue()/mq_notify()/rt_sigqueueinfo() source. */
|
||||
__get_user(tinfo->_sifields._rt._pid, &info->_sifields._rt._pid);
|
||||
__get_user(tinfo->_sifields._rt._uid, &info->_sifields._rt._uid);
|
||||
/* XXX: potential problem if 64 bit */
|
||||
__get_user(sival_ptr, &info->_sifields._rt._sigval.sival_ptr);
|
||||
tinfo->_sifields._rt._sigval.sival_ptr = sival_ptr;
|
||||
|
||||
si_type = QEMU_SI_RT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
tinfo->si_code = deposit32(si_code, 16, 16, si_type);
|
||||
}
|
||||
|
||||
static void print_siginfo(const target_siginfo_t *tinfo)
|
||||
{
|
||||
/* Print a target_siginfo_t in the format desired for printing
|
||||
@ -206,26 +293,26 @@ static void print_siginfo(const target_siginfo_t *tinfo)
|
||||
|
||||
switch (si_type) {
|
||||
case QEMU_SI_KILL:
|
||||
gemu_log(", si_pid = %u, si_uid = %u",
|
||||
gemu_log(", si_pid=%u, si_uid=%u",
|
||||
(unsigned int)tinfo->_sifields._kill._pid,
|
||||
(unsigned int)tinfo->_sifields._kill._uid);
|
||||
break;
|
||||
case QEMU_SI_TIMER:
|
||||
gemu_log(", si_timer1 = %u, si_timer2 = %u",
|
||||
gemu_log(", si_timer1=%u, si_timer2=%u",
|
||||
tinfo->_sifields._timer._timer1,
|
||||
tinfo->_sifields._timer._timer2);
|
||||
break;
|
||||
case QEMU_SI_POLL:
|
||||
gemu_log(", si_band = %d, si_fd = %d",
|
||||
gemu_log(", si_band=%d, si_fd=%d",
|
||||
tinfo->_sifields._sigpoll._band,
|
||||
tinfo->_sifields._sigpoll._fd);
|
||||
break;
|
||||
case QEMU_SI_FAULT:
|
||||
gemu_log(", si_addr = ");
|
||||
gemu_log(", si_addr=");
|
||||
print_pointer(tinfo->_sifields._sigfault._addr, 1);
|
||||
break;
|
||||
case QEMU_SI_CHLD:
|
||||
gemu_log(", si_pid = %u, si_uid = %u, si_status = %d"
|
||||
gemu_log(", si_pid=%u, si_uid=%u, si_status=%d"
|
||||
", si_utime=" TARGET_ABI_FMT_ld
|
||||
", si_stime=" TARGET_ABI_FMT_ld,
|
||||
(unsigned int)(tinfo->_sifields._sigchld._pid),
|
||||
@ -235,7 +322,7 @@ static void print_siginfo(const target_siginfo_t *tinfo)
|
||||
tinfo->_sifields._sigchld._stime);
|
||||
break;
|
||||
case QEMU_SI_RT:
|
||||
gemu_log(", si_pid = %u, si_uid = %u, si_sigval = " TARGET_ABI_FMT_ld,
|
||||
gemu_log(", si_pid=%u, si_uid=%u, si_sigval=" TARGET_ABI_FMT_ld,
|
||||
(unsigned int)tinfo->_sifields._rt._pid,
|
||||
(unsigned int)tinfo->_sifields._rt._uid,
|
||||
tinfo->_sifields._rt._sigval.sival_ptr);
|
||||
@ -1901,6 +1988,57 @@ print_rt_sigprocmask(const struct syscallname *name,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_rt_sigqueueinfo
|
||||
static void
|
||||
print_rt_sigqueueinfo(const struct syscallname *name,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||
{
|
||||
void *p;
|
||||
target_siginfo_t uinfo;
|
||||
|
||||
print_syscall_prologue(name);
|
||||
print_raw_param("%d", arg0, 0);
|
||||
print_signal(arg1, 0);
|
||||
p = lock_user(VERIFY_READ, arg2, sizeof(target_siginfo_t), 1);
|
||||
if (p) {
|
||||
get_target_siginfo(&uinfo, p);
|
||||
print_siginfo(&uinfo);
|
||||
|
||||
unlock_user(p, arg2, 0);
|
||||
} else {
|
||||
print_pointer(arg2, 1);
|
||||
}
|
||||
print_syscall_epilogue(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_rt_tgsigqueueinfo
|
||||
static void
|
||||
print_rt_tgsigqueueinfo(const struct syscallname *name,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||
{
|
||||
void *p;
|
||||
target_siginfo_t uinfo;
|
||||
|
||||
print_syscall_prologue(name);
|
||||
print_raw_param("%d", arg0, 0);
|
||||
print_raw_param("%d", arg1, 0);
|
||||
print_signal(arg2, 0);
|
||||
p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
|
||||
if (p) {
|
||||
get_target_siginfo(&uinfo, p);
|
||||
print_siginfo(&uinfo);
|
||||
|
||||
unlock_user(p, arg3, 0);
|
||||
} else {
|
||||
print_pointer(arg3, 1);
|
||||
}
|
||||
print_syscall_epilogue(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_syslog
|
||||
static void
|
||||
print_syslog_action(abi_ulong arg, int last)
|
||||
@ -2415,6 +2553,33 @@ print_kill(const struct syscallname *name,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_tkill
|
||||
static void
|
||||
print_tkill(const struct syscallname *name,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||
{
|
||||
print_syscall_prologue(name);
|
||||
print_raw_param("%d", arg0, 0);
|
||||
print_signal(arg1, 1);
|
||||
print_syscall_epilogue(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_tgkill
|
||||
static void
|
||||
print_tgkill(const struct syscallname *name,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||
{
|
||||
print_syscall_prologue(name);
|
||||
print_raw_param("%d", arg0, 0);
|
||||
print_raw_param("%d", arg1, 0);
|
||||
print_signal(arg2, 1);
|
||||
print_syscall_epilogue(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* An array of all of the syscalls we know about
|
||||
*/
|
||||
|
@ -290,7 +290,7 @@
|
||||
{ TARGET_NR_getegid32, "getegid32" , NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_geteuid
|
||||
{ TARGET_NR_geteuid, "geteuid" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_geteuid, "geteuid" , "%s()", NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_geteuid32
|
||||
{ TARGET_NR_geteuid32, "geteuid32" , NULL, NULL, NULL },
|
||||
@ -338,7 +338,7 @@
|
||||
{ TARGET_NR_getpmsg, "getpmsg" , NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_getppid
|
||||
{ TARGET_NR_getppid, "getppid" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_getppid, "getppid" , "%s()", NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_getpriority
|
||||
{ TARGET_NR_getpriority, "getpriority", "%s(%#x,%#x)", NULL, NULL },
|
||||
@ -381,13 +381,13 @@
|
||||
NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_gettid
|
||||
{ TARGET_NR_gettid, "gettid" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_gettid, "gettid" , "%s()", NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_gettimeofday
|
||||
{ TARGET_NR_gettimeofday, "gettimeofday" , NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_getuid
|
||||
{ TARGET_NR_getuid, "getuid" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_getuid, "getuid" , "%s()", NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_getuid32
|
||||
{ TARGET_NR_getuid32, "getuid32" , NULL, NULL, NULL },
|
||||
@ -1155,7 +1155,7 @@
|
||||
{ TARGET_NR_rt_sigprocmask, "rt_sigprocmask" , NULL, print_rt_sigprocmask, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_rt_sigqueueinfo
|
||||
{ TARGET_NR_rt_sigqueueinfo, "rt_sigqueueinfo" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_rt_sigqueueinfo, "rt_sigqueueinfo" , NULL, print_rt_sigqueueinfo, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_rt_sigreturn
|
||||
{ TARGET_NR_rt_sigreturn, "rt_sigreturn" , NULL, NULL, NULL },
|
||||
@ -1167,7 +1167,7 @@
|
||||
{ TARGET_NR_rt_sigtimedwait, "rt_sigtimedwait" , NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_rt_tgsigqueueinfo
|
||||
{ TARGET_NR_rt_tgsigqueueinfo, "rt_tgsigqueueinfo" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_rt_tgsigqueueinfo, "rt_tgsigqueueinfo" , NULL, print_rt_tgsigqueueinfo, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_sched_getaffinity
|
||||
{ TARGET_NR_sched_getaffinity, "sched_getaffinity" , NULL, NULL, NULL },
|
||||
@ -1498,7 +1498,7 @@
|
||||
{ TARGET_NR_tee, "tee" , NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_tgkill
|
||||
{ TARGET_NR_tgkill, "tgkill" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_tgkill, "tgkill" , NULL, print_tgkill, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_time
|
||||
{ TARGET_NR_time, "time" , NULL, NULL, NULL },
|
||||
@ -1534,7 +1534,7 @@
|
||||
{ TARGET_NR_times, "times" , NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_tkill
|
||||
{ TARGET_NR_tkill, "tkill" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_tkill, "tkill" , NULL, print_tkill, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_truncate
|
||||
{ TARGET_NR_truncate, "truncate" , NULL, NULL, NULL },
|
||||
|
@ -238,6 +238,7 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
|
||||
#define __NR_sys_getdents64 __NR_getdents64
|
||||
#define __NR_sys_getpriority __NR_getpriority
|
||||
#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
|
||||
#define __NR_sys_rt_tgsigqueueinfo __NR_rt_tgsigqueueinfo
|
||||
#define __NR_sys_syslog __NR_syslog
|
||||
#define __NR_sys_futex __NR_futex
|
||||
#define __NR_sys_inotify_init __NR_inotify_init
|
||||
@ -274,7 +275,9 @@ _syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, co
|
||||
_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
|
||||
loff_t *, res, uint, wh);
|
||||
#endif
|
||||
_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
|
||||
_syscall3(int, sys_rt_sigqueueinfo, pid_t, pid, int, sig, siginfo_t *, uinfo)
|
||||
_syscall4(int, sys_rt_tgsigqueueinfo, pid_t, pid, pid_t, tid, int, sig,
|
||||
siginfo_t *, uinfo)
|
||||
_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
|
||||
#ifdef __NR_exit_group
|
||||
_syscall1(int,exit_group,int,error_code)
|
||||
@ -7358,52 +7361,19 @@ int host_to_target_waitstatus(int status)
|
||||
|
||||
static int open_self_cmdline(void *cpu_env, int fd)
|
||||
{
|
||||
int fd_orig = -1;
|
||||
bool word_skipped = false;
|
||||
CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
|
||||
struct linux_binprm *bprm = ((TaskState *)cpu->opaque)->bprm;
|
||||
int i;
|
||||
|
||||
fd_orig = open("/proc/self/cmdline", O_RDONLY);
|
||||
if (fd_orig < 0) {
|
||||
return fd_orig;
|
||||
}
|
||||
for (i = 0; i < bprm->argc; i++) {
|
||||
size_t len = strlen(bprm->argv[i]) + 1;
|
||||
|
||||
while (true) {
|
||||
ssize_t nb_read;
|
||||
char buf[128];
|
||||
char *cp_buf = buf;
|
||||
|
||||
nb_read = read(fd_orig, buf, sizeof(buf));
|
||||
if (nb_read < 0) {
|
||||
int e = errno;
|
||||
fd_orig = close(fd_orig);
|
||||
errno = e;
|
||||
if (write(fd, bprm->argv[i], len) != len) {
|
||||
return -1;
|
||||
} else if (nb_read == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!word_skipped) {
|
||||
/* Skip the first string, which is the path to qemu-*-static
|
||||
instead of the actual command. */
|
||||
cp_buf = memchr(buf, 0, nb_read);
|
||||
if (cp_buf) {
|
||||
/* Null byte found, skip one string */
|
||||
cp_buf++;
|
||||
nb_read -= cp_buf - buf;
|
||||
word_skipped = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (word_skipped) {
|
||||
if (write(fd, cp_buf, nb_read) != nb_read) {
|
||||
int e = errno;
|
||||
close(fd_orig);
|
||||
errno = e;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return close(fd_orig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int open_self_maps(void *cpu_env, int fd)
|
||||
@ -7671,6 +7641,55 @@ static target_timer_t get_timer_id(abi_long arg)
|
||||
return timerid;
|
||||
}
|
||||
|
||||
static abi_long swap_data_eventfd(void *buf, size_t len)
|
||||
{
|
||||
uint64_t *counter = buf;
|
||||
int i;
|
||||
|
||||
if (len < sizeof(uint64_t)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i += sizeof(uint64_t)) {
|
||||
*counter = tswap64(*counter);
|
||||
counter++;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static TargetFdTrans target_eventfd_trans = {
|
||||
.host_to_target_data = swap_data_eventfd,
|
||||
.target_to_host_data = swap_data_eventfd,
|
||||
};
|
||||
|
||||
#if (defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)) || \
|
||||
(defined(CONFIG_INOTIFY1) && defined(TARGET_NR_inotify_init1) && \
|
||||
defined(__NR_inotify_init1))
|
||||
static abi_long host_to_target_data_inotify(void *buf, size_t len)
|
||||
{
|
||||
struct inotify_event *ev;
|
||||
int i;
|
||||
uint32_t name_len;
|
||||
|
||||
for (i = 0; i < len; i += sizeof(struct inotify_event) + name_len) {
|
||||
ev = (struct inotify_event *)((char *)buf + i);
|
||||
name_len = ev->len;
|
||||
|
||||
ev->wd = tswap32(ev->wd);
|
||||
ev->mask = tswap32(ev->mask);
|
||||
ev->cookie = tswap32(ev->cookie);
|
||||
ev->len = tswap32(name_len);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static TargetFdTrans target_inotify_trans = {
|
||||
.host_to_target_data = host_to_target_data_inotify,
|
||||
};
|
||||
#endif
|
||||
|
||||
/* do_syscall() should always have a single exit point at the end so
|
||||
that actions, such as logging of syscall results, can be performed.
|
||||
All errnos that do_syscall() returns must be -TARGET_<errcode>. */
|
||||
@ -7767,7 +7786,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
case TARGET_NR_write:
|
||||
if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
|
||||
goto efault;
|
||||
ret = get_errno(safe_write(arg1, p, arg3));
|
||||
if (fd_trans_target_to_host_data(arg1)) {
|
||||
void *copy = g_malloc(arg3);
|
||||
memcpy(copy, p, arg3);
|
||||
ret = fd_trans_target_to_host_data(arg1)(copy, arg3);
|
||||
if (ret >= 0) {
|
||||
ret = get_errno(safe_write(arg1, copy, ret));
|
||||
}
|
||||
g_free(copy);
|
||||
} else {
|
||||
ret = get_errno(safe_write(arg1, p, arg3));
|
||||
}
|
||||
unlock_user(p, arg2, 0);
|
||||
break;
|
||||
#ifdef TARGET_NR_open
|
||||
@ -7926,8 +7955,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
envc++;
|
||||
}
|
||||
|
||||
argp = alloca((argc + 1) * sizeof(void *));
|
||||
envp = alloca((envc + 1) * sizeof(void *));
|
||||
argp = g_new0(char *, argc + 1);
|
||||
envp = g_new0(char *, envc + 1);
|
||||
|
||||
for (gp = guest_argp, q = argp; gp;
|
||||
gp += sizeof(abi_ulong), q++) {
|
||||
@ -7988,6 +8017,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
break;
|
||||
unlock_user(*q, addr, 0);
|
||||
}
|
||||
|
||||
g_free(argp);
|
||||
g_free(envp);
|
||||
}
|
||||
break;
|
||||
case TARGET_NR_chdir:
|
||||
@ -8592,17 +8624,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
#ifdef TARGET_NR_ssetmask /* not on alpha */
|
||||
case TARGET_NR_ssetmask:
|
||||
{
|
||||
sigset_t set, oset, cur_set;
|
||||
sigset_t set, oset;
|
||||
abi_ulong target_set = arg1;
|
||||
/* We only have one word of the new mask so we must read
|
||||
* the rest of it with do_sigprocmask() and OR in this word.
|
||||
* We are guaranteed that a do_sigprocmask() that only queries
|
||||
* the signal mask will not fail.
|
||||
*/
|
||||
ret = do_sigprocmask(0, NULL, &cur_set);
|
||||
assert(!ret);
|
||||
target_to_host_old_sigset(&set, &target_set);
|
||||
sigorset(&set, &set, &cur_set);
|
||||
ret = do_sigprocmask(SIG_SETMASK, &set, &oset);
|
||||
if (!ret) {
|
||||
host_to_target_old_sigset(&target_set, &oset);
|
||||
@ -8847,10 +8871,23 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
goto efault;
|
||||
}
|
||||
target_to_host_siginfo(&uinfo, p);
|
||||
unlock_user(p, arg1, 0);
|
||||
unlock_user(p, arg3, 0);
|
||||
ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
|
||||
}
|
||||
break;
|
||||
case TARGET_NR_rt_tgsigqueueinfo:
|
||||
{
|
||||
siginfo_t uinfo;
|
||||
|
||||
p = lock_user(VERIFY_READ, arg4, sizeof(target_siginfo_t), 1);
|
||||
if (!p) {
|
||||
goto efault;
|
||||
}
|
||||
target_to_host_siginfo(&uinfo, p);
|
||||
unlock_user(p, arg4, 0);
|
||||
ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, arg3, &uinfo));
|
||||
}
|
||||
break;
|
||||
#ifdef TARGET_NR_sigreturn
|
||||
case TARGET_NR_sigreturn:
|
||||
if (block_signals()) {
|
||||
@ -11229,6 +11266,15 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
|
||||
#ifdef TARGET_NR_fadvise64_64
|
||||
case TARGET_NR_fadvise64_64:
|
||||
#if defined(TARGET_PPC)
|
||||
/* 6 args: fd, advice, offset (high, low), len (high, low) */
|
||||
ret = arg2;
|
||||
arg2 = arg3;
|
||||
arg3 = arg4;
|
||||
arg4 = arg5;
|
||||
arg5 = arg6;
|
||||
arg6 = ret;
|
||||
#else
|
||||
/* 6 args: fd, offset (high, low), len (high, low), advice */
|
||||
if (regpairs_aligned(cpu_env)) {
|
||||
/* offset is in (3,4), len in (5,6) and advice in 7 */
|
||||
@ -11238,6 +11284,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
arg5 = arg6;
|
||||
arg6 = arg7;
|
||||
}
|
||||
#endif
|
||||
ret = -host_to_target_errno(posix_fadvise(arg1,
|
||||
target_offset64(arg2, arg3),
|
||||
target_offset64(arg4, arg5),
|
||||
@ -11694,6 +11741,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
|
||||
case TARGET_NR_inotify_init:
|
||||
ret = get_errno(sys_inotify_init());
|
||||
fd_trans_register(ret, &target_inotify_trans);
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_INOTIFY1
|
||||
@ -11701,6 +11749,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
case TARGET_NR_inotify_init1:
|
||||
ret = get_errno(sys_inotify_init1(target_to_host_bitmask(arg1,
|
||||
fcntl_flags_tbl)));
|
||||
fd_trans_register(ret, &target_inotify_trans);
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
@ -11866,7 +11915,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);
|
||||
fd_trans_register(ret, &target_eventfd_trans);
|
||||
break;
|
||||
#endif
|
||||
#if defined(TARGET_NR_eventfd2)
|
||||
@ -11880,7 +11929,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);
|
||||
fd_trans_register(ret, &target_eventfd_trans);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user