diff options
Diffstat (limited to 'linux-user/syscall.c')
-rw-r--r-- | linux-user/syscall.c | 338 |
1 files changed, 237 insertions, 101 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c index b8c278b..fc37028 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -26,6 +26,9 @@ #include "tcg/startup.h" #include "target_mman.h" #include "exec/page-protection.h" +#include "exec/mmap-lock.h" +#include "exec/tb-flush.h" +#include "exec/translation-block.h" #include <elf.h> #include <endian.h> #include <grp.h> @@ -54,7 +57,6 @@ #include <utime.h> #include <sys/sysinfo.h> #include <sys/signalfd.h> -//#include <sys/user.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/tcp.h> @@ -136,14 +138,16 @@ #include "signal-common.h" #include "loader.h" #include "user-mmap.h" +#include "user/page-protection.h" #include "user/safe-syscall.h" +#include "user/signal.h" #include "qemu/guest-random.h" #include "qemu/selfmap.h" #include "user/syscall-trace.h" #include "special-errno.h" #include "qapi/error.h" #include "fd-trans.h" -#include "cpu_loop-common.h" +#include "user/cpu_loop.h" #ifndef CLONE_IO #define CLONE_IO 0x80000000 /* Clone io context */ @@ -359,7 +363,8 @@ _syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len, #define __NR_sys_sched_setaffinity __NR_sched_setaffinity _syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len, unsigned long *, user_mask_ptr); -/* sched_attr is not defined in glibc */ +/* sched_attr is not defined in glibc < 2.41 */ +#ifndef SCHED_ATTR_SIZE_VER0 struct sched_attr { uint32_t size; uint32_t sched_policy; @@ -372,6 +377,7 @@ struct sched_attr { uint32_t sched_util_min; uint32_t sched_util_max; }; +#endif #define __NR_sys_sched_getattr __NR_sched_getattr _syscall4(int, sys_sched_getattr, pid_t, pid, struct sched_attr *, attr, unsigned int, size, unsigned int, flags); @@ -602,6 +608,33 @@ static int check_zeroed_user(abi_long addr, size_t ksize, size_t usize) return 1; } +/* + * Copies a target struct to a host struct, in a way that guarantees + * backwards-compatibility for struct syscall arguments. + * + * Similar to kernels uaccess.h:copy_struct_from_user() + */ +int copy_struct_from_user(void *dst, size_t ksize, abi_ptr src, size_t usize) +{ + size_t size = MIN(ksize, usize); + size_t rest = MAX(ksize, usize) - size; + + /* Deal with trailing bytes. */ + if (usize < ksize) { + memset(dst + size, 0, rest); + } else if (usize > ksize) { + int ret = check_zeroed_user(src, ksize, usize); + if (ret <= 0) { + return ret ?: -TARGET_E2BIG; + } + } + /* Copy the interoperable parts of the struct. */ + if (copy_from_user(dst, src, size)) { + return -TARGET_EFAULT; + } + return 0; +} + #define safe_syscall0(type, name) \ static type safe_##name(void) \ { \ @@ -653,6 +686,10 @@ safe_syscall3(ssize_t, read, int, fd, void *, buff, size_t, count) safe_syscall3(ssize_t, write, int, fd, const void *, buff, size_t, count) safe_syscall4(int, openat, int, dirfd, const char *, pathname, \ int, flags, mode_t, mode) + +safe_syscall4(int, openat2, int, dirfd, const char *, pathname, \ + const struct open_how_ver0 *, how, size_t, size) + #if defined(TARGET_NR_wait4) || defined(TARGET_NR_waitpid) safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \ struct rusage *, rusage) @@ -759,10 +796,8 @@ safe_syscall6(ssize_t, copy_file_range, int, infd, loff_t *, pinoff, * the libc function. */ #define safe_ioctl(...) safe_syscall(__NR_ioctl, __VA_ARGS__) -/* Similarly for fcntl. Note that callers must always: - * pass the F_GETLK64 etc constants rather than the unsuffixed F_GETLK - * use the flock64 struct rather than unsuffixed flock - * This will then work and use a 64-bit offset for both 32-bit and 64-bit hosts. +/* Similarly for fcntl. Since we always build with LFS enabled, + * we should be using the 64-bit structures automatically. */ #ifdef __NR_fcntl64 #define safe_fcntl(...) safe_syscall(__NR_fcntl64, __VA_ARGS__) @@ -1797,7 +1832,7 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh, *dst = tswap32(*dst); } } else { - qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n", + qemu_log_mask(LOG_UNIMP, "Unsupported target ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type); memcpy(data, target_data, len); } @@ -1968,6 +2003,16 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh, (void *) &errh->offender, sizeof(errh->offender)); break; } + case IP_PKTINFO: + { + struct in_pktinfo *pkti = data; + struct target_in_pktinfo *target_pi = target_data; + + __put_user(pkti->ipi_ifindex, &target_pi->ipi_ifindex); + target_pi->ipi_spec_dst.s_addr = pkti->ipi_spec_dst.s_addr; + target_pi->ipi_addr.s_addr = pkti->ipi_addr.s_addr; + break; + } default: goto unimplemented; } @@ -2019,7 +2064,7 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh, default: unimplemented: - qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n", + qemu_log_mask(LOG_UNIMP, "Unsupported host ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type); memcpy(target_data, data, MIN(len, tgt_len)); if (tgt_len > len) { @@ -2090,16 +2135,23 @@ static abi_long do_setsockopt(int sockfd, int level, int optname, } ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val))); break; + case IP_MULTICAST_IF: case IP_ADD_MEMBERSHIP: case IP_DROP_MEMBERSHIP: { struct ip_mreqn ip_mreq; struct target_ip_mreqn *target_smreqn; + int min_size; QEMU_BUILD_BUG_ON(sizeof(struct ip_mreq) != sizeof(struct target_ip_mreq)); - if (optlen < sizeof (struct target_ip_mreq) || + if (optname == IP_MULTICAST_IF) { + min_size = sizeof(struct in_addr); + } else { + min_size = sizeof(struct target_ip_mreq); + } + if (optlen < min_size || optlen > sizeof (struct target_ip_mreqn)) { return -TARGET_EINVAL; } @@ -2109,13 +2161,14 @@ static abi_long do_setsockopt(int sockfd, int level, int optname, return -TARGET_EFAULT; } ip_mreq.imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr; - ip_mreq.imr_address.s_addr = target_smreqn->imr_address.s_addr; - if (optlen == sizeof(struct target_ip_mreqn)) { - ip_mreq.imr_ifindex = tswapal(target_smreqn->imr_ifindex); - optlen = sizeof(struct ip_mreqn); + if (optlen >= sizeof(struct target_ip_mreq)) { + ip_mreq.imr_address.s_addr = target_smreqn->imr_address.s_addr; + if (optlen >= sizeof(struct target_ip_mreqn)) { + __put_user(target_smreqn->imr_ifindex, &ip_mreq.imr_ifindex); + optlen = sizeof(struct ip_mreqn); + } } unlock_user(target_smreqn, optval_addr, 0); - ret = get_errno(setsockopt(sockfd, level, optname, &ip_mreq, optlen)); break; } @@ -6722,13 +6775,13 @@ static int target_to_host_fcntl_cmd(int cmd) ret = cmd; break; case TARGET_F_GETLK: - ret = F_GETLK64; + ret = F_GETLK; break; case TARGET_F_SETLK: - ret = F_SETLK64; + ret = F_SETLK; break; case TARGET_F_SETLKW: - ret = F_SETLKW64; + ret = F_SETLKW; break; case TARGET_F_GETOWN: ret = F_GETOWN; @@ -6744,13 +6797,13 @@ static int target_to_host_fcntl_cmd(int cmd) break; #if TARGET_ABI_BITS == 32 case TARGET_F_GETLK64: - ret = F_GETLK64; + ret = F_GETLK; break; case TARGET_F_SETLK64: - ret = F_SETLK64; + ret = F_SETLK; break; case TARGET_F_SETLKW64: - ret = F_SETLKW64; + ret = F_SETLKW; break; #endif case TARGET_F_SETLEASE: @@ -6804,8 +6857,8 @@ static int target_to_host_fcntl_cmd(int cmd) * them to 5, 6 and 7 before making the syscall(). Since we make the * syscall directly, adjust to what is supported by the kernel. */ - if (ret >= F_GETLK64 && ret <= F_SETLKW64) { - ret -= F_GETLK64 - 5; + if (ret >= F_GETLK && ret <= F_SETLKW) { + ret -= F_GETLK - 5; } #endif @@ -6838,7 +6891,7 @@ static int host_to_target_flock(int type) return type; } -static inline abi_long copy_from_user_flock(struct flock64 *fl, +static inline abi_long copy_from_user_flock(struct flock *fl, abi_ulong target_flock_addr) { struct target_flock *target_fl; @@ -6863,7 +6916,7 @@ static inline abi_long copy_from_user_flock(struct flock64 *fl, } static inline abi_long copy_to_user_flock(abi_ulong target_flock_addr, - const struct flock64 *fl) + const struct flock *fl) { struct target_flock *target_fl; short l_type; @@ -6882,8 +6935,8 @@ static inline abi_long copy_to_user_flock(abi_ulong target_flock_addr, return 0; } -typedef abi_long from_flock64_fn(struct flock64 *fl, abi_ulong target_addr); -typedef abi_long to_flock64_fn(abi_ulong target_addr, const struct flock64 *fl); +typedef abi_long from_flock64_fn(struct flock *fl, abi_ulong target_addr); +typedef abi_long to_flock64_fn(abi_ulong target_addr, const struct flock *fl); #if defined(TARGET_ARM) && TARGET_ABI_BITS == 32 struct target_oabi_flock64 { @@ -6894,7 +6947,7 @@ struct target_oabi_flock64 { abi_int l_pid; } QEMU_PACKED; -static inline abi_long copy_from_user_oabi_flock64(struct flock64 *fl, +static inline abi_long copy_from_user_oabi_flock64(struct flock *fl, abi_ulong target_flock_addr) { struct target_oabi_flock64 *target_fl; @@ -6919,7 +6972,7 @@ static inline abi_long copy_from_user_oabi_flock64(struct flock64 *fl, } static inline abi_long copy_to_user_oabi_flock64(abi_ulong target_flock_addr, - const struct flock64 *fl) + const struct flock *fl) { struct target_oabi_flock64 *target_fl; short l_type; @@ -6939,7 +6992,7 @@ static inline abi_long copy_to_user_oabi_flock64(abi_ulong target_flock_addr, } #endif -static inline abi_long copy_from_user_flock64(struct flock64 *fl, +static inline abi_long copy_from_user_flock64(struct flock *fl, abi_ulong target_flock_addr) { struct target_flock64 *target_fl; @@ -6964,7 +7017,7 @@ static inline abi_long copy_from_user_flock64(struct flock64 *fl, } static inline abi_long copy_to_user_flock64(abi_ulong target_flock_addr, - const struct flock64 *fl) + const struct flock *fl) { struct target_flock64 *target_fl; short l_type; @@ -6985,7 +7038,7 @@ static inline abi_long copy_to_user_flock64(abi_ulong target_flock_addr, static abi_long do_fcntl(int fd, int cmd, abi_ulong arg) { - struct flock64 fl64; + struct flock fl; #ifdef F_GETOWN_EX struct f_owner_ex fox; struct target_f_owner_ex *target_fox; @@ -6998,45 +7051,45 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg) switch(cmd) { case TARGET_F_GETLK: - ret = copy_from_user_flock(&fl64, arg); + ret = copy_from_user_flock(&fl, arg); if (ret) { return ret; } - ret = get_errno(safe_fcntl(fd, host_cmd, &fl64)); + ret = get_errno(safe_fcntl(fd, host_cmd, &fl)); if (ret == 0) { - ret = copy_to_user_flock(arg, &fl64); + ret = copy_to_user_flock(arg, &fl); } break; case TARGET_F_SETLK: case TARGET_F_SETLKW: - ret = copy_from_user_flock(&fl64, arg); + ret = copy_from_user_flock(&fl, arg); if (ret) { return ret; } - ret = get_errno(safe_fcntl(fd, host_cmd, &fl64)); + ret = get_errno(safe_fcntl(fd, host_cmd, &fl)); break; case TARGET_F_GETLK64: case TARGET_F_OFD_GETLK: - ret = copy_from_user_flock64(&fl64, arg); + ret = copy_from_user_flock64(&fl, arg); if (ret) { return ret; } - ret = get_errno(safe_fcntl(fd, host_cmd, &fl64)); + ret = get_errno(safe_fcntl(fd, host_cmd, &fl)); if (ret == 0) { - ret = copy_to_user_flock64(arg, &fl64); + ret = copy_to_user_flock64(arg, &fl); } break; case TARGET_F_SETLK64: case TARGET_F_SETLKW64: case TARGET_F_OFD_SETLK: case TARGET_F_OFD_SETLKW: - ret = copy_from_user_flock64(&fl64, arg); + ret = copy_from_user_flock64(&fl, arg); if (ret) { return ret; } - ret = get_errno(safe_fcntl(fd, host_cmd, &fl64)); + ret = get_errno(safe_fcntl(fd, host_cmd, &fl)); break; case TARGET_F_GETFL: @@ -7205,12 +7258,24 @@ static inline int tswapid(int id) #else #define __NR_sys_setgroups __NR_setgroups #endif +#ifdef __NR_sys_setreuid32 +#define __NR_sys_setreuid __NR_setreuid32 +#else +#define __NR_sys_setreuid __NR_setreuid +#endif +#ifdef __NR_sys_setregid32 +#define __NR_sys_setregid __NR_setregid32 +#else +#define __NR_sys_setregid __NR_setregid +#endif _syscall1(int, sys_setuid, uid_t, uid) _syscall1(int, sys_setgid, gid_t, gid) _syscall3(int, sys_setresuid, uid_t, ruid, uid_t, euid, uid_t, suid) _syscall3(int, sys_setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid) _syscall2(int, sys_setgroups, int, size, gid_t *, grouplist) +_syscall2(int, sys_setreuid, uid_t, ruid, uid_t, euid); +_syscall2(int, sys_setregid, gid_t, rgid, gid_t, egid); void syscall_init(void) { @@ -7267,7 +7332,7 @@ static inline abi_long target_truncate64(CPUArchState *cpu_env, const char *arg1 arg2 = arg3; arg3 = arg4; } - return get_errno(truncate64(arg1, target_offset64(arg2, arg3))); + return get_errno(truncate(arg1, target_offset64(arg2, arg3))); } #endif @@ -7281,7 +7346,7 @@ static inline abi_long target_ftruncate64(CPUArchState *cpu_env, abi_long arg1, arg2 = arg3; arg3 = arg4; } - return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3))); + return get_errno(ftruncate(arg1, target_offset64(arg2, arg3))); } #endif @@ -8070,8 +8135,8 @@ static void open_self_maps_4(const struct open_self_maps_data *d, * Callback for walk_memory_regions, when read_self_maps() fails. * Proceed without the benefit of host /proc/self/maps cross-check. */ -static int open_self_maps_3(void *opaque, target_ulong guest_start, - target_ulong guest_end, unsigned long flags) +static int open_self_maps_3(void *opaque, vaddr guest_start, + vaddr guest_end, int flags) { static const MapInfo mi = { .is_priv = true }; @@ -8082,8 +8147,8 @@ static int open_self_maps_3(void *opaque, target_ulong guest_start, /* * Callback for walk_memory_regions, when read_self_maps() succeeds. */ -static int open_self_maps_2(void *opaque, target_ulong guest_start, - target_ulong guest_end, unsigned long flags) +static int open_self_maps_2(void *opaque, vaddr guest_start, + vaddr guest_end, int flags) { const struct open_self_maps_data *d = opaque; uintptr_t host_start = (uintptr_t)g2h_untagged(guest_start); @@ -8122,17 +8187,19 @@ static int open_self_maps_1(CPUArchState *env, int fd, bool smaps) { struct open_self_maps_data d = { .ts = get_task_state(env_cpu(env)), - .host_maps = read_self_maps(), .fd = fd, .smaps = smaps }; + mmap_lock(); + d.host_maps = read_self_maps(); if (d.host_maps) { walk_memory_regions(&d, open_self_maps_2); free_self_maps(d.host_maps); } else { walk_memory_regions(&d, open_self_maps_3); } + mmap_unlock(); return 0; } @@ -8168,6 +8235,19 @@ static int open_self_stat(CPUArchState *cpu_env, int fd) } else if (i == 3) { /* ppid */ g_string_printf(buf, FMT_pid " ", getppid()); + } else if (i == 4) { + /* pgid */ + g_string_printf(buf, FMT_pid " ", getpgrp()); + } else if (i == 19) { + /* num_threads */ + int cpus = 0; + WITH_RCU_READ_LOCK_GUARD() { + CPUState *cpu_iter; + CPU_FOREACH(cpu_iter) { + cpus++; + } + } + g_string_printf(buf, "%d ", cpus); } else if (i == 21) { /* starttime */ g_string_printf(buf, "%" PRIu64 " ", ts->start_boottime); @@ -8324,8 +8404,9 @@ static int open_net_route(CPUArchState *cpu_env, int fd) } #endif -int do_guest_openat(CPUArchState *cpu_env, int dirfd, const char *fname, - int flags, mode_t mode, bool safe) +static int maybe_do_fake_open(CPUArchState *cpu_env, int dirfd, + const char *fname, int flags, mode_t mode, + int openat2_resolve, bool safe) { g_autofree char *proc_name = NULL; const char *pathname; @@ -8362,6 +8443,12 @@ int do_guest_openat(CPUArchState *cpu_env, int dirfd, const char *fname, } if (is_proc_myself(pathname, "exe")) { + /* Honor openat2 resolve flags */ + if ((openat2_resolve & RESOLVE_NO_MAGICLINKS) || + (openat2_resolve & RESOLVE_NO_SYMLINKS)) { + errno = ELOOP; + return -1; + } if (safe) { return safe_openat(dirfd, exec_path, flags, mode); } else { @@ -8408,6 +8495,17 @@ int do_guest_openat(CPUArchState *cpu_env, int dirfd, const char *fname, return fd; } + return -2; +} + +int do_guest_openat(CPUArchState *cpu_env, int dirfd, const char *pathname, + int flags, mode_t mode, bool safe) +{ + int fd = maybe_do_fake_open(cpu_env, dirfd, pathname, flags, mode, 0, safe); + if (fd > -2) { + return fd; + } + if (safe) { return safe_openat(dirfd, path(pathname), flags, mode); } else { @@ -8415,6 +8513,49 @@ int do_guest_openat(CPUArchState *cpu_env, int dirfd, const char *fname, } } + +static int do_openat2(CPUArchState *cpu_env, abi_long dirfd, + abi_ptr guest_pathname, abi_ptr guest_open_how, + abi_ulong guest_size) +{ + struct open_how_ver0 how = {0}; + char *pathname; + int ret; + + if (guest_size < sizeof(struct target_open_how_ver0)) { + return -TARGET_EINVAL; + } + ret = copy_struct_from_user(&how, sizeof(how), guest_open_how, guest_size); + if (ret) { + if (ret == -TARGET_E2BIG) { + qemu_log_mask(LOG_UNIMP, + "Unimplemented openat2 open_how size: " + TARGET_ABI_FMT_lu "\n", guest_size); + } + return ret; + } + pathname = lock_user_string(guest_pathname); + if (!pathname) { + return -TARGET_EFAULT; + } + + how.flags = target_to_host_bitmask(tswap64(how.flags), fcntl_flags_tbl); + how.mode = tswap64(how.mode); + how.resolve = tswap64(how.resolve); + int fd = maybe_do_fake_open(cpu_env, dirfd, pathname, how.flags, how.mode, + how.resolve, true); + if (fd > -2) { + ret = get_errno(fd); + } else { + ret = get_errno(safe_openat2(dirfd, pathname, &how, + sizeof(struct open_how_ver0))); + } + + fd_trans_unregister(ret); + unlock_user(pathname, guest_pathname, 0); + return ret; +} + ssize_t do_guest_readlink(const char *pathname, char *buf, size_t bufsiz) { ssize_t ret; @@ -8656,7 +8797,7 @@ static int do_getdents(abi_long dirfd, abi_long arg2, abi_long count) void *tdirp; int hlen, hoff, toff; int hreclen, treclen; - off64_t prev_diroff = 0; + off_t prev_diroff = 0; hdirp = g_try_malloc(count); if (!hdirp) { @@ -8709,7 +8850,7 @@ static int do_getdents(abi_long dirfd, abi_long arg2, abi_long count) * Return what we have, resetting the file pointer to the * location of the first record not returned. */ - lseek64(dirfd, prev_diroff, SEEK_SET); + lseek(dirfd, prev_diroff, SEEK_SET); break; } @@ -8743,7 +8884,7 @@ static int do_getdents64(abi_long dirfd, abi_long arg2, abi_long count) void *tdirp; int hlen, hoff, toff; int hreclen, treclen; - off64_t prev_diroff = 0; + off_t prev_diroff = 0; hdirp = g_try_malloc(count); if (!hdirp) { @@ -8785,7 +8926,7 @@ static int do_getdents64(abi_long dirfd, abi_long arg2, abi_long count) * Return what we have, resetting the file pointer to the * location of the first record not returned. */ - lseek64(dirfd, prev_diroff, SEEK_SET); + lseek(dirfd, prev_diroff, SEEK_SET); break; } @@ -8843,7 +8984,7 @@ static int do_getdents64(abi_long dirfd, abi_long arg2, abi_long count) #define RISCV_HWPROBE_EXT_ZFHMIN (1 << 28) #define RISCV_HWPROBE_EXT_ZIHINTNTL (1 << 29) #define RISCV_HWPROBE_EXT_ZVFH (1 << 30) -#define RISCV_HWPROBE_EXT_ZVFHMIN (1 << 31) +#define RISCV_HWPROBE_EXT_ZVFHMIN (1ULL << 31) #define RISCV_HWPROBE_EXT_ZFA (1ULL << 32) #define RISCV_HWPROBE_EXT_ZTSO (1ULL << 33) #define RISCV_HWPROBE_EXT_ZACAS (1ULL << 34) @@ -8982,35 +9123,38 @@ static void risc_hwprobe_fill_pairs(CPURISCVState *env, } } -static int cpu_set_valid(abi_long arg3, abi_long arg4) +/* + * If the cpumask_t of (target_cpus, cpusetsize) cannot be read: -EFAULT. + * If the cpumast_t has no bits set: -EINVAL. + * Otherwise the cpumask_t contains some bit set: 0. + * Unlike the kernel, we do not mask cpumask_t by the set of online cpus, + * nor bound the search by cpumask_size(). + */ +static int nonempty_cpu_set(abi_ulong cpusetsize, abi_ptr target_cpus) { - int ret, i, tmp; - size_t host_mask_size, target_mask_size; - unsigned long *host_mask; - - /* - * cpu_set_t represent CPU masks as bit masks of type unsigned long *. - * arg3 contains the cpu count. - */ - tmp = (8 * sizeof(abi_ulong)); - target_mask_size = ((arg3 + tmp - 1) / tmp) * sizeof(abi_ulong); - host_mask_size = (target_mask_size + (sizeof(*host_mask) - 1)) & - ~(sizeof(*host_mask) - 1); - - host_mask = alloca(host_mask_size); + unsigned char *p = lock_user(VERIFY_READ, target_cpus, cpusetsize, 1); + int ret = -TARGET_EFAULT; - ret = target_to_host_cpu_mask(host_mask, host_mask_size, - arg4, target_mask_size); - if (ret != 0) { - return ret; - } - - for (i = 0 ; i < host_mask_size / sizeof(*host_mask); i++) { - if (host_mask[i] != 0) { - return 0; + if (p) { + ret = -TARGET_EINVAL; + /* + * Since we only care about the empty/non-empty state of the cpumask_t + * not the individual bits, we do not need to repartition the bits + * from target abi_ulong to host unsigned long. + * + * Note that the kernel does not round up cpusetsize to a multiple of + * sizeof(abi_ulong). After bounding cpusetsize by cpumask_size(), + * it copies exactly cpusetsize bytes into a zeroed buffer. + */ + for (abi_ulong i = 0; i < cpusetsize; ++i) { + if (p[i]) { + ret = 0; + break; + } } + unlock_user(p, target_cpus, 0); } - return -TARGET_EINVAL; + return ret; } static abi_long do_riscv_hwprobe(CPUArchState *cpu_env, abi_long arg1, @@ -9027,7 +9171,7 @@ static abi_long do_riscv_hwprobe(CPUArchState *cpu_env, abi_long arg1, /* check cpu_set */ if (arg3 != 0) { - ret = cpu_set_valid(arg3, arg4); + ret = nonempty_cpu_set(arg3, arg4); if (ret != 0) { return ret; } @@ -9187,6 +9331,9 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, fd_trans_unregister(ret); unlock_user(p, arg2, 0); return ret; + case TARGET_NR_openat2: + ret = do_openat2(cpu_env, arg1, arg2, arg3, arg4); + return ret; #if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE) case TARGET_NR_name_to_handle_at: ret = do_name_to_handle_at(arg1, arg2, arg3, arg4, arg5); @@ -10472,10 +10619,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, return ret; #ifdef TARGET_NR_mmap case TARGET_NR_mmap: -#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \ - (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \ - defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \ - || defined(TARGET_S390X) +#ifdef TARGET_ARCH_WANT_SYS_OLD_MMAP { abi_ulong *v; abi_ulong v1, v2, v3, v4, v5, v6; @@ -11516,7 +11660,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, return -TARGET_EFAULT; } } - ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5))); + ret = get_errno(pread(arg1, p, arg3, target_offset64(arg4, arg5))); unlock_user(p, arg2, ret); return ret; case TARGET_NR_pwrite64: @@ -11533,7 +11677,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, return -TARGET_EFAULT; } } - ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5))); + ret = get_errno(pwrite(arg1, p, arg3, target_offset64(arg4, arg5))); unlock_user(p, arg2, 0); return ret; #endif @@ -11828,9 +11972,9 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, return get_errno(high2lowgid(getegid())); #endif case TARGET_NR_setreuid: - return get_errno(setreuid(low2highuid(arg1), low2highuid(arg2))); + return get_errno(sys_setreuid(low2highuid(arg1), low2highuid(arg2))); case TARGET_NR_setregid: - return get_errno(setregid(low2highgid(arg1), low2highgid(arg2))); + return get_errno(sys_setregid(low2highgid(arg1), low2highgid(arg2))); case TARGET_NR_getgroups: { /* the same code as for TARGET_NR_getgroups32 */ int gidsetsize = arg1; @@ -12160,11 +12304,11 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_setreuid32 case TARGET_NR_setreuid32: - return get_errno(setreuid(arg1, arg2)); + return get_errno(sys_setreuid(arg1, arg2)); #endif #ifdef TARGET_NR_setregid32 case TARGET_NR_setregid32: - return get_errno(setregid(arg1, arg2)); + return get_errno(sys_setregid(arg1, arg2)); #endif #ifdef TARGET_NR_getgroups32 case TARGET_NR_getgroups32: @@ -12393,7 +12537,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, case TARGET_NR_fcntl64: { int cmd; - struct flock64 fl; + struct flock fl; from_flock64_fn *copyfrom = copy_from_user_flock64; to_flock64_fn *copyto = copy_to_user_flock64; @@ -12628,14 +12772,6 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, #if defined(TARGET_MIPS) cpu_env->active_tc.CP0_UserLocal = arg1; return 0; -#elif defined(TARGET_CRIS) - if (arg1 & 0xff) - ret = -TARGET_EINVAL; - else { - cpu_env->pregs[PR_PID] = arg1; - ret = 0; - } - return ret; #elif defined(TARGET_I386) && defined(TARGET_ABI32) return do_set_thread_area(cpu_env, arg1); #elif defined(TARGET_M68K) |