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:
Peter Maydell 2017-06-01 15:50:40 +01:00
commit c077a998eb
3 changed files with 284 additions and 70 deletions

View File

@ -188,6 +188,93 @@ static void print_si_code(int arg)
gemu_log("%s", codename); 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) static void print_siginfo(const target_siginfo_t *tinfo)
{ {
/* Print a target_siginfo_t in the format desired for printing /* 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) { switch (si_type) {
case QEMU_SI_KILL: 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._pid,
(unsigned int)tinfo->_sifields._kill._uid); (unsigned int)tinfo->_sifields._kill._uid);
break; break;
case QEMU_SI_TIMER: 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._timer1,
tinfo->_sifields._timer._timer2); tinfo->_sifields._timer._timer2);
break; break;
case QEMU_SI_POLL: 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._band,
tinfo->_sifields._sigpoll._fd); tinfo->_sifields._sigpoll._fd);
break; break;
case QEMU_SI_FAULT: case QEMU_SI_FAULT:
gemu_log(", si_addr = "); gemu_log(", si_addr=");
print_pointer(tinfo->_sifields._sigfault._addr, 1); print_pointer(tinfo->_sifields._sigfault._addr, 1);
break; break;
case QEMU_SI_CHLD: 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_utime=" TARGET_ABI_FMT_ld
", si_stime=" TARGET_ABI_FMT_ld, ", si_stime=" TARGET_ABI_FMT_ld,
(unsigned int)(tinfo->_sifields._sigchld._pid), (unsigned int)(tinfo->_sifields._sigchld._pid),
@ -235,7 +322,7 @@ static void print_siginfo(const target_siginfo_t *tinfo)
tinfo->_sifields._sigchld._stime); tinfo->_sifields._sigchld._stime);
break; break;
case QEMU_SI_RT: 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._pid,
(unsigned int)tinfo->_sifields._rt._uid, (unsigned int)tinfo->_sifields._rt._uid,
tinfo->_sifields._rt._sigval.sival_ptr); tinfo->_sifields._rt._sigval.sival_ptr);
@ -1901,6 +1988,57 @@ print_rt_sigprocmask(const struct syscallname *name,
} }
#endif #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 #ifdef TARGET_NR_syslog
static void static void
print_syslog_action(abi_ulong arg, int last) print_syslog_action(abi_ulong arg, int last)
@ -2415,6 +2553,33 @@ print_kill(const struct syscallname *name,
} }
#endif #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 * An array of all of the syscalls we know about
*/ */

View File

@ -290,7 +290,7 @@
{ TARGET_NR_getegid32, "getegid32" , NULL, NULL, NULL }, { TARGET_NR_getegid32, "getegid32" , NULL, NULL, NULL },
#endif #endif
#ifdef TARGET_NR_geteuid #ifdef TARGET_NR_geteuid
{ TARGET_NR_geteuid, "geteuid" , NULL, NULL, NULL }, { TARGET_NR_geteuid, "geteuid" , "%s()", NULL, NULL },
#endif #endif
#ifdef TARGET_NR_geteuid32 #ifdef TARGET_NR_geteuid32
{ TARGET_NR_geteuid32, "geteuid32" , NULL, NULL, NULL }, { TARGET_NR_geteuid32, "geteuid32" , NULL, NULL, NULL },
@ -338,7 +338,7 @@
{ TARGET_NR_getpmsg, "getpmsg" , NULL, NULL, NULL }, { TARGET_NR_getpmsg, "getpmsg" , NULL, NULL, NULL },
#endif #endif
#ifdef TARGET_NR_getppid #ifdef TARGET_NR_getppid
{ TARGET_NR_getppid, "getppid" , NULL, NULL, NULL }, { TARGET_NR_getppid, "getppid" , "%s()", NULL, NULL },
#endif #endif
#ifdef TARGET_NR_getpriority #ifdef TARGET_NR_getpriority
{ TARGET_NR_getpriority, "getpriority", "%s(%#x,%#x)", NULL, NULL }, { TARGET_NR_getpriority, "getpriority", "%s(%#x,%#x)", NULL, NULL },
@ -381,13 +381,13 @@
NULL, NULL }, NULL, NULL },
#endif #endif
#ifdef TARGET_NR_gettid #ifdef TARGET_NR_gettid
{ TARGET_NR_gettid, "gettid" , NULL, NULL, NULL }, { TARGET_NR_gettid, "gettid" , "%s()", NULL, NULL },
#endif #endif
#ifdef TARGET_NR_gettimeofday #ifdef TARGET_NR_gettimeofday
{ TARGET_NR_gettimeofday, "gettimeofday" , NULL, NULL, NULL }, { TARGET_NR_gettimeofday, "gettimeofday" , NULL, NULL, NULL },
#endif #endif
#ifdef TARGET_NR_getuid #ifdef TARGET_NR_getuid
{ TARGET_NR_getuid, "getuid" , NULL, NULL, NULL }, { TARGET_NR_getuid, "getuid" , "%s()", NULL, NULL },
#endif #endif
#ifdef TARGET_NR_getuid32 #ifdef TARGET_NR_getuid32
{ TARGET_NR_getuid32, "getuid32" , NULL, NULL, NULL }, { TARGET_NR_getuid32, "getuid32" , NULL, NULL, NULL },
@ -1155,7 +1155,7 @@
{ TARGET_NR_rt_sigprocmask, "rt_sigprocmask" , NULL, print_rt_sigprocmask, NULL }, { TARGET_NR_rt_sigprocmask, "rt_sigprocmask" , NULL, print_rt_sigprocmask, NULL },
#endif #endif
#ifdef TARGET_NR_rt_sigqueueinfo #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 #endif
#ifdef TARGET_NR_rt_sigreturn #ifdef TARGET_NR_rt_sigreturn
{ TARGET_NR_rt_sigreturn, "rt_sigreturn" , NULL, NULL, NULL }, { TARGET_NR_rt_sigreturn, "rt_sigreturn" , NULL, NULL, NULL },
@ -1167,7 +1167,7 @@
{ TARGET_NR_rt_sigtimedwait, "rt_sigtimedwait" , NULL, NULL, NULL }, { TARGET_NR_rt_sigtimedwait, "rt_sigtimedwait" , NULL, NULL, NULL },
#endif #endif
#ifdef TARGET_NR_rt_tgsigqueueinfo #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 #endif
#ifdef TARGET_NR_sched_getaffinity #ifdef TARGET_NR_sched_getaffinity
{ TARGET_NR_sched_getaffinity, "sched_getaffinity" , NULL, NULL, NULL }, { TARGET_NR_sched_getaffinity, "sched_getaffinity" , NULL, NULL, NULL },
@ -1498,7 +1498,7 @@
{ TARGET_NR_tee, "tee" , NULL, NULL, NULL }, { TARGET_NR_tee, "tee" , NULL, NULL, NULL },
#endif #endif
#ifdef TARGET_NR_tgkill #ifdef TARGET_NR_tgkill
{ TARGET_NR_tgkill, "tgkill" , NULL, NULL, NULL }, { TARGET_NR_tgkill, "tgkill" , NULL, print_tgkill, NULL },
#endif #endif
#ifdef TARGET_NR_time #ifdef TARGET_NR_time
{ TARGET_NR_time, "time" , NULL, NULL, NULL }, { TARGET_NR_time, "time" , NULL, NULL, NULL },
@ -1534,7 +1534,7 @@
{ TARGET_NR_times, "times" , NULL, NULL, NULL }, { TARGET_NR_times, "times" , NULL, NULL, NULL },
#endif #endif
#ifdef TARGET_NR_tkill #ifdef TARGET_NR_tkill
{ TARGET_NR_tkill, "tkill" , NULL, NULL, NULL }, { TARGET_NR_tkill, "tkill" , NULL, print_tkill, NULL },
#endif #endif
#ifdef TARGET_NR_truncate #ifdef TARGET_NR_truncate
{ TARGET_NR_truncate, "truncate" , NULL, NULL, NULL }, { TARGET_NR_truncate, "truncate" , NULL, NULL, NULL },

View File

@ -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_getdents64 __NR_getdents64
#define __NR_sys_getpriority __NR_getpriority #define __NR_sys_getpriority __NR_getpriority
#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo #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_syslog __NR_syslog
#define __NR_sys_futex __NR_futex #define __NR_sys_futex __NR_futex
#define __NR_sys_inotify_init __NR_inotify_init #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, _syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
loff_t *, res, uint, wh); loff_t *, res, uint, wh);
#endif #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) _syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
#ifdef __NR_exit_group #ifdef __NR_exit_group
_syscall1(int,exit_group,int,error_code) _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) static int open_self_cmdline(void *cpu_env, int fd)
{ {
int fd_orig = -1; CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
bool word_skipped = false; struct linux_binprm *bprm = ((TaskState *)cpu->opaque)->bprm;
int i;
fd_orig = open("/proc/self/cmdline", O_RDONLY); for (i = 0; i < bprm->argc; i++) {
if (fd_orig < 0) { size_t len = strlen(bprm->argv[i]) + 1;
return fd_orig;
}
while (true) { if (write(fd, bprm->argv[i], len) != len) {
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;
return -1; 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) 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; 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 /* do_syscall() should always have a single exit point at the end so
that actions, such as logging of syscall results, can be performed. that actions, such as logging of syscall results, can be performed.
All errnos that do_syscall() returns must be -TARGET_<errcode>. */ 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: case TARGET_NR_write:
if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1))) if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
goto efault; 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); unlock_user(p, arg2, 0);
break; break;
#ifdef TARGET_NR_open #ifdef TARGET_NR_open
@ -7926,8 +7955,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
envc++; envc++;
} }
argp = alloca((argc + 1) * sizeof(void *)); argp = g_new0(char *, argc + 1);
envp = alloca((envc + 1) * sizeof(void *)); envp = g_new0(char *, envc + 1);
for (gp = guest_argp, q = argp; gp; for (gp = guest_argp, q = argp; gp;
gp += sizeof(abi_ulong), q++) { gp += sizeof(abi_ulong), q++) {
@ -7988,6 +8017,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
break; break;
unlock_user(*q, addr, 0); unlock_user(*q, addr, 0);
} }
g_free(argp);
g_free(envp);
} }
break; break;
case TARGET_NR_chdir: 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 */ #ifdef TARGET_NR_ssetmask /* not on alpha */
case TARGET_NR_ssetmask: case TARGET_NR_ssetmask:
{ {
sigset_t set, oset, cur_set; sigset_t set, oset;
abi_ulong target_set = arg1; 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); target_to_host_old_sigset(&set, &target_set);
sigorset(&set, &set, &cur_set);
ret = do_sigprocmask(SIG_SETMASK, &set, &oset); ret = do_sigprocmask(SIG_SETMASK, &set, &oset);
if (!ret) { if (!ret) {
host_to_target_old_sigset(&target_set, &oset); 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; goto efault;
} }
target_to_host_siginfo(&uinfo, p); 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)); ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
} }
break; 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 #ifdef TARGET_NR_sigreturn
case TARGET_NR_sigreturn: case TARGET_NR_sigreturn:
if (block_signals()) { if (block_signals()) {
@ -11229,6 +11266,15 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#ifdef TARGET_NR_fadvise64_64 #ifdef TARGET_NR_fadvise64_64
case 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 */ /* 6 args: fd, offset (high, low), len (high, low), advice */
if (regpairs_aligned(cpu_env)) { if (regpairs_aligned(cpu_env)) {
/* offset is in (3,4), len in (5,6) and advice in 7 */ /* 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; arg5 = arg6;
arg6 = arg7; arg6 = arg7;
} }
#endif
ret = -host_to_target_errno(posix_fadvise(arg1, ret = -host_to_target_errno(posix_fadvise(arg1,
target_offset64(arg2, arg3), target_offset64(arg2, arg3),
target_offset64(arg4, arg5), 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) #if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
case TARGET_NR_inotify_init: case TARGET_NR_inotify_init:
ret = get_errno(sys_inotify_init()); ret = get_errno(sys_inotify_init());
fd_trans_register(ret, &target_inotify_trans);
break; break;
#endif #endif
#ifdef CONFIG_INOTIFY1 #ifdef CONFIG_INOTIFY1
@ -11701,6 +11749,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_inotify_init1: case TARGET_NR_inotify_init1:
ret = get_errno(sys_inotify_init1(target_to_host_bitmask(arg1, ret = get_errno(sys_inotify_init1(target_to_host_bitmask(arg1,
fcntl_flags_tbl))); fcntl_flags_tbl)));
fd_trans_register(ret, &target_inotify_trans);
break; break;
#endif #endif
#endif #endif
@ -11866,7 +11915,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#if defined(TARGET_NR_eventfd) #if defined(TARGET_NR_eventfd)
case TARGET_NR_eventfd: case TARGET_NR_eventfd:
ret = get_errno(eventfd(arg1, 0)); ret = get_errno(eventfd(arg1, 0));
fd_trans_unregister(ret); fd_trans_register(ret, &target_eventfd_trans);
break; break;
#endif #endif
#if defined(TARGET_NR_eventfd2) #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; host_flags |= O_CLOEXEC;
} }
ret = get_errno(eventfd(arg1, host_flags)); ret = get_errno(eventfd(arg1, host_flags));
fd_trans_unregister(ret); fd_trans_register(ret, &target_eventfd_trans);
break; break;
} }
#endif #endif