diff options
Diffstat (limited to 'linux-user')
-rw-r--r-- | linux-user/arm/syscall_nr.h | 2 | ||||
-rw-r--r-- | linux-user/elfload.c | 18 | ||||
-rw-r--r-- | linux-user/ioctls.h | 3 | ||||
-rw-r--r-- | linux-user/syscall.c | 87 | ||||
-rw-r--r-- | linux-user/syscall_types.h | 2 |
5 files changed, 86 insertions, 26 deletions
diff --git a/linux-user/arm/syscall_nr.h b/linux-user/arm/syscall_nr.h index bef847cfae..7d7be7cfe9 100644 --- a/linux-user/arm/syscall_nr.h +++ b/linux-user/arm/syscall_nr.h @@ -350,7 +350,7 @@ #define TARGET_NR_vmsplice (343) #define TARGET_NR_move_pages (344) #define TARGET_NR_getcpu (345) - /* 346 for epoll_pwait */ +#define TARGET_NR_epoll_pwait (346) #define TARGET_NR_kexec_load (347) #define TARGET_NR_utimensat (348) #define TARGET_NR_signalfd (349) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index bea803bd13..1c04fcf3cc 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -2355,9 +2355,9 @@ struct elf_note_info { }; struct vm_area_struct { - abi_ulong vma_start; /* start vaddr of memory region */ - abi_ulong vma_end; /* end vaddr of memory region */ - abi_ulong vma_flags; /* protection etc. flags for the region */ + target_ulong vma_start; /* start vaddr of memory region */ + target_ulong vma_end; /* end vaddr of memory region */ + abi_ulong vma_flags; /* protection etc. flags for the region */ QTAILQ_ENTRY(vm_area_struct) vma_link; }; @@ -2368,13 +2368,13 @@ struct mm_struct { static struct mm_struct *vma_init(void); static void vma_delete(struct mm_struct *); -static int vma_add_mapping(struct mm_struct *, abi_ulong, - abi_ulong, abi_ulong); +static int vma_add_mapping(struct mm_struct *, target_ulong, + target_ulong, abi_ulong); static int vma_get_mapping_count(const struct mm_struct *); static struct vm_area_struct *vma_first(const struct mm_struct *); static struct vm_area_struct *vma_next(struct vm_area_struct *); static abi_ulong vma_dump_size(const struct vm_area_struct *); -static int vma_walker(void *priv, abi_ulong start, abi_ulong end, +static int vma_walker(void *priv, target_ulong start, target_ulong end, unsigned long flags); static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t); @@ -2466,8 +2466,8 @@ static void vma_delete(struct mm_struct *mm) g_free(mm); } -static int vma_add_mapping(struct mm_struct *mm, abi_ulong start, - abi_ulong end, abi_ulong flags) +static int vma_add_mapping(struct mm_struct *mm, target_ulong start, + target_ulong end, abi_ulong flags) { struct vm_area_struct *vma; @@ -2535,7 +2535,7 @@ static abi_ulong vma_dump_size(const struct vm_area_struct *vma) return (vma->vma_end - vma->vma_start); } -static int vma_walker(void *priv, abi_ulong start, abi_ulong end, +static int vma_walker(void *priv, target_ulong start, target_ulong end, unsigned long flags) { struct mm_struct *mm = (struct mm_struct *)priv; diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 609b27cf0b..e672655100 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -78,7 +78,8 @@ IOCTL(BLKRAGET, IOC_R, MK_PTR(TYPE_LONG)) IOCTL(BLKSSZGET, IOC_R, MK_PTR(TYPE_LONG)) IOCTL(BLKBSZGET, IOC_R, MK_PTR(TYPE_INT)) - IOCTL(BLKPG, IOC_W, MK_PTR(MK_STRUCT(STRUCT_blkpg_ioctl_arg))) + IOCTL_SPECIAL(BLKPG, IOC_W, do_ioctl_blkpg, + MK_PTR(MK_STRUCT(STRUCT_blkpg_ioctl_arg))) #ifdef FIBMAP IOCTL(FIBMAP, IOC_W | IOC_R, MK_PTR(TYPE_LONG)) #endif diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 8fe9df7b87..a175cc15f8 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -58,7 +58,6 @@ int __clone2(int (*fn)(void *), void *child_stack_base, #include <sys/shm.h> #include <sys/sem.h> #include <sys/statfs.h> -#include <sys/timerfd.h> #include <utime.h> #include <sys/sysinfo.h> //#include <sys/user.h> @@ -67,6 +66,9 @@ int __clone2(int (*fn)(void *), void *child_stack_base, #include <linux/wireless.h> #include <linux/icmp.h> #include "qemu-common.h" +#ifdef CONFIG_TIMERFD +#include <sys/timerfd.h> +#endif #ifdef TARGET_GPROF #include <sys/gmon.h> #endif @@ -3696,6 +3698,59 @@ out: return ret; } +static abi_long do_ioctl_blkpg(const IOCTLEntry *ie, uint8_t *buf_temp, int fd, + abi_long cmd, abi_long arg) +{ + void *argptr; + int target_size; + const argtype *arg_type = ie->arg_type; + const argtype part_arg_type[] = { MK_STRUCT(STRUCT_blkpg_partition) }; + abi_long ret; + + struct blkpg_ioctl_arg *host_blkpg = (void*)buf_temp; + struct blkpg_partition host_part; + + /* Read and convert blkpg */ + arg_type++; + target_size = thunk_type_size(arg_type, 0); + argptr = lock_user(VERIFY_READ, arg, target_size, 1); + if (!argptr) { + ret = -TARGET_EFAULT; + goto out; + } + thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); + unlock_user(argptr, arg, 0); + + switch (host_blkpg->op) { + case BLKPG_ADD_PARTITION: + case BLKPG_DEL_PARTITION: + /* payload is struct blkpg_partition */ + break; + default: + /* Unknown opcode */ + ret = -TARGET_EINVAL; + goto out; + } + + /* Read and convert blkpg->data */ + arg = (abi_long)(uintptr_t)host_blkpg->data; + target_size = thunk_type_size(part_arg_type, 0); + argptr = lock_user(VERIFY_READ, arg, target_size, 1); + if (!argptr) { + ret = -TARGET_EFAULT; + goto out; + } + thunk_convert(&host_part, argptr, part_arg_type, THUNK_HOST); + unlock_user(argptr, arg, 0); + + /* Swizzle the data pointer to our local copy and call! */ + host_blkpg->data = &host_part; + ret = get_errno(ioctl(fd, ie->host_cmd, host_blkpg)); + +out: + return ret; +} + static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp, int fd, abi_long cmd, abi_long arg) { @@ -9562,11 +9617,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, { /* args: timer_t timerid, int flags, const struct itimerspec *new_value, * struct itimerspec * old_value */ - arg1 &= 0xffff; - if (arg3 == 0 || arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) { + target_ulong timerid = arg1; + + if (arg3 == 0 || timerid >= ARRAY_SIZE(g_posix_timers)) { ret = -TARGET_EINVAL; } else { - timer_t htimer = g_posix_timers[arg1]; + timer_t htimer = g_posix_timers[timerid]; struct itimerspec hspec_new = {{0},}, hspec_old = {{0},}; target_to_host_itimerspec(&hspec_new, arg3); @@ -9582,13 +9638,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_timer_gettime: { /* args: timer_t timerid, struct itimerspec *curr_value */ - arg1 &= 0xffff; + target_ulong timerid = arg1; + if (!arg2) { return -TARGET_EFAULT; - } else if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) { + } else if (timerid >= ARRAY_SIZE(g_posix_timers)) { ret = -TARGET_EINVAL; } else { - timer_t htimer = g_posix_timers[arg1]; + timer_t htimer = g_posix_timers[timerid]; struct itimerspec hspec; ret = get_errno(timer_gettime(htimer, &hspec)); @@ -9604,11 +9661,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_timer_getoverrun: { /* args: timer_t timerid */ - arg1 &= 0xffff; - if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) { + target_ulong timerid = arg1; + + if (timerid >= ARRAY_SIZE(g_posix_timers)) { ret = -TARGET_EINVAL; } else { - timer_t htimer = g_posix_timers[arg1]; + timer_t htimer = g_posix_timers[timerid]; ret = get_errno(timer_getoverrun(htimer)); } break; @@ -9619,13 +9677,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_timer_delete: { /* args: timer_t timerid */ - arg1 &= 0xffff; - if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) { + target_ulong timerid = arg1; + + if (timerid >= ARRAY_SIZE(g_posix_timers)) { ret = -TARGET_EINVAL; } else { - timer_t htimer = g_posix_timers[arg1]; + timer_t htimer = g_posix_timers[timerid]; ret = get_errno(timer_delete(htimer)); - g_posix_timers[arg1] = 0; + g_posix_timers[timerid] = 0; } break; } diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h index 9d0c92d054..1fd4ee0bfd 100644 --- a/linux-user/syscall_types.h +++ b/linux-user/syscall_types.h @@ -252,4 +252,4 @@ STRUCT(blkpg_ioctl_arg, TYPE_INT, /* op */ TYPE_INT, /* flags */ TYPE_INT, /* datalen */ - MK_PTR(MK_STRUCT(STRUCT_blkpg_partition))) /* data */ + TYPE_PTRVOID) /* data */ |