From: Martin Schwidefsky <schwidefsky@de.ibm.com>

 - 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(&regs32, &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)

_