166eed099SWarner Losh /* 266eed099SWarner Losh * BSD syscalls 366eed099SWarner Losh * 466eed099SWarner Losh * Copyright (c) 2003-2008 Fabrice Bellard 566eed099SWarner Losh * Copyright (c) 2013-2014 Stacey D. Son 666eed099SWarner Losh * 766eed099SWarner Losh * This program is free software; you can redistribute it and/or modify 866eed099SWarner Losh * it under the terms of the GNU General Public License as published by 966eed099SWarner Losh * the Free Software Foundation; either version 2 of the License, or 1066eed099SWarner Losh * (at your option) any later version. 1166eed099SWarner Losh * 1266eed099SWarner Losh * This program is distributed in the hope that it will be useful, 1366eed099SWarner Losh * but WITHOUT ANY WARRANTY; without even the implied warranty of 1466eed099SWarner Losh * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1566eed099SWarner Losh * GNU General Public License for more details. 1666eed099SWarner Losh * 1766eed099SWarner Losh * You should have received a copy of the GNU General Public License 1866eed099SWarner Losh * along with this program; if not, see <http://www.gnu.org/licenses/>. 1966eed099SWarner Losh */ 2066eed099SWarner Losh 2166eed099SWarner Losh /* 2266eed099SWarner Losh * We need the FreeBSD "legacy" definitions. Rust needs the FreeBSD 11 system 2366eed099SWarner Losh * calls since it doesn't use libc at all, so we have to emulate that despite 2466eed099SWarner Losh * FreeBSD 11 being EOL'd. 2566eed099SWarner Losh */ 2666eed099SWarner Losh #define _WANT_FREEBSD11_STAT 2766eed099SWarner Losh #define _WANT_FREEBSD11_STATFS 2866eed099SWarner Losh #define _WANT_FREEBSD11_DIRENT 2966eed099SWarner Losh #define _WANT_KERNEL_ERRNO 3066eed099SWarner Losh #define _WANT_SEMUN 3166eed099SWarner Losh #include "qemu/osdep.h" 3266eed099SWarner Losh #include "qemu/cutils.h" 3366eed099SWarner Losh #include "qemu/path.h" 3466eed099SWarner Losh #include <sys/syscall.h> 3566eed099SWarner Losh #include <sys/param.h> 3666eed099SWarner Losh #include <sys/sysctl.h> 3766eed099SWarner Losh #include <utime.h> 3866eed099SWarner Losh 3966eed099SWarner Losh #include "qemu.h" 4066eed099SWarner Losh #include "signal-common.h" 4166eed099SWarner Losh #include "user/syscall-trace.h" 4266eed099SWarner Losh 43c5c84d16SWarner Losh #include "bsd-file.h" 44c5c84d16SWarner Losh 4566eed099SWarner Losh void target_set_brk(abi_ulong new_brk) 4666eed099SWarner Losh { 4766eed099SWarner Losh } 4866eed099SWarner Losh 49deeff83bSWarner Losh /* 50deeff83bSWarner Losh * errno conversion. 51deeff83bSWarner Losh */ 52deeff83bSWarner Losh abi_long get_errno(abi_long ret) 53deeff83bSWarner Losh { 54deeff83bSWarner Losh if (ret == -1) { 55deeff83bSWarner Losh return -host_to_target_errno(errno); 56deeff83bSWarner Losh } else { 57deeff83bSWarner Losh return ret; 58deeff83bSWarner Losh } 59deeff83bSWarner Losh } 60deeff83bSWarner Losh 61deeff83bSWarner Losh int host_to_target_errno(int err) 62deeff83bSWarner Losh { 63deeff83bSWarner Losh /* 64deeff83bSWarner Losh * All the BSDs have the property that the error numbers are uniform across 65deeff83bSWarner Losh * all architectures for a given BSD, though they may vary between different 66deeff83bSWarner Losh * BSDs. 67deeff83bSWarner Losh */ 68deeff83bSWarner Losh return err; 69deeff83bSWarner Losh } 70deeff83bSWarner Losh 7166eed099SWarner Losh bool is_error(abi_long ret) 7266eed099SWarner Losh { 7366eed099SWarner Losh return (abi_ulong)ret >= (abi_ulong)(-4096); 7466eed099SWarner Losh } 7566eed099SWarner Losh 7666eed099SWarner Losh /* 77*1ed771b2SWarner Losh * Unlocks a iovec. Unlike unlock_iovec, it assumes the tvec array itself is 78*1ed771b2SWarner Losh * already locked from target_addr. It will be unlocked as well as all the iovec 79*1ed771b2SWarner Losh * elements. 80*1ed771b2SWarner Losh */ 81*1ed771b2SWarner Losh static void helper_unlock_iovec(struct target_iovec *target_vec, 82*1ed771b2SWarner Losh abi_ulong target_addr, struct iovec *vec, 83*1ed771b2SWarner Losh int count, int copy) 84*1ed771b2SWarner Losh { 85*1ed771b2SWarner Losh for (int i = 0; i < count; i++) { 86*1ed771b2SWarner Losh abi_ulong base = tswapal(target_vec[i].iov_base); 87*1ed771b2SWarner Losh 88*1ed771b2SWarner Losh if (vec[i].iov_base) { 89*1ed771b2SWarner Losh unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0); 90*1ed771b2SWarner Losh } 91*1ed771b2SWarner Losh } 92*1ed771b2SWarner Losh unlock_user(target_vec, target_addr, 0); 93*1ed771b2SWarner Losh } 94*1ed771b2SWarner Losh 95*1ed771b2SWarner Losh struct iovec *lock_iovec(int type, abi_ulong target_addr, 96*1ed771b2SWarner Losh int count, int copy) 97*1ed771b2SWarner Losh { 98*1ed771b2SWarner Losh struct target_iovec *target_vec; 99*1ed771b2SWarner Losh struct iovec *vec; 100*1ed771b2SWarner Losh abi_ulong total_len, max_len; 101*1ed771b2SWarner Losh int i; 102*1ed771b2SWarner Losh int err = 0; 103*1ed771b2SWarner Losh 104*1ed771b2SWarner Losh if (count == 0) { 105*1ed771b2SWarner Losh errno = 0; 106*1ed771b2SWarner Losh return NULL; 107*1ed771b2SWarner Losh } 108*1ed771b2SWarner Losh if (count < 0 || count > IOV_MAX) { 109*1ed771b2SWarner Losh errno = EINVAL; 110*1ed771b2SWarner Losh return NULL; 111*1ed771b2SWarner Losh } 112*1ed771b2SWarner Losh 113*1ed771b2SWarner Losh vec = g_try_new0(struct iovec, count); 114*1ed771b2SWarner Losh if (vec == NULL) { 115*1ed771b2SWarner Losh errno = ENOMEM; 116*1ed771b2SWarner Losh return NULL; 117*1ed771b2SWarner Losh } 118*1ed771b2SWarner Losh 119*1ed771b2SWarner Losh target_vec = lock_user(VERIFY_READ, target_addr, 120*1ed771b2SWarner Losh count * sizeof(struct target_iovec), 1); 121*1ed771b2SWarner Losh if (target_vec == NULL) { 122*1ed771b2SWarner Losh err = EFAULT; 123*1ed771b2SWarner Losh goto fail2; 124*1ed771b2SWarner Losh } 125*1ed771b2SWarner Losh 126*1ed771b2SWarner Losh max_len = 0x7fffffff & MIN(TARGET_PAGE_MASK, PAGE_MASK); 127*1ed771b2SWarner Losh total_len = 0; 128*1ed771b2SWarner Losh 129*1ed771b2SWarner Losh for (i = 0; i < count; i++) { 130*1ed771b2SWarner Losh abi_ulong base = tswapal(target_vec[i].iov_base); 131*1ed771b2SWarner Losh abi_long len = tswapal(target_vec[i].iov_len); 132*1ed771b2SWarner Losh 133*1ed771b2SWarner Losh if (len < 0) { 134*1ed771b2SWarner Losh err = EINVAL; 135*1ed771b2SWarner Losh goto fail; 136*1ed771b2SWarner Losh } else if (len == 0) { 137*1ed771b2SWarner Losh /* Zero length pointer is ignored. */ 138*1ed771b2SWarner Losh vec[i].iov_base = 0; 139*1ed771b2SWarner Losh } else { 140*1ed771b2SWarner Losh vec[i].iov_base = lock_user(type, base, len, copy); 141*1ed771b2SWarner Losh /* 142*1ed771b2SWarner Losh * If the first buffer pointer is bad, this is a fault. But 143*1ed771b2SWarner Losh * subsequent bad buffers will result in a partial write; this is 144*1ed771b2SWarner Losh * realized by filling the vector with null pointers and zero 145*1ed771b2SWarner Losh * lengths. 146*1ed771b2SWarner Losh */ 147*1ed771b2SWarner Losh if (!vec[i].iov_base) { 148*1ed771b2SWarner Losh if (i == 0) { 149*1ed771b2SWarner Losh err = EFAULT; 150*1ed771b2SWarner Losh goto fail; 151*1ed771b2SWarner Losh } else { 152*1ed771b2SWarner Losh /* 153*1ed771b2SWarner Losh * Fail all the subsequent addresses, they are already 154*1ed771b2SWarner Losh * zero'd. 155*1ed771b2SWarner Losh */ 156*1ed771b2SWarner Losh goto out; 157*1ed771b2SWarner Losh } 158*1ed771b2SWarner Losh } 159*1ed771b2SWarner Losh if (len > max_len - total_len) { 160*1ed771b2SWarner Losh len = max_len - total_len; 161*1ed771b2SWarner Losh } 162*1ed771b2SWarner Losh } 163*1ed771b2SWarner Losh vec[i].iov_len = len; 164*1ed771b2SWarner Losh total_len += len; 165*1ed771b2SWarner Losh } 166*1ed771b2SWarner Losh out: 167*1ed771b2SWarner Losh unlock_user(target_vec, target_addr, 0); 168*1ed771b2SWarner Losh return vec; 169*1ed771b2SWarner Losh 170*1ed771b2SWarner Losh fail: 171*1ed771b2SWarner Losh helper_unlock_iovec(target_vec, target_addr, vec, i, copy); 172*1ed771b2SWarner Losh fail2: 173*1ed771b2SWarner Losh g_free(vec); 174*1ed771b2SWarner Losh errno = err; 175*1ed771b2SWarner Losh return NULL; 176*1ed771b2SWarner Losh } 177*1ed771b2SWarner Losh 178*1ed771b2SWarner Losh /* 17966eed099SWarner Losh * do_syscall() should always have a single exit point at the end so that 18066eed099SWarner Losh * actions, such as logging of syscall results, can be performed. All errnos 18166eed099SWarner Losh * that do_syscall() returns must be -TARGET_<errcode>. 18266eed099SWarner Losh */ 18366eed099SWarner Losh abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1, 18466eed099SWarner Losh abi_long arg2, abi_long arg3, abi_long arg4, 18566eed099SWarner Losh abi_long arg5, abi_long arg6, abi_long arg7, 18666eed099SWarner Losh abi_long arg8) 18766eed099SWarner Losh { 18866eed099SWarner Losh return 0; 18966eed099SWarner Losh } 19066eed099SWarner Losh 19166eed099SWarner Losh void syscall_init(void) 19266eed099SWarner Losh { 19366eed099SWarner Losh } 194