#include <linux/soundcard.h>
#include <linux/kd.h>
#include <linux/mtio.h>
-
-#ifdef HAVE_SYS_MOUNT_FSCONFIG
-/*
- * glibc >= 2.36 linux/mount.h conflicts with sys/mount.h,
- * which in turn prevents use of linux/fs.h. So we have to
- * define the constants ourselves for now.
- */
-#define FS_IOC_GETFLAGS _IOR('f', 1, long)
-#define FS_IOC_SETFLAGS _IOW('f', 2, long)
-#define FS_IOC_GETVERSION _IOR('v', 1, long)
-#define FS_IOC_SETVERSION _IOW('v', 2, long)
-#define FS_IOC_FIEMAP _IOWR('f', 11, struct fiemap)
-#define FS_IOC32_GETFLAGS _IOR('f', 1, int)
-#define FS_IOC32_SETFLAGS _IOW('f', 2, int)
-#define FS_IOC32_GETVERSION _IOR('v', 1, int)
-#define FS_IOC32_SETVERSION _IOW('v', 2, int)
-
-#define BLKGETSIZE64 _IOR(0x12,114,size_t)
-#define BLKDISCARD _IO(0x12,119)
-#define BLKIOMIN _IO(0x12,120)
-#define BLKIOOPT _IO(0x12,121)
-#define BLKALIGNOFF _IO(0x12,122)
-#define BLKPBSZGET _IO(0x12,123)
-#define BLKDISCARDZEROES _IO(0x12,124)
-#define BLKSECDISCARD _IO(0x12,125)
-#define BLKROTATIONAL _IO(0x12,126)
-#define BLKZEROOUT _IO(0x12,127)
-
-#define FIBMAP _IO(0x00,1)
-#define FIGETBSZ _IO(0x00,2)
-
-struct file_clone_range {
- __s64 src_fd;
- __u64 src_offset;
- __u64 src_length;
- __u64 dest_offset;
-};
-
-#define FICLONE _IOW(0x94, 9, int)
-#define FICLONERANGE _IOW(0x94, 13, struct file_clone_range)
-
-#else
#include <linux/fs.h>
-#endif
#include <linux/fd.h>
#if defined(CONFIG_FIEMAP)
#include <linux/fiemap.h>
#ifdef __NR_exit_group
_syscall1(int,exit_group,int,error_code)
#endif
+#if defined(__NR_close_range) && defined(TARGET_NR_close_range)
+#define __NR_sys_close_range __NR_close_range
+_syscall3(int,sys_close_range,int,first,int,last,int,flags)
+#ifndef CLOSE_RANGE_CLOEXEC
+#define CLOSE_RANGE_CLOEXEC (1U << 2)
+#endif
+#endif
#if defined(__NR_futex)
_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
const struct timespec *,timeout,int *,uaddr2,int,val3)
#endif
safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \
int, options, struct rusage *, rusage)
-safe_syscall3(int, execve, const char *, filename, char **, argv, char **, envp)
+safe_syscall5(int, execveat, int, dirfd, const char *, filename,
+ char **, argv, char **, envp, int, flags)
#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \
defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
safe_syscall6(int, pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, \
__get_user(cred->pid, &target_cred->pid);
__get_user(cred->uid, &target_cred->uid);
__get_user(cred->gid, &target_cred->gid);
+ } else if (cmsg->cmsg_level == SOL_ALG) {
+ uint32_t *dst = (uint32_t *)data;
+
+ memcpy(dst, target_data, len);
+ /* fix endianess of first 32-bit word */
+ if (len >= sizeof(uint32_t)) {
+ *dst = tswap32(*dst);
+ }
} else {
qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n",
cmsg->cmsg_level, cmsg->cmsg_type);
ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
if (ret < 0)
return ret;
- if (optname == SO_TYPE) {
+ switch (optname) {
+ case SO_TYPE:
val = host_to_target_sock_type(val);
+ break;
+ case SO_ERROR:
+ val = host_to_target_errno(val);
+ break;
}
if (len > lv)
len = lv;
if (fd_trans_host_to_target_data(fd)) {
ret = fd_trans_host_to_target_data(fd)(msg.msg_iov->iov_base,
MIN(msg.msg_iov->iov_len, len));
- } else {
+ }
+ if (!is_error(ret)) {
ret = host_to_target_cmsg(msgp, &msg);
}
if (!is_error(ret)) {
for (i = 0; i < se->nb_fields; i++) {
if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) {
assert(*field_types == TYPE_PTRVOID);
- target_rt_dev_ptr = (abi_ulong *)(argptr + src_offsets[i]);
+ target_rt_dev_ptr = argptr + src_offsets[i];
host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]);
if (*target_rt_dev_ptr != 0) {
*host_rt_dev_ptr = (unsigned long)lock_user_string(
#if defined(TARGET_HPPA)
static int open_cpuinfo(CPUArchState *cpu_env, int fd)
{
- dprintf(fd, "cpu family\t: PA-RISC 1.1e\n");
- dprintf(fd, "cpu\t\t: PA7300LC (PCX-L2)\n");
- dprintf(fd, "capabilities\t: os32\n");
- dprintf(fd, "model\t\t: 9000/778/B160L\n");
- dprintf(fd, "model name\t: Merlin L2 160 QEMU (9000/778/B160L)\n");
+ int i, num_cpus;
+
+ num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
+ for (i = 0; i < num_cpus; i++) {
+ dprintf(fd, "processor\t: %d\n", i);
+ dprintf(fd, "cpu family\t: PA-RISC 1.1e\n");
+ dprintf(fd, "cpu\t\t: PA7300LC (PCX-L2)\n");
+ dprintf(fd, "capabilities\t: os32\n");
+ dprintf(fd, "model\t\t: 9000/778/B160L - "
+ "Merlin L2 160 QEMU (9000/778/B160L)\n\n");
+ }
return 0;
}
#endif
return safe_openat(dirfd, path(pathname), flags, mode);
}
+static int do_execveat(CPUArchState *cpu_env, int dirfd,
+ abi_long pathname, abi_long guest_argp,
+ abi_long guest_envp, int flags)
+{
+ int ret;
+ char **argp, **envp;
+ int argc, envc;
+ abi_ulong gp;
+ abi_ulong addr;
+ char **q;
+ void *p;
+
+ argc = 0;
+
+ for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
+ if (get_user_ual(addr, gp)) {
+ return -TARGET_EFAULT;
+ }
+ if (!addr) {
+ break;
+ }
+ argc++;
+ }
+ envc = 0;
+ for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
+ if (get_user_ual(addr, gp)) {
+ return -TARGET_EFAULT;
+ }
+ if (!addr) {
+ break;
+ }
+ envc++;
+ }
+
+ argp = g_new0(char *, argc + 1);
+ envp = g_new0(char *, envc + 1);
+
+ for (gp = guest_argp, q = argp; gp; gp += sizeof(abi_ulong), q++) {
+ if (get_user_ual(addr, gp)) {
+ goto execve_efault;
+ }
+ if (!addr) {
+ break;
+ }
+ *q = lock_user_string(addr);
+ if (!*q) {
+ goto execve_efault;
+ }
+ }
+ *q = NULL;
+
+ for (gp = guest_envp, q = envp; gp; gp += sizeof(abi_ulong), q++) {
+ if (get_user_ual(addr, gp)) {
+ goto execve_efault;
+ }
+ if (!addr) {
+ break;
+ }
+ *q = lock_user_string(addr);
+ if (!*q) {
+ goto execve_efault;
+ }
+ }
+ *q = NULL;
+
+ /*
+ * Although execve() is not an interruptible syscall it is
+ * a special case where we must use the safe_syscall wrapper:
+ * if we allow a signal to happen before we make the host
+ * syscall then we will 'lose' it, because at the point of
+ * execve the process leaves QEMU's control. So we use the
+ * safe syscall wrapper to ensure that we either take the
+ * signal as a guest signal, or else it does not happen
+ * before the execve completes and makes it the other
+ * program's problem.
+ */
+ p = lock_user_string(pathname);
+ if (!p) {
+ goto execve_efault;
+ }
+
+ if (is_proc_myself(p, "exe")) {
+ ret = get_errno(safe_execveat(dirfd, exec_path, argp, envp, flags));
+ } else {
+ ret = get_errno(safe_execveat(dirfd, p, argp, envp, flags));
+ }
+
+ unlock_user(p, pathname, 0);
+
+ goto execve_end;
+
+execve_efault:
+ ret = -TARGET_EFAULT;
+
+execve_end:
+ for (gp = guest_argp, q = argp; *q; gp += sizeof(abi_ulong), q++) {
+ if (get_user_ual(addr, gp) || !addr) {
+ break;
+ }
+ unlock_user(*q, addr, 0);
+ }
+ for (gp = guest_envp, q = envp; *q; gp += sizeof(abi_ulong), q++) {
+ if (get_user_ual(addr, gp) || !addr) {
+ break;
+ }
+ unlock_user(*q, addr, 0);
+ }
+
+ g_free(argp);
+ g_free(envp);
+ return ret;
+}
+
#define TIMER_MAGIC 0x0caf0000
#define TIMER_MAGIC_MASK 0xffff0000
if (CPU_NEXT(first_cpu)) {
TaskState *ts = cpu->opaque;
- object_property_set_bool(OBJECT(cpu), "realized", false, NULL);
+ if (ts->child_tidptr) {
+ put_user_u32(0, ts->child_tidptr);
+ do_sys_futex(g2h(cpu, ts->child_tidptr),
+ FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
+ }
+
+ object_unparent(OBJECT(cpu));
object_unref(OBJECT(cpu));
/*
* At this point the CPU should be unrealized and removed
pthread_mutex_unlock(&clone_lock);
- if (ts->child_tidptr) {
- put_user_u32(0, ts->child_tidptr);
- do_sys_futex(g2h(cpu, ts->child_tidptr),
- FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
- }
thread_cpu = NULL;
g_free(ts);
rcu_unregister_thread();
case TARGET_NR_close:
fd_trans_unregister(arg1);
return get_errno(close(arg1));
+#if defined(__NR_close_range) && defined(TARGET_NR_close_range)
+ case TARGET_NR_close_range:
+ ret = get_errno(sys_close_range(arg1, arg2, arg3));
+ if (ret == 0 && !(arg3 & CLOSE_RANGE_CLOEXEC)) {
+ abi_long fd, maxfd;
+ maxfd = MIN(arg2, target_fd_max);
+ for (fd = arg1; fd < maxfd; fd++) {
+ fd_trans_unregister(fd);
+ }
+ }
+ return ret;
+#endif
case TARGET_NR_brk:
return do_brk(arg1);
unlock_user(p, arg2, 0);
return ret;
#endif
+ case TARGET_NR_execveat:
+ return do_execveat(cpu_env, arg1, arg2, arg3, arg4, arg5);
case TARGET_NR_execve:
- {
- char **argp, **envp;
- int argc, envc;
- abi_ulong gp;
- abi_ulong guest_argp;
- abi_ulong guest_envp;
- abi_ulong addr;
- char **q;
-
- argc = 0;
- guest_argp = arg2;
- for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
- if (get_user_ual(addr, gp))
- return -TARGET_EFAULT;
- if (!addr)
- break;
- argc++;
- }
- envc = 0;
- guest_envp = arg3;
- for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
- if (get_user_ual(addr, gp))
- return -TARGET_EFAULT;
- if (!addr)
- break;
- envc++;
- }
-
- argp = g_new0(char *, argc + 1);
- envp = g_new0(char *, envc + 1);
-
- for (gp = guest_argp, q = argp; gp;
- gp += sizeof(abi_ulong), q++) {
- if (get_user_ual(addr, gp))
- goto execve_efault;
- if (!addr)
- break;
- if (!(*q = lock_user_string(addr)))
- goto execve_efault;
- }
- *q = NULL;
-
- for (gp = guest_envp, q = envp; gp;
- gp += sizeof(abi_ulong), q++) {
- if (get_user_ual(addr, gp))
- goto execve_efault;
- if (!addr)
- break;
- if (!(*q = lock_user_string(addr)))
- goto execve_efault;
- }
- *q = NULL;
-
- if (!(p = lock_user_string(arg1)))
- goto execve_efault;
- /* Although execve() is not an interruptible syscall it is
- * a special case where we must use the safe_syscall wrapper:
- * if we allow a signal to happen before we make the host
- * syscall then we will 'lose' it, because at the point of
- * execve the process leaves QEMU's control. So we use the
- * safe syscall wrapper to ensure that we either take the
- * signal as a guest signal, or else it does not happen
- * before the execve completes and makes it the other
- * program's problem.
- */
- if (is_proc_myself(p, "exe")) {
- ret = get_errno(safe_execve(exec_path, argp, envp));
- } else {
- ret = get_errno(safe_execve(p, argp, envp));
- }
- unlock_user(p, arg1, 0);
-
- goto execve_end;
-
- execve_efault:
- ret = -TARGET_EFAULT;
-
- execve_end:
- for (gp = guest_argp, q = argp; *q;
- gp += sizeof(abi_ulong), q++) {
- if (get_user_ual(addr, gp)
- || !addr)
- break;
- unlock_user(*q, addr, 0);
- }
- for (gp = guest_envp, q = envp; *q;
- gp += sizeof(abi_ulong), q++) {
- if (get_user_ual(addr, gp)
- || !addr)
- break;
- unlock_user(*q, addr, 0);
- }
-
- g_free(argp);
- g_free(envp);
- }
- return ret;
+ return do_execveat(cpu_env, AT_FDCWD, arg1, arg2, arg3, 0);
case TARGET_NR_chdir:
if (!(p = lock_user_string(arg1)))
return -TARGET_EFAULT;