Commit 8fa29920 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] sys_stime needs a compat function

I realized that the best way to get the sys_time/sys_stime problem fixed is
to make sys_time 64 bit safe by using "time_t *" instead of "int *" and to
introduce two proper compat functions compat_sys_time and compat_sys_stime.

The prototype change of sys_time is transparent for 32 bit architectures
because both "int" and "time_t" are 32 bit.  For 64 bit the type change
would be wrong but luckily no 64 bit architecture uses sys_time/sys_stime
in 64 bit mode.  The patch makes the following change:

ia64     : Remove sys32_time, use compat_sys_time and
           add (!!) compat_sys_stime to compat syscall table.
mips     : Use compat_sys_time/compat_sys_stime in 32 bit syscall table.
           Add #ifdef magic to compile sys_time/sys_stime and
           compat_sys_time/compat_sys_stime only if needed.
parisc   : Remove sys32_time, use compat_sys_time and compat_sys_stime.
ppc64    : remove sys32_time, ppc64_sys32_stime and ppc64_sys_stime.
           Use common compat_sys_time, compat_sys_stime and sys_stime.
s390     : Use compat_sys_stime. Add #ifdef magic to compile
           sys_time/sys_stime and compat_sys_time/compat_sys_stime only
           if needed.
sparc64  : Use compat_sys_time/compat_Sys_stime in 32 bit syscall table.
um       : Remove um_time and um_stime. Use common functions sys_time and
           sys_stime. This adds a CAP_SYS_TIME check to UMs stime call.
x86_64   : Remove sys32_time. Use compat_sys_time and compat_sys_stime
           in 32 bit syscall table.

The original stime bug is fixed for mips, parisc, s390, sparc64 and
x86_64. Can the arch-maintainers please take a look at this?

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

Convert compat_time_t to time_t in 32 bit emulation for sys_stime and
consolidate all the different implementation of sys_time, sys_stime and
their 32-bit emulation parts.
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent d6326c18
......@@ -223,7 +223,7 @@ ia32_syscall_table:
data8 sys_unlink /* 10 */
data8 ia32_execve
data8 sys_chdir
data8 sys32_time
data8 compat_sys_time
data8 sys_mknod
data8 sys_chmod /* 15 */
data8 sys_lchown /* 16-bit version */
......@@ -235,7 +235,7 @@ ia32_syscall_table:
data8 sys_oldumount
data8 sys_setuid /* 16-bit version */
data8 sys_getuid /* 16-bit version */
data8 sys_ni_syscall /* sys_stime is not supported on IA64 */ /* 25 */
data8 compat_sys_stime /* 25 */
data8 sys32_ptrace
data8 sys32_alarm
data8 sys_ni_syscall
......
......@@ -1425,27 +1425,6 @@ sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth)
return -EINVAL;
}
/*
* sys_time() can be implemented in user-level using
* sys_gettimeofday(). IA64 did this but i386 Linux did not
* so we have to implement this system call here.
*/
asmlinkage long
sys32_time (int __user *tloc)
{
int i;
struct timeval tv;
do_gettimeofday(&tv);
i = tv.tv_sec;
if (tloc) {
if (put_user(i, tloc))
i = -EFAULT;
}
return i;
}
asmlinkage long
compat_sys_wait4 (compat_pid_t pid, compat_uint_t * stat_addr, int options,
struct compat_rusage *ru);
......
......@@ -236,7 +236,7 @@ sys_call_table:
PTR sys_unlink /* 4010 */
PTR sys32_execve
PTR sys_chdir
PTR sys_time
PTR compat_sys_time
PTR sys_mknod
PTR sys_chmod /* 4015 */
PTR sys_lchown
......@@ -248,7 +248,7 @@ sys_call_table:
PTR sys_oldumount
PTR sys_setuid
PTR sys_getuid
PTR sys_stime /* 4025 */
PTR compat_sys_stime /* 4025 */
PTR sys32_ptrace
PTR sys_alarm
PTR sys_ni_syscall /* was sys_fstat */
......
......@@ -206,21 +206,6 @@ static inline long get_ts32(struct timespec *o, struct compat_timeval *i)
return 0;
}
asmlinkage long sys32_time(compat_time_t *tloc)
{
struct timeval tv;
compat_time_t now32;
do_gettimeofday(&tv);
now32 = tv.tv_sec;
if (tloc)
if (put_user(now32, tloc))
now32 = -EFAULT;
return now32;
}
asmlinkage int
sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz)
{
......
......@@ -74,7 +74,7 @@
ENTRY_DIFF(execve_wrapper)
ENTRY_SAME(chdir)
/* See comments in kernel/time.c!!! Maybe we don't need this? */
ENTRY_DIFF(time)
ENTRY_COMP(time)
ENTRY_SAME(mknod)
ENTRY_SAME(chmod) /* 15 */
ENTRY_SAME(lchown)
......@@ -91,7 +91,7 @@
ENTRY_SAME(bind)
ENTRY_SAME(setuid)
ENTRY_SAME(getuid)
ENTRY_SAME(stime) /* 25 */
ENTRY_COMP(stime) /* 25 */
ENTRY_SAME(ptrace)
ENTRY_SAME(alarm)
/* see stat comment */
......
......@@ -700,7 +700,7 @@ _GLOBAL(sys_call_table32)
.llong .sys_unlink /* 10 */
.llong .sys32_execve
.llong .sys_chdir
.llong .sys32_time
.llong .compat_sys_time
.llong .sys_mknod
.llong .sys_chmod /* 15 */
.llong .sys_lchown
......@@ -712,7 +712,7 @@ _GLOBAL(sys_call_table32)
.llong .sys_oldumount
.llong .sys_setuid
.llong .sys_getuid
.llong .ppc64_sys32_stime /* 25 */
.llong .compat_sys_stime /* 25 */
.llong .sys32_ptrace
.llong .sys_alarm
.llong .sys_ni_syscall /* old fstat syscall */
......@@ -987,7 +987,7 @@ _GLOBAL(sys_call_table)
.llong .sys_ni_syscall /* old umount syscall */
.llong .sys_setuid
.llong .sys_getuid
.llong .ppc64_sys_stime /* 25 */
.llong .sys_stime /* 25 */
.llong .sys_ptrace
.llong .sys_alarm
.llong .sys_ni_syscall /* old fstat syscall */
......
......@@ -1154,23 +1154,6 @@ asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
return error;
}
asmlinkage long sys32_time(compat_time_t __user * tloc)
{
compat_time_t secs;
struct timeval tv;
do_gettimeofday( &tv );
secs = tv.tv_sec;
if (tloc) {
if (put_user(secs,tloc))
secs = -EFAULT;
}
return secs;
}
asmlinkage int sys32_olduname(struct oldold_utsname __user * name)
{
int error;
......
......@@ -418,60 +418,6 @@ int do_settimeofday(struct timespec *tv)
EXPORT_SYMBOL(do_settimeofday);
/*
* This function is a copy of the architecture independent function
* but which calls do_settimeofday rather than setting the xtime
* fields itself. This way, the fields which are used for
* do_settimeofday get updated too.
*/
long ppc64_sys32_stime(int __user * tptr)
{
int value;
struct timespec myTimeval;
int err;
if (get_user(value, tptr))
return -EFAULT;
myTimeval.tv_sec = value;
myTimeval.tv_nsec = 0;
err = security_settime(&myTimeval, NULL);
if (err)
return err;
do_settimeofday(&myTimeval);
return 0;
}
/*
* This function is a copy of the architecture independent function
* but which calls do_settimeofday rather than setting the xtime
* fields itself. This way, the fields which are used for
* do_settimeofday get updated too.
*/
long ppc64_sys_stime(long __user * tptr)
{
long value;
struct timespec myTimeval;
int err;
if (get_user(value, tptr))
return -EFAULT;
myTimeval.tv_sec = value;
myTimeval.tv_nsec = 0;
err = security_settime(&myTimeval, NULL);
if (err)
return err;
do_settimeofday(&myTimeval);
return 0;
}
void __init time_init(void)
{
/* This function is only called on the boot processor */
......
......@@ -64,7 +64,7 @@ sys32_chdir_wrapper:
.globl sys32_time_wrapper
sys32_time_wrapper:
llgtr %r2,%r2 # int *
jg sys_time # branch to system call
jg compat_sys_time # branch to system call
.globl sys32_mknod_wrapper
sys32_mknod_wrapper:
......@@ -1076,8 +1076,8 @@ sys32_lstat64_wrapper:
.globl sys32_stime_wrapper
sys32_stime_wrapper:
llgtr %r2,%r2 # int *
jg sys_stime # branch to system call
llgtr %r2,%r2 # long *
jg compat_sys_stime # branch to system call
.globl sys32_sysctl_wrapper
sys32_sysctl_wrapper:
......
......@@ -25,7 +25,7 @@ sys_call_table32:
/*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys32_chown16, sys32_mknod
/*15*/ .word sys_chmod, sys32_lchown16, sparc_brk, sys32_perfctr, sys32_lseek
/*20*/ .word sys_getpid, sys_capget, sys_capset, sys32_setuid16, sys32_getuid16
/*25*/ .word sys_time, sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause
/*25*/ .word compat_sys_time, sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause
/*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice
.word sys_chown, sys_sync, sys32_kill, compat_sys_newstat, sys32_sendfile
/*40*/ .word compat_sys_newlstat, sys_dup, sys_pipe, compat_sys_times, sys_getuid
......@@ -66,7 +66,7 @@ sys_call_table32:
.word sys32_ipc, sys32_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex
/*220*/ .word sys32_sigprocmask, sys_ni_syscall, sys32_delete_module, sys_ni_syscall, sys32_getpgid
.word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys32_setfsuid16, sys32_setfsgid16
/*230*/ .word sys32_select, sys_time, sys_nis_syscall, sys_stime, compat_sys_statfs64
/*230*/ .word sys32_select, compat_sys_time, sys_nis_syscall, compat_sys_stime, compat_sys_statfs64
.word compat_sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall
/*240*/ .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler
.word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep
......
......@@ -315,7 +315,7 @@ ia32_sys_call_table:
.quad sys_unlink /* 10 */
.quad stub32_execve
.quad sys_chdir
.quad sys32_time
.quad compat_sys_time
.quad sys_mknod
.quad sys_chmod /* 15 */
.quad sys_lchown16
......@@ -327,7 +327,7 @@ ia32_sys_call_table:
.quad sys_oldumount /* old_umount */
.quad sys_setuid16
.quad sys_getuid16
.quad sys_stime /* stime */ /* 25 */
.quad compat_sys_stime /* stime */ /* 25 */
.quad sys32_ptrace /* ptrace */
.quad sys_alarm
.quad sys_fstat /* (old)fstat */
......
......@@ -492,26 +492,6 @@ sys32_old_select(struct sel_arg_struct __user *arg)
compat_ptr(a.exp), compat_ptr(a.tvp));
}
/*
* sys_time() can be implemented in user-level using
* sys_gettimeofday(). x86-64 did this but i386 Linux did not
* so we have to implement this system call here.
*/
asmlinkage long sys32_time(int __user * tloc)
{
int i;
struct timeval tv;
do_gettimeofday(&tv);
i = tv.tv_sec;
if (tloc) {
if (put_user(i,tloc))
i = -EFAULT;
}
return i;
}
extern asmlinkage long
compat_sys_wait4(compat_pid_t pid, compat_uint_t * stat_addr, int options,
struct compat_rusage *ru);
......
......@@ -281,6 +281,7 @@
# define __ARCH_WANT_SYS_OLDUMOUNT
# define __ARCH_WANT_SYS_SIGPENDING
# define __ARCH_WANT_SYS_SIGPROCMASK
# define __ARCH_WANT_COMPAT_SYS_TIME
#endif
#if !defined(__ASSEMBLY__) && !defined(ASSEMBLER)
......
......@@ -1106,7 +1106,6 @@ type name (atype a,btype b,ctype c,dtype d,etype e,ftype f) \
#define __ARCH_WANT_SYS_GETHOSTNAME
#define __ARCH_WANT_SYS_PAUSE
#define __ARCH_WANT_SYS_SGETMASK
#define __ARCH_WANT_SYS_TIME
#define __ARCH_WANT_SYS_UTIME
#define __ARCH_WANT_SYS_WAITPID
#define __ARCH_WANT_SYS_SOCKETCALL
......@@ -1122,6 +1121,12 @@ type name (atype a,btype b,ctype c,dtype d,etype e,ftype f) \
# ifndef __mips64
# define __ARCH_WANT_STAT64
# endif
# ifdef CONFIG_MIPS32
# define __ARCH_WANT_SYS_TIME
# endif
# ifdef CONFIG_MIPS32_O32
# define __ARCH_WANT_COMPAT_SYS_TIME
# endif
#endif
#ifdef __KERNEL_SYSCALLS__
......
......@@ -912,6 +912,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
#define __ARCH_WANT_SYS_SGETMASK
#define __ARCH_WANT_SYS_SIGNAL
#define __ARCH_WANT_SYS_TIME
#define __ARCH_WANT_COMPAT_SYS_TIME
#define __ARCH_WANT_SYS_UTIME
#define __ARCH_WANT_SYS_WAITPID
#define __ARCH_WANT_SYS_SOCKETCALL
......
......@@ -431,6 +431,7 @@ static inline _syscall3(int, execve, __const__ char *, file, char **, argv,
#define __ARCH_WANT_SYS_SGETMASK
#define __ARCH_WANT_SYS_SIGNAL
#define __ARCH_WANT_SYS_TIME
#define __ARCH_WANT_COMPAT_SYS_TIME
#define __ARCH_WANT_SYS_UTIME
#define __ARCH_WANT_SYS_WAITPID
#define __ARCH_WANT_SYS_SOCKETCALL
......
......@@ -520,7 +520,6 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
#define __ARCH_WANT_SYS_GETHOSTNAME
#define __ARCH_WANT_SYS_PAUSE
#define __ARCH_WANT_SYS_SIGNAL
#define __ARCH_WANT_SYS_TIME
#define __ARCH_WANT_SYS_UTIME
#define __ARCH_WANT_SYS_SOCKETCALL
#define __ARCH_WANT_SYS_FADVISE64
......@@ -532,9 +531,11 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
#define __ARCH_WANT_SYS_SIGPENDING
#define __ARCH_WANT_SYS_SIGPROCMASK
#define __ARCH_WANT_SYS_RT_SIGACTION
# ifndef CONFIG_ARCH_S390X
# ifdef CONFIG_ARCH_S390_31
# define __ARCH_WANT_STAT64
# define __ARCH_WANT_SYS_TIME
# endif
# define __ARCH_WANT_COMPAT_SYS_TIME
#endif
#ifdef __KERNEL_SYSCALLS__
......
......@@ -489,6 +489,7 @@ asmlinkage long sys_rt_sigaction(int sig,
#define __ARCH_WANT_SYS_SGETMASK
#define __ARCH_WANT_SYS_SIGNAL
#define __ARCH_WANT_SYS_TIME
#define __ARCH_WANT_COMPAT_SYS_TIME
#define __ARCH_WANT_SYS_UTIME
#define __ARCH_WANT_SYS_WAITPID
#define __ARCH_WANT_SYS_SOCKETCALL
......
......@@ -581,7 +581,6 @@ do { \
#define __ARCH_WANT_SYS_PAUSE
#define __ARCH_WANT_SYS_SGETMASK
#define __ARCH_WANT_SYS_SIGNAL
#define __ARCH_WANT_SYS_TIME
#define __ARCH_WANT_SYS_UTIME
#define __ARCH_WANT_SYS_WAITPID
#define __ARCH_WANT_SYS_SOCKETCALL
......@@ -594,6 +593,7 @@ do { \
#define __ARCH_WANT_SYS_SIGPENDING
#define __ARCH_WANT_SYS_SIGPROCMASK
#define __ARCH_WANT_SYS_RT_SIGACTION
#define __ARCH_WANT_COMPAT_SYS_TIME
#endif
#ifndef __KERNEL_SYSCALLS__
......
......@@ -63,7 +63,7 @@ struct mq_attr;
#include <linux/quota.h>
#include <linux/key.h>
asmlinkage long sys_time(int __user *tloc);
asmlinkage long sys_time(time_t __user *tloc);
asmlinkage long sys_stime(time_t __user *tptr);
asmlinkage long sys_gettimeofday(struct timeval __user *tv,
struct timezone __user *tz);
......
......@@ -20,6 +20,7 @@
#include <linux/futex.h> /* for FUTEX_WAIT */
#include <linux/syscalls.h>
#include <linux/unistd.h>
#include <linux/security.h>
#include <asm/uaccess.h>
......@@ -680,3 +681,42 @@ long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
return 0;
}
#ifdef __ARCH_WANT_COMPAT_SYS_TIME
/* compat_time_t is a 32 bit "long" and needs to get converted. */
asmlinkage long compat_sys_time(compat_time_t __user * tloc)
{
compat_time_t i;
struct timeval tv;
do_gettimeofday(&tv);
i = tv.tv_sec;
if (tloc) {
if (put_user(i,tloc))
i = -EFAULT;
}
return i;
}
asmlinkage long compat_sys_stime(compat_time_t __user *tptr)
{
struct timespec tv;
int err;
if (get_user(tv.tv_sec, tptr))
return -EFAULT;
tv.tv_nsec = 0;
err = security_settime(&tv, NULL);
if (err)
return err;
do_settimeofday(&tv);
return 0;
}
#endif /* __ARCH_WANT_COMPAT_SYS_TIME */
......@@ -52,12 +52,10 @@ EXPORT_SYMBOL(sys_tz);
* sys_gettimeofday(). Is this for backwards compatibility? If so,
* why not move it into the appropriate arch directory (for those
* architectures that need it).
*
* XXX This function is NOT 64-bit clean!
*/
asmlinkage long sys_time(int __user * tloc)
asmlinkage long sys_time(time_t __user * tloc)
{
int i;
time_t i;
struct timeval tv;
do_gettimeofday(&tv);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment