From: Martin Schwidefsky - Add emulation for sys_fadvise64 and sys_fadvise64_64. - Use common code wrapper for sys_sched_setaffinity and sys_sched_getaffinity. - Remove unused put_rusage. - Add ssize_t checks for iovec lengths in do_readv_writev32. - Add emulation for posix timer system calls. --- 25-akpm/arch/s390/kernel/compat_linux.c | 153 ++++++++++-------------------- 25-akpm/arch/s390/kernel/compat_linux.h | 18 +++ 25-akpm/arch/s390/kernel/compat_signal.c | 3 25-akpm/arch/s390/kernel/compat_wrapper.S | 77 ++++++++++++++- 25-akpm/arch/s390/kernel/syscalls.S | 22 ++-- 5 files changed, 162 insertions(+), 111 deletions(-) diff -puN arch/s390/kernel/compat_linux.c~s390-09-32-bit-emulation-fixes arch/s390/kernel/compat_linux.c --- 25/arch/s390/kernel/compat_linux.c~s390-09-32-bit-emulation-fixes Thu Jan 8 14:11:36 2004 +++ 25-akpm/arch/s390/kernel/compat_linux.c Thu Jan 8 14:11:36 2004 @@ -5,6 +5,7 @@ * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), * Gerhard Tonn (ton@de.ibm.com) + * Thomas Spatzier (tspat@de.ibm.com) * * Conversion between 31bit and 64bit native syscalls. * @@ -934,19 +935,32 @@ static long do_readv_writev32(int type, tot_len = 0; i = count; ivp = iov; + retval = -EINVAL; while(i > 0) { - u32 len; + compat_ssize_t tmp = tot_len; + compat_ssize_t len; u32 buf; - __get_user(len, &vector->iov_len); - __get_user(buf, &vector->iov_base); + if (__get_user(len, &vector->iov_len) || + __get_user(buf, &vector->iov_base)) { + retval = -EFAULT; + goto out; + } + if (len < 0) /* size_t not fitting an ssize_t32 .. */ + goto out; tot_len += len; + if (tot_len < tmp) /* maths overflow on the compat_ssize_t */ + goto out; ivp->iov_base = (void *)A(buf); ivp->iov_len = (__kernel_size_t) len; vector++; ivp++; i--; } + if (tot_len == 0) { + retval = 0; + goto out; + } inode = file->f_dentry->d_inode; /* VERIFY_WRITE actually means a read, as we write to user space */ @@ -1500,50 +1514,6 @@ out: return err; } -struct rusage32 { - struct compat_timeval ru_utime; - struct compat_timeval ru_stime; - s32 ru_maxrss; - s32 ru_ixrss; - s32 ru_idrss; - s32 ru_isrss; - s32 ru_minflt; - s32 ru_majflt; - s32 ru_nswap; - s32 ru_inblock; - s32 ru_oublock; - s32 ru_msgsnd; - s32 ru_msgrcv; - s32 ru_nsignals; - s32 ru_nvcsw; - s32 ru_nivcsw; -}; - -static int put_rusage (struct rusage32 *ru, struct rusage *r) -{ - int err; - - err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec); - err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec); - err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec); - err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec); - err |= __put_user (r->ru_maxrss, &ru->ru_maxrss); - err |= __put_user (r->ru_ixrss, &ru->ru_ixrss); - err |= __put_user (r->ru_idrss, &ru->ru_idrss); - err |= __put_user (r->ru_isrss, &ru->ru_isrss); - err |= __put_user (r->ru_minflt, &ru->ru_minflt); - err |= __put_user (r->ru_majflt, &ru->ru_majflt); - err |= __put_user (r->ru_nswap, &ru->ru_nswap); - err |= __put_user (r->ru_inblock, &ru->ru_inblock); - err |= __put_user (r->ru_oublock, &ru->ru_oublock); - err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd); - err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv); - err |= __put_user (r->ru_nsignals, &ru->ru_nsignals); - err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw); - err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw); - return err; -} - struct sysinfo32 { s32 uptime; u32 loads[3]; @@ -2706,56 +2676,6 @@ out: return error; } -extern asmlinkage int sys_sched_setaffinity(pid_t pid, unsigned int len, - unsigned long *user_mask_ptr); - -asmlinkage int sys32_sched_setaffinity(compat_pid_t pid, unsigned int len, - u32 *user_mask_ptr) -{ - unsigned long kernel_mask; - mm_segment_t old_fs; - int ret; - - if (get_user(kernel_mask, user_mask_ptr)) - return -EFAULT; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_sched_setaffinity(pid, - /* XXX Nice api... */ - sizeof(kernel_mask), - &kernel_mask); - set_fs(old_fs); - - return ret; -} - -extern asmlinkage int sys_sched_getaffinity(pid_t pid, unsigned int len, - unsigned long *user_mask_ptr); - -asmlinkage int sys32_sched_getaffinity(compat_pid_t pid, unsigned int len, - u32 *user_mask_ptr) -{ - unsigned long kernel_mask; - mm_segment_t old_fs; - int ret; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_sched_getaffinity(pid, - /* XXX Nice api... */ - sizeof(kernel_mask), - &kernel_mask); - set_fs(old_fs); - - if (ret == 0) { - if (put_user(kernel_mask, user_mask_ptr)) - ret = -EFAULT; - } - - return ret; -} - asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count); asmlinkage compat_ssize_t sys32_read(unsigned int fd, char * buf, size_t count) @@ -2792,4 +2712,43 @@ asmlinkage int sys32_clone(struct pt_reg parent_tidptr, child_tidptr); } +/* + * Wrapper function for sys_timer_create. + */ +extern asmlinkage long +sys_timer_create(clockid_t, struct sigevent *, timer_t *); + +asmlinkage long +sys32_timer_create(clockid_t which_clock, struct sigevent32 *se32, + timer_t *timer_id) +{ + struct sigevent se; + timer_t ktimer_id; + mm_segment_t old_fs; + long ret; + + if (se32 == NULL) + return sys_timer_create(which_clock, NULL, timer_id); + /* XXX: converting se32 to se is filthy because of the + * two union members. For now it is ok, because the pointers + * are not touched in kernel. + */ + memset(&se, 0, sizeof(se)); + if (get_user(se.sigev_value.sival_int, &se32->sigev_value.sival_int) || + get_user(se.sigev_signo, &se32->sigev_signo) || + get_user(se.sigev_notify, &se32->sigev_notify) || + copy_from_user(&se._sigev_un._pad, &se32->_sigev_un._pad, + sizeof(se._sigev_un._pad))) + return -EFAULT; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_timer_create(which_clock, &se, &ktimer_id); + set_fs(old_fs); + + if (!ret) + ret = put_user (ktimer_id, timer_id); + + return ret; +} diff -puN arch/s390/kernel/compat_linux.h~s390-09-32-bit-emulation-fixes arch/s390/kernel/compat_linux.h --- 25/arch/s390/kernel/compat_linux.h~s390-09-32-bit-emulation-fixes Thu Jan 8 14:11:36 2004 +++ 25-akpm/arch/s390/kernel/compat_linux.h Thu Jan 8 14:11:36 2004 @@ -190,4 +190,22 @@ struct ucontext32 { compat_sigset_t uc_sigmask; /* mask last for extensibility */ }; +#define SIGEV_PAD_SIZE32 ((SIGEV_MAX_SIZE/sizeof(int)) - 3) +struct sigevent32 { + union { + int sival_int; + u32 sival_ptr; + } sigev_value; + int sigev_signo; + int sigev_notify; + union { + int _pad[SIGEV_PAD_SIZE32]; + int _tid; + struct { + u32 *_function; + u32 *_attribute; + } _sigev_thread; + } _sigev_un; +}; + #endif /* _ASM_S390X_S390_H */ diff -puN arch/s390/kernel/compat_signal.c~s390-09-32-bit-emulation-fixes arch/s390/kernel/compat_signal.c --- 25/arch/s390/kernel/compat_signal.c~s390-09-32-bit-emulation-fixes Thu Jan 8 14:11:36 2004 +++ 25-akpm/arch/s390/kernel/compat_signal.c Thu Jan 8 14:11:36 2004 @@ -314,6 +314,9 @@ static int restore_sigregs32(struct pt_r _s390_regs_common32 regs32; int err, i; + /* Alwys make any pending restarted system call return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + err = __copy_from_user(®s32, &sregs->regs, sizeof(regs32)); if (err) return err; diff -puN arch/s390/kernel/compat_wrapper.S~s390-09-32-bit-emulation-fixes arch/s390/kernel/compat_wrapper.S --- 25/arch/s390/kernel/compat_wrapper.S~s390-09-32-bit-emulation-fixes Thu Jan 8 14:11:36 2004 +++ 25-akpm/arch/s390/kernel/compat_wrapper.S Thu Jan 8 14:11:36 2004 @@ -135,7 +135,7 @@ sys32_alarm_wrapper: compat_sys_utime_wrapper: llgtr %r2,%r2 # char * llgtr %r3,%r3 # struct compat_utimbuf * - jg compat_sys_utime # branch to system call + jg compat_sys_utime # branch to system call .globl sys32_access_wrapper sys32_access_wrapper: @@ -1192,14 +1192,14 @@ sys32_sched_setaffinity_wrapper: lgfr %r2,%r2 # int llgfr %r3,%r3 # unsigned int llgtr %r4,%r4 # unsigned long * - jg sys32_sched_setaffinity + jg compat_sys_sched_setaffinity .globl sys32_sched_getaffinity_wrapper sys32_sched_getaffinity_wrapper: lgfr %r2,%r2 # int llgfr %r3,%r3 # unsigned int llgtr %r4,%r4 # unsigned long * - jg sys32_sched_getaffinity + jg compat_sys_sched_getaffinity .globl sys32_exit_group_wrapper sys32_exit_group_wrapper: @@ -1232,6 +1232,77 @@ sys_epoll_wait_wrapper: lgfr %r5,%r5 # int jg sys_epoll_wait # branch to system call + .globl sys32_fadvise64_wrapper +sys32_fadvise64_wrapper: + lgfr %r2,%r2 # int + sllg %r3,%r3,32 # get high word of 64bit loff_t + or %r3,%r4 # get low word of 64bit loff_t + llgfr %r4,%r5 # size_t (unsigned long) + lgfr %r5,%r6 # int + jg sys_fadvise64 + + .globl sys32_fadvise64_64_wrapper +sys32_fadvise64_64_wrapper: + llgtr %r2,%r2 # struct fadvise64_64_args * + jg s390_fadvise64_64 + + .globl sys32_clock_settime_wrapper +sys32_clock_settime_wrapper: + lgfr %r2,%r2 # clockid_t (int) + llgtr %r3,%r3 # struct compat_timespec * + jg compat_clock_settime + + .globl sys32_clock_gettime_wrapper +sys32_clock_gettime_wrapper: + lgfr %r2,%r2 # clockid_t (int) + llgtr %r3,%r3 # struct compat_timespec * + jg compat_clock_gettime + + .globl sys32_clock_getres_wrapper +sys32_clock_getres_wrapper: + lgfr %r2,%r2 # clockid_t (int) + llgtr %r3,%r3 # struct compat_timespec * + jg compat_clock_getres + + .globl sys32_clock_nanosleep_wrapper +sys32_clock_nanosleep_wrapper: + lgfr %r2,%r2 # clockid_t (int) + lgfr %r3,%r3 # int + llgtr %r4,%r4 # struct compat_timespec * + llgtr %r5,%r5 # struct compat_timespec * + jg compat_clock_nanosleep + + .globl sys32_timer_create_wrapper +sys32_timer_create_wrapper: + lgfr %r2,%r2 # timer_t (int) + llgtr %r3,%r3 # struct compat_sigevent * + llgtr %r4,%r4 # timer_t * + jg sys32_timer_create + + .globl sys32_timer_settime_wrapper +sys32_timer_settime_wrapper: + lgfr %r2,%r2 # timer_t (int) + lgfr %r3,%r3 # int + llgtr %r4,%r4 # struct compat_itimerspec * + llgtr %r5,%r5 # struct compat_itimerspec * + jg compat_timer_settime + + .globl sys32_timer_gettime_wrapper +sys32_timer_gettime_wrapper: + lgfr %r2,%r2 # timer_t (int) + llgtr %r3,%r3 # struct compat_itimerspec * + jg compat_timer_gettime + + .globl sys32_timer_getoverrun_wrapper +sys32_timer_getoverrun_wrapper: + lgfr %r2,%r2 # timer_t (int) + jg sys_timer_getoverrun + + .globl sys32_timer_delete_wrapper +sys32_timer_delete_wrapper: + lgfr %r2,%r2 # timer_t (int) + jg sys_timer_delete + .globl sys32_io_setup_wrapper sys32_io_setup_wrapper: llgfr %r2,%r2 # unsigned int diff -puN arch/s390/kernel/syscalls.S~s390-09-32-bit-emulation-fixes arch/s390/kernel/syscalls.S --- 25/arch/s390/kernel/syscalls.S~s390-09-32-bit-emulation-fixes Thu Jan 8 14:11:36 2004 +++ 25-akpm/arch/s390/kernel/syscalls.S Thu Jan 8 14:11:36 2004 @@ -261,15 +261,15 @@ SYSCALL(sys_epoll_create,sys_epoll_creat SYSCALL(sys_epoll_ctl,sys_epoll_ctl,sys_epoll_ctl_wrapper) /* 250 */ SYSCALL(sys_epoll_wait,sys_epoll_wait,sys_epoll_wait_wrapper) SYSCALL(sys_set_tid_address,sys_set_tid_address,sys32_set_tid_address_wrapper) -SYSCALL(s390_fadvise64,sys_fadvise64_64,sys_ni_syscall) -SYSCALL(sys_timer_create,sys_timer_create,sys_ni_syscall) -SYSCALL(sys_timer_settime,sys_timer_settime,sys_ni_syscall) /* 255 */ -SYSCALL(sys_timer_gettime,sys_timer_gettime,sys_ni_syscall) -SYSCALL(sys_timer_getoverrun,sys_timer_getoverrun,sys_ni_syscall) -SYSCALL(sys_timer_delete,sys_timer_delete,sys_ni_syscall) -SYSCALL(sys_clock_settime,sys_clock_settime,sys_ni_syscall) -SYSCALL(sys_clock_gettime,sys_clock_gettime,sys_ni_syscall) /* 260 */ -SYSCALL(sys_clock_getres,sys_clock_getres,sys_ni_syscall) -SYSCALL(sys_clock_nanosleep,sys_clock_nanosleep,sys_ni_syscall) +SYSCALL(s390_fadvise64,sys_fadvise64_64,sys32_fadvise64_wrapper) +SYSCALL(sys_timer_create,sys_timer_create,sys32_timer_create_wrapper) +SYSCALL(sys_timer_settime,sys_timer_settime,sys32_timer_settime_wrapper) /* 255 */ +SYSCALL(sys_timer_gettime,sys_timer_gettime,sys32_timer_gettime_wrapper) +SYSCALL(sys_timer_getoverrun,sys_timer_getoverrun,sys32_timer_getoverrun_wrapper) +SYSCALL(sys_timer_delete,sys_timer_delete,sys32_timer_delete_wrapper) +SYSCALL(sys_clock_settime,sys_clock_settime,sys32_clock_settime_wrapper) +SYSCALL(sys_clock_gettime,sys_clock_gettime,sys32_clock_gettime_wrapper) /* 260 */ +SYSCALL(sys_clock_getres,sys_clock_getres,sys32_clock_getres_wrapper) +SYSCALL(sys_clock_nanosleep,sys_clock_nanosleep,sys32_clock_nanosleep_wrapper) NI_SYSCALL /* reserved for vserver */ -SYSCALL(s390_fadvise64_64,sys_ni_syscall,sys_ni_syscall) +SYSCALL(s390_fadvise64_64,sys_ni_syscall,sys32_fadvise64_64_wrapper) _