Commit b418da16 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Linus Torvalds

compat: generic compat get/settimeofday

Nothing arch specific in get/settimeofday.  The details of the timeval
conversion varied a little from arch to arch, but all with the same
results.

Also add an extern declaration for sys_tz to linux/time.h because externs
in .c files are fowned upon.  I'll kill the externs in various other files
in a sparate patch.

[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Acked-by: David S. Miller <davem@davemloft.net> [ sparc bits ]
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Acked-by: default avatarKyle McMartin <kyle@mcmartin.ca>
Cc: Matthew Wilcox <matthew@wil.cx>
Cc: Grant Grundler <grundler@parisc-linux.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent f7a5000f
...@@ -251,8 +251,8 @@ ia32_syscall_table: ...@@ -251,8 +251,8 @@ ia32_syscall_table:
data8 compat_sys_setrlimit /* 75 */ data8 compat_sys_setrlimit /* 75 */
data8 compat_sys_old_getrlimit data8 compat_sys_old_getrlimit
data8 compat_sys_getrusage data8 compat_sys_getrusage
data8 sys32_gettimeofday data8 compat_sys_gettimeofday
data8 sys32_settimeofday data8 compat_sys_settimeofday
data8 sys32_getgroups16 /* 80 */ data8 sys32_getgroups16 /* 80 */
data8 sys32_setgroups16 data8 sys32_setgroups16
data8 sys32_old_select data8 sys32_old_select
......
...@@ -1113,68 +1113,12 @@ sys32_pipe (int __user *fd) ...@@ -1113,68 +1113,12 @@ sys32_pipe (int __user *fd)
return retval; return retval;
} }
static inline long
get_tv32 (struct timeval *o, struct compat_timeval __user *i)
{
return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
(__get_user(o->tv_sec, &i->tv_sec) | __get_user(o->tv_usec, &i->tv_usec)));
}
static inline long
put_tv32 (struct compat_timeval __user *o, struct timeval *i)
{
return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
(__put_user(i->tv_sec, &o->tv_sec) | __put_user(i->tv_usec, &o->tv_usec)));
}
asmlinkage unsigned long asmlinkage unsigned long
sys32_alarm (unsigned int seconds) sys32_alarm (unsigned int seconds)
{ {
return alarm_setitimer(seconds); return alarm_setitimer(seconds);
} }
/* Translations due to time_t size differences. Which affects all
sorts of things, like timeval and itimerval. */
extern struct timezone sys_tz;
asmlinkage long
sys32_gettimeofday (struct compat_timeval __user *tv, struct timezone __user *tz)
{
if (tv) {
struct timeval ktv;
do_gettimeofday(&ktv);
if (put_tv32(tv, &ktv))
return -EFAULT;
}
if (tz) {
if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
return -EFAULT;
}
return 0;
}
asmlinkage long
sys32_settimeofday (struct compat_timeval __user *tv, struct timezone __user *tz)
{
struct timeval ktv;
struct timespec kts;
struct timezone ktz;
if (tv) {
if (get_tv32(&ktv, tv))
return -EFAULT;
kts.tv_sec = ktv.tv_sec;
kts.tv_nsec = ktv.tv_usec * 1000;
}
if (tz) {
if (copy_from_user(&ktz, tz, sizeof(ktz)))
return -EFAULT;
}
return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
}
struct sel_arg_struct { struct sel_arg_struct {
unsigned int n; unsigned int n;
unsigned int inp; unsigned int inp;
......
...@@ -133,72 +133,6 @@ asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy, ...@@ -133,72 +133,6 @@ asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy,
return sys_ftruncate(fd, merge_64(a2, a3)); return sys_ftruncate(fd, merge_64(a2, a3));
} }
static inline long
get_tv32(struct timeval *o, struct compat_timeval __user *i)
{
return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
(__get_user(o->tv_sec, &i->tv_sec) |
__get_user(o->tv_usec, &i->tv_usec)));
}
static inline long
put_tv32(struct compat_timeval __user *o, struct timeval *i)
{
return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
(__put_user(i->tv_sec, &o->tv_sec) |
__put_user(i->tv_usec, &o->tv_usec)));
}
extern struct timezone sys_tz;
asmlinkage int
sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
{
if (tv) {
struct timeval ktv;
do_gettimeofday(&ktv);
if (put_tv32(tv, &ktv))
return -EFAULT;
}
if (tz) {
if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
return -EFAULT;
}
return 0;
}
static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
{
long usec;
if (!access_ok(VERIFY_READ, i, sizeof(*i)))
return -EFAULT;
if (__get_user(o->tv_sec, &i->tv_sec))
return -EFAULT;
if (__get_user(usec, &i->tv_usec))
return -EFAULT;
o->tv_nsec = usec * 1000;
return 0;
}
asmlinkage int
sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
{
struct timespec kts;
struct timezone ktz;
if (tv) {
if (get_ts32(&kts, tv))
return -EFAULT;
}
if (tz) {
if (copy_from_user(&ktz, tz, sizeof(ktz)))
return -EFAULT;
}
return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
}
asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high, asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high,
unsigned int offset_low, loff_t __user * result, unsigned int offset_low, loff_t __user * result,
unsigned int origin) unsigned int origin)
......
...@@ -214,7 +214,7 @@ EXPORT(sysn32_call_table) ...@@ -214,7 +214,7 @@ EXPORT(sysn32_call_table)
PTR sys_fchown PTR sys_fchown
PTR sys_lchown PTR sys_lchown
PTR sys_umask PTR sys_umask
PTR sys32_gettimeofday PTR compat_sys_gettimeofday
PTR compat_sys_getrlimit /* 6095 */ PTR compat_sys_getrlimit /* 6095 */
PTR compat_sys_getrusage PTR compat_sys_getrusage
PTR compat_sys_sysinfo PTR compat_sys_sysinfo
...@@ -279,7 +279,7 @@ EXPORT(sysn32_call_table) ...@@ -279,7 +279,7 @@ EXPORT(sysn32_call_table)
PTR sys_chroot PTR sys_chroot
PTR sys_sync PTR sys_sync
PTR sys_acct PTR sys_acct
PTR sys32_settimeofday PTR compat_sys_settimeofday
PTR compat_sys_mount /* 6160 */ PTR compat_sys_mount /* 6160 */
PTR sys_umount PTR sys_umount
PTR sys_swapon PTR sys_swapon
......
...@@ -283,8 +283,8 @@ sys_call_table: ...@@ -283,8 +283,8 @@ sys_call_table:
PTR compat_sys_setrlimit /* 4075 */ PTR compat_sys_setrlimit /* 4075 */
PTR compat_sys_getrlimit PTR compat_sys_getrlimit
PTR compat_sys_getrusage PTR compat_sys_getrusage
PTR sys32_gettimeofday PTR compat_sys_gettimeofday
PTR sys32_settimeofday PTR compat_sys_settimeofday
PTR sys_getgroups /* 4080 */ PTR sys_getgroups /* 4080 */
PTR sys_setgroups PTR sys_setgroups
PTR sys_ni_syscall /* old_select */ PTR sys_ni_syscall /* old_select */
......
...@@ -179,64 +179,6 @@ asmlinkage long sys32_sched_rr_get_interval(pid_t pid, ...@@ -179,64 +179,6 @@ asmlinkage long sys32_sched_rr_get_interval(pid_t pid,
return ret; return ret;
} }
static int
put_compat_timeval(struct compat_timeval __user *u, struct timeval *t)
{
struct compat_timeval t32;
t32.tv_sec = t->tv_sec;
t32.tv_usec = t->tv_usec;
return copy_to_user(u, &t32, sizeof t32);
}
static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
{
long usec;
if (__get_user(o->tv_sec, &i->tv_sec))
return -EFAULT;
if (__get_user(usec, &i->tv_usec))
return -EFAULT;
o->tv_nsec = usec * 1000;
return 0;
}
asmlinkage int
sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
{
extern void do_gettimeofday(struct timeval *tv);
if (tv) {
struct timeval ktv;
do_gettimeofday(&ktv);
if (put_compat_timeval(tv, &ktv))
return -EFAULT;
}
if (tz) {
extern struct timezone sys_tz;
if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
return -EFAULT;
}
return 0;
}
asmlinkage
int sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
{
struct timespec kts;
struct timezone ktz;
if (tv) {
if (get_ts32(&kts, tv))
return -EFAULT;
}
if (tz) {
if (copy_from_user(&ktz, tz, sizeof(ktz)))
return -EFAULT;
}
return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
}
/*** copied from mips64 ***/ /*** copied from mips64 ***/
/* /*
* Ooo, nasty. We need here to frob 32-bit unsigned longs to * Ooo, nasty. We need here to frob 32-bit unsigned longs to
......
...@@ -149,8 +149,8 @@ ...@@ -149,8 +149,8 @@
ENTRY_COMP(getrlimit) ENTRY_COMP(getrlimit)
ENTRY_COMP(getrusage) ENTRY_COMP(getrusage)
/* struct timeval and timezone are maybe?? consistent wide and narrow */ /* struct timeval and timezone are maybe?? consistent wide and narrow */
ENTRY_DIFF(gettimeofday) ENTRY_COMP(gettimeofday)
ENTRY_DIFF(settimeofday) ENTRY_COMP(settimeofday)
ENTRY_SAME(getgroups) /* 80 */ ENTRY_SAME(getgroups) /* 80 */
ENTRY_SAME(setgroups) ENTRY_SAME(setgroups)
/* struct socketaddr... */ /* struct socketaddr... */
......
...@@ -71,69 +71,6 @@ asmlinkage long compat_sys_sysfs(u32 option, u32 arg1, u32 arg2) ...@@ -71,69 +71,6 @@ asmlinkage long compat_sys_sysfs(u32 option, u32 arg1, u32 arg2)
return sys_sysfs((int)option, arg1, arg2); return sys_sysfs((int)option, arg1, arg2);
} }
static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
{
long usec;
if (!access_ok(VERIFY_READ, i, sizeof(*i)))
return -EFAULT;
if (__get_user(o->tv_sec, &i->tv_sec))
return -EFAULT;
if (__get_user(usec, &i->tv_usec))
return -EFAULT;
o->tv_nsec = usec * 1000;
return 0;
}
static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
{
return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
(__put_user(i->tv_sec, &o->tv_sec) |
__put_user(i->tv_usec, &o->tv_usec)));
}
/* Translations due to time_t size differences. Which affects all
sorts of things, like timeval and itimerval. */
extern struct timezone sys_tz;
asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
{
if (tv) {
struct timeval ktv;
do_gettimeofday(&ktv);
if (put_tv32(tv, &ktv))
return -EFAULT;
}
if (tz) {
if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
return -EFAULT;
}
return 0;
}
asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
{
struct timespec kts;
struct timezone ktz;
if (tv) {
if (get_ts32(&kts, tv))
return -EFAULT;
}
if (tz) {
if (copy_from_user(&ktz, tz, sizeof(ktz)))
return -EFAULT;
}
return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
}
#ifdef CONFIG_SYSVIPC #ifdef CONFIG_SYSVIPC
long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr, long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr,
u32 fifth) u32 fifth)
......
...@@ -279,22 +279,6 @@ asmlinkage long sys32_getegid16(void) ...@@ -279,22 +279,6 @@ asmlinkage long sys32_getegid16(void)
return high2lowgid(current->egid); return high2lowgid(current->egid);
} }
/* 32-bit timeval and related flotsam. */
static inline long get_tv32(struct timeval *o, struct compat_timeval __user *i)
{
return (!access_ok(VERIFY_READ, o, sizeof(*o)) ||
(__get_user(o->tv_sec, &i->tv_sec) ||
__get_user(o->tv_usec, &i->tv_usec)));
}
static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
{
return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
(__put_user(i->tv_sec, &o->tv_sec) ||
__put_user(i->tv_usec, &o->tv_usec)));
}
/* /*
* sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation. * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation.
* *
...@@ -522,57 +506,6 @@ sys32_delete_module(const char __user *name_user, unsigned int flags) ...@@ -522,57 +506,6 @@ sys32_delete_module(const char __user *name_user, unsigned int flags)
#endif /* CONFIG_MODULES */ #endif /* CONFIG_MODULES */
/* Translations due to time_t size differences. Which affects all
sorts of things, like timeval and itimerval. */
extern struct timezone sys_tz;
asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
{
if (tv) {
struct timeval ktv;
do_gettimeofday(&ktv);
if (put_tv32(tv, &ktv))
return -EFAULT;
}
if (tz) {
if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
return -EFAULT;
}
return 0;
}
static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
{
long usec;
if (!access_ok(VERIFY_READ, i, sizeof(*i)))
return -EFAULT;
if (__get_user(o->tv_sec, &i->tv_sec))
return -EFAULT;
if (__get_user(usec, &i->tv_usec))
return -EFAULT;
o->tv_nsec = usec * 1000;
return 0;
}
asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
{
struct timespec kts;
struct timezone ktz;
if (tv) {
if (get_ts32(&kts, tv))
return -EFAULT;
}
if (tz) {
if (copy_from_user(&ktz, tz, sizeof(ktz)))
return -EFAULT;
}
return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
}
asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf, asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf,
size_t count, u32 poshi, u32 poslo) size_t count, u32 poshi, u32 poslo)
{ {
......
...@@ -202,10 +202,6 @@ long sys32_execve(void); ...@@ -202,10 +202,6 @@ long sys32_execve(void);
long sys32_init_module(void __user *umod, unsigned long len, long sys32_init_module(void __user *umod, unsigned long len,
const char __user *uargs); const char __user *uargs);
long sys32_delete_module(const char __user *name_user, unsigned int flags); long sys32_delete_module(const char __user *name_user, unsigned int flags);
long sys32_gettimeofday(struct compat_timeval __user *tv,
struct timezone __user *tz);
long sys32_settimeofday(struct compat_timeval __user *tv,
struct timezone __user *tz);
long sys32_pread64(unsigned int fd, char __user *ubuf, size_t count, long sys32_pread64(unsigned int fd, char __user *ubuf, size_t count,
u32 poshi, u32 poslo); u32 poshi, u32 poslo);
long sys32_pwrite64(unsigned int fd, const char __user *ubuf, long sys32_pwrite64(unsigned int fd, const char __user *ubuf,
......
...@@ -332,17 +332,17 @@ compat_sys_getrusage_wrapper: ...@@ -332,17 +332,17 @@ compat_sys_getrusage_wrapper:
llgtr %r3,%r3 # struct rusage_emu31 * llgtr %r3,%r3 # struct rusage_emu31 *
jg compat_sys_getrusage # branch to system call jg compat_sys_getrusage # branch to system call
.globl sys32_gettimeofday_wrapper .globl compat_sys_gettimeofday_wrapper
sys32_gettimeofday_wrapper: compat_sys_gettimeofday_wrapper:
llgtr %r2,%r2 # struct timeval_emu31 * llgtr %r2,%r2 # struct timeval_emu31 *
llgtr %r3,%r3 # struct timezone * llgtr %r3,%r3 # struct timezone *
jg sys32_gettimeofday # branch to system call jg compat_sys_gettimeofday # branch to system call
.globl sys32_settimeofday_wrapper .globl compat_sys_settimeofday_wrapper
sys32_settimeofday_wrapper: compat_sys_settimeofday_wrapper:
llgtr %r2,%r2 # struct timeval_emu31 * llgtr %r2,%r2 # struct timeval_emu31 *
llgtr %r3,%r3 # struct timezone * llgtr %r3,%r3 # struct timezone *
jg sys32_settimeofday # branch to system call jg compat_sys_settimeofday # branch to system call
.globl sys32_getgroups16_wrapper .globl sys32_getgroups16_wrapper
sys32_getgroups16_wrapper: sys32_getgroups16_wrapper:
......
...@@ -86,8 +86,8 @@ SYSCALL(sys_sethostname,sys_sethostname,sys32_sethostname_wrapper) ...@@ -86,8 +86,8 @@ SYSCALL(sys_sethostname,sys_sethostname,sys32_sethostname_wrapper)
SYSCALL(sys_setrlimit,sys_setrlimit,compat_sys_setrlimit_wrapper) /* 75 */ SYSCALL(sys_setrlimit,sys_setrlimit,compat_sys_setrlimit_wrapper) /* 75 */
SYSCALL(sys_old_getrlimit,sys_getrlimit,compat_sys_old_getrlimit_wrapper) SYSCALL(sys_old_getrlimit,sys_getrlimit,compat_sys_old_getrlimit_wrapper)
SYSCALL(sys_getrusage,sys_getrusage,compat_sys_getrusage_wrapper) SYSCALL(sys_getrusage,sys_getrusage,compat_sys_getrusage_wrapper)
SYSCALL(sys_gettimeofday,sys_gettimeofday,sys32_gettimeofday_wrapper) SYSCALL(sys_gettimeofday,sys_gettimeofday,compat_sys_gettimeofday_wrapper)
SYSCALL(sys_settimeofday,sys_settimeofday,sys32_settimeofday_wrapper) SYSCALL(sys_settimeofday,sys_settimeofday,compat_sys_settimeofday_wrapper)
SYSCALL(sys_getgroups16,sys_ni_syscall,sys32_getgroups16_wrapper) /* 80 old getgroups16 syscall */ SYSCALL(sys_getgroups16,sys_ni_syscall,sys32_getgroups16_wrapper) /* 80 old getgroups16 syscall */
SYSCALL(sys_setgroups16,sys_ni_syscall,sys32_setgroups16_wrapper) /* old setgroups16 syscall */ SYSCALL(sys_setgroups16,sys_ni_syscall,sys32_setgroups16_wrapper) /* old setgroups16 syscall */
NI_SYSCALL /* old select syscall */ NI_SYSCALL /* old select syscall */
......
...@@ -58,15 +58,6 @@ ...@@ -58,15 +58,6 @@
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/compat_signal.h> #include <asm/compat_signal.h>
/* 32-bit timeval and related flotsam. */
static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
{
return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
(__put_user(i->tv_sec, &o->tv_sec) |
__put_user(i->tv_usec, &o->tv_usec)));
}
#ifdef CONFIG_SYSVIPC #ifdef CONFIG_SYSVIPC
asmlinkage long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr, u32 fifth) asmlinkage long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr, u32 fifth)
{ {
...@@ -487,59 +478,6 @@ asmlinkage long sys32_delete_module(const char __user *name_user) ...@@ -487,59 +478,6 @@ asmlinkage long sys32_delete_module(const char __user *name_user)
#endif /* CONFIG_MODULES */ #endif /* CONFIG_MODULES */
/* Translations due to time_t size differences. Which affects all
sorts of things, like timeval and itimerval. */
extern struct timezone sys_tz;
asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv,
struct timezone __user *tz)
{
if (tv) {
struct timeval ktv;
do_gettimeofday(&ktv);
if (put_tv32(tv, &ktv))
return -EFAULT;
}
if (tz) {
if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
return -EFAULT;
}
return 0;
}
static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
{
long usec;
if (!access_ok(VERIFY_READ, i, sizeof(*i)))
return -EFAULT;
if (__get_user(o->tv_sec, &i->tv_sec))
return -EFAULT;
if (__get_user(usec, &i->tv_usec))
return -EFAULT;
o->tv_nsec = usec * 1000;
return 0;
}
asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv,
struct timezone __user *tz)
{
struct timespec kts;
struct timezone ktz;
if (tv) {
if (get_ts32(&kts, tv))
return -EFAULT;
}
if (tz) {
if (copy_from_user(&ktz, tz, sizeof(ktz)))
return -EFAULT;
}
return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
}
asmlinkage compat_ssize_t sys32_pread64(unsigned int fd, asmlinkage compat_ssize_t sys32_pread64(unsigned int fd,
char __user *ubuf, char __user *ubuf,
compat_size_t count, compat_size_t count,
......
...@@ -41,8 +41,8 @@ sys_call_table32: ...@@ -41,8 +41,8 @@ sys_call_table32:
/*100*/ .word sys32_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending /*100*/ .word sys32_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending
.word compat_sys_rt_sigtimedwait, sys32_rt_sigqueueinfo, compat_sys_rt_sigsuspend, sys_setresuid, sys_getresuid .word compat_sys_rt_sigtimedwait, sys32_rt_sigqueueinfo, compat_sys_rt_sigsuspend, sys_setresuid, sys_getresuid
/*110*/ .word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall /*110*/ .word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall
.word sys32_getgroups, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd .word sys32_getgroups, compat_sys_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
/*120*/ .word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys_fchown16, sys_fchmod /*120*/ .word compat_sys_readv, compat_sys_writev, compat_sys_settimeofday, sys_fchown16, sys_fchmod
.word sys_nis_syscall, sys_setreuid16, sys_setregid16, sys_rename, sys_truncate .word sys_nis_syscall, sys_setreuid16, sys_setregid16, sys_rename, sys_truncate
/*130*/ .word sys_ftruncate, sys_flock, compat_sys_lstat64, sys_nis_syscall, sys_nis_syscall /*130*/ .word sys_ftruncate, sys_flock, compat_sys_lstat64, sys_nis_syscall, sys_nis_syscall
.word sys_nis_syscall, sys32_mkdir, sys_rmdir, compat_sys_utimes, compat_sys_stat64 .word sys_nis_syscall, sys32_mkdir, sys_rmdir, compat_sys_utimes, compat_sys_stat64
......
...@@ -571,8 +571,8 @@ ia32_sys_call_table: ...@@ -571,8 +571,8 @@ ia32_sys_call_table:
.quad compat_sys_setrlimit /* 75 */ .quad compat_sys_setrlimit /* 75 */
.quad compat_sys_old_getrlimit /* old_getrlimit */ .quad compat_sys_old_getrlimit /* old_getrlimit */
.quad compat_sys_getrusage .quad compat_sys_getrusage
.quad sys32_gettimeofday .quad compat_sys_gettimeofday
.quad sys32_settimeofday .quad compat_sys_settimeofday
.quad sys_getgroups16 /* 80 */ .quad sys_getgroups16 /* 80 */
.quad sys_setgroups16 .quad sys_setgroups16
.quad sys32_old_select .quad sys32_old_select
......
...@@ -367,75 +367,11 @@ asmlinkage long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, ...@@ -367,75 +367,11 @@ asmlinkage long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
return 0; return 0;
} }
static inline long get_tv32(struct timeval *o, struct compat_timeval __user *i)
{
int err = -EFAULT;
if (access_ok(VERIFY_READ, i, sizeof(*i))) {
err = __get_user(o->tv_sec, &i->tv_sec);
err |= __get_user(o->tv_usec, &i->tv_usec);
}
return err;
}
static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
{
int err = -EFAULT;
if (access_ok(VERIFY_WRITE, o, sizeof(*o))) {
err = __put_user(i->tv_sec, &o->tv_sec);
err |= __put_user(i->tv_usec, &o->tv_usec);
}
return err;
}
asmlinkage long sys32_alarm(unsigned int seconds) asmlinkage long sys32_alarm(unsigned int seconds)
{ {
return alarm_setitimer(seconds); return alarm_setitimer(seconds);
} }
/*
* Translations due to time_t size differences. Which affects all
* sorts of things, like timeval and itimerval.
*/
asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv,
struct timezone __user *tz)
{
if (tv) {
struct timeval ktv;
do_gettimeofday(&ktv);
if (put_tv32(tv, &ktv))
return -EFAULT;
}
if (tz) {
if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
return -EFAULT;
}
return 0;
}
asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv,
struct timezone __user *tz)
{
struct timeval ktv;
struct timespec kts;
struct timezone ktz;
if (tv) {
if (get_tv32(&ktv, tv))
return -EFAULT;
kts.tv_sec = ktv.tv_sec;
kts.tv_nsec = ktv.tv_usec * NSEC_PER_USEC;
}
if (tz) {
if (copy_from_user(&ktz, tz, sizeof(ktz)))
return -EFAULT;
}
return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
}
struct sel_arg_struct { struct sel_arg_struct {
unsigned int n; unsigned int n;
unsigned int inp; unsigned int inp;
......
...@@ -234,6 +234,11 @@ extern int get_compat_itimerspec(struct itimerspec *dst, ...@@ -234,6 +234,11 @@ extern int get_compat_itimerspec(struct itimerspec *dst,
extern int put_compat_itimerspec(struct compat_itimerspec __user *dst, extern int put_compat_itimerspec(struct compat_itimerspec __user *dst,
const struct itimerspec *src); const struct itimerspec *src);
asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv,
struct timezone __user *tz);
asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv,
struct timezone __user *tz);
asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp); asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp);
extern int compat_printk(const char *fmt, ...); extern int compat_printk(const char *fmt, ...);
......
...@@ -29,6 +29,8 @@ struct timezone { ...@@ -29,6 +29,8 @@ struct timezone {
#ifdef __KERNEL__ #ifdef __KERNEL__
extern struct timezone sys_tz;
/* Parameters used to convert the timespec values: */ /* Parameters used to convert the timespec values: */
#define MSEC_PER_SEC 1000L #define MSEC_PER_SEC 1000L
#define USEC_PER_MSEC 1000L #define USEC_PER_MSEC 1000L
......
...@@ -26,6 +26,64 @@ ...@@ -26,6 +26,64 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
/*
* Note that the native side is already converted to a timespec, because
* that's what we want anyway.
*/
static int compat_get_timeval(struct timespec *o,
struct compat_timeval __user *i)
{
long usec;
if (get_user(o->tv_sec, &i->tv_sec) ||
get_user(usec, &i->tv_usec))
return -EFAULT;
o->tv_nsec = usec * 1000;
return 0;
}
static int compat_put_timeval(struct compat_timeval __user *o,
struct timeval *i)
{
return (put_user(i->tv_sec, &o->tv_sec) ||
put_user(i->tv_usec, &o->tv_usec)) ? -EFAULT : 0;
}
asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv,
struct timezone __user *tz)
{
if (tv) {
struct timeval ktv;
do_gettimeofday(&ktv);
if (compat_put_timeval(tv, &ktv))
return -EFAULT;
}
if (tz) {
if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
return -EFAULT;
}
return 0;
}
asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv,
struct timezone __user *tz)
{
struct timespec kts;
struct timezone ktz;
if (tv) {
if (compat_get_timeval(&kts, tv))
return -EFAULT;
}
if (tz) {
if (copy_from_user(&ktz, tz, sizeof(ktz)))
return -EFAULT;
}
return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
}
int get_compat_timespec(struct timespec *ts, const struct compat_timespec __user *cts) int get_compat_timespec(struct timespec *ts, const struct compat_timespec __user *cts)
{ {
return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) || return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) ||
......
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