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