[PATCH] lightweight robust futexes: compat
[safe/jmp/linux-2.6] / kernel / compat.c
1 /*
2  *  linux/kernel/compat.c
3  *
4  *  Kernel compatibililty routines for e.g. 32 bit syscall support
5  *  on 64 bit kernels.
6  *
7  *  Copyright (C) 2002-2003 Stephen Rothwell, IBM Corporation
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License version 2 as
11  *  published by the Free Software Foundation.
12  */
13
14 #include <linux/linkage.h>
15 #include <linux/compat.h>
16 #include <linux/errno.h>
17 #include <linux/time.h>
18 #include <linux/signal.h>
19 #include <linux/sched.h>        /* for MAX_SCHEDULE_TIMEOUT */
20 #include <linux/syscalls.h>
21 #include <linux/unistd.h>
22 #include <linux/security.h>
23 #include <linux/timex.h>
24
25 #include <asm/uaccess.h>
26
27 int get_compat_timespec(struct timespec *ts, const struct compat_timespec __user *cts)
28 {
29         return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) ||
30                         __get_user(ts->tv_sec, &cts->tv_sec) ||
31                         __get_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
32 }
33
34 int put_compat_timespec(const struct timespec *ts, struct compat_timespec __user *cts)
35 {
36         return (!access_ok(VERIFY_WRITE, cts, sizeof(*cts)) ||
37                         __put_user(ts->tv_sec, &cts->tv_sec) ||
38                         __put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
39 }
40
41 static long compat_nanosleep_restart(struct restart_block *restart)
42 {
43         unsigned long expire = restart->arg0, now = jiffies;
44         struct compat_timespec __user *rmtp;
45
46         /* Did it expire while we handled signals? */
47         if (!time_after(expire, now))
48                 return 0;
49
50         expire = schedule_timeout_interruptible(expire - now);
51         if (expire == 0)
52                 return 0;
53
54         rmtp = (struct compat_timespec __user *)restart->arg1;
55         if (rmtp) {
56                 struct compat_timespec ct;
57                 struct timespec t;
58
59                 jiffies_to_timespec(expire, &t);
60                 ct.tv_sec = t.tv_sec;
61                 ct.tv_nsec = t.tv_nsec;
62                 if (copy_to_user(rmtp, &ct, sizeof(ct)))
63                         return -EFAULT;
64         }
65         /* The 'restart' block is already filled in */
66         return -ERESTART_RESTARTBLOCK;
67 }
68
69 asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp,
70                 struct compat_timespec __user *rmtp)
71 {
72         struct timespec t;
73         struct restart_block *restart;
74         unsigned long expire;
75
76         if (get_compat_timespec(&t, rqtp))
77                 return -EFAULT;
78
79         if ((t.tv_nsec >= 1000000000L) || (t.tv_nsec < 0) || (t.tv_sec < 0))
80                 return -EINVAL;
81
82         expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec);
83         expire = schedule_timeout_interruptible(expire);
84         if (expire == 0)
85                 return 0;
86
87         if (rmtp) {
88                 jiffies_to_timespec(expire, &t);
89                 if (put_compat_timespec(&t, rmtp))
90                         return -EFAULT;
91         }
92         restart = &current_thread_info()->restart_block;
93         restart->fn = compat_nanosleep_restart;
94         restart->arg0 = jiffies + expire;
95         restart->arg1 = (unsigned long) rmtp;
96         return -ERESTART_RESTARTBLOCK;
97 }
98
99 static inline long get_compat_itimerval(struct itimerval *o,
100                 struct compat_itimerval __user *i)
101 {
102         return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
103                 (__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) |
104                  __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) |
105                  __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) |
106                  __get_user(o->it_value.tv_usec, &i->it_value.tv_usec)));
107 }
108
109 static inline long put_compat_itimerval(struct compat_itimerval __user *o,
110                 struct itimerval *i)
111 {
112         return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
113                 (__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
114                  __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) |
115                  __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) |
116                  __put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));
117 }
118
119 asmlinkage long compat_sys_getitimer(int which,
120                 struct compat_itimerval __user *it)
121 {
122         struct itimerval kit;
123         int error;
124
125         error = do_getitimer(which, &kit);
126         if (!error && put_compat_itimerval(it, &kit))
127                 error = -EFAULT;
128         return error;
129 }
130
131 asmlinkage long compat_sys_setitimer(int which,
132                 struct compat_itimerval __user *in,
133                 struct compat_itimerval __user *out)
134 {
135         struct itimerval kin, kout;
136         int error;
137
138         if (in) {
139                 if (get_compat_itimerval(&kin, in))
140                         return -EFAULT;
141         } else
142                 memset(&kin, 0, sizeof(kin));
143
144         error = do_setitimer(which, &kin, out ? &kout : NULL);
145         if (error || !out)
146                 return error;
147         if (put_compat_itimerval(out, &kout))
148                 return -EFAULT;
149         return 0;
150 }
151
152 asmlinkage long compat_sys_times(struct compat_tms __user *tbuf)
153 {
154         /*
155          *      In the SMP world we might just be unlucky and have one of
156          *      the times increment as we use it. Since the value is an
157          *      atomically safe type this is just fine. Conceptually its
158          *      as if the syscall took an instant longer to occur.
159          */
160         if (tbuf) {
161                 struct compat_tms tmp;
162                 struct task_struct *tsk = current;
163                 struct task_struct *t;
164                 cputime_t utime, stime, cutime, cstime;
165
166                 read_lock(&tasklist_lock);
167                 utime = tsk->signal->utime;
168                 stime = tsk->signal->stime;
169                 t = tsk;
170                 do {
171                         utime = cputime_add(utime, t->utime);
172                         stime = cputime_add(stime, t->stime);
173                         t = next_thread(t);
174                 } while (t != tsk);
175
176                 /*
177                  * While we have tasklist_lock read-locked, no dying thread
178                  * can be updating current->signal->[us]time.  Instead,
179                  * we got their counts included in the live thread loop.
180                  * However, another thread can come in right now and
181                  * do a wait call that updates current->signal->c[us]time.
182                  * To make sure we always see that pair updated atomically,
183                  * we take the siglock around fetching them.
184                  */
185                 spin_lock_irq(&tsk->sighand->siglock);
186                 cutime = tsk->signal->cutime;
187                 cstime = tsk->signal->cstime;
188                 spin_unlock_irq(&tsk->sighand->siglock);
189                 read_unlock(&tasklist_lock);
190
191                 tmp.tms_utime = compat_jiffies_to_clock_t(cputime_to_jiffies(utime));
192                 tmp.tms_stime = compat_jiffies_to_clock_t(cputime_to_jiffies(stime));
193                 tmp.tms_cutime = compat_jiffies_to_clock_t(cputime_to_jiffies(cutime));
194                 tmp.tms_cstime = compat_jiffies_to_clock_t(cputime_to_jiffies(cstime));
195                 if (copy_to_user(tbuf, &tmp, sizeof(tmp)))
196                         return -EFAULT;
197         }
198         return compat_jiffies_to_clock_t(jiffies);
199 }
200
201 /*
202  * Assumption: old_sigset_t and compat_old_sigset_t are both
203  * types that can be passed to put_user()/get_user().
204  */
205
206 asmlinkage long compat_sys_sigpending(compat_old_sigset_t __user *set)
207 {
208         old_sigset_t s;
209         long ret;
210         mm_segment_t old_fs = get_fs();
211
212         set_fs(KERNEL_DS);
213         ret = sys_sigpending((old_sigset_t __user *) &s);
214         set_fs(old_fs);
215         if (ret == 0)
216                 ret = put_user(s, set);
217         return ret;
218 }
219
220 asmlinkage long compat_sys_sigprocmask(int how, compat_old_sigset_t __user *set,
221                 compat_old_sigset_t __user *oset)
222 {
223         old_sigset_t s;
224         long ret;
225         mm_segment_t old_fs;
226
227         if (set && get_user(s, set))
228                 return -EFAULT;
229         old_fs = get_fs();
230         set_fs(KERNEL_DS);
231         ret = sys_sigprocmask(how,
232                               set ? (old_sigset_t __user *) &s : NULL,
233                               oset ? (old_sigset_t __user *) &s : NULL);
234         set_fs(old_fs);
235         if (ret == 0)
236                 if (oset)
237                         ret = put_user(s, oset);
238         return ret;
239 }
240
241 asmlinkage long compat_sys_setrlimit(unsigned int resource,
242                 struct compat_rlimit __user *rlim)
243 {
244         struct rlimit r;
245         int ret;
246         mm_segment_t old_fs = get_fs ();
247
248         if (resource >= RLIM_NLIMITS) 
249                 return -EINVAL; 
250
251         if (!access_ok(VERIFY_READ, rlim, sizeof(*rlim)) ||
252             __get_user(r.rlim_cur, &rlim->rlim_cur) ||
253             __get_user(r.rlim_max, &rlim->rlim_max))
254                 return -EFAULT;
255
256         if (r.rlim_cur == COMPAT_RLIM_INFINITY)
257                 r.rlim_cur = RLIM_INFINITY;
258         if (r.rlim_max == COMPAT_RLIM_INFINITY)
259                 r.rlim_max = RLIM_INFINITY;
260         set_fs(KERNEL_DS);
261         ret = sys_setrlimit(resource, (struct rlimit __user *) &r);
262         set_fs(old_fs);
263         return ret;
264 }
265
266 #ifdef COMPAT_RLIM_OLD_INFINITY
267
268 asmlinkage long compat_sys_old_getrlimit(unsigned int resource,
269                 struct compat_rlimit __user *rlim)
270 {
271         struct rlimit r;
272         int ret;
273         mm_segment_t old_fs = get_fs();
274
275         set_fs(KERNEL_DS);
276         ret = sys_old_getrlimit(resource, &r);
277         set_fs(old_fs);
278
279         if (!ret) {
280                 if (r.rlim_cur > COMPAT_RLIM_OLD_INFINITY)
281                         r.rlim_cur = COMPAT_RLIM_INFINITY;
282                 if (r.rlim_max > COMPAT_RLIM_OLD_INFINITY)
283                         r.rlim_max = COMPAT_RLIM_INFINITY;
284
285                 if (!access_ok(VERIFY_WRITE, rlim, sizeof(*rlim)) ||
286                     __put_user(r.rlim_cur, &rlim->rlim_cur) ||
287                     __put_user(r.rlim_max, &rlim->rlim_max))
288                         return -EFAULT;
289         }
290         return ret;
291 }
292
293 #endif
294
295 asmlinkage long compat_sys_getrlimit (unsigned int resource,
296                 struct compat_rlimit __user *rlim)
297 {
298         struct rlimit r;
299         int ret;
300         mm_segment_t old_fs = get_fs();
301
302         set_fs(KERNEL_DS);
303         ret = sys_getrlimit(resource, (struct rlimit __user *) &r);
304         set_fs(old_fs);
305         if (!ret) {
306                 if (r.rlim_cur > COMPAT_RLIM_INFINITY)
307                         r.rlim_cur = COMPAT_RLIM_INFINITY;
308                 if (r.rlim_max > COMPAT_RLIM_INFINITY)
309                         r.rlim_max = COMPAT_RLIM_INFINITY;
310
311                 if (!access_ok(VERIFY_WRITE, rlim, sizeof(*rlim)) ||
312                     __put_user(r.rlim_cur, &rlim->rlim_cur) ||
313                     __put_user(r.rlim_max, &rlim->rlim_max))
314                         return -EFAULT;
315         }
316         return ret;
317 }
318
319 int put_compat_rusage(const struct rusage *r, struct compat_rusage __user *ru)
320 {
321         if (!access_ok(VERIFY_WRITE, ru, sizeof(*ru)) ||
322             __put_user(r->ru_utime.tv_sec, &ru->ru_utime.tv_sec) ||
323             __put_user(r->ru_utime.tv_usec, &ru->ru_utime.tv_usec) ||
324             __put_user(r->ru_stime.tv_sec, &ru->ru_stime.tv_sec) ||
325             __put_user(r->ru_stime.tv_usec, &ru->ru_stime.tv_usec) ||
326             __put_user(r->ru_maxrss, &ru->ru_maxrss) ||
327             __put_user(r->ru_ixrss, &ru->ru_ixrss) ||
328             __put_user(r->ru_idrss, &ru->ru_idrss) ||
329             __put_user(r->ru_isrss, &ru->ru_isrss) ||
330             __put_user(r->ru_minflt, &ru->ru_minflt) ||
331             __put_user(r->ru_majflt, &ru->ru_majflt) ||
332             __put_user(r->ru_nswap, &ru->ru_nswap) ||
333             __put_user(r->ru_inblock, &ru->ru_inblock) ||
334             __put_user(r->ru_oublock, &ru->ru_oublock) ||
335             __put_user(r->ru_msgsnd, &ru->ru_msgsnd) ||
336             __put_user(r->ru_msgrcv, &ru->ru_msgrcv) ||
337             __put_user(r->ru_nsignals, &ru->ru_nsignals) ||
338             __put_user(r->ru_nvcsw, &ru->ru_nvcsw) ||
339             __put_user(r->ru_nivcsw, &ru->ru_nivcsw))
340                 return -EFAULT;
341         return 0;
342 }
343
344 asmlinkage long compat_sys_getrusage(int who, struct compat_rusage __user *ru)
345 {
346         struct rusage r;
347         int ret;
348         mm_segment_t old_fs = get_fs();
349
350         set_fs(KERNEL_DS);
351         ret = sys_getrusage(who, (struct rusage __user *) &r);
352         set_fs(old_fs);
353
354         if (ret)
355                 return ret;
356
357         if (put_compat_rusage(&r, ru))
358                 return -EFAULT;
359
360         return 0;
361 }
362
363 asmlinkage long
364 compat_sys_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options,
365         struct compat_rusage __user *ru)
366 {
367         if (!ru) {
368                 return sys_wait4(pid, stat_addr, options, NULL);
369         } else {
370                 struct rusage r;
371                 int ret;
372                 unsigned int status;
373                 mm_segment_t old_fs = get_fs();
374
375                 set_fs (KERNEL_DS);
376                 ret = sys_wait4(pid,
377                                 (stat_addr ?
378                                  (unsigned int __user *) &status : NULL),
379                                 options, (struct rusage __user *) &r);
380                 set_fs (old_fs);
381
382                 if (ret > 0) {
383                         if (put_compat_rusage(&r, ru))
384                                 return -EFAULT;
385                         if (stat_addr && put_user(status, stat_addr))
386                                 return -EFAULT;
387                 }
388                 return ret;
389         }
390 }
391
392 asmlinkage long compat_sys_waitid(int which, compat_pid_t pid,
393                 struct compat_siginfo __user *uinfo, int options,
394                 struct compat_rusage __user *uru)
395 {
396         siginfo_t info;
397         struct rusage ru;
398         long ret;
399         mm_segment_t old_fs = get_fs();
400
401         memset(&info, 0, sizeof(info));
402
403         set_fs(KERNEL_DS);
404         ret = sys_waitid(which, pid, (siginfo_t __user *)&info, options,
405                          uru ? (struct rusage __user *)&ru : NULL);
406         set_fs(old_fs);
407
408         if ((ret < 0) || (info.si_signo == 0))
409                 return ret;
410
411         if (uru) {
412                 ret = put_compat_rusage(&ru, uru);
413                 if (ret)
414                         return ret;
415         }
416
417         BUG_ON(info.si_code & __SI_MASK);
418         info.si_code |= __SI_CHLD;
419         return copy_siginfo_to_user32(uinfo, &info);
420 }
421
422 static int compat_get_user_cpu_mask(compat_ulong_t __user *user_mask_ptr,
423                                     unsigned len, cpumask_t *new_mask)
424 {
425         unsigned long *k;
426
427         if (len < sizeof(cpumask_t))
428                 memset(new_mask, 0, sizeof(cpumask_t));
429         else if (len > sizeof(cpumask_t))
430                 len = sizeof(cpumask_t);
431
432         k = cpus_addr(*new_mask);
433         return compat_get_bitmap(k, user_mask_ptr, len * 8);
434 }
435
436 asmlinkage long compat_sys_sched_setaffinity(compat_pid_t pid,
437                                              unsigned int len,
438                                              compat_ulong_t __user *user_mask_ptr)
439 {
440         cpumask_t new_mask;
441         int retval;
442
443         retval = compat_get_user_cpu_mask(user_mask_ptr, len, &new_mask);
444         if (retval)
445                 return retval;
446
447         return sched_setaffinity(pid, new_mask);
448 }
449
450 asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len,
451                                              compat_ulong_t __user *user_mask_ptr)
452 {
453         int ret;
454         cpumask_t mask;
455         unsigned long *k;
456         unsigned int min_length = sizeof(cpumask_t);
457
458         if (NR_CPUS <= BITS_PER_COMPAT_LONG)
459                 min_length = sizeof(compat_ulong_t);
460
461         if (len < min_length)
462                 return -EINVAL;
463
464         ret = sched_getaffinity(pid, &mask);
465         if (ret < 0)
466                 return ret;
467
468         k = cpus_addr(mask);
469         ret = compat_put_bitmap(user_mask_ptr, k, min_length * 8);
470         if (ret)
471                 return ret;
472
473         return min_length;
474 }
475
476 static int get_compat_itimerspec(struct itimerspec *dst, 
477                                  struct compat_itimerspec __user *src)
478
479         if (get_compat_timespec(&dst->it_interval, &src->it_interval) ||
480             get_compat_timespec(&dst->it_value, &src->it_value))
481                 return -EFAULT;
482         return 0;
483
484
485 static int put_compat_itimerspec(struct compat_itimerspec __user *dst, 
486                                  struct itimerspec *src)
487
488         if (put_compat_timespec(&src->it_interval, &dst->it_interval) ||
489             put_compat_timespec(&src->it_value, &dst->it_value))
490                 return -EFAULT;
491         return 0;
492
493
494 long compat_sys_timer_create(clockid_t which_clock,
495                         struct compat_sigevent __user *timer_event_spec,
496                         timer_t __user *created_timer_id)
497 {
498         struct sigevent __user *event = NULL;
499
500         if (timer_event_spec) {
501                 struct sigevent kevent;
502
503                 event = compat_alloc_user_space(sizeof(*event));
504                 if (get_compat_sigevent(&kevent, timer_event_spec) ||
505                     copy_to_user(event, &kevent, sizeof(*event)))
506                         return -EFAULT;
507         }
508
509         return sys_timer_create(which_clock, event, created_timer_id);
510 }
511
512 long compat_sys_timer_settime(timer_t timer_id, int flags,
513                           struct compat_itimerspec __user *new, 
514                           struct compat_itimerspec __user *old)
515
516         long err;
517         mm_segment_t oldfs;
518         struct itimerspec newts, oldts;
519
520         if (!new)
521                 return -EINVAL;
522         if (get_compat_itimerspec(&newts, new))
523                 return -EFAULT; 
524         oldfs = get_fs();
525         set_fs(KERNEL_DS);
526         err = sys_timer_settime(timer_id, flags,
527                                 (struct itimerspec __user *) &newts,
528                                 (struct itimerspec __user *) &oldts);
529         set_fs(oldfs); 
530         if (!err && old && put_compat_itimerspec(old, &oldts))
531                 return -EFAULT;
532         return err;
533
534
535 long compat_sys_timer_gettime(timer_t timer_id,
536                 struct compat_itimerspec __user *setting)
537
538         long err;
539         mm_segment_t oldfs;
540         struct itimerspec ts; 
541
542         oldfs = get_fs();
543         set_fs(KERNEL_DS);
544         err = sys_timer_gettime(timer_id,
545                                 (struct itimerspec __user *) &ts); 
546         set_fs(oldfs); 
547         if (!err && put_compat_itimerspec(setting, &ts))
548                 return -EFAULT;
549         return err;
550
551
552 long compat_sys_clock_settime(clockid_t which_clock,
553                 struct compat_timespec __user *tp)
554 {
555         long err;
556         mm_segment_t oldfs;
557         struct timespec ts; 
558
559         if (get_compat_timespec(&ts, tp))
560                 return -EFAULT; 
561         oldfs = get_fs();
562         set_fs(KERNEL_DS);      
563         err = sys_clock_settime(which_clock,
564                                 (struct timespec __user *) &ts);
565         set_fs(oldfs);
566         return err;
567
568
569 long compat_sys_clock_gettime(clockid_t which_clock,
570                 struct compat_timespec __user *tp)
571 {
572         long err;
573         mm_segment_t oldfs;
574         struct timespec ts; 
575
576         oldfs = get_fs();
577         set_fs(KERNEL_DS);
578         err = sys_clock_gettime(which_clock,
579                                 (struct timespec __user *) &ts);
580         set_fs(oldfs);
581         if (!err && put_compat_timespec(&ts, tp))
582                 return -EFAULT; 
583         return err;
584
585
586 long compat_sys_clock_getres(clockid_t which_clock,
587                 struct compat_timespec __user *tp)
588 {
589         long err;
590         mm_segment_t oldfs;
591         struct timespec ts; 
592
593         oldfs = get_fs();
594         set_fs(KERNEL_DS);
595         err = sys_clock_getres(which_clock,
596                                (struct timespec __user *) &ts);
597         set_fs(oldfs);
598         if (!err && tp && put_compat_timespec(&ts, tp))
599                 return -EFAULT; 
600         return err;
601
602
603 long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
604                             struct compat_timespec __user *rqtp,
605                             struct compat_timespec __user *rmtp)
606 {
607         long err;
608         mm_segment_t oldfs;
609         struct timespec in, out; 
610
611         if (get_compat_timespec(&in, rqtp)) 
612                 return -EFAULT;
613
614         oldfs = get_fs();
615         set_fs(KERNEL_DS);
616         err = sys_clock_nanosleep(which_clock, flags,
617                                   (struct timespec __user *) &in,
618                                   (struct timespec __user *) &out);
619         set_fs(oldfs);
620         if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
621             put_compat_timespec(&out, rmtp))
622                 return -EFAULT;
623         return err;     
624
625
626 /*
627  * We currently only need the following fields from the sigevent
628  * structure: sigev_value, sigev_signo, sig_notify and (sometimes
629  * sigev_notify_thread_id).  The others are handled in user mode.
630  * We also assume that copying sigev_value.sival_int is sufficient
631  * to keep all the bits of sigev_value.sival_ptr intact.
632  */
633 int get_compat_sigevent(struct sigevent *event,
634                 const struct compat_sigevent __user *u_event)
635 {
636         memset(event, 0, sizeof(*event));
637         return (!access_ok(VERIFY_READ, u_event, sizeof(*u_event)) ||
638                 __get_user(event->sigev_value.sival_int,
639                         &u_event->sigev_value.sival_int) ||
640                 __get_user(event->sigev_signo, &u_event->sigev_signo) ||
641                 __get_user(event->sigev_notify, &u_event->sigev_notify) ||
642                 __get_user(event->sigev_notify_thread_id,
643                         &u_event->sigev_notify_thread_id))
644                 ? -EFAULT : 0;
645 }
646
647 long compat_get_bitmap(unsigned long *mask, compat_ulong_t __user *umask,
648                        unsigned long bitmap_size)
649 {
650         int i, j;
651         unsigned long m;
652         compat_ulong_t um;
653         unsigned long nr_compat_longs;
654
655         /* align bitmap up to nearest compat_long_t boundary */
656         bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);
657
658         if (!access_ok(VERIFY_READ, umask, bitmap_size / 8))
659                 return -EFAULT;
660
661         nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
662
663         for (i = 0; i < BITS_TO_LONGS(bitmap_size); i++) {
664                 m = 0;
665
666                 for (j = 0; j < sizeof(m)/sizeof(um); j++) {
667                         /*
668                          * We dont want to read past the end of the userspace
669                          * bitmap. We must however ensure the end of the
670                          * kernel bitmap is zeroed.
671                          */
672                         if (nr_compat_longs-- > 0) {
673                                 if (__get_user(um, umask))
674                                         return -EFAULT;
675                         } else {
676                                 um = 0;
677                         }
678
679                         umask++;
680                         m |= (long)um << (j * BITS_PER_COMPAT_LONG);
681                 }
682                 *mask++ = m;
683         }
684
685         return 0;
686 }
687
688 long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
689                        unsigned long bitmap_size)
690 {
691         int i, j;
692         unsigned long m;
693         compat_ulong_t um;
694         unsigned long nr_compat_longs;
695
696         /* align bitmap up to nearest compat_long_t boundary */
697         bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);
698
699         if (!access_ok(VERIFY_WRITE, umask, bitmap_size / 8))
700                 return -EFAULT;
701
702         nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
703
704         for (i = 0; i < BITS_TO_LONGS(bitmap_size); i++) {
705                 m = *mask++;
706
707                 for (j = 0; j < sizeof(m)/sizeof(um); j++) {
708                         um = m;
709
710                         /*
711                          * We dont want to write past the end of the userspace
712                          * bitmap.
713                          */
714                         if (nr_compat_longs-- > 0) {
715                                 if (__put_user(um, umask))
716                                         return -EFAULT;
717                         }
718
719                         umask++;
720                         m >>= 4*sizeof(um);
721                         m >>= 4*sizeof(um);
722                 }
723         }
724
725         return 0;
726 }
727
728 void
729 sigset_from_compat (sigset_t *set, compat_sigset_t *compat)
730 {
731         switch (_NSIG_WORDS) {
732 #if defined (__COMPAT_ENDIAN_SWAP__)
733         case 4: set->sig[3] = compat->sig[7] | (((long)compat->sig[6]) << 32 );
734         case 3: set->sig[2] = compat->sig[5] | (((long)compat->sig[4]) << 32 );
735         case 2: set->sig[1] = compat->sig[3] | (((long)compat->sig[2]) << 32 );
736         case 1: set->sig[0] = compat->sig[1] | (((long)compat->sig[0]) << 32 );
737 #else
738         case 4: set->sig[3] = compat->sig[6] | (((long)compat->sig[7]) << 32 );
739         case 3: set->sig[2] = compat->sig[4] | (((long)compat->sig[5]) << 32 );
740         case 2: set->sig[1] = compat->sig[2] | (((long)compat->sig[3]) << 32 );
741         case 1: set->sig[0] = compat->sig[0] | (((long)compat->sig[1]) << 32 );
742 #endif
743         }
744 }
745
746 asmlinkage long
747 compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese,
748                 struct compat_siginfo __user *uinfo,
749                 struct compat_timespec __user *uts, compat_size_t sigsetsize)
750 {
751         compat_sigset_t s32;
752         sigset_t s;
753         int sig;
754         struct timespec t;
755         siginfo_t info;
756         long ret, timeout = 0;
757
758         if (sigsetsize != sizeof(sigset_t))
759                 return -EINVAL;
760
761         if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t)))
762                 return -EFAULT;
763         sigset_from_compat(&s, &s32);
764         sigdelsetmask(&s,sigmask(SIGKILL)|sigmask(SIGSTOP));
765         signotset(&s);
766
767         if (uts) {
768                 if (get_compat_timespec (&t, uts))
769                         return -EFAULT;
770                 if (t.tv_nsec >= 1000000000L || t.tv_nsec < 0
771                                 || t.tv_sec < 0)
772                         return -EINVAL;
773         }
774
775         spin_lock_irq(&current->sighand->siglock);
776         sig = dequeue_signal(current, &s, &info);
777         if (!sig) {
778                 timeout = MAX_SCHEDULE_TIMEOUT;
779                 if (uts)
780                         timeout = timespec_to_jiffies(&t)
781                                 +(t.tv_sec || t.tv_nsec);
782                 if (timeout) {
783                         current->real_blocked = current->blocked;
784                         sigandsets(&current->blocked, &current->blocked, &s);
785
786                         recalc_sigpending();
787                         spin_unlock_irq(&current->sighand->siglock);
788
789                         timeout = schedule_timeout_interruptible(timeout);
790
791                         spin_lock_irq(&current->sighand->siglock);
792                         sig = dequeue_signal(current, &s, &info);
793                         current->blocked = current->real_blocked;
794                         siginitset(&current->real_blocked, 0);
795                         recalc_sigpending();
796                 }
797         }
798         spin_unlock_irq(&current->sighand->siglock);
799
800         if (sig) {
801                 ret = sig;
802                 if (uinfo) {
803                         if (copy_siginfo_to_user32(uinfo, &info))
804                                 ret = -EFAULT;
805                 }
806         }else {
807                 ret = timeout?-EINTR:-EAGAIN;
808         }
809         return ret;
810
811 }
812
813 #ifdef __ARCH_WANT_COMPAT_SYS_TIME
814
815 /* compat_time_t is a 32 bit "long" and needs to get converted. */
816
817 asmlinkage long compat_sys_time(compat_time_t __user * tloc)
818 {
819         compat_time_t i;
820         struct timeval tv;
821
822         do_gettimeofday(&tv);
823         i = tv.tv_sec;
824
825         if (tloc) {
826                 if (put_user(i,tloc))
827                         i = -EFAULT;
828         }
829         return i;
830 }
831
832 asmlinkage long compat_sys_stime(compat_time_t __user *tptr)
833 {
834         struct timespec tv;
835         int err;
836
837         if (get_user(tv.tv_sec, tptr))
838                 return -EFAULT;
839
840         tv.tv_nsec = 0;
841
842         err = security_settime(&tv, NULL);
843         if (err)
844                 return err;
845
846         do_settimeofday(&tv);
847         return 0;
848 }
849
850 #endif /* __ARCH_WANT_COMPAT_SYS_TIME */
851
852 #ifdef __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
853 asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat_size_t sigsetsize)
854 {
855         sigset_t newset;
856         compat_sigset_t newset32;
857
858         /* XXX: Don't preclude handling different sized sigset_t's.  */
859         if (sigsetsize != sizeof(sigset_t))
860                 return -EINVAL;
861
862         if (copy_from_user(&newset32, unewset, sizeof(compat_sigset_t)))
863                 return -EFAULT;
864         sigset_from_compat(&newset, &newset32);
865         sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
866
867         spin_lock_irq(&current->sighand->siglock);
868         current->saved_sigmask = current->blocked;
869         current->blocked = newset;
870         recalc_sigpending();
871         spin_unlock_irq(&current->sighand->siglock);
872
873         current->state = TASK_INTERRUPTIBLE;
874         schedule();
875         set_thread_flag(TIF_RESTORE_SIGMASK);
876         return -ERESTARTNOHAND;
877 }
878 #endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */
879
880 asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp)
881 {
882         struct timex txc;
883         int ret;
884
885         memset(&txc, 0, sizeof(struct timex));
886
887         if (!access_ok(VERIFY_READ, utp, sizeof(struct compat_timex)) ||
888                         __get_user(txc.modes, &utp->modes) ||
889                         __get_user(txc.offset, &utp->offset) ||
890                         __get_user(txc.freq, &utp->freq) ||
891                         __get_user(txc.maxerror, &utp->maxerror) ||
892                         __get_user(txc.esterror, &utp->esterror) ||
893                         __get_user(txc.status, &utp->status) ||
894                         __get_user(txc.constant, &utp->constant) ||
895                         __get_user(txc.precision, &utp->precision) ||
896                         __get_user(txc.tolerance, &utp->tolerance) ||
897                         __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
898                         __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
899                         __get_user(txc.tick, &utp->tick) ||
900                         __get_user(txc.ppsfreq, &utp->ppsfreq) ||
901                         __get_user(txc.jitter, &utp->jitter) ||
902                         __get_user(txc.shift, &utp->shift) ||
903                         __get_user(txc.stabil, &utp->stabil) ||
904                         __get_user(txc.jitcnt, &utp->jitcnt) ||
905                         __get_user(txc.calcnt, &utp->calcnt) ||
906                         __get_user(txc.errcnt, &utp->errcnt) ||
907                         __get_user(txc.stbcnt, &utp->stbcnt))
908                 return -EFAULT;
909
910         ret = do_adjtimex(&txc);
911
912         if (!access_ok(VERIFY_WRITE, utp, sizeof(struct compat_timex)) ||
913                         __put_user(txc.modes, &utp->modes) ||
914                         __put_user(txc.offset, &utp->offset) ||
915                         __put_user(txc.freq, &utp->freq) ||
916                         __put_user(txc.maxerror, &utp->maxerror) ||
917                         __put_user(txc.esterror, &utp->esterror) ||
918                         __put_user(txc.status, &utp->status) ||
919                         __put_user(txc.constant, &utp->constant) ||
920                         __put_user(txc.precision, &utp->precision) ||
921                         __put_user(txc.tolerance, &utp->tolerance) ||
922                         __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
923                         __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
924                         __put_user(txc.tick, &utp->tick) ||
925                         __put_user(txc.ppsfreq, &utp->ppsfreq) ||
926                         __put_user(txc.jitter, &utp->jitter) ||
927                         __put_user(txc.shift, &utp->shift) ||
928                         __put_user(txc.stabil, &utp->stabil) ||
929                         __put_user(txc.jitcnt, &utp->jitcnt) ||
930                         __put_user(txc.calcnt, &utp->calcnt) ||
931                         __put_user(txc.errcnt, &utp->errcnt) ||
932                         __put_user(txc.stbcnt, &utp->stbcnt))
933                 ret = -EFAULT;
934
935         return ret;
936 }