Syscall target errno fixes, by Thayne Harbaugh.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3418 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
ths 2007-10-20 20:23:07 +00:00
parent 1931e26054
commit 0da46a6e2e
2 changed files with 100 additions and 55 deletions

View File

@ -438,6 +438,7 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
} }
} }
/* do_sigaltstack() returns target values and errnos. */
int do_sigaltstack(const struct target_sigaltstack *uss, int do_sigaltstack(const struct target_sigaltstack *uss,
struct target_sigaltstack *uoss, struct target_sigaltstack *uoss,
abi_ulong sp) abi_ulong sp)
@ -457,18 +458,18 @@ int do_sigaltstack(const struct target_sigaltstack *uss,
{ {
struct target_sigaltstack ss; struct target_sigaltstack ss;
ret = -EFAULT; ret = -TARGET_EFAULT;
if (!access_ok(VERIFY_READ, uss, sizeof(*uss)) if (!access_ok(VERIFY_READ, uss, sizeof(*uss))
|| __get_user(ss.ss_sp, &uss->ss_sp) || __get_user(ss.ss_sp, &uss->ss_sp)
|| __get_user(ss.ss_size, &uss->ss_size) || __get_user(ss.ss_size, &uss->ss_size)
|| __get_user(ss.ss_flags, &uss->ss_flags)) || __get_user(ss.ss_flags, &uss->ss_flags))
goto out; goto out;
ret = -EPERM; ret = -TARGET_EPERM;
if (on_sig_stack(sp)) if (on_sig_stack(sp))
goto out; goto out;
ret = -EINVAL; ret = -TARGET_EINVAL;
if (ss.ss_flags != TARGET_SS_DISABLE if (ss.ss_flags != TARGET_SS_DISABLE
&& ss.ss_flags != TARGET_SS_ONSTACK && ss.ss_flags != TARGET_SS_ONSTACK
&& ss.ss_flags != 0) && ss.ss_flags != 0)
@ -478,7 +479,7 @@ int do_sigaltstack(const struct target_sigaltstack *uss,
ss.ss_size = 0; ss.ss_size = 0;
ss.ss_sp = 0; ss.ss_sp = 0;
} else { } else {
ret = -ENOMEM; ret = -TARGET_ENOMEM;
if (ss.ss_size < MINSIGSTKSZ) if (ss.ss_size < MINSIGSTKSZ)
goto out; goto out;
} }
@ -488,7 +489,7 @@ int do_sigaltstack(const struct target_sigaltstack *uss,
} }
if (uoss) { if (uoss) {
ret = -EFAULT; ret = -TARGET_EFAULT;
if (!access_ok(VERIFY_WRITE, uoss, sizeof(oss))) if (!access_ok(VERIFY_WRITE, uoss, sizeof(oss)))
goto out; goto out;
memcpy(uoss, &oss, sizeof(oss)); memcpy(uoss, &oss, sizeof(oss));
@ -499,12 +500,14 @@ out:
return ret; return ret;
} }
/* do_sigaction() return host values and errnos */
int do_sigaction(int sig, const struct target_sigaction *act, int do_sigaction(int sig, const struct target_sigaction *act,
struct target_sigaction *oact) struct target_sigaction *oact)
{ {
struct emulated_sigaction *k; struct emulated_sigaction *k;
struct sigaction act1; struct sigaction act1;
int host_sig; int host_sig;
int ret = 0;
if (sig < 1 || sig > TARGET_NSIG || sig == SIGKILL || sig == SIGSTOP) if (sig < 1 || sig > TARGET_NSIG || sig == SIGKILL || sig == SIGSTOP)
return -EINVAL; return -EINVAL;
@ -546,10 +549,10 @@ int do_sigaction(int sig, const struct target_sigaction *act,
} else { } else {
act1.sa_sigaction = host_signal_handler; act1.sa_sigaction = host_signal_handler;
} }
sigaction(host_sig, &act1, NULL); ret = sigaction(host_sig, &act1, NULL);
} }
} }
return 0; return ret;
} }
#ifndef offsetof #ifndef offsetof

View File

@ -167,6 +167,8 @@ type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \
#ifdef __NR_gettid #ifdef __NR_gettid
_syscall0(int, gettid) _syscall0(int, gettid)
#else #else
/* This is a replacement for the host gettid() and must return a host
errno. */
static int gettid(void) { static int gettid(void) {
return -ENOSYS; return -ENOSYS;
} }
@ -389,6 +391,7 @@ void target_set_brk(abi_ulong new_brk)
target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk); target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
} }
/* do_brk() must return target values and target errnos. */
abi_long do_brk(abi_ulong new_brk) abi_long do_brk(abi_ulong new_brk)
{ {
abi_ulong brk_page; abi_ulong brk_page;
@ -398,7 +401,7 @@ abi_long do_brk(abi_ulong new_brk)
if (!new_brk) if (!new_brk)
return target_brk; return target_brk;
if (new_brk < target_original_brk) if (new_brk < target_original_brk)
return -ENOMEM; return -TARGET_ENOMEM;
brk_page = HOST_PAGE_ALIGN(target_brk); brk_page = HOST_PAGE_ALIGN(target_brk);
@ -532,6 +535,7 @@ static inline void host_to_target_timeval(abi_ulong target_addr,
} }
/* do_select() must return target values and target errnos. */
static abi_long do_select(int n, static abi_long do_select(int n,
abi_ulong rfd_p, abi_ulong wfd_p, abi_ulong rfd_p, abi_ulong wfd_p,
abi_ulong efd_p, abi_ulong target_tv) abi_ulong efd_p, abi_ulong target_tv)
@ -706,6 +710,7 @@ static inline void host_to_target_cmsg(struct target_msghdr *target_msgh,
msgh->msg_controllen = tswapl(space); msgh->msg_controllen = tswapl(space);
} }
/* do_setsockopt() Must return target values and target errnos. */
static abi_long do_setsockopt(int sockfd, int level, int optname, static abi_long do_setsockopt(int sockfd, int level, int optname,
abi_ulong optval, socklen_t optlen) abi_ulong optval, socklen_t optlen)
{ {
@ -716,7 +721,7 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
case SOL_TCP: case SOL_TCP:
/* TCP options all take an 'int' value. */ /* TCP options all take an 'int' value. */
if (optlen < sizeof(uint32_t)) if (optlen < sizeof(uint32_t))
return -EINVAL; return -TARGET_EINVAL;
val = tget32(optval); val = tget32(optval);
ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val))); ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
@ -814,7 +819,7 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
goto unimplemented; goto unimplemented;
} }
if (optlen < sizeof(uint32_t)) if (optlen < sizeof(uint32_t))
return -EINVAL; return -TARGET_EINVAL;
val = tget32(optval); val = tget32(optval);
ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val))); ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
@ -822,11 +827,12 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
default: default:
unimplemented: unimplemented:
gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname); gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
ret = -ENOSYS; ret = -TARGET_ENOSYS;
} }
return ret; return ret;
} }
/* do_getsockopt() Must return target values and target errnos. */
static abi_long do_getsockopt(int sockfd, int level, int optname, static abi_long do_getsockopt(int sockfd, int level, int optname,
abi_ulong optval, abi_ulong optlen) abi_ulong optval, abi_ulong optlen)
{ {
@ -853,7 +859,7 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
int_case: int_case:
len = tget32(optlen); len = tget32(optlen);
if (len < 0) if (len < 0)
return -EINVAL; return -TARGET_EINVAL;
lv = sizeof(int); lv = sizeof(int);
ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv)); ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
if (ret < 0) if (ret < 0)
@ -886,7 +892,7 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
case IP_MULTICAST_LOOP: case IP_MULTICAST_LOOP:
len = tget32(optlen); len = tget32(optlen);
if (len < 0) if (len < 0)
return -EINVAL; return -TARGET_EINVAL;
lv = sizeof(int); lv = sizeof(int);
ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv)); ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
if (ret < 0) if (ret < 0)
@ -910,7 +916,7 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
unimplemented: unimplemented:
gemu_log("getsockopt level=%d optname=%d not yet supported\n", gemu_log("getsockopt level=%d optname=%d not yet supported\n",
level, optname); level, optname);
ret = -ENOSYS; ret = -TARGET_ENOSYS;
break; break;
} }
return ret; return ret;
@ -947,6 +953,7 @@ static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
unlock_user (target_vec, target_addr, 0); unlock_user (target_vec, target_addr, 0);
} }
/* do_socket() Must return target values and target errnos. */
static abi_long do_socket(int domain, int type, int protocol) static abi_long do_socket(int domain, int type, int protocol)
{ {
#if defined(TARGET_MIPS) #if defined(TARGET_MIPS)
@ -974,6 +981,7 @@ static abi_long do_socket(int domain, int type, int protocol)
return get_errno(socket(domain, type, protocol)); return get_errno(socket(domain, type, protocol));
} }
/* do_bind() Must return target values and target errnos. */
static abi_long do_bind(int sockfd, abi_ulong target_addr, static abi_long do_bind(int sockfd, abi_ulong target_addr,
socklen_t addrlen) socklen_t addrlen)
{ {
@ -983,6 +991,7 @@ static abi_long do_bind(int sockfd, abi_ulong target_addr,
return get_errno(bind(sockfd, addr, addrlen)); return get_errno(bind(sockfd, addr, addrlen));
} }
/* do_connect() Must return target values and target errnos. */
static abi_long do_connect(int sockfd, abi_ulong target_addr, static abi_long do_connect(int sockfd, abi_ulong target_addr,
socklen_t addrlen) socklen_t addrlen)
{ {
@ -992,6 +1001,7 @@ static abi_long do_connect(int sockfd, abi_ulong target_addr,
return get_errno(connect(sockfd, addr, addrlen)); return get_errno(connect(sockfd, addr, addrlen));
} }
/* do_sendrecvmsg() Must return target values and target errnos. */
static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
int flags, int send) int flags, int send)
{ {
@ -1035,6 +1045,7 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
return ret; return ret;
} }
/* do_accept() Must return target values and target errnos. */
static abi_long do_accept(int fd, abi_ulong target_addr, static abi_long do_accept(int fd, abi_ulong target_addr,
abi_ulong target_addrlen) abi_ulong target_addrlen)
{ {
@ -1050,6 +1061,7 @@ static abi_long do_accept(int fd, abi_ulong target_addr,
return ret; return ret;
} }
/* do_getpeername() Must return target values and target errnos. */
static abi_long do_getpeername(int fd, abi_ulong target_addr, static abi_long do_getpeername(int fd, abi_ulong target_addr,
abi_ulong target_addrlen) abi_ulong target_addrlen)
{ {
@ -1065,6 +1077,7 @@ static abi_long do_getpeername(int fd, abi_ulong target_addr,
return ret; return ret;
} }
/* do_getsockname() Must return target values and target errnos. */
static abi_long do_getsockname(int fd, abi_ulong target_addr, static abi_long do_getsockname(int fd, abi_ulong target_addr,
abi_ulong target_addrlen) abi_ulong target_addrlen)
{ {
@ -1080,6 +1093,7 @@ static abi_long do_getsockname(int fd, abi_ulong target_addr,
return ret; return ret;
} }
/* do_socketpair() Must return target values and target errnos. */
static abi_long do_socketpair(int domain, int type, int protocol, static abi_long do_socketpair(int domain, int type, int protocol,
abi_ulong target_tab) abi_ulong target_tab)
{ {
@ -1094,6 +1108,7 @@ static abi_long do_socketpair(int domain, int type, int protocol,
return ret; return ret;
} }
/* do_sendto() Must return target values and target errnos. */
static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags, static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
abi_ulong target_addr, socklen_t addrlen) abi_ulong target_addr, socklen_t addrlen)
{ {
@ -1113,6 +1128,7 @@ static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
return ret; return ret;
} }
/* do_recvfrom() Must return target values and target errnos. */
static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags, static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
abi_ulong target_addr, abi_ulong target_addr,
abi_ulong target_addrlen) abi_ulong target_addrlen)
@ -1144,6 +1160,7 @@ static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
} }
#ifdef TARGET_NR_socketcall #ifdef TARGET_NR_socketcall
/* 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)
{ {
abi_long ret; abi_long ret;
@ -1301,7 +1318,7 @@ static abi_long do_socketcall(int num, abi_ulong vptr)
break; break;
default: default:
gemu_log("Unsupported socketcall: %d\n", num); gemu_log("Unsupported socketcall: %d\n", num);
ret = -ENOSYS; ret = -TARGET_ENOSYS;
break; break;
} }
return ret; return ret;
@ -1639,6 +1656,7 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp,
} }
/* ??? This only works with linear mappings. */ /* ??? This only works with linear mappings. */
/* do_ipc() must return target values and target errnos. */
static abi_long do_ipc(unsigned int call, int first, static abi_long do_ipc(unsigned int call, int first,
int second, int third, int second, int third,
abi_long ptr, abi_long fifth) abi_long ptr, abi_long fifth)
@ -1667,7 +1685,7 @@ static abi_long do_ipc(unsigned int call, int first,
case IPCOP_semtimedop: case IPCOP_semtimedop:
gemu_log("Unsupported ipc call: %d (version %d)\n", call, version); gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ret = -ENOSYS; ret = -TARGET_ENOSYS;
break; break;
case IPCOP_msgget: case IPCOP_msgget:
@ -1723,7 +1741,7 @@ static abi_long do_ipc(unsigned int call, int first,
} }
} }
if (put_user(raddr, (abi_ulong *)third)) if (put_user(raddr, (abi_ulong *)third))
return -EFAULT; return -TARGET_EFAULT;
ret = 0; ret = 0;
break; break;
case IPCOP_shmdt: case IPCOP_shmdt:
@ -1757,7 +1775,7 @@ static abi_long do_ipc(unsigned int call, int first,
default: default:
unimplemented: unimplemented:
gemu_log("Unsupported ipc call: %d (version %d)\n", call, version); gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ret = -ENOSYS; ret = -TARGET_ENOSYS;
break; break;
} }
return ret; return ret;
@ -1803,6 +1821,7 @@ IOCTLEntry ioctl_entries[] = {
}; };
/* ??? Implement proper locking for ioctls. */ /* ??? Implement proper locking for ioctls. */
/* do_ioctl() Must return target values and target errnos. */
static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg) static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
{ {
const IOCTLEntry *ie; const IOCTLEntry *ie;
@ -1816,7 +1835,7 @@ static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
for(;;) { for(;;) {
if (ie->target_cmd == 0) { if (ie->target_cmd == 0) {
gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd); gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
return -ENOSYS; return -TARGET_ENOSYS;
} }
if (ie->target_cmd == cmd) if (ie->target_cmd == cmd)
break; break;
@ -1871,7 +1890,7 @@ static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
default: default:
gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n", gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
(long)cmd, arg_type[0]); (long)cmd, arg_type[0]);
ret = -ENOSYS; ret = -TARGET_ENOSYS;
break; break;
} }
return ret; return ret;
@ -2106,6 +2125,7 @@ static int read_ldt(abi_ulong ptr, unsigned long bytecount)
} }
/* XXX: add locking support */ /* XXX: add locking support */
/* write_ldt() returns host errnos */
static int write_ldt(CPUX86State *env, static int write_ldt(CPUX86State *env,
abi_ulong ptr, unsigned long bytecount, int oldmode) abi_ulong ptr, unsigned long bytecount, int oldmode)
{ {
@ -2188,6 +2208,8 @@ install:
} }
/* specific and weird i386 syscalls */ /* specific and weird i386 syscalls */
/* do_modify_ldt() returns host errnos (it is inconsistent with the
other do_*() functions which return target errnos). */
int do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr, unsigned long bytecount) int do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr, unsigned long bytecount)
{ {
int ret = -ENOSYS; int ret = -ENOSYS;
@ -2220,6 +2242,8 @@ static int clone_func(void *arg)
return 0; return 0;
} }
/* do_fork() Must return host values and target errnos (unlike most
do_*() functions). */
int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp) int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp)
{ {
int ret; int ret;
@ -2547,6 +2571,9 @@ static inline void host_to_target_timespec(abi_ulong target_addr,
unlock_user_struct(target_ts, target_addr, 1); unlock_user_struct(target_ts, target_addr, 1);
} }
/* 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>. */
abi_long do_syscall(void *cpu_env, int num, abi_long arg1, abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg2, abi_long arg3, abi_long arg4,
abi_long arg5, abi_long arg6) abi_long arg5, abi_long arg6)
@ -2590,12 +2617,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#if defined(TARGET_NR_openat) && defined(__NR_openat) #if defined(TARGET_NR_openat) && defined(__NR_openat)
case TARGET_NR_openat: case TARGET_NR_openat:
if (!arg2) { if (!arg2) {
ret = -EFAULT; ret = -TARGET_EFAULT;
goto fail; goto fail;
} }
p = lock_user_string(arg2); p = lock_user_string(arg2);
if (!access_ok(VERIFY_READ, p, 1)) if (!access_ok(VERIFY_READ, p, 1))
ret = -EFAULT; /* Don't "goto fail" so that cleanup can happen. */
ret = -TARGET_EFAULT;
else else
ret = get_errno(sys_openat(arg1, ret = get_errno(sys_openat(arg1,
path(p), path(p),
@ -2644,16 +2672,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#if defined(TARGET_NR_linkat) && defined(__NR_linkat) #if defined(TARGET_NR_linkat) && defined(__NR_linkat)
case TARGET_NR_linkat: case TARGET_NR_linkat:
if (!arg2 || !arg4) { if (!arg2 || !arg4) {
ret = -EFAULT; ret = -TARGET_EFAULT;
goto fail; goto fail;
} }
{ {
void * p2 = NULL; void * p2 = NULL;
p = lock_user_string(arg2); p = lock_user_string(arg2);
p2 = lock_user_string(arg4); p2 = lock_user_string(arg4);
if (!access_ok(VERIFY_READ, p, 1) if (!access_ok(VERIFY_READ, p, 1)
|| !access_ok(VERIFY_READ, p2, 1)) || !access_ok(VERIFY_READ, p2, 1))
ret = -EFAULT; /* Don't "goto fail" so that cleanup can happen. */
ret = -TARGET_EFAULT;
else else
ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5)); ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
if (p2) if (p2)
@ -2671,12 +2700,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat) #if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
case TARGET_NR_unlinkat: case TARGET_NR_unlinkat:
if (!arg2) { if (!arg2) {
ret = -EFAULT; ret = -TARGET_EFAULT;
goto fail; goto fail;
} }
p = lock_user_string(arg2); p = lock_user_string(arg2);
if (!access_ok(VERIFY_READ, p, 1)) if (!access_ok(VERIFY_READ, p, 1))
ret = -EFAULT; /* Don't "goto fail" so that cleanup can happen. */
ret = -TARGET_EFAULT;
else else
ret = get_errno(sys_unlinkat(arg1, p, arg3)); ret = get_errno(sys_unlinkat(arg1, p, arg3));
if (p) if (p)
@ -2762,12 +2792,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat) #if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
case TARGET_NR_mknodat: case TARGET_NR_mknodat:
if (!arg2) { if (!arg2) {
ret = -EFAULT; ret = -TARGET_EFAULT;
goto fail; goto fail;
} }
p = lock_user_string(arg2); p = lock_user_string(arg2);
if (!access_ok(VERIFY_READ, p, 1)) if (!access_ok(VERIFY_READ, p, 1))
ret = -EFAULT; /* Don't "goto fail" so that cleanup can happen. */
ret = -TARGET_EFAULT;
else else
ret = get_errno(sys_mknodat(arg1, p, arg3, arg4)); ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
if (p) if (p)
@ -2894,12 +2925,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat) #if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
case TARGET_NR_faccessat: case TARGET_NR_faccessat:
if (!arg2) { if (!arg2) {
ret = -EFAULT; ret = -TARGET_EFAULT;
goto fail; goto fail;
} }
p = lock_user_string(arg2); p = lock_user_string(arg2);
if (!access_ok(VERIFY_READ, p, 1)) if (!access_ok(VERIFY_READ, p, 1))
ret = -EFAULT; /* Don't "goto fail" so that cleanup can happen. */
ret = -TARGET_EFAULT;
else else
ret = get_errno(sys_faccessat(arg1, p, arg3, arg4)); ret = get_errno(sys_faccessat(arg1, p, arg3, arg4));
if (p) if (p)
@ -2935,8 +2967,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#if defined(TARGET_NR_renameat) && defined(__NR_renameat) #if defined(TARGET_NR_renameat) && defined(__NR_renameat)
case TARGET_NR_renameat: case TARGET_NR_renameat:
if (!arg2 || !arg4) { if (!arg2 || !arg4) {
ret = -EFAULT; ret = -TARGET_EFAULT;
goto fail; goto fail;
} }
{ {
void *p2 = NULL; void *p2 = NULL;
@ -2944,7 +2976,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
p2 = lock_user_string(arg4); p2 = lock_user_string(arg4);
if (!access_ok(VERIFY_READ, p, 1) if (!access_ok(VERIFY_READ, p, 1)
|| !access_ok(VERIFY_READ, p2, 1)) || !access_ok(VERIFY_READ, p2, 1))
ret = -EFAULT; /* Don't "goto fail" so that cleanup can happen. */
ret = -TARGET_EFAULT;
else else
ret = get_errno(sys_renameat(arg1, p, arg3, p2)); ret = get_errno(sys_renameat(arg1, p, arg3, p2));
if (p2) if (p2)
@ -2962,12 +2995,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat) #if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
case TARGET_NR_mkdirat: case TARGET_NR_mkdirat:
if (!arg2) { if (!arg2) {
ret = -EFAULT; ret = -TARGET_EFAULT;
goto fail; goto fail;
} }
p = lock_user_string(arg2); p = lock_user_string(arg2);
if (!access_ok(VERIFY_READ, p, 1)) if (!access_ok(VERIFY_READ, p, 1))
ret = -EFAULT; /* Don't "goto fail" so that cleanup can happen. */
ret = -TARGET_EFAULT;
else else
ret = get_errno(sys_mkdirat(arg1, p, arg3)); ret = get_errno(sys_mkdirat(arg1, p, arg3));
if (p) if (p)
@ -3202,7 +3236,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
how = SIG_SETMASK; how = SIG_SETMASK;
break; break;
default: default:
ret = -EINVAL; ret = -TARGET_EINVAL;
goto fail; goto fail;
} }
p = lock_user(arg2, sizeof(target_sigset_t), 1); p = lock_user(arg2, sizeof(target_sigset_t), 1);
@ -3239,7 +3273,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
how = SIG_SETMASK; how = SIG_SETMASK;
break; break;
default: default:
ret = -EINVAL; ret = -TARGET_EINVAL;
goto fail; goto fail;
} }
p = lock_user(arg2, sizeof(target_sigset_t), 1); p = lock_user(arg2, sizeof(target_sigset_t), 1);
@ -3434,16 +3468,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat) #if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
case TARGET_NR_symlinkat: case TARGET_NR_symlinkat:
if (!arg1 || !arg3) { if (!arg1 || !arg3) {
ret = -EFAULT; ret = -TARGET_EFAULT;
goto fail; goto fail;
} }
{ {
void *p2 = NULL; void *p2 = NULL;
p = lock_user_string(arg1); p = lock_user_string(arg1);
p2 = lock_user_string(arg3); p2 = lock_user_string(arg3);
if (!access_ok(VERIFY_READ, p, 1) if (!access_ok(VERIFY_READ, p, 1)
|| !access_ok(VERIFY_READ, p2, 1)) || !access_ok(VERIFY_READ, p2, 1))
ret = -EFAULT; /* Don't "goto fail" so that cleanup can happen. */
ret = -TARGET_EFAULT;
else else
ret = get_errno(sys_symlinkat(p, arg2, p2)); ret = get_errno(sys_symlinkat(p, arg2, p2));
if (p2) if (p2)
@ -3470,16 +3505,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat) #if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
case TARGET_NR_readlinkat: case TARGET_NR_readlinkat:
if (!arg2 || !arg3) { if (!arg2 || !arg3) {
ret = -EFAULT; ret = -TARGET_EFAULT;
goto fail; goto fail;
} }
{ {
void *p2 = NULL; void *p2 = NULL;
p = lock_user_string(arg2); p = lock_user_string(arg2);
p2 = lock_user(arg3, arg4, 0); p2 = lock_user(arg3, arg4, 0);
if (!access_ok(VERIFY_READ, p, 1) if (!access_ok(VERIFY_READ, p, 1)
|| !access_ok(VERIFY_READ, p2, 1)) || !access_ok(VERIFY_READ, p2, 1))
ret = -EFAULT; /* Don't "goto fail" so that cleanup can happen. */
ret = -TARGET_EFAULT;
else else
ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4)); ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
if (p2) if (p2)
@ -3596,12 +3632,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat) #if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
case TARGET_NR_fchmodat: case TARGET_NR_fchmodat:
if (!arg2) { if (!arg2) {
ret = -EFAULT; ret = -TARGET_EFAULT;
goto fail; goto fail;
} }
p = lock_user_string(arg2); p = lock_user_string(arg2);
if (!access_ok(VERIFY_READ, p, 1)) if (!access_ok(VERIFY_READ, p, 1))
ret = -EFAULT; /* Don't "goto fail" so that cleanup can happen. */
ret = -TARGET_EFAULT;
else else
ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4)); ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4));
if (p) if (p)
@ -4055,8 +4092,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
abi_long count = arg3; abi_long count = arg3;
dirp = malloc(count); dirp = malloc(count);
if (!dirp) if (!dirp) {
return -ENOMEM; ret = -TARGET_EFAULT;
goto fail;
}
ret = get_errno(sys_getdents(arg1, dirp, count)); ret = get_errno(sys_getdents(arg1, dirp, count));
if (!is_error(ret)) { if (!is_error(ret)) {
@ -4213,9 +4252,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
break; break;
#endif #endif
case TARGET_NR__sysctl: case TARGET_NR__sysctl:
/* We don't implement this, but ENODIR is always a safe /* We don't implement this, but ENOTDIR is always a safe
return value. */ return value. */
return -ENOTDIR; ret = -TARGET_ENOTDIR;
break;
case TARGET_NR_sched_setparam: case TARGET_NR_sched_setparam:
{ {
struct sched_param *target_schp; struct sched_param *target_schp;
@ -4514,12 +4554,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) #if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
case TARGET_NR_fchownat: case TARGET_NR_fchownat:
if (!arg2) { if (!arg2) {
ret = -EFAULT; ret = -TARGET_EFAULT;
goto fail; goto fail;
} }
p = lock_user_string(arg2); p = lock_user_string(arg2);
if (!access_ok(VERIFY_READ, p, 1)) if (!access_ok(VERIFY_READ, p, 1))
ret = -EFAULT; /* Don't "goto fail" so that cleanup can happen. */
ret = -TARGET_EFAULT;
else else
ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5)); ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
if (p) if (p)
@ -4958,7 +4999,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
else { else {
p = lock_user_string(arg2); p = lock_user_string(arg2);
if (!access_ok(VERIFY_READ, p, 1)) if (!access_ok(VERIFY_READ, p, 1))
ret = -EFAULT; /* Don't "goto fail" so that cleanup can happen. */
ret = -TARGET_EFAULT;
else else
ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4)); ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4));
if (p) if (p)
@ -4974,7 +5016,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || defined(TARGET_NR_getdomainname) || defined(TARGET_NR_set_robust_list) #if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || defined(TARGET_NR_getdomainname) || defined(TARGET_NR_set_robust_list)
unimplemented_nowarn: unimplemented_nowarn:
#endif #endif
ret = -ENOSYS; ret = -TARGET_ENOSYS;
break; break;
} }
fail: fail: