OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [tags/] [linux-2.6/] [linux-2.6.24_orig/] [kernel/] [compat.c] - Blame information for rev 8

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.