The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kernel/compat.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: e1e19d0d59589714b03f2eebec89adcc


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.