aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2008-10-16 01:02:06 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-16 14:21:33 -0400
commitb418da16dd44810e5d5a22bba377cca80512a524 (patch)
tree20ac32ea027bb8d978a22fbfaf6580fd34518aa5
parentf7a5000f7a8924e9c5fad1801616601d6dc65a17 (diff)
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: Christoph 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: Kyle 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: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/ia64/ia32/ia32_entry.S4
-rw-r--r--arch/ia64/ia32/sys_ia32.c56
-rw-r--r--arch/mips/kernel/linux32.c66
-rw-r--r--arch/mips/kernel/scall64-n32.S4
-rw-r--r--arch/mips/kernel/scall64-o32.S4
-rw-r--r--arch/parisc/kernel/sys_parisc32.c58
-rw-r--r--arch/parisc/kernel/syscall_table.S4
-rw-r--r--arch/powerpc/kernel/sys_ppc32.c63
-rw-r--r--arch/s390/kernel/compat_linux.c67
-rw-r--r--arch/s390/kernel/compat_linux.h4
-rw-r--r--arch/s390/kernel/compat_wrapper.S12
-rw-r--r--arch/s390/kernel/syscalls.S4
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c62
-rw-r--r--arch/sparc64/kernel/systbls.S4
-rw-r--r--arch/x86/ia32/ia32entry.S4
-rw-r--r--arch/x86/ia32/sys_ia32.c64
-rw-r--r--include/linux/compat.h5
-rw-r--r--include/linux/time.h2
-rw-r--r--kernel/compat.c58
19 files changed, 85 insertions, 460 deletions
diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
index ff88c48c5d19..53505bb04771 100644
--- a/arch/ia64/ia32/ia32_entry.S
+++ b/arch/ia64/ia32/ia32_entry.S
@@ -251,8 +251,8 @@ ia32_syscall_table:
251 data8 compat_sys_setrlimit /* 75 */ 251 data8 compat_sys_setrlimit /* 75 */
252 data8 compat_sys_old_getrlimit 252 data8 compat_sys_old_getrlimit
253 data8 compat_sys_getrusage 253 data8 compat_sys_getrusage
254 data8 sys32_gettimeofday 254 data8 compat_sys_gettimeofday
255 data8 sys32_settimeofday 255 data8 compat_sys_settimeofday
256 data8 sys32_getgroups16 /* 80 */ 256 data8 sys32_getgroups16 /* 80 */
257 data8 sys32_setgroups16 257 data8 sys32_setgroups16
258 data8 sys32_old_select 258 data8 sys32_old_select
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index 2362a8eefb30..f4430bb4bbdc 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -1113,68 +1113,12 @@ sys32_pipe (int __user *fd)
1113 return retval; 1113 return retval;
1114} 1114}
1115 1115
1116static inline long
1117get_tv32 (struct timeval *o, struct compat_timeval __user *i)
1118{
1119 return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
1120 (__get_user(o->tv_sec, &i->tv_sec) | __get_user(o->tv_usec, &i->tv_usec)));
1121}
1122
1123static inline long
1124put_tv32 (struct compat_timeval __user *o, struct timeval *i)
1125{
1126 return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
1127 (__put_user(i->tv_sec, &o->tv_sec) | __put_user(i->tv_usec, &o->tv_usec)));
1128}
1129
1130asmlinkage unsigned long 1116asmlinkage unsigned long
1131sys32_alarm (unsigned int seconds) 1117sys32_alarm (unsigned int seconds)
1132{ 1118{
1133 return alarm_setitimer(seconds); 1119 return alarm_setitimer(seconds);
1134} 1120}
1135 1121
1136/* Translations due to time_t size differences. Which affects all
1137 sorts of things, like timeval and itimerval. */
1138
1139extern struct timezone sys_tz;
1140
1141asmlinkage long
1142sys32_gettimeofday (struct compat_timeval __user *tv, struct timezone __user *tz)
1143{
1144 if (tv) {
1145 struct timeval ktv;
1146 do_gettimeofday(&ktv);
1147 if (put_tv32(tv, &ktv))
1148 return -EFAULT;
1149 }
1150 if (tz) {
1151 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
1152 return -EFAULT;
1153 }
1154 return 0;
1155}
1156
1157asmlinkage long
1158sys32_settimeofday (struct compat_timeval __user *tv, struct timezone __user *tz)
1159{
1160 struct timeval ktv;
1161 struct timespec kts;
1162 struct timezone ktz;
1163
1164 if (tv) {
1165 if (get_tv32(&ktv, tv))
1166 return -EFAULT;
1167 kts.tv_sec = ktv.tv_sec;
1168 kts.tv_nsec = ktv.tv_usec * 1000;
1169 }
1170 if (tz) {
1171 if (copy_from_user(&ktz, tz, sizeof(ktz)))
1172 return -EFAULT;
1173 }
1174
1175 return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
1176}
1177
1178struct sel_arg_struct { 1122struct sel_arg_struct {
1179 unsigned int n; 1123 unsigned int n;
1180 unsigned int inp; 1124 unsigned int inp;
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 89223a9bff2c..aa2c55e3b55f 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -133,72 +133,6 @@ asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy,
133 return sys_ftruncate(fd, merge_64(a2, a3)); 133 return sys_ftruncate(fd, merge_64(a2, a3));
134} 134}
135 135
136static inline long
137get_tv32(struct timeval *o, struct compat_timeval __user *i)
138{
139 return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
140 (__get_user(o->tv_sec, &i->tv_sec) |
141 __get_user(o->tv_usec, &i->tv_usec)));
142}
143
144static inline long
145put_tv32(struct compat_timeval __user *o, struct timeval *i)
146{
147 return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
148 (__put_user(i->tv_sec, &o->tv_sec) |
149 __put_user(i->tv_usec, &o->tv_usec)));
150}
151
152extern struct timezone sys_tz;
153
154asmlinkage int
155sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
156{
157 if (tv) {
158 struct timeval ktv;
159 do_gettimeofday(&ktv);
160 if (put_tv32(tv, &ktv))
161 return -EFAULT;
162 }
163 if (tz) {
164 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
165 return -EFAULT;
166 }
167 return 0;
168}
169
170static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
171{
172 long usec;
173
174 if (!access_ok(VERIFY_READ, i, sizeof(*i)))
175 return -EFAULT;
176 if (__get_user(o->tv_sec, &i->tv_sec))
177 return -EFAULT;
178 if (__get_user(usec, &i->tv_usec))
179 return -EFAULT;
180 o->tv_nsec = usec * 1000;
181 return 0;
182}
183
184asmlinkage int
185sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
186{
187 struct timespec kts;
188 struct timezone ktz;
189
190 if (tv) {
191 if (get_ts32(&kts, tv))
192 return -EFAULT;
193 }
194 if (tz) {
195 if (copy_from_user(&ktz, tz, sizeof(ktz)))
196 return -EFAULT;
197 }
198
199 return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
200}
201
202asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high, 136asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high,
203 unsigned int offset_low, loff_t __user * result, 137 unsigned int offset_low, loff_t __user * result,
204 unsigned int origin) 138 unsigned int origin)
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 324c5499dec2..e266b3aa6560 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -214,7 +214,7 @@ EXPORT(sysn32_call_table)
214 PTR sys_fchown 214 PTR sys_fchown
215 PTR sys_lchown 215 PTR sys_lchown
216 PTR sys_umask 216 PTR sys_umask
217 PTR sys32_gettimeofday 217 PTR compat_sys_gettimeofday
218 PTR compat_sys_getrlimit /* 6095 */ 218 PTR compat_sys_getrlimit /* 6095 */
219 PTR compat_sys_getrusage 219 PTR compat_sys_getrusage
220 PTR compat_sys_sysinfo 220 PTR compat_sys_sysinfo
@@ -279,7 +279,7 @@ EXPORT(sysn32_call_table)
279 PTR sys_chroot 279 PTR sys_chroot
280 PTR sys_sync 280 PTR sys_sync
281 PTR sys_acct 281 PTR sys_acct
282 PTR sys32_settimeofday 282 PTR compat_sys_settimeofday
283 PTR compat_sys_mount /* 6160 */ 283 PTR compat_sys_mount /* 6160 */
284 PTR sys_umount 284 PTR sys_umount
285 PTR sys_swapon 285 PTR sys_swapon
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 85fedac99a57..6c7ef8313ebd 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -283,8 +283,8 @@ sys_call_table:
283 PTR compat_sys_setrlimit /* 4075 */ 283 PTR compat_sys_setrlimit /* 4075 */
284 PTR compat_sys_getrlimit 284 PTR compat_sys_getrlimit
285 PTR compat_sys_getrusage 285 PTR compat_sys_getrusage
286 PTR sys32_gettimeofday 286 PTR compat_sys_gettimeofday
287 PTR sys32_settimeofday 287 PTR compat_sys_settimeofday
288 PTR sys_getgroups /* 4080 */ 288 PTR sys_getgroups /* 4080 */
289 PTR sys_setgroups 289 PTR sys_setgroups
290 PTR sys_ni_syscall /* old_select */ 290 PTR sys_ni_syscall /* old_select */
diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
index 2c3af17e049c..0838155b7a88 100644
--- a/arch/parisc/kernel/sys_parisc32.c
+++ b/arch/parisc/kernel/sys_parisc32.c
@@ -179,64 +179,6 @@ asmlinkage long sys32_sched_rr_get_interval(pid_t pid,
179 return ret; 179 return ret;
180} 180}
181 181
182static int
183put_compat_timeval(struct compat_timeval __user *u, struct timeval *t)
184{
185 struct compat_timeval t32;
186 t32.tv_sec = t->tv_sec;
187 t32.tv_usec = t->tv_usec;
188 return copy_to_user(u, &t32, sizeof t32);
189}
190
191static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
192{
193 long usec;
194
195 if (__get_user(o->tv_sec, &i->tv_sec))
196 return -EFAULT;
197 if (__get_user(usec, &i->tv_usec))
198 return -EFAULT;
199 o->tv_nsec = usec * 1000;
200 return 0;
201}
202
203asmlinkage int
204sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
205{
206 extern void do_gettimeofday(struct timeval *tv);
207
208 if (tv) {
209 struct timeval ktv;
210 do_gettimeofday(&ktv);
211 if (put_compat_timeval(tv, &ktv))
212 return -EFAULT;
213 }
214 if (tz) {
215 extern struct timezone sys_tz;
216 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
217 return -EFAULT;
218 }
219 return 0;
220}
221
222asmlinkage
223int sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
224{
225 struct timespec kts;
226 struct timezone ktz;
227
228 if (tv) {
229 if (get_ts32(&kts, tv))
230 return -EFAULT;
231 }
232 if (tz) {
233 if (copy_from_user(&ktz, tz, sizeof(ktz)))
234 return -EFAULT;
235 }
236
237 return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
238}
239
240/*** copied from mips64 ***/ 182/*** copied from mips64 ***/
241/* 183/*
242 * Ooo, nasty. We need here to frob 32-bit unsigned longs to 184 * Ooo, nasty. We need here to frob 32-bit unsigned longs to
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 6b5ac38f5a99..c7e59f548817 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -149,8 +149,8 @@
149 ENTRY_COMP(getrlimit) 149 ENTRY_COMP(getrlimit)
150 ENTRY_COMP(getrusage) 150 ENTRY_COMP(getrusage)
151 /* struct timeval and timezone are maybe?? consistent wide and narrow */ 151 /* struct timeval and timezone are maybe?? consistent wide and narrow */
152 ENTRY_DIFF(gettimeofday) 152 ENTRY_COMP(gettimeofday)
153 ENTRY_DIFF(settimeofday) 153 ENTRY_COMP(settimeofday)
154 ENTRY_SAME(getgroups) /* 80 */ 154 ENTRY_SAME(getgroups) /* 80 */
155 ENTRY_SAME(setgroups) 155 ENTRY_SAME(setgroups)
156 /* struct socketaddr... */ 156 /* struct socketaddr... */
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
index d00599bb24a1..bb1cfcfdbbbb 100644
--- a/arch/powerpc/kernel/sys_ppc32.c
+++ b/arch/powerpc/kernel/sys_ppc32.c
@@ -71,69 +71,6 @@ asmlinkage long compat_sys_sysfs(u32 option, u32 arg1, u32 arg2)
71 return sys_sysfs((int)option, arg1, arg2); 71 return sys_sysfs((int)option, arg1, arg2);
72} 72}
73 73
74static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
75{
76 long usec;
77
78 if (!access_ok(VERIFY_READ, i, sizeof(*i)))
79 return -EFAULT;
80 if (__get_user(o->tv_sec, &i->tv_sec))
81 return -EFAULT;
82 if (__get_user(usec, &i->tv_usec))
83 return -EFAULT;
84 o->tv_nsec = usec * 1000;
85 return 0;
86}
87
88static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
89{
90 return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
91 (__put_user(i->tv_sec, &o->tv_sec) |
92 __put_user(i->tv_usec, &o->tv_usec)));
93}
94
95
96
97
98/* Translations due to time_t size differences. Which affects all
99 sorts of things, like timeval and itimerval. */
100extern struct timezone sys_tz;
101
102asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
103{
104 if (tv) {
105 struct timeval ktv;
106 do_gettimeofday(&ktv);
107 if (put_tv32(tv, &ktv))
108 return -EFAULT;
109 }
110 if (tz) {
111 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
112 return -EFAULT;
113 }
114
115 return 0;
116}
117
118
119
120asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
121{
122 struct timespec kts;
123 struct timezone ktz;
124
125 if (tv) {
126 if (get_ts32(&kts, tv))
127 return -EFAULT;
128 }
129 if (tz) {
130 if (copy_from_user(&ktz, tz, sizeof(ktz)))
131 return -EFAULT;
132 }
133
134 return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
135}
136
137#ifdef CONFIG_SYSVIPC 74#ifdef CONFIG_SYSVIPC
138long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr, 75long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr,
139 u32 fifth) 76 u32 fifth)
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 9b471d785ec1..4646382af34f 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -279,22 +279,6 @@ asmlinkage long sys32_getegid16(void)
279 return high2lowgid(current->egid); 279 return high2lowgid(current->egid);
280} 280}
281 281
282/* 32-bit timeval and related flotsam. */
283
284static inline long get_tv32(struct timeval *o, struct compat_timeval __user *i)
285{
286 return (!access_ok(VERIFY_READ, o, sizeof(*o)) ||
287 (__get_user(o->tv_sec, &i->tv_sec) ||
288 __get_user(o->tv_usec, &i->tv_usec)));
289}
290
291static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
292{
293 return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
294 (__put_user(i->tv_sec, &o->tv_sec) ||
295 __put_user(i->tv_usec, &o->tv_usec)));
296}
297
298/* 282/*
299 * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation. 283 * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation.
300 * 284 *
@@ -522,57 +506,6 @@ sys32_delete_module(const char __user *name_user, unsigned int flags)
522 506
523#endif /* CONFIG_MODULES */ 507#endif /* CONFIG_MODULES */
524 508
525/* Translations due to time_t size differences. Which affects all
526 sorts of things, like timeval and itimerval. */
527
528extern struct timezone sys_tz;
529
530asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
531{
532 if (tv) {
533 struct timeval ktv;
534 do_gettimeofday(&ktv);
535 if (put_tv32(tv, &ktv))
536 return -EFAULT;
537 }
538 if (tz) {
539 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
540 return -EFAULT;
541 }
542 return 0;
543}
544
545static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
546{
547 long usec;
548
549 if (!access_ok(VERIFY_READ, i, sizeof(*i)))
550 return -EFAULT;
551 if (__get_user(o->tv_sec, &i->tv_sec))
552 return -EFAULT;
553 if (__get_user(usec, &i->tv_usec))
554 return -EFAULT;
555 o->tv_nsec = usec * 1000;
556 return 0;
557}
558
559asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
560{
561 struct timespec kts;
562 struct timezone ktz;
563
564 if (tv) {
565 if (get_ts32(&kts, tv))
566 return -EFAULT;
567 }
568 if (tz) {
569 if (copy_from_user(&ktz, tz, sizeof(ktz)))
570 return -EFAULT;
571 }
572
573 return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
574}
575
576asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf, 509asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf,
577 size_t count, u32 poshi, u32 poslo) 510 size_t count, u32 poshi, u32 poslo)
578{ 511{
diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h
index 05f8516366ab..836a28842900 100644
--- a/arch/s390/kernel/compat_linux.h
+++ b/arch/s390/kernel/compat_linux.h
@@ -202,10 +202,6 @@ long sys32_execve(void);
202long sys32_init_module(void __user *umod, unsigned long len, 202long sys32_init_module(void __user *umod, unsigned long len,
203 const char __user *uargs); 203 const char __user *uargs);
204long sys32_delete_module(const char __user *name_user, unsigned int flags); 204long sys32_delete_module(const char __user *name_user, unsigned int flags);
205long sys32_gettimeofday(struct compat_timeval __user *tv,
206 struct timezone __user *tz);
207long sys32_settimeofday(struct compat_timeval __user *tv,
208 struct timezone __user *tz);
209long sys32_pread64(unsigned int fd, char __user *ubuf, size_t count, 205long sys32_pread64(unsigned int fd, char __user *ubuf, size_t count,
210 u32 poshi, u32 poslo); 206 u32 poshi, u32 poslo);
211long sys32_pwrite64(unsigned int fd, const char __user *ubuf, 207long sys32_pwrite64(unsigned int fd, const char __user *ubuf,
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index ee51ca9e23b5..fc2c97197a53 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -332,17 +332,17 @@ compat_sys_getrusage_wrapper:
332 llgtr %r3,%r3 # struct rusage_emu31 * 332 llgtr %r3,%r3 # struct rusage_emu31 *
333 jg compat_sys_getrusage # branch to system call 333 jg compat_sys_getrusage # branch to system call
334 334
335 .globl sys32_gettimeofday_wrapper 335 .globl compat_sys_gettimeofday_wrapper
336sys32_gettimeofday_wrapper: 336compat_sys_gettimeofday_wrapper:
337 llgtr %r2,%r2 # struct timeval_emu31 * 337 llgtr %r2,%r2 # struct timeval_emu31 *
338 llgtr %r3,%r3 # struct timezone * 338 llgtr %r3,%r3 # struct timezone *
339 jg sys32_gettimeofday # branch to system call 339 jg compat_sys_gettimeofday # branch to system call
340 340
341 .globl sys32_settimeofday_wrapper 341 .globl compat_sys_settimeofday_wrapper
342sys32_settimeofday_wrapper: 342compat_sys_settimeofday_wrapper:
343 llgtr %r2,%r2 # struct timeval_emu31 * 343 llgtr %r2,%r2 # struct timeval_emu31 *
344 llgtr %r3,%r3 # struct timezone * 344 llgtr %r3,%r3 # struct timezone *
345 jg sys32_settimeofday # branch to system call 345 jg compat_sys_settimeofday # branch to system call
346 346
347 .globl sys32_getgroups16_wrapper 347 .globl sys32_getgroups16_wrapper
348sys32_getgroups16_wrapper: 348sys32_getgroups16_wrapper:
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 3ae303914b42..2d61787949d5 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -86,8 +86,8 @@ SYSCALL(sys_sethostname,sys_sethostname,sys32_sethostname_wrapper)
86SYSCALL(sys_setrlimit,sys_setrlimit,compat_sys_setrlimit_wrapper) /* 75 */ 86SYSCALL(sys_setrlimit,sys_setrlimit,compat_sys_setrlimit_wrapper) /* 75 */
87SYSCALL(sys_old_getrlimit,sys_getrlimit,compat_sys_old_getrlimit_wrapper) 87SYSCALL(sys_old_getrlimit,sys_getrlimit,compat_sys_old_getrlimit_wrapper)
88SYSCALL(sys_getrusage,sys_getrusage,compat_sys_getrusage_wrapper) 88SYSCALL(sys_getrusage,sys_getrusage,compat_sys_getrusage_wrapper)
89SYSCALL(sys_gettimeofday,sys_gettimeofday,sys32_gettimeofday_wrapper) 89SYSCALL(sys_gettimeofday,sys_gettimeofday,compat_sys_gettimeofday_wrapper)
90SYSCALL(sys_settimeofday,sys_settimeofday,sys32_settimeofday_wrapper) 90SYSCALL(sys_settimeofday,sys_settimeofday,compat_sys_settimeofday_wrapper)
91SYSCALL(sys_getgroups16,sys_ni_syscall,sys32_getgroups16_wrapper) /* 80 old getgroups16 syscall */ 91SYSCALL(sys_getgroups16,sys_ni_syscall,sys32_getgroups16_wrapper) /* 80 old getgroups16 syscall */
92SYSCALL(sys_setgroups16,sys_ni_syscall,sys32_setgroups16_wrapper) /* old setgroups16 syscall */ 92SYSCALL(sys_setgroups16,sys_ni_syscall,sys32_setgroups16_wrapper) /* old setgroups16 syscall */
93NI_SYSCALL /* old select syscall */ 93NI_SYSCALL /* old select syscall */
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 73a33dc3bcca..e800503879e4 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -58,15 +58,6 @@
58#include <asm/mmu_context.h> 58#include <asm/mmu_context.h>
59#include <asm/compat_signal.h> 59#include <asm/compat_signal.h>
60 60
61/* 32-bit timeval and related flotsam. */
62
63static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
64{
65 return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
66 (__put_user(i->tv_sec, &o->tv_sec) |
67 __put_user(i->tv_usec, &o->tv_usec)));
68}
69
70#ifdef CONFIG_SYSVIPC 61#ifdef CONFIG_SYSVIPC
71asmlinkage long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr, u32 fifth) 62asmlinkage long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr, u32 fifth)
72{ 63{
@@ -487,59 +478,6 @@ asmlinkage long sys32_delete_module(const char __user *name_user)
487 478
488#endif /* CONFIG_MODULES */ 479#endif /* CONFIG_MODULES */
489 480
490/* Translations due to time_t size differences. Which affects all
491 sorts of things, like timeval and itimerval. */
492
493extern struct timezone sys_tz;
494
495asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv,
496 struct timezone __user *tz)
497{
498 if (tv) {
499 struct timeval ktv;
500 do_gettimeofday(&ktv);
501 if (put_tv32(tv, &ktv))
502 return -EFAULT;
503 }
504 if (tz) {
505 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
506 return -EFAULT;
507 }
508 return 0;
509}
510
511static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
512{
513 long usec;
514
515 if (!access_ok(VERIFY_READ, i, sizeof(*i)))
516 return -EFAULT;
517 if (__get_user(o->tv_sec, &i->tv_sec))
518 return -EFAULT;
519 if (__get_user(usec, &i->tv_usec))
520 return -EFAULT;
521 o->tv_nsec = usec * 1000;
522 return 0;
523}
524
525asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv,
526 struct timezone __user *tz)
527{
528 struct timespec kts;
529 struct timezone ktz;
530
531 if (tv) {
532 if (get_ts32(&kts, tv))
533 return -EFAULT;
534 }
535 if (tz) {
536 if (copy_from_user(&ktz, tz, sizeof(ktz)))
537 return -EFAULT;
538 }
539
540 return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
541}
542
543asmlinkage compat_ssize_t sys32_pread64(unsigned int fd, 481asmlinkage compat_ssize_t sys32_pread64(unsigned int fd,
544 char __user *ubuf, 482 char __user *ubuf,
545 compat_size_t count, 483 compat_size_t count,
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 5daee4b04dd5..b2fa4c163638 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -41,8 +41,8 @@ sys_call_table32:
41/*100*/ .word sys32_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending 41/*100*/ .word sys32_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending
42 .word compat_sys_rt_sigtimedwait, sys32_rt_sigqueueinfo, compat_sys_rt_sigsuspend, sys_setresuid, sys_getresuid 42 .word compat_sys_rt_sigtimedwait, sys32_rt_sigqueueinfo, compat_sys_rt_sigsuspend, sys_setresuid, sys_getresuid
43/*110*/ .word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall 43/*110*/ .word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall
44 .word sys32_getgroups, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd 44 .word sys32_getgroups, compat_sys_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
45/*120*/ .word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys_fchown16, sys_fchmod 45/*120*/ .word compat_sys_readv, compat_sys_writev, compat_sys_settimeofday, sys_fchown16, sys_fchmod
46 .word sys_nis_syscall, sys_setreuid16, sys_setregid16, sys_rename, sys_truncate 46 .word sys_nis_syscall, sys_setreuid16, sys_setregid16, sys_rename, sys_truncate
47/*130*/ .word sys_ftruncate, sys_flock, compat_sys_lstat64, sys_nis_syscall, sys_nis_syscall 47/*130*/ .word sys_ftruncate, sys_flock, compat_sys_lstat64, sys_nis_syscall, sys_nis_syscall
48 .word sys_nis_syscall, sys32_mkdir, sys_rmdir, compat_sys_utimes, compat_sys_stat64 48 .word sys_nis_syscall, sys32_mkdir, sys_rmdir, compat_sys_utimes, compat_sys_stat64
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index eb4314768bf7..256b00b61892 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -571,8 +571,8 @@ ia32_sys_call_table:
571 .quad compat_sys_setrlimit /* 75 */ 571 .quad compat_sys_setrlimit /* 75 */
572 .quad compat_sys_old_getrlimit /* old_getrlimit */ 572 .quad compat_sys_old_getrlimit /* old_getrlimit */
573 .quad compat_sys_getrusage 573 .quad compat_sys_getrusage
574 .quad sys32_gettimeofday 574 .quad compat_sys_gettimeofday
575 .quad sys32_settimeofday 575 .quad compat_sys_settimeofday
576 .quad sys_getgroups16 /* 80 */ 576 .quad sys_getgroups16 /* 80 */
577 .quad sys_setgroups16 577 .quad sys_setgroups16
578 .quad sys32_old_select 578 .quad sys32_old_select
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c
index 4d3ad8d78a4d..2e09dcd3c0a6 100644
--- a/arch/x86/ia32/sys_ia32.c
+++ b/arch/x86/ia32/sys_ia32.c
@@ -367,75 +367,11 @@ asmlinkage long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
367 return 0; 367 return 0;
368} 368}
369 369
370static inline long get_tv32(struct timeval *o, struct compat_timeval __user *i)
371{
372 int err = -EFAULT;
373
374 if (access_ok(VERIFY_READ, i, sizeof(*i))) {
375 err = __get_user(o->tv_sec, &i->tv_sec);
376 err |= __get_user(o->tv_usec, &i->tv_usec);
377 }
378 return err;
379}
380
381static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
382{
383 int err = -EFAULT;
384
385 if (access_ok(VERIFY_WRITE, o, sizeof(*o))) {
386 err = __put_user(i->tv_sec, &o->tv_sec);
387 err |= __put_user(i->tv_usec, &o->tv_usec);
388 }
389 return err;
390}
391
392asmlinkage long sys32_alarm(unsigned int seconds) 370asmlinkage long sys32_alarm(unsigned int seconds)
393{ 371{
394 return alarm_setitimer(seconds); 372 return alarm_setitimer(seconds);
395} 373}
396 374
397/*
398 * Translations due to time_t size differences. Which affects all
399 * sorts of things, like timeval and itimerval.
400 */
401asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv,
402 struct timezone __user *tz)
403{
404 if (tv) {
405 struct timeval ktv;
406
407 do_gettimeofday(&ktv);
408 if (put_tv32(tv, &ktv))
409 return -EFAULT;
410 }
411 if (tz) {
412 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
413 return -EFAULT;
414 }
415 return 0;
416}
417
418asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv,
419 struct timezone __user *tz)
420{
421 struct timeval ktv;
422 struct timespec kts;
423 struct timezone ktz;
424
425 if (tv) {
426 if (get_tv32(&ktv, tv))
427 return -EFAULT;
428 kts.tv_sec = ktv.tv_sec;
429 kts.tv_nsec = ktv.tv_usec * NSEC_PER_USEC;
430 }
431 if (tz) {
432 if (copy_from_user(&ktz, tz, sizeof(ktz)))
433 return -EFAULT;
434 }
435
436 return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
437}
438
439struct sel_arg_struct { 375struct sel_arg_struct {
440 unsigned int n; 376 unsigned int n;
441 unsigned int inp; 377 unsigned int inp;
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 999dddd8d939..f061a1ea1b74 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -234,6 +234,11 @@ extern int get_compat_itimerspec(struct itimerspec *dst,
234extern int put_compat_itimerspec(struct compat_itimerspec __user *dst, 234extern int put_compat_itimerspec(struct compat_itimerspec __user *dst,
235 const struct itimerspec *src); 235 const struct itimerspec *src);
236 236
237asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv,
238 struct timezone __user *tz);
239asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv,
240 struct timezone __user *tz);
241
237asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp); 242asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp);
238 243
239extern int compat_printk(const char *fmt, ...); 244extern int compat_printk(const char *fmt, ...);
diff --git a/include/linux/time.h b/include/linux/time.h
index e15206a7e82e..51e883df0fa5 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -29,6 +29,8 @@ struct timezone {
29 29
30#ifdef __KERNEL__ 30#ifdef __KERNEL__
31 31
32extern struct timezone sys_tz;
33
32/* Parameters used to convert the timespec values: */ 34/* Parameters used to convert the timespec values: */
33#define MSEC_PER_SEC 1000L 35#define MSEC_PER_SEC 1000L
34#define USEC_PER_MSEC 1000L 36#define USEC_PER_MSEC 1000L
diff --git a/kernel/compat.c b/kernel/compat.c
index 32c254a8ab9a..143990e48cb9 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -26,6 +26,64 @@
26 26
27#include <asm/uaccess.h> 27#include <asm/uaccess.h>
28 28
29/*
30 * Note that the native side is already converted to a timespec, because
31 * that's what we want anyway.
32 */
33static int compat_get_timeval(struct timespec *o,
34 struct compat_timeval __user *i)
35{
36 long usec;
37
38 if (get_user(o->tv_sec, &i->tv_sec) ||
39 get_user(usec, &i->tv_usec))
40 return -EFAULT;
41 o->tv_nsec = usec * 1000;
42 return 0;
43}
44
45static int compat_put_timeval(struct compat_timeval __user *o,
46 struct timeval *i)
47{
48 return (put_user(i->tv_sec, &o->tv_sec) ||
49 put_user(i->tv_usec, &o->tv_usec)) ? -EFAULT : 0;
50}
51
52asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv,
53 struct timezone __user *tz)
54{
55 if (tv) {
56 struct timeval ktv;
57 do_gettimeofday(&ktv);
58 if (compat_put_timeval(tv, &ktv))
59 return -EFAULT;
60 }
61 if (tz) {
62 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
63 return -EFAULT;
64 }
65
66 return 0;
67}
68
69asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv,
70 struct timezone __user *tz)
71{
72 struct timespec kts;
73 struct timezone ktz;
74
75 if (tv) {
76 if (compat_get_timeval(&kts, tv))
77 return -EFAULT;
78 }
79 if (tz) {
80 if (copy_from_user(&ktz, tz, sizeof(ktz)))
81 return -EFAULT;
82 }
83
84 return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
85}
86
29int get_compat_timespec(struct timespec *ts, const struct compat_timespec __user *cts) 87int get_compat_timespec(struct timespec *ts, const struct compat_timespec __user *cts)
30{ 88{
31 return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) || 89 return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) ||